Matrix r5059
Loading...
Searching...
No Matches
forceCanonical.c
Go to the documentation of this file.
1/* C implementation of methods for forceCanonical */
2
3#include "Mdefines.h"
4#include "M5.h"
5#include "idz.h"
6
7SEXP dense_force_canonical(SEXP from, const char *class, int check)
8{
9 if (class[1] == 'g' && class[0] != 'n')
10 return from;
11 SEXP x = GET_SLOT(from, Matrix_xSym);
12 int naToUnitIfPattern = (check) ? 0 : 1;
13 if (class[0] == 'n' && !naToUnitIfPattern) {
14 int *px = LOGICAL(x);
15 R_xlen_t nx = XLENGTH(x);
16 while (nx-- > 0) if (*(px++) == NA_LOGICAL) break;
17 naToUnitIfPattern = nx >= 0;
18 if (class[1] == 'g' && !naToUnitIfPattern)
19 return from;
20 }
21 PROTECT(x);
22 int *pdim = DIM(from), m = pdim[0], n = pdim[1],
23 packed = class[2] == 'p', canonical = !naToUnitIfPattern;
24 char ul = '\0', ct = (class[1] == 'p') ? 'C' : '\0', nu = '\0';
25 if (class[1] != 'g')
26 ul = UPLO(from);
27 if (class[1] == 's' && class[0] == 'z')
28 ct = TRANS(from);
29 if (class[1] == 't')
30 nu = DIAG(from);
31 if (canonical) {
32#define TEMPLATE(c) \
33 do { \
34 c##TYPE *px = c##PTR(x); \
35 canonical = (!packed) \
36 ? !c##NAME(test2)(px, (size_t) n, ul, ct, nu) \
37 : !c##NAME(test1)(px, (size_t) n, ul, ct, nu); \
38 } while (0)
39 SWITCH5(class[0], TEMPLATE);
40#undef TEMPLATE
41 if (canonical) {
42 UNPROTECT(1); /* x */
43 return from;
44 }
45 }
46 SEXP y = PROTECT(Rf_allocVector(TYPEOF(x), XLENGTH(x)));
47#define TEMPLATE(c) \
48 do { \
49 c##TYPE *px = c##PTR(x), *py = c##PTR(y); \
50 if (class[1] == 'g') \
51 memcpy(py, px, sizeof(c##TYPE) * (size_t) m * (size_t) n); \
52 else if (!packed) \
53 c##NAME(force2)(py, px, (size_t) n, ul, ct, nu); \
54 else \
55 c##NAME(force1)(py, px, (size_t) n, ul, ct, nu); \
56 } while (0)
57 SWITCH4(class[0], TEMPLATE);
58#undef TEMPLATE
59 if (class[0] == 'n' && naToUnitIfPattern) {
60 int *py = LOGICAL(y);
61 R_xlen_t ny = XLENGTH(y);
62 while (ny-- > 0) { *py = *py != 0; ++py; }
63 }
64 SEXP to = PROTECT(newObject(class));
65 SET_DIM(to, m, n);
66 SET_DIMNAMES(to, 0, DIMNAMES(from, 0));
67 if (class[1] != 'g' && ul != 'U')
68 SET_UPLO(to);
69 if (class[1] == 's' && ct != 'C' && class[0] == 'z')
70 SET_TRANS(to);
71 if (class[1] != 't')
73 if (class[1] == 'o')
74 COPY_SLOT(to, from, Matrix_sdSym);
75 SET_SLOT(to, Matrix_xSym, y);
76 UNPROTECT(3); /* to, y, x */
77 return to;
78}
79
80SEXP sparse_force_canonical(SEXP from, const char *class, int check)
81{
82 SEXP to = from;
83 switch (class[1]) {
84 case 'g':
85 break;
86 case 's':
87 case 'p':
88 if (class[0] == 'z' && TRANS(from) == 'C') {
89 SEXP x = PROTECT(GET_SLOT(from, Matrix_xSym));
90 Rcomplex *px = COMPLEX(x);
91 int n = DIM(from)[1], canonical = (check) ? 1 : 0;
92 char ul = UPLO(from);
93 if (class[2] != 'T') {
94 SEXP iSym = (class[2] == 'C') ? Matrix_iSym : Matrix_jSym,
95 p = PROTECT(GET_SLOT(from, Matrix_pSym)),
96 i = PROTECT(GET_SLOT(from, iSym));
97 int *pp = INTEGER(p) + 1, *pi = INTEGER(i), j, k_, k, kend,
98 up = (class[2] == 'C') == (ul == 'U');
99 j = 0; k = 0;
100 if (canonical) {
101 for (; j < n; ++j) {
102 kend = pp[j];
103 if (k < kend && pi[k_ = (up) ? kend - 1 : k] == j &&
104 (ISNAN(px[k_].i) || px[k_].i != 0.0))
105 break;
106 k = kend;
107 }
108 canonical = j == n;
109 }
110 if (!canonical) {
111 SEXP y = PROTECT(duplicateVector(x));
112 Rcomplex *py = COMPLEX(y);
113 for (; j < n; ++j) {
114 kend = pp[j];
115 if (k < kend && pi[k_ = (up) ? kend - 1 : k] == j)
116 py[k_].r = 0.0;
117 }
118 PROTECT(to = newObject(class));
119 SET_DIM(to, n, n);
120 SET_DIMNAMES(to, 0, DIMNAMES(from, 0));
121 if (ul != 'U')
122 SET_UPLO(to);
123 SET_SLOT(to, Matrix_pSym, p);
124 SET_SLOT(to, Matrix_iSym, i);
125 SET_SLOT(to, Matrix_xSym, y);
126 UNPROTECT(2); /* to, y */
127 }
128 UNPROTECT(2); /* i, p */
129 } else {
130 SEXP i = PROTECT(GET_SLOT(from, Matrix_iSym)),
131 j = PROTECT(GET_SLOT(from, Matrix_jSym));
132 int *pi = INTEGER(i), *pj = INTEGER(j);
133 R_xlen_t k = 0, kend = XLENGTH(i);
134 if (canonical) {
135 for (; k < kend; ++k)
136 if (pi[k] == pj[k] &&
137 (ISNAN(px[k].i) || px[k].i != 0.0))
138 break;
139 canonical = k == kend;
140 }
141 if (!canonical) {
142 SEXP y = PROTECT(duplicateVector(x));
143 Rcomplex *py = COMPLEX(y);
144 for (; k < kend; ++k)
145 if (pi[k] == pj[k])
146 py[k].i = 0.0;
147 PROTECT(to = newObject(class));
148 SET_DIM(to, n, n);
149 SET_DIMNAMES(to, 0, DIMNAMES(from, 0));
150 if (ul != 'U')
151 SET_UPLO(to);
152 SET_SLOT(to, Matrix_iSym, i);
153 SET_SLOT(to, Matrix_jSym, j);
154 SET_SLOT(to, Matrix_xSym, y);
155 UNPROTECT(2); /* to, y */
156 }
157 UNPROTECT(2); /* j, i */
158 }
159 UNPROTECT(1); /* x */
160 }
161 case 'o':
162 break;
163 case 't':
164 if (DIAG(from) != 'N') {
165 /* defined in ./diag.c : */
166 SEXP sparse_diag_set(SEXP, const char *, SEXP);
167 SEXP value = R_NilValue;
168#define TEMPLATE(c) \
169 do { \
170 value = Rf_allocVector(c##TYPESXP, 1); \
171 c##PTR(value)[0] = c##UNIT; \
172 } while (0)
173 SWITCH4(class[0], TEMPLATE);
174#undef TEMPLATE
175 PROTECT(value);
176 to = sparse_diag_set(from, class, value);
177 UNPROTECT(1); /* value */
178 }
179 break;
180 default:
181 Rf_error("should never happen ...");
182 to = R_NilValue;
183 break;
184 }
185 return to;
186}
187
188SEXP R_dense_force_canonical(SEXP s_from, SEXP s_check)
189{
190 const char *class = Matrix_class(s_from, valid_dense, 0, __func__);
191
192 int check;
193 VALID_LOGIC2(s_check, check);
194
195 return dense_force_canonical(s_from, class, check);
196}
197
198SEXP R_sparse_force_canonical(SEXP s_from, SEXP s_check)
199{
200 const char *class = Matrix_class(s_from, valid_sparse, 0, __func__);
201
202 int check;
203 VALID_LOGIC2(s_check, check);
204
205 return sparse_force_canonical(s_from, class, check);
206}
#define SWITCH5(c, template)
Definition M5.h:327
#define SWITCH4(c, template)
Definition M5.h:315
#define SET_DIM(x, m, n)
Definition Mdefines.h:87
const char * valid_dense[]
Definition objects.c:3
#define SET_UPLO(x)
Definition Mdefines.h:103
#define DIAG(x)
Definition Mdefines.h:111
#define UPLO(x)
Definition Mdefines.h:101
#define SET_DIMNAMES(x, mode, value)
Definition Mdefines.h:98
SEXP duplicateVector(SEXP)
Definition utils.c:42
const char * Matrix_class(SEXP, const char **, int, const char *)
Definition objects.c:112
#define DIMNAMES(x, mode)
Definition Mdefines.h:96
#define SET_TRANS(x)
Definition Mdefines.h:108
#define TRANS(x)
Definition Mdefines.h:106
#define DIM(x)
Definition Mdefines.h:85
#define GET_SLOT(x, name)
Definition Mdefines.h:72
SEXP newObject(const char *)
Definition objects.c:13
#define COPY_SLOT(dest, src, name)
Definition Mdefines.h:75
const char * valid_sparse[]
Definition Mdefines.h:328
#define SET_SLOT(x, name, value)
Definition Mdefines.h:73
#define VALID_LOGIC2(s, d)
Definition Mdefines.h:216
#define TYPEOF(s)
Definition Mdefines.h:123
SEXP sparse_diag_set(SEXP from, const char *class, SEXP value)
Definition diag.c:271
SEXP R_sparse_force_canonical(SEXP s_from, SEXP s_check)
#define TEMPLATE(c)
SEXP dense_force_canonical(SEXP from, const char *class, int check)
SEXP sparse_force_canonical(SEXP from, const char *class, int check)
SEXP R_dense_force_canonical(SEXP s_from, SEXP s_check)
SEXP Matrix_sdSym
Definition init.c:629
SEXP Matrix_factorsSym
Definition init.c:606
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