Matrix r5059
Loading...
Searching...
No Matches
isCanonical.c
Go to the documentation of this file.
1/* C implementation of methods for isCanonical */
2
3#include "Mdefines.h"
4#include "M5.h"
5#include "idz.h"
6
7int dense_is_canonical(SEXP obj, const char *class)
8{
9 if (class[1] == 'g' && class[0] != 'n')
10 return 1;
11 SEXP x = GET_SLOT(obj, Matrix_xSym);
12 if (class[0] == 'n') {
13 int *px = LOGICAL(x);
14 R_xlen_t nx = XLENGTH(x);
15 while (nx-- > 0) if (*(px++) == NA_LOGICAL) return 0;
16 if (class[1] == 'g')
17 return 1;
18 }
19 PROTECT(x);
20 int n = DIM(obj)[1], packed = class[2] == 'p';
21 char ul = UPLO(obj), ct = (class[1] == 'p') ? 'C' : '\0', nu = '\0';
22 if (class[1] == 's' && class[0] == 'z')
23 ct = TRANS(obj);
24 if (class[1] == 't')
25 nu = DIAG(obj);
26 UNPROTECT(1); /* x */
27#define TEMPLATE(c) \
28 do { \
29 c##TYPE *px = c##PTR(x); \
30 return (!packed) \
31 ? !c##NAME(test2)(px, (size_t) n, ul, ct, nu) \
32 : !c##NAME(test1)(px, (size_t) n, ul, ct, nu); \
33 } while (0)
34 SWITCH5(class[0], TEMPLATE);
35#undef TEMPLATE
36 Rf_error("should never happen ...");
37 return 0;
38}
39
40int sparse_is_canonical(SEXP obj, const char *class)
41{
42 switch (class[1]) {
43 case 'g':
44 return 1;
45 case 's':
46 if (class[0] == 'z' && TRANS(obj) == 'C') {
47 SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym));
48 Rcomplex *px = COMPLEX(x);
49 int n = DIM(obj)[1];
50 char ul = UPLO(obj);
51 if (class[2] != 'T') {
52 SEXP iSym = (class[2] == 'C') ? Matrix_iSym : Matrix_jSym,
53 p = PROTECT(GET_SLOT(obj, Matrix_pSym)),
54 i = PROTECT(GET_SLOT(obj, iSym));
55 int *pp = INTEGER(p) + 1, *pi = INTEGER(i), j, k_, k, kend,
56 up = (class[2] == 'C') == (ul == 'U');
57 UNPROTECT(3); /* i, p, x */
58 for (j = 0, k = 0; j < n; ++j) {
59 kend = pp[j];
60 if (k < kend && pi[k_ = (up) ? kend - 1 : k] == j &&
61 (ISNAN(px[k_].i) || px[k_].i != 0.0))
62 return 0;
63 k = kend;
64 }
65 } else {
66 SEXP i = PROTECT(GET_SLOT(obj, Matrix_iSym)),
67 j = PROTECT(GET_SLOT(obj, Matrix_jSym));
68 int *pi = INTEGER(i), *pj = INTEGER(j);
69 R_xlen_t k, kend = XLENGTH(i);
70 UNPROTECT(3); /* j, i, x */
71 for (k = 0; k < kend; ++k)
72 if (pi[k] == pj[k] &&
73 (ISNAN(px[k].i) || px[k].i != 0.0))
74 return 0;
75 }
76 }
77 return 1;
78 case 't':
79 return DIAG(obj) == 'N';
80 default:
81 Rf_error("should never happen ...");
82 return 0;
83 }
84}
85
86SEXP R_dense_is_canonical(SEXP s_obj)
87{
88 const char *class = Matrix_class(s_obj, valid_dense, 6, __func__);
89 return Rf_ScalarLogical(dense_is_canonical(s_obj, class));
90}
91
92SEXP R_sparse_is_canonical(SEXP s_obj)
93{
94 const char *class = Matrix_class(s_obj, valid_sparse, 6, __func__);
95 return Rf_ScalarLogical(sparse_is_canonical(s_obj, class));
96}
#define SWITCH5(c, template)
Definition M5.h:327
const char * valid_dense[]
Definition objects.c:3
#define DIAG(x)
Definition Mdefines.h:111
#define UPLO(x)
Definition Mdefines.h:101
const char * Matrix_class(SEXP, const char **, int, const char *)
Definition objects.c:112
#define TRANS(x)
Definition Mdefines.h:106
#define DIM(x)
Definition Mdefines.h:85
#define GET_SLOT(x, name)
Definition Mdefines.h:72
const char * valid_sparse[]
Definition Mdefines.h:328
SEXP Matrix_xSym
Definition init.c:635
SEXP Matrix_iSym
Definition init.c:607
SEXP Matrix_jSym
Definition init.c:610
SEXP Matrix_pSym
Definition init.c:622
SEXP R_dense_is_canonical(SEXP s_obj)
Definition isCanonical.c:86
int sparse_is_canonical(SEXP obj, const char *class)
Definition isCanonical.c:40
SEXP R_sparse_is_canonical(SEXP s_obj)
Definition isCanonical.c:92
int dense_is_canonical(SEXP obj, const char *class)
Definition isCanonical.c:7
#define TEMPLATE(c)