Matrix r4655
Loading...
Searching...
No Matches
t_subassign.c
Go to the documentation of this file.
1/*------ Definition of a template for [diln]Csparse_subassign(...) : *
2 * -------- ~~~~~~~~~~~~~~~~~~~~~~
3 * i.e., included several times from ./Csparse.c
4 * ~~~~~~~~~~~
5 * _slot_kind : use the integer codes matching x_slot_kind in ./Csparse.c
6 */
7
8#ifdef _d_Csp_
9
10# define Csparse_subassign dCsparse_subassign
11# define x_CLASSES "dgCMatrix",/* 0 */ "dtCMatrix" /* 1 */
12# define sparseVECTOR "dsparseVector"
13# define slot_kind_x 0
14# define _DOUBLE_x
15# define _has_x_slot_
16
17# undef _d_Csp_
18
19#elif defined (_l_Csp_)
20
21# define Csparse_subassign lCsparse_subassign
22# define x_CLASSES "lgCMatrix",/* 0 */ "ltCMatrix" /* 1 */
23# define sparseVECTOR "lsparseVector"
24# define slot_kind_x 1
25# define _LGL_x
26# define _has_x_slot_
27
28# undef _l_Csp_
29
30#elif defined (_i_Csp_)
31
32# define Csparse_subassign iCsparse_subassign
33# define x_CLASSES "igCMatrix",/* 0 */ "itCMatrix" /* 1 */
34# define sparseVECTOR "isparseVector"
35# define slot_kind_x 2
36# define _INT_x
37# define _has_x_slot_
38
39# undef _i_Csp_
40
41#elif defined (_n_Csp_)
42
43# define Csparse_subassign nCsparse_subassign
44# define x_CLASSES "ngCMatrix",/* 0 */ "ntCMatrix" /* 1 */
45# define sparseVECTOR "nsparseVector"
46# define slot_kind_x -1
47# define _INT_x
48/* withOUT 'x' slot -- CARE! we assume that this is the *ONLY* case w/o x slot */
49
50# undef _n_Csp_
51
52#elif defined (_z_Csp_)
53
54// # error "zgC* not yet implemented"
55# define Csparse_subassign zCsparse_subassign
56# define x_CLASSES "zgCMatrix",/* 0 */ "ztCMatrix" /* 1 */
57# define sparseVECTOR "zsparseVector"
58# define slot_kind_x 3
59# define _CPLX_x
60# define _has_x_slot_
61
62# undef _z_Csp_
63
64#else
65
66# error "no valid _[dilnz]gC_ option"
67
68#endif
69// -------------------------------------------------
70
71#ifdef _DOUBLE_x
72
73# define Type_x double
74# define Type_x_0_init(_VAR_) double _VAR_ = 0.
75# define Type_x_1_init(_VAR_) double _VAR_ = 1.
76# define STYP_x REAL
77# define SXP_x REALSXP
78#undef _DOUBLE_x
79
80#elif defined (_LGL_x)
81
82# define Type_x int
83# define Type_x_0_init(_VAR_) int _VAR_ = 0
84# define Type_x_1_init(_VAR_) int _VAR_ = 1
85# define STYP_x LOGICAL
86# define SXP_x LGLSXP
87#undef _LGL_x
88
89#elif defined (_INT_x)
90
91# define Type_x int
92# define Type_x_0_init(_VAR_) int _VAR_ = 0
93# define Type_x_1_init(_VAR_) int _VAR_ = 1
94# define STYP_x INTEGER
95# define SXP_x INTSXP
96#undef _INT_x
97
98#elif defined (_CPLX_x)
99
100# define Type_x Rcomplex
101# define Type_x_0_init(_VAR_) Rcomplex _VAR_; _VAR_.r = _VAR_.i = 0.
102# define Type_x_1_init(_VAR_) Rcomplex _VAR_; _VAR_.r = 1.; _VAR_.i = 0.
103# define STYP_x COMPLEX
104# define SXP_x CPLXSXP
105
106#else
107# error "invalid macro logic"
108#endif
109
110
111
122SEXP Csparse_subassign(SEXP x, SEXP i_, SEXP j_, SEXP value)
123{
124 static const char
125 *valid_cM [] = { // the only ones, for "the moment". FIXME: extend (!)
126 x_CLASSES,
127 ""},
128 // value: assume a "dsparseVector" for now -- slots: (i, length, x)
129 *valid_spv[] = { sparseVECTOR, // = "the one with the same slot-class"
130 // all others: ctype_v slot_kind
131 "nsparseVector",// 1 -1
132 "lsparseVector",// 2 1
133 "isparseVector",// 3 2
134 "dsparseVector",// 4 0
135 "zsparseVector",// 5 3
136 ""};
137
138 int ctype_x = R_check_class_etc(x, valid_cM),
139 ctype_v = R_check_class_etc(value, valid_spv);
140 if (ctype_x < 0)
141 error(_("invalid class of 'x' in Csparse_subassign()"));
142 if (ctype_v < 0)
143 error(_("invalid class of 'value' in Csparse_subassign()"));
144 Rboolean value_is_nsp = ctype_v == 1;
145#ifndef _has_x_slot_ // i.e. "n.CMatrix" : sparseVECTOR == "nsparseVector"
146 if(!value_is_nsp) value_is_nsp = (ctype_v == 0);
147#endif
148
149 SEXP
150 islot = GET_SLOT(x, Matrix_iSym),
151 dimslot = GET_SLOT(x, Matrix_DimSym),
152 i_cp = PROTECT(coerceVector(i_, INTSXP)),
153 j_cp = PROTECT(coerceVector(j_, INTSXP));
154 // for d.CMatrix and l.CMatrix but not n.CMatrix:
155
156 int *dims = INTEGER(dimslot),
157 ncol = dims[1], /* nrow = dims[0], */
158 *i = INTEGER(i_cp), len_i = LENGTH(i_cp),
159 *j = INTEGER(j_cp), len_j = LENGTH(j_cp),
160 k,
161 nnz_x = LENGTH(islot);
162 int nnz = nnz_x;
163
164#define MATRIX_SUBASSIGN_VERBOSE
165// Temporary hack for debugging --- remove eventually -- FIXME
166#ifdef MATRIX_SUBASSIGN_VERBOSE
167 Rboolean verbose = i[0] < 0;
168 if(verbose) {
169 i[0] = -i[0];
170 REprintf("Csparse_subassign() x[i,j] <- val; x is \"%s\"; value \"%s\" is_nsp=%d\n",
171 valid_cM[ctype_x], valid_spv[ctype_v], (int)value_is_nsp);
172 }
173#endif
174
175 SEXP val_i_slot, val_x_slot;
176 val_i_slot = PROTECT(coerceVector(GET_SLOT(value, Matrix_iSym), REALSXP));
177 double *val_i = REAL(val_i_slot);
178 int nnz_val = LENGTH(GET_SLOT(value, Matrix_iSym)), n_prot = 4;
179 Type_x *val_x = NULL;
180 if(!value_is_nsp) {
181 if(ctype_v) { // matrix 'x' and 'value' are of different kinds
182 switch((enum x_slot_kind) slot_kind_x) {
183 case x_pattern:// "n"
184 case x_logical:// "l"
185 if(ctype_v >= 3)
186 warning(_("x[] <- val: val is coerced to logical for \"%s\" x"),
187 valid_cM[ctype_x]);
188 break;
189 case x_integer:
190 if(ctype_v >= 4)
191 error(_("x[] <- val: val should be integer or logical, is coerced to integer, for \"%s\" x"),
192 valid_cM[ctype_x]);
193 break;
194 case x_double:
195 case x_complex: // coercion should be tried (and fail for complex -> double) below
196 break;
197 default:
198 error(_("programming error in Csparse_subassign() should never happen"));
199 }
200 // otherwise: "coerce" : as(., <sparseVector>) :
201 val_x_slot = PROTECT(coerceVector(GET_SLOT(value, Matrix_xSym), SXP_x)); n_prot++;
202 val_x = STYP_x(val_x_slot);
203 } else {
204 val_x = STYP_x( GET_SLOT(value, Matrix_xSym));
205 }
206 }
207 int64_t len_val = (int64_t) asReal(GET_SLOT(value, Matrix_lengthSym));
208 /* llen_i = (int64_t) len_i; */
209
210 SEXP ans;
211 /* Instead of simple "duplicate": PROTECT(ans = duplicate(x)) , build up: */
212 // Assuming that ans will have the same basic Matrix type as x :
213 ans = PROTECT(newObject(valid_cM[ctype_x]));
214 SET_SLOT(ans, Matrix_DimSym, duplicate(dimslot));
216 SET_SLOT(ans, Matrix_pSym, duplicate(GET_SLOT(x, Matrix_pSym)));
217 SEXP r_pslot = GET_SLOT(ans, Matrix_pSym);
218 // and assign the i- and x- slots at the end, as they are potentially modified
219 // not just in content, but also in their *length*
220 int *rp = INTEGER(r_pslot),
221 *ri = R_Calloc(nnz_x, int); // to contain the final i - slot
222 Memcpy(ri, INTEGER(islot), nnz_x);
223 Type_x_0_init(z_ans);
224 Type_x_1_init(one_ans);
225#ifdef _has_x_slot_
226 Type_x *rx = R_Calloc(nnz_x, Type_x); // to contain the final x - slot
227 Memcpy(rx, STYP_x(GET_SLOT(x, Matrix_xSym)), nnz_x);
228#endif
229 // NB: nnz_x : will always be the "current allocated length" of (i, x) slots
230 // -- nnz : the current *used* length; always nnz <= nnz_x
231
232 int jj, j_val = 0; // in "running" conceptionally through all value[i+ jj*len_i]
233 // values, we are "below"/"before" the (j_val)-th non-zero one.
234 // e.g. if value = (0,0,...,0), have nnz_val == 0, j_val must remain == 0
235 int64_t ii_val;// == "running" index (i + jj*len_i) % len_val for value[]
236 for(jj = 0, ii_val=0; jj < len_j; jj++) {
237 int j__ = j[jj];
238 /* int64_t j_l = jj * llen_i; */
239 R_CheckUserInterrupt();
240 for(int ii = 0; ii < len_i; ii++, ii_val++) {
241 int i__ = i[ii], p1, p2;
242 if(nnz_val && ii_val >= len_val) { // "recycle" indexing into value[]
243 ii_val -= len_val; // = (ii + jj*len_i) % len_val
244 j_val = 0;
245 }
246 int64_t ii_v1;//= ii_val + 1;
247 Type_x v, /* := value[(ii + j_l) % len_val]
248 = .sparseVector_sub((ii + j_l) % len_val,
249 nnz_val, val_i, val_x, len_val)
250 */
251 M_ij;
252 int ind;
253 Rboolean have_entry = FALSE;
254
255 // note that rp[]'s may have *changed* even when 'j' remained!
256 // "FIXME": do this only *when* rp[] has changed
257 p1 = rp[j__], p2 = rp[j__ + 1];
258
259 // v := value[(ii + j_l) % len_val] = value[ii_val]
260 v = z_ans;
261 if(j_val < nnz_val) { // maybe find v := non-zero value[ii_val]
262 ii_v1 = ii_val + 1;
263 if(ii_v1 < val_i[j_val]) { // typical case: are still in zero-stretch
264 // v = z_ans (== 0)
265 } else if(ii_v1 == val_i[j_val]) { // have a match
266 v = (value_is_nsp) ? one_ans : val_x[j_val];
267 j_val++;// from now on, look at the next non-zero entry
268 } else { // ii_v1 > val_i[j_val]
269 REprintf("programming thinko in Csparse_subassign(*, i=%d,j=%d): ii_v=%lld, v@i[j_val=%d]=%g\n",
270 i__,j__, (long long)ii_v1, j_val, val_i[j_val]);
271 j_val++;// from now on, look at the next non-zero entry
272 }
273 }
274 // --------------- M_ij := getM(i., j.) --------------------------------
275 M_ij = z_ans; // as in ./t_sparseVector.c
276 for(ind = p1; ind < p2; ind++) {
277 if(ri[ind] >= i__) {
278 if(ri[ind] == i__) {
279#ifdef _has_x_slot_
280 M_ij = rx[ind];
281#else
282 M_ij = 1;
283#endif
284#ifdef MATRIX_SUBASSIGN_VERBOSE
285 if(verbose)
286 REprintf("have entry x[%d, %d] = %g\n", i__, j__,
287# ifdef _CPLX_x
288 (double)M_ij.r);
289# else
290 (double)M_ij);
291# endif
292#endif
293 have_entry = TRUE;
294 } else { // ri[ind] > i__
295#ifdef MATRIX_SUBASSIGN_VERBOSE
296 if(verbose)
297 REprintf("@i > i__ = %d --> ind-- = %d\n", i__, ind);
298#endif
299 }
300 break;
301 }
302 }
303
304 //-- R: if(getM(i., j.) != (v <- getV(ii, jj)))
305
306 // if(contents differ) ==> value needs to be changed :
307#ifdef _CPLX_x
308 if(M_ij.r != v.r || M_ij.i != v.i) {
309#else
310 if(M_ij != v) {
311#endif
312
313#ifdef MATRIX_SUBASSIGN_VERBOSE
314 if(verbose)
315 REprintf("setting x[%d, %d] <- %g", i__,j__,
316# ifdef _CPLX_x
317 (double) v.r);
318# else
319 (double) v);
320# endif
321#endif
322 // (otherwise: nothing to do):
323 // setM(i__, j__, v)
324 // ----------------------------------------------------------
325
326#ifndef _has_x_slot_
327 if(v == z_ans) {
328 // Case I ----- remove x[i, j] = M_ij which we know is *non*-zero
329// BUT it is more efficient (memory-management!) *NOT* to remove,
331// currently using drop0() in R code
332 // we know : have_entry = TRUE ;
333 // ri[ind] == i__; M_ij = rx[ind];
334#ifdef MATRIX_SUBASSIGN_VERBOSE
335 if(verbose)
336 REprintf(" rm ind=%d\n", ind);
337#endif
338 // remove the 'ind'-th element from x@i and x@x :
339 nnz-- ;
340 for(k=ind; k < nnz; k++) {
341 ri[k] = ri[k+1];
342#ifdef _has_x_slot_
343 rx[k] = rx[k+1];
344#endif
345 }
346 for(k=j__ + 1; k <= ncol; k++) {
347 rp[k] = rp[k] - 1;
348 }
349 }
350 else
351#endif
352 if(have_entry) {
353 // Case II ----- replace (non-empty) x[i,j] by v -------
354#ifdef MATRIX_SUBASSIGN_VERBOSE
355 if(verbose)
356 REprintf(" repl. ind=%d\n", ind);
357#endif
358#ifdef _has_x_slot_
359 rx[ind] = v;
360#endif
361 } else {
362 // Case III ----- v != 0 : insert v into "empty" x[i,j] ----
363
364 // extend the i and x slot by one entry : ---------------------
365 if(nnz+1 > nnz_x) { // need to reallocate:
366#ifdef MATRIX_SUBASSIGN_VERBOSE
367 if(verbose) REprintf(" R_Realloc()ing: nnz_x=%d", nnz_x);
368#endif
369 // do it "only" 1x,..4x at the very most increasing by the
370 // nnz-length of "value":
371 nnz_x += (1 + nnz_val / 4);
372#ifdef MATRIX_SUBASSIGN_VERBOSE
373 if(verbose) REprintf("(nnz_v=%d) --> %d ", nnz_val, nnz_x);
374#endif
375 // C doc on realloc() says that the old content is *preserve*d
376 ri = R_Realloc(ri, nnz_x, int);
377#ifdef _has_x_slot_
378 rx = R_Realloc(rx, nnz_x, Type_x);
379#endif
380 }
381 // 3) fill them ...
382
383 int i1 = ind;
384#ifdef MATRIX_SUBASSIGN_VERBOSE
385 if(verbose)
386 REprintf(" INSERT p12=(%d,%d) -> ind=%d -> i1 = %d\n",
387 p1,p2, ind, i1);
388#endif
389
390 // shift the "upper values" *before* the insertion:
391 for(int l = nnz-1; l >= i1; l--) {
392 ri[l+1] = ri[l];
393#ifdef _has_x_slot_
394 rx[l+1] = rx[l];
395#endif
396 }
397 ri[i1] = i__;
398#ifdef _has_x_slot_
399 rx[i1] = v;
400#endif
401 nnz++;
402 // the columns j "right" of the current one :
403 for(k=j__ + 1; k <= ncol; k++)
404 rp[k]++;
405 }
406 }
407#ifdef MATRIX_SUBASSIGN_VERBOSE
408 else if(verbose) REprintf("M_ij == v = %g\n",
409# ifdef _CPLX_x
410 (double) v.r);
411# else
412 (double) v);
413# endif
414#endif
415 }// for( ii )
416 }// for( jj )
417
418 if(ctype_x == 1) { // triangularMatrix: copy the 'diag' and 'uplo' slots
419 SET_SLOT(ans, Matrix_uploSym, duplicate(GET_SLOT(x, Matrix_uploSym)));
420 SET_SLOT(ans, Matrix_diagSym, duplicate(GET_SLOT(x, Matrix_diagSym)));
421 }
422 // now assign the i- and x- slots, free memory and return :
423 PROTECT(islot = allocVector(INTSXP, nnz));
424 Memcpy(INTEGER(islot), ri, nnz);
425 SET_SLOT(ans, Matrix_iSym, islot);
426 UNPROTECT(1);
427#ifdef _has_x_slot_
428 PROTECT(islot = allocVector(SXP_x, nnz));
429 Memcpy(STYP_x(islot), rx, nnz);
430 SET_SLOT(ans, Matrix_xSym, islot);
431 UNPROTECT(1);
432 R_Free(rx);
433#endif
434 R_Free(ri);
435 UNPROTECT(n_prot);
436 return ans;
437}
438
439#undef Csparse_subassign
440#undef x_CLASSES
441#undef sparseVECTOR
442
443#undef Type_x
444#undef STYP_x
445#undef SXP_x
446#undef Type_x_0_init
447#undef Type_x_1_init
448#undef _has_x_slot_
449#undef slot_kind_x
450
451#ifdef _CPLX_x
452# undef _CPLX_x
453#endif
454
455
456
#define _(String)
Definition Mdefines.h:44
#define SET_SLOT(x, what, value)
Definition Mdefines.h:86
#define GET_SLOT(x, what)
Definition Mdefines.h:85
SEXP newObject(const char *)
Definition objects.c:4
SEXP Matrix_DimSym
Definition Msymbols.h:3
SEXP Matrix_xSym
Definition Msymbols.h:22
SEXP Matrix_lengthSym
Definition Msymbols.h:15
SEXP Matrix_iSym
Definition Msymbols.h:13
SEXP Matrix_DimNamesSym
Definition Msymbols.h:2
SEXP Matrix_diagSym
Definition Msymbols.h:11
SEXP Matrix_uploSym
Definition Msymbols.h:21
SEXP Matrix_pSym
Definition Msymbols.h:17
x_slot_kind
Definition subassign.c:4
@ x_double
Definition subassign.c:7
@ x_complex
Definition subassign.c:10
@ x_integer
Definition subassign.c:9
@ x_logical
Definition subassign.c:8
@ x_pattern
Definition subassign.c:6
SEXP Csparse_subassign(SEXP x, SEXP i_, SEXP j_, SEXP value)
Subassignment: x[i,j] <- value.