20void matmultDim(SEXP x, SEXP y,
char *xtrans,
char *ytrans,
char *ztrans,
21 int *m,
int *n,
int *v)
23 int xt = *xtrans ==
'C' || *xtrans ==
'T';
if (!xt) *xtrans =
'N';
24 int yt = *ytrans ==
'C' || *ytrans ==
'T';
if (!yt) *ytrans =
'N';
25 int zt = *ztrans ==
'C' || *ztrans ==
'T';
if (!zt) *ztrans =
'N';
26 if (y == R_NilValue) {
28 Rf_error(
_(
"should never happen ..."));
30 xdim = (
TYPEOF(x) == OBJSXP)
32 if (
TYPEOF(xdim) == INTSXP && LENGTH(xdim) == 2) {
34 *m = *n = INTEGER(xdim)[(xt) ? 1 : 0];
35 }
else if (XLENGTH(x) <= INT_MAX) {
37 *m = *n = (xt) ? 1 : LENGTH(x);
39 Rf_error(
_(
"dimensions cannot exceed %s"),
"2^31-1");
47 xdim = (
TYPEOF(x) == OBJSXP)
49 ydim = (
TYPEOF(y) == OBJSXP)
51 int xm, xn, ym, yn, x2, y2;
52 xm = xn = ym = yn = -1;
53 x2 =
TYPEOF(xdim) == INTSXP && LENGTH(xdim) == 2;
54 y2 =
TYPEOF(ydim) == INTSXP && LENGTH(ydim) == 2;
56 int *pxdim = INTEGER(xdim);
59 }
else if (XLENGTH(x) > INT_MAX)
60 Rf_error(
_(
"dimensions cannot exceed %s"),
"2^31-1");
62 int *pydim = INTEGER(ydim);
65 }
else if (XLENGTH(y) > INT_MAX)
66 Rf_error(
_(
"dimensions cannot exceed %s"),
"2^31-1");
72 int k = (yt) ? yn : ym, xl = LENGTH(x);
73 if (k == xl || (k == 1 && !(xt))) {
76 xt = (k == xl) ? 1 : 0;
80 int k = (xt) ? xm : xn, yl = LENGTH(y);
82 if (xm == 1 || xn == 1) {
85 yt = (((xt) ? xn : xm) == 1) ? 0 : 1;
88 if (k == yl || k == 1) {
91 yt = (k == yl) ? 0 : 1;
96 int xl = LENGTH(x), yl = LENGTH(y);
112 ym = (xl == 1) ? 1 : yl;
113 yn = (xl == 1) ? yl : 1;
116 if (((xt) ? xm : xn) != ((yt) ? yn : ym))
117 Rf_error(
_(
"non-conformable arguments"));
122 SWAP(xt, yt,
int, !);
125 if (*v % 2) *xtrans = (xt) ?
'T' :
'N';
126 if (*v > 1) *ytrans = (yt) ?
'T' :
'N';
131void matmultDN(SEXP dest, SEXP asrc,
int ai, SEXP bsrc,
int bi) {
133 if ((s = VECTOR_ELT(asrc, ai)) != R_NilValue)
134 SET_VECTOR_ELT(dest, 0, s);
135 if ((s = VECTOR_ELT(bsrc, bi)) != R_NilValue)
136 SET_VECTOR_ELT(dest, 1, s);
137 PROTECT(asrc = Rf_getAttrib(asrc, R_NamesSymbol));
138 PROTECT(bsrc = Rf_getAttrib(bsrc, R_NamesSymbol));
139 if (asrc != R_NilValue || bsrc != R_NilValue) {
140 SEXP destnms = PROTECT(Rf_allocVector(STRSXP, 2));
141 if (asrc != R_NilValue && CHAR(s = STRING_ELT(asrc, ai))[0] !=
'\0')
142 SET_STRING_ELT(destnms, 0, s);
143 if (bsrc != R_NilValue && CHAR(s = STRING_ELT(bsrc, bi))[0] !=
'\0')
144 SET_STRING_ELT(destnms, 1, s);
145 Rf_setAttrib(dest, R_NamesSymbol, destnms);
152#define CONJ2(_X_, _M_, _N_) \
154 size_t m = (size_t) _M_, n = (size_t) _N_, xlen = m * n; \
155 Rcomplex *x = (Rcomplex *) _X_; \
156 Rcomplex *y = (Rcomplex *) R_alloc(xlen, sizeof(Rcomplex)); \
157 zvconj(x, y, xlen); \
161#define CONJ1(_X_, _N_) \
163 size_t n = (size_t) _N_, xlen = PACKED_LENGTH(n); \
164 Rcomplex *x = (Rcomplex *) _X_; \
165 Rcomplex *y = (Rcomplex *) R_alloc(xlen, sizeof(Rcomplex)); \
166 zvconj(x, y, xlen); \
174 int *padim =
DIM(a), am = padim[0], an = padim[1],
175 rm = (atrans !=
'N') ? an : am, rk = (atrans !=
'N') ? am : an;
177 if (b == R_NilValue) {
179 if ((int_fast64_t) rm * rm > R_XLEN_T_MAX)
180 Rf_error(
_(
"attempt to allocate vector of length exceeding %s"),
185 char rct = (
TYPEOF(ax) != CPLXSXP || ((atrans !=
'N') ? atrans : btrans) ==
'C') ?
'C' :
'T';
187 char rcl[] =
"...Matrix";
188 rcl[0] = (
TYPEOF(ax) == CPLXSXP) ?
'z' :
'd';
189 rcl[1] = (rct ==
'C') ?
'p' :
's';
190 rcl[2] = (rct ==
'C') ?
'o' :
'y';
196 SEXP adimnames = PROTECT(
DIMNAMES(a, 0)),
197 rdimnames = PROTECT(
DIMNAMES(r, 0));
198 symDN(rdimnames, adimnames, (atrans !=
'N') ? 1 : 0);
205 SEXP rx = PROTECT(Rf_allocVector(
TYPEOF(ax), (R_xlen_t) rm * rm));
206 if (
TYPEOF(ax) == CPLXSXP) {
207 Rcomplex *prx = COMPLEX(rx);
208 memset(prx, 0,
sizeof(Rcomplex) * (
size_t) rm * (
size_t) rm);
210 Rcomplex *pax = COMPLEX(ax),
213 F77_CALL(zherk)(
"U", &atrans, &rm, &rk,
217 F77_CALL(zsyrk)(
"U", &atrans, &rm, &rk,
222 double *prx = REAL(rx);
223 memset(prx, 0,
sizeof(
double) * (
size_t) rm * (
size_t) rm);
225 double *pax = REAL(ax),
226 zero = 0.0, one = 1.0;
227 F77_CALL(dsyrk)(
"U", &atrans, &rm, &rk,
241 int *pbdim =
DIM(b), bm = pbdim[0], bn = pbdim[1],
242 rn = (btrans !=
'N') ? bm : bn;
244 if (rk != ((btrans !=
'N') ? bn : bm))
245 Rf_error(
_(
"non-conformable arguments"));
246 if ((int_fast64_t) rm * rn > R_XLEN_T_MAX)
247 Rf_error(
_(
"attempt to allocate vector of length exceeding %s"),
252 char rcl[] =
".geMatrix";
253 rcl[0] = (
TYPEOF(ax) == CPLXSXP) ?
'z' :
'd';
258 SEXP adimnames = PROTECT(
DIMNAMES(a, 0)),
259 bdimnames = PROTECT(
DIMNAMES(b, 0)),
260 rdimnames = PROTECT(
DIMNAMES(r, 0));
262 adimnames, (atrans !=
'N') ? 1 : 0,
263 bdimnames, (btrans !=
'N') ? 0 : 1);
266 if (rm > 0 && rn > 0) {
267 SEXP rx = PROTECT(Rf_allocVector(
TYPEOF(ax), (R_xlen_t) rm * rn));
268 if (
TYPEOF(ax) == CPLXSXP) {
269 Rcomplex *prx = COMPLEX(rx);
271 memset(prx, 0,
sizeof(Rcomplex) * (
size_t) rm * (
size_t) rn);
274 Rcomplex *pax = COMPLEX(ax), *pbx = COMPLEX(bx),
276 F77_CALL(zgemm)(&atrans, &btrans, &rm, &rn, &rk,
277 & one, pax, &am, pbx, &bm,
282 double *prx = REAL(rx);
284 memset(prx, 0,
sizeof(
double) * (
size_t) rm * (
size_t) rn);
287 double *pax = REAL(ax), *pbx = REAL(bx),
288 zero = 0.0, one = 1.0;
289 F77_CALL(dgemm)(&atrans, &btrans, &rm, &rn, &rk,
290 & one, pax, &am, pbx, &bm,
312 int *pbdim =
DIM(b), bm = pbdim[0], bn = pbdim[1],
313 rm = (btrans !=
'N') ? bn : bm, rn = (btrans !=
'N') ? bm : bn;
315 if (rk != (((aside ==
'L') == (btrans !=
'N')) ? bn : bm))
316 Rf_error(
_(
"non-conformable arguments"));
317 if ((int_fast64_t) rm * rn > R_XLEN_T_MAX)
318 Rf_error(
_(
"attempt to allocate vector of length exceeding %s"),
323 char rcl[] =
".geMatrix";
324 rcl[0] = (
TYPEOF(ax) == CPLXSXP) ?
'z' :
'd';
329 SEXP adimnames = PROTECT(
DIMNAMES(a, -1)),
330 bdimnames = PROTECT(
DIMNAMES(b, 0)),
331 rdimnames = PROTECT(
DIMNAMES(r, 0));
333 matmultDN(rdimnames, adimnames, 0, bdimnames, btrans ==
'N');
335 matmultDN(rdimnames, bdimnames, btrans !=
'N', adimnames, 1);
350 if (rm > 0 && rn > 0) {
352 rx = PROTECT(Rf_allocVector(
TYPEOF(ax), (R_xlen_t) rm * rn));
355 d = (aside ==
'L') ? rn : rm,
356 binc = (aside ==
'L') ? bm : 1,
357 bincp = (aside ==
'L') ? 1 : bm,
358 rinc = (aside ==
'L') ? 1 : rm,
359 rincp = (aside ==
'L') ? rm : 1;
361 if (
TYPEOF(ax) == CPLXSXP) {
362 Rcomplex *pax = COMPLEX(ax), *pbx = COMPLEX(bx), *prx = COMPLEX(rx),
366 if (atrans !=
'N' && atrans != act)
369 F77_CALL(zhemm)(&aside, &aul, &rm, &rn,
370 & one, pax, &rk, pbx, &bm,
373 F77_CALL(zsymm)(&aside, &aul, &rm, &rn,
374 & one, pax, &rk, pbx, &bm,
378 if (atrans !=
'N' && atrans != act)
383 if (((atrans !=
'N') ? atrans : act) != btrans)
386 for (i = 0; i < d; ++i) {
388 F77_CALL(zhemv)( &aul, &rk,
389 & one, pax, &rk, pbx, &binc,
390 &zero, prx, &rinc
FCONE);
392 F77_CALL(zsymv)( &aul, &rk,
393 & one, pax, &rk, pbx, &binc,
394 &zero, prx, &rinc
FCONE);
398 if (aside !=
'L' && btrans ==
'C')
399 zvconj(pax, NULL, (
size_t) rk * (
size_t) rk);
402 double *pax = REAL(ax), *pbx = REAL(bx), *prx = REAL(rx),
403 zero = 0.0, one = 1.0;
405 F77_CALL(dsymm)(&aside, &aul, &rm, &rn,
406 & one, pax, &rk, pbx, &bm,
409 for (i = 0; i < d; ++i) {
410 F77_CALL(dsymv)( &aul, &rk,
411 &one, pax, &rk, pbx, &binc,
412 &zero, prx, &rinc
FCONE);
433 int *pbdim =
DIM(b), bm = pbdim[0], bn = pbdim[1],
434 rm = (btrans !=
'N') ? bn : bm, rn = (btrans !=
'N') ? bm : bn;
436 if (rk != (((aside ==
'L') == (btrans !=
'N')) ? bn : bm))
437 Rf_error(
_(
"non-conformable arguments"));
438 if ((int_fast64_t) rm * rn > R_XLEN_T_MAX)
439 Rf_error(
_(
"attempt to allocate vector of length exceeding %s"),
444 char rcl[] =
".geMatrix";
445 rcl[0] = (
TYPEOF(ax) == CPLXSXP) ?
'z' :
'd';
450 SEXP adimnames = PROTECT(
DIMNAMES(a, -1)),
451 bdimnames = PROTECT(
DIMNAMES(b, 0)),
452 rdimnames = PROTECT(
DIMNAMES(r, 0));
454 matmultDN(rdimnames, adimnames, 0, bdimnames, btrans ==
'N');
456 matmultDN(rdimnames, bdimnames, btrans !=
'N', adimnames, 1);
472 if (rm > 0 && rn > 0) {
474 rx = PROTECT(Rf_allocVector(REALSXP, (R_xlen_t) rm * rn));
477 d = ( aside ==
'L' ) ? rn : rm,
478 binc = ((aside ==
'L') == (btrans !=
'N')) ? bm : 1,
479 bincp = ((aside ==
'L') == (btrans !=
'N')) ? 1 : bm,
480 rinc = ( aside ==
'L' ) ? 1 : rm,
481 rincp = ( aside ==
'L' ) ? rm : 1;
483 if (
TYPEOF(ax) == CPLXSXP) {
484 Rcomplex *pax = COMPLEX(ax), *pbx = COMPLEX(bx), *prx = COMPLEX(rx),
488 if (atrans !=
'N' && atrans != act)
493 if (btrans !=
'N' && ((atrans !=
'N') ? atrans : act) != btrans)
495 if (btrans ==
'N' && ((atrans !=
'N') ? atrans : act) ==
'C')
498 for (i = 0; i < d; ++i) {
500 F77_CALL(zhpmv)(&aul, &rk,
501 & one, pax, pbx, &binc,
502 &zero, prx, &rinc
FCONE);
504 F77_CALL(zspmv)(&aul, &rk,
505 & one, pax, pbx, &binc,
506 &zero, prx, &rinc
FCONE);
511 ((btrans !=
'N') ? btrans : ((atrans !=
'N') ? atrans : act)) ==
'C')
512 zvconj(prx, NULL, (
size_t) rm * (
size_t) rn);
514 double *pax = REAL(ax), *pbx = REAL(bx), *prx = REAL(rx),
515 zero = 0.0, one = 1.0;
516 for (i = 0; i < d; ++i) {
517 F77_CALL(dspmv)(&aul, &rk,
518 & one, pax, pbx, &binc,
519 &zero, prx, &rinc
FCONE);
540 int *pbdim =
DIM(b), bm = pbdim[0], bn = pbdim[1],
541 rm = (btrans !=
'N') ? bn : bm, rn = (btrans !=
'N') ? bm : bn;
543 if (rk != (((aside ==
'L') == (btrans !=
'N')) ? bn : bm))
544 Rf_error(
_(
"non-conformable arguments"));
545 if ((int_fast64_t) rm * rn > R_XLEN_T_MAX)
546 Rf_error(
_(
"attempt to allocate vector of length exceeding %s"),
551 char rcl[] =
"...Matrix";
552 rcl[0] = (
TYPEOF(ax) == CPLXSXP) ?
'z' :
'd';
553 rcl[1] = (triangular != 0) ?
't' :
'g';
554 rcl[2] = (triangular != 0) ?
'r' :
'e';
559 SEXP adimnames = PROTECT(
DIMNAMES(a, 0)),
560 bdimnames = PROTECT(
DIMNAMES(b, 0)),
561 rdimnames = PROTECT(
DIMNAMES(r, 0));
563 matmultDN(rdimnames, adimnames, atrans !=
'N', bdimnames, btrans ==
'N');
565 matmultDN(rdimnames, bdimnames, btrans !=
'N', adimnames, atrans ==
'N');
573 if (triangular < -1 || triangular > 1)
587 if (rm > 0 && rn > 0) {
589 rx = PROTECT(Rf_allocVector(
TYPEOF(ax), (R_xlen_t) rm * rn));
590 if (
TYPEOF(ax) == CPLXSXP) {
591 Rcomplex *pax = COMPLEX(ax), *pbx = COMPLEX(bx), *prx = COMPLEX(rx),
593 ztrans2(prx, pbx, (
size_t) bm, (
size_t) bn, btrans);
594 F77_CALL(ztrmm)(&aside, &aul, &atrans, &anu, &rm, &rn,
597 double *pax = REAL(ax), *pbx = REAL(bx), *prx = REAL(rx),
599 dtrans2(prx, pbx, (
size_t) bm, (
size_t) bn, btrans);
600 F77_CALL(dtrmm)(&aside, &aul, &atrans, &anu, &rm, &rn,
619 int *pbdim =
DIM(b), bm = pbdim[0], bn = pbdim[1],
620 rm = (btrans !=
'N') ? bn : bm, rn = (btrans !=
'N') ? bm : bn;
622 if (rk != (((aside ==
'L') == (btrans !=
'N')) ? bn : bm))
623 Rf_error(
_(
"non-conformable arguments"));
624 if ((int_fast64_t) rm * rn > R_XLEN_T_MAX)
625 Rf_error(
_(
"attempt to allocate vector of length exceeding %s"),
630 char rcl[] =
"...Matrix";
631 rcl[0] = (
TYPEOF(ax) == CPLXSXP) ?
'z' :
'd';
632 rcl[1] = (triangular != 0) ?
't' :
'g';
633 rcl[2] = (triangular != 0) ?
'r' :
'e';
638 SEXP adimnames = PROTECT(
DIMNAMES(a, 0)),
639 bdimnames = PROTECT(
DIMNAMES(b, 0)),
640 rdimnames = PROTECT(
DIMNAMES(r, 0));
642 matmultDN(rdimnames, adimnames, atrans !=
'N', bdimnames, btrans ==
'N');
644 matmultDN(rdimnames, bdimnames, btrans !=
'N', adimnames, atrans ==
'N');
652 if (triangular < -1 || triangular > 1)
668 if (rm > 0 && rn > 0) {
670 rx = PROTECT(Rf_allocVector(REALSXP, (R_xlen_t) rm * rn));
671 int i, rinc = (aside ==
'L') ? 1 : rm, rincp = (aside ==
'L') ? rm : 1;
674 atransp = (aside ==
'L')
675 ? atrans : ((atrans !=
'N') ?
'N' : ((btrans !=
'N') ? btrans :
'T')),
676 btransp = (aside ==
'L')
677 ? btrans : ((btrans !=
'N') ?
'T' :
'N');
679 if (
TYPEOF(ax) == CPLXSXP) {
680 Rcomplex *pax = COMPLEX(ax), *pbx = COMPLEX(bx), *prx = COMPLEX(rx);
681 if (aside !=
'L' && atrans !=
'N' && btrans !=
'N' && atrans != btrans)
683 ztrans2(prx, pbx, (
size_t) bm, (
size_t) bn, btransp);
684 if (aside !=
'L' && atrans ==
'C' && btrans ==
'N')
685 zvconj(prx, NULL, (
size_t) rm * (
size_t) rn);
686 for (i = 0; i < rn; ++i) {
687 F77_CALL(ztpmv)(&aul, &atransp, &anu, &rk,
692 ((btrans !=
'N') ? btrans : ((atrans !=
'N') ? atrans :
'T')) ==
'C')
693 zvconj(prx, NULL, (
size_t) rm * (
size_t) rn);
695 double *pax = REAL(ax), *pbx = REAL(bx), *prx = REAL(rx);
696 dtrans2(prx, pbx, (
size_t) bm, (
size_t) bn, btransp);
697 for (i = 0; i < rn; ++i) {
698 F77_CALL(dtpmv)(&aul, &atransp, &anu, &rk,
712 SEXP s_xtrans, SEXP s_ytrans)
715 xtrans = CHAR(STRING_ELT(s_xtrans, 0))[0],
716 ytrans = CHAR(STRING_ELT(s_ytrans, 0))[0],
719 matmultDim(s_x, s_y, &xtrans, &ytrans, &ztrans, &m, &n, &v);
721 PROTECT_INDEX xpid, ypid;
722 PROTECT_WITH_INDEX(s_x, &xpid);
723 PROTECT_WITH_INDEX(s_y, &ypid);
725#define DO_S3(_A_, _TRANS_, _PID_, _ISV_) \
727 if (TYPEOF(_A_) != OBJSXP) { \
728 REPROTECT(_A_ = matrix_as_dense(_A_, ",ge", '\0', '\0', '\0', (_TRANS_ != 'N') ? 0 : 1, 0), _PID_); \
731 SET_VECTOR_ELT(DIMNAMES(_A_, 0), \
732 (_TRANS_ != 'N') ? 1 : 0, R_NilValue); \
738 DO_S3(s_x, xtrans, xpid, v % 2);
739 if (s_y != R_NilValue)
740 DO_S3(s_y, ytrans, ypid, v > 1);
745 const char *xclass = NULL, *yclass = NULL;
747 if (s_y != R_NilValue)
750 char kind = (xclass[0] ==
'z' || (s_y != R_NilValue && yclass[0] ==
'z'))
753#define DO_AS(_A_, _CLASS_, _TRANS_, _PID_) \
755 if (_CLASS_[0] != kind) { \
756 REPROTECT(_A_ = dense_as_kind(_A_, _CLASS_, kind, 0), _PID_); \
757 _CLASS_ = Matrix_class(_A_, valid, 6, __func__); \
761 DO_AS(s_x, xclass, xtrans, xpid);
762 if (s_y != R_NilValue)
763 DO_AS(s_y, yclass, ytrans, ypid);
767 if (s_y == R_NilValue) {
770 }
else if (xclass[1] ==
'g' && yclass[1] ==
'g') {
772 }
else if (xclass[1] ==
'g' || yclass[1] ==
'g') {
773 s_x = (xclass[1] ==
'g')
774 ? ((yclass[1] ==
's')
775 ? ((yclass[2] !=
'p')
778 : ((yclass[2] !=
'p')
781 : ((xclass[1] ==
's')
782 ? ((xclass[2] !=
'p')
785 : ((xclass[2] !=
'p')
788 }
else if (xclass[1] ==
's' && yclass[1] ==
's') {
789 if (xclass[2] ==
'p' && yclass[2] ==
'p') {
792 }
else if (xclass[2] ==
'p') {
799 }
else if (xclass[1] ==
's' || yclass[1] ==
's') {
800 if (xclass[1] ==
's') {
802 s_x = (yclass[2] !=
'p')
807 s_x = (xclass[2] !=
'p')
816 char xul = UPLO(s_x), xnu = DIAG(s_x), \
817 yul = UPLO(s_y), ynu = DIAG(s_y); \
819 xul = (xul == 'U') ? 'L' : 'U'; \
821 yul = (yul == 'U') ? 'L' : 'U'; \
822 triangular = (xul != yul) ? 0 : ((xnu != ynu || xnu == 'N') ? 1 : 2); \
824 triangular = -triangular; \
829 if (xclass[2] ==
'p' && yclass[2] ==
'p') {
832 }
else if (xclass[2] ==
'p') {
849 int triangular,
int boolean)
852#define ASMODE(_TRANS_) ((boolean) ? 0 : (((_TRANS_) != 'C') ? 1 : 2))
854 cholmod_sparse *X =
M2CHS(x, !
boolean), *Y = NULL, *Z = NULL;
857 char zclass[] =
"..CMatrix";
859 if (y == R_NilValue) {
861 zclass[0] = (boolean) ?
'n' : ((X->xtype != CHOLMOD_COMPLEX) ?
'd' :
'z');
862 zclass[1] = (boolean) ?
's' : ((X->xtype != CHOLMOD_COMPLEX) ?
'p' : ((((xtrans !=
'N') ? xtrans : ytrans) ==
'C') ?
'p' :
's'));
865 X = cholmod_transpose(X,
ASMODE(xtrans), &
c);
866 Z = cholmod_aat(X, NULL, 0,
ASMODE((xtrans !=
'N') ? xtrans : ytrans), &
c);
868 cholmod_free_sparse(&X, &
c);
871 X = cholmod_copy(Z, (ztrans !=
'N') ? -1 : 1, !
boolean, &
c);
872 cholmod_free_sparse(&Z, &
c);
874 PROTECT(z =
CHS2M(Z, !
boolean, zclass[1]));
875 cholmod_free_sparse(&Z, &
c);
877 SEXP xdimnames = PROTECT(
DIMNAMES(x, 0)),
878 zdimnames = PROTECT(
DIMNAMES(z, 0));
879 symDN(zdimnames, xdimnames, (xtrans !=
'N') ? 1 : 0);
884 if (zclass[1] ==
's' && zclass[0] ==
'z')
889 Y =
M2CHS(y, !
boolean);
891 if (((xtrans !=
'N') ? X->nrow : X->ncol) !=
892 ((ytrans !=
'N') ? Y->ncol : Y->nrow))
893 Rf_error(
_(
"non-conformable arguments"));
895 zclass[0] = (boolean) ?
'n' : ((X->xtype != CHOLMOD_COMPLEX && Y->xtype != CHOLMOD_COMPLEX) ?
'd' :
'z');
896 zclass[1] = (triangular != 0) ?
't' :
'g';
899 X = cholmod_transpose(X,
ASMODE(xtrans), &
c);
901 Y = cholmod_transpose(Y,
ASMODE(ytrans), &
c);
902 Z = cholmod_ssmult(X, Y, 0, !
boolean, 1, &
c);
904 cholmod_free_sparse(&X, &
c);
906 cholmod_free_sparse(&Y, &
c);
908 cholmod_band_inplace(-((
int) Z->nrow), -1, !
boolean, Z, &
c);
909 else if (triangular > 1)
910 cholmod_band_inplace(1, (
int) Z->ncol, !
boolean, Z, &
c);
911 PROTECT(z =
CHS2M(Z, !
boolean, zclass[1]));
912 cholmod_free_sparse(&Z, &
c);
914 SEXP xdimnames = PROTECT(
DIMNAMES(x, 0)),
915 ydimnames = PROTECT(
DIMNAMES(y, 0)),
916 zdimnames = PROTECT(
DIMNAMES(z, 0));
918 xdimnames, (xtrans !=
'N') ? 1 : 0,
919 ydimnames, (ytrans !=
'N') ? 0 : 1);
924 if (triangular < -1 || triangular > 1)
940 int triangular,
int symmetric)
942 cholmod_sparse *X =
M2CHS(x, 1);
943 X->stype = symmetric;
945 cholmod_dense *Y =
M2CHD(y, ytrans);
947 if (((xtrans !=
'N') ? X->nrow : X->ncol) != Y->nrow)
948 Rf_error(
_(
"non-conformable arguments"));
949 size_t m = (xtrans !=
'N') ? X->ncol : X->nrow, n = Y->ncol;
950 if (m * n > R_XLEN_T_MAX)
951 Rf_error(
_(
"attempt to allocate vector of length exceeding %s"),
954 if (X->xtype == CHOLMOD_COMPLEX && xtrans ==
'T')
955 CONJ2(X->x, X->nrow, X->ncol);
957 char zclass[] =
"...Matrix";
958 zclass[0] = (X->xtype != CHOLMOD_COMPLEX && Y->xtype != CHOLMOD_COMPLEX) ?
'd' :
'z';
959 zclass[1] = (triangular != 0) ?
't' :
'g';
960 zclass[2] = (triangular != 0) ?
'r' :
'e';
964 (
int) ((ztrans !=
'N') ? n : m),
965 (
int) ((ztrans !=
'N') ? m : n));
967 SEXP xdimnames = PROTECT(
DIMNAMES(x, -(symmetric != 0))),
968 ydimnames = PROTECT(
DIMNAMES(y, 0)),
969 zdimnames = PROTECT(
DIMNAMES(z, 0));
972 ydimnames, (ytrans !=
'N') ? 0 : 1,
973 xdimnames, (xtrans !=
'N') ? 1 : 0);
976 xdimnames, (xtrans !=
'N') ? 1 : 0,
977 ydimnames, (ytrans !=
'N') ? 0 : 1);
980 if (triangular != 0 && (ztrans !=
'N') == (triangular > 0))
982 if (triangular < -1 || triangular > 1)
985 double alpha[2] = { 1.0, 0.0 }, beta[2] = { 0.0, 0.0 };
986 cholmod_dense *Z = (cholmod_dense *) R_alloc(1,
sizeof(cholmod_dense));
987 memset(Z, 0,
sizeof(cholmod_dense));
991 Z->nzmax = Z->nrow * Z->ncol;
996 if (zclass[0] ==
'z') {
997 PROTECT(zx = Rf_allocVector(CPLXSXP, (R_xlen_t) (m * n)));
998 Z->x = (ztrans !=
'N')
999 ? (Rcomplex *) R_alloc(m * n,
sizeof(Rcomplex))
1002 PROTECT(zx = Rf_allocVector(REALSXP, (R_xlen_t) (m * n)));
1003 Z->x = (ztrans !=
'N')
1004 ? (
double *) R_alloc(m * n,
sizeof(
double))
1007 cholmod_sdmult(X, xtrans !=
'N', alpha, beta, Y, Z, &
c);
1008 if (ztrans !=
'N') {
1009 if (zclass[0] ==
'z')
1010 ztrans2(COMPLEX(zx), (Rcomplex *) Z->x, m, n, ztrans);
1012 dtrans2( REAL(zx), (
double *) Z->x, m, n, ztrans);
1022 SEXP s_xtrans, SEXP s_ytrans, SEXP s_ztrans,
1025 if (
TYPEOF(s_boolean) != LGLSXP || LENGTH(s_boolean) < 1)
1026 Rf_error(
_(
"invalid '%s' to '%s'"),
"boolean", __func__);
1027 int boolean = LOGICAL(s_boolean)[0];
1030 xtrans = CHAR(STRING_ELT(s_xtrans, 0))[0],
1031 ytrans = CHAR(STRING_ELT(s_ytrans, 0))[0],
1032 ztrans = CHAR(STRING_ELT(s_ztrans, 0))[0];
1034 matmultDim(s_x, s_y, &xtrans, &ytrans, &ztrans, &m, &n, &v);
1036 PROTECT_INDEX xpid, ypid;
1037 PROTECT_WITH_INDEX(s_x, &xpid);
1038 PROTECT_WITH_INDEX(s_y, &ypid);
1040#define DO_S3(_A_, _TRANS_, _PID_, _ISV_) \
1042 if (TYPEOF(_A_) != OBJSXP) { \
1043 if (boolean == NA_LOGICAL || !boolean) \
1044 REPROTECT(_A_ = matrix_as_dense (_A_, ",ge", '\0', '\0', '\0', (_TRANS_ != 'N') ? 0 : 1, 0), _PID_); \
1045 else if (_TRANS_ != 'N') \
1046 REPROTECT(_A_ = matrix_as_sparse(_A_, "ngR", '\0', '\0', '\0', 0), _PID_); \
1048 REPROTECT(_A_ = matrix_as_sparse(_A_, "ngC", '\0', '\0', '\0', 0), _PID_); \
1051 SET_VECTOR_ELT(DIMNAMES(_A_, 0), \
1052 (_TRANS_ != 'N') ? 1 : 0, R_NilValue); \
1058 DO_S3(s_x, xtrans, xpid, v % 2);
1059 if (s_y != R_NilValue)
1060 DO_S3(s_y, ytrans, ypid, v > 1);
1065 const char *xclass = NULL, *yclass = NULL;
1067 if (s_y != R_NilValue)
1070 if (
boolean == NA_LOGICAL)
1071 boolean = xclass[0] ==
'n' && (s_y == R_NilValue || yclass[0] ==
'n');
1072 char kind = (boolean) ?
'n' :
1073 ((xclass[0] !=
'z' && (s_y == R_NilValue || yclass[0] !=
'z')) ?
'd' :
'z');
1075#define DO_AS(_A_, _CLASS_, _TRANS_, _PID_) \
1077 if (_CLASS_[2] != 'C' && _TRANS_ != 'N') { \
1078 if (_CLASS_[2] != 'R' && _CLASS_[2] != 'T') { \
1079 REPROTECT(_A_ = dense_as_sparse(_A_, _CLASS_, 'R'), _PID_); \
1080 _CLASS_ = Matrix_class(_A_, valid, 6, __func__); \
1082 REPROTECT(_A_ = sparse_transpose(_A_, _CLASS_, _TRANS_, 1), _PID_); \
1083 _CLASS_ = Matrix_class(_A_, valid, 6, __func__); \
1086 if (_CLASS_[2] != 'C') { \
1087 if (_CLASS_[2] != 'R' && _CLASS_[2] != 'T') \
1088 REPROTECT(_A_ = dense_as_sparse(_A_, _CLASS_, 'C'), _PID_); \
1090 REPROTECT(_A_ = sparse_as_Csparse(_A_, _CLASS_), _PID_); \
1091 _CLASS_ = Matrix_class(_A_, valid, 6, __func__); \
1093 if (_TRANS_ != 'N' && _CLASS_[1] == 's' && \
1094 (_CLASS_[0] != 'z' || TRANS(_A_) == _TRANS_)) \
1096 if (_CLASS_[0] != kind) { \
1098 REPROTECT(_A_ = sparse_dropzero(_A_, _CLASS_, 0.0), _PID_); \
1100 REPROTECT(_A_ = sparse_as_kind(_A_, _CLASS_, kind), _PID_); \
1101 _CLASS_ = Matrix_class(_A_, valid, 6, __func__); \
1106 DO_AS(s_x, xclass, xtrans, xpid);
1108 if (s_y == R_NilValue) {
1111 s_x, s_y, xtrans, ytrans, ztrans, 0,
boolean);
1117 if (xclass[1] ==
't' && yclass[1] ==
't')
1120 if (!
boolean && yclass[2] !=
'C' && yclass[2] !=
'R' && yclass[2] !=
'T') {
1121 if (xclass[1] ==
's' && xclass[0] ==
'z' &&
TRANS(s_x) !=
'C') {
1125 int symmetric = xclass[1] ==
's';
1126 if (symmetric &&
UPLO(s_x) !=
'U')
1127 symmetric = -symmetric;
1128 if (yclass[0] != kind) {
1135 s_x, s_y, xtrans, ytrans, ztrans, triangular, symmetric);
1140 DO_AS(s_y, yclass, ytrans, ypid);
1147 s_x, s_y, xtrans, ytrans, ztrans, triangular,
boolean);
1152#define zSCALE(x, y) \
1154 Rcomplex tmp = (x); \
1155 (x).r = tmp.r * (y).r - tmp.i * (y).i; \
1156 (x).i = tmp.r * (y).i + tmp.i * (y).r; \
1158#define dSCALE(x, y) \
1160#define lSCALE(x, y) \
1163#define SCALE3(t, index) \
1166 case CPLXSXP: SCALE(z, index); break; \
1167 case REALSXP: SCALE(d, index); break; \
1168 case LGLSXP: SCALE(l, index); break; \
1177 int i, j, packed = XLENGTH(x) != (int_fast64_t) m * n;
1179#define SCALE(c, index) \
1181 c##TYPE *px = c##PTR(x), *pd = c##PTR(d); \
1183 for (j = 0; j < n; ++j) { \
1184 for (i = 0; i < m; ++i) { \
1185 c##SCALE(*px, pd[index]); \
1189 } else if (ul == 'U') { \
1190 for (j = 0; j < n; ++j) { \
1191 for (i = 0; i <= j; ++i) { \
1192 c##SCALE(*px, pd[index]); \
1199 for (j = 0; j < n; ++j) { \
1202 for (i = j; i < n; ++i) { \
1203 c##SCALE(*px, pd[index]); \
1208 if (nu != '\0' && nu != 'N') { \
1209 size_t n_ = (size_t) n; \
1211 c##NAME(copy2)(n_, c##PTR(x), n_ + 1, pd, 1); \
1212 else if (ul == 'U') \
1213 c##NAME(copy1)(n_, c##PTR(x), 2 , 1, 0, pd, 1, 0, 0); \
1215 c##NAME(copy1)(n_, c##PTR(x), n_, 1, 1, pd, 1, 0, 0); \
1227 int i, j, packed = XLENGTH(x) != (int_fast64_t) m * n;
1242 int *pp = INTEGER(p) + 1, n = (int) (XLENGTH(p) - 1), j, k, kend;
1245#define SCALE(c, index) \
1247 c##TYPE *px = c##PTR(x), *pd = c##PTR(d); \
1248 for (j = 0, k = 0; j < n; ++j) { \
1250 while (k < kend) { \
1251 c##SCALE(*px, *pd); \
1274 int *pi = INTEGER(i), k, kend = INTEGER(p)[XLENGTH(p) - 1];
1277#define SCALE(c, index) \
1279 c##TYPE *px = c##PTR(x), *pd = c##PTR(d); \
1280 for (k = 0; k < kend; ++k) { \
1281 c##SCALE(*px, pd[*pi]); \
1298 int *pi = INTEGER(i);
1299 R_xlen_t k, kend = XLENGTH(i);
1311 SEXP s_xtrans, SEXP s_ytrans,
1314 SEXP _s_x = s_x, _s_y = s_y;
1316 if (
TYPEOF(s_boolean) != LGLSXP || LENGTH(s_boolean) < 1)
1317 Rf_error(
_(
"invalid '%s' to '%s'"),
"boolean", __func__);
1318 int boolean = LOGICAL(s_boolean)[0];
1321 xtrans = CHAR(STRING_ELT(s_xtrans, 0))[0],
1322 ytrans = CHAR(STRING_ELT(s_ytrans, 0))[0],
1325 matmultDim(s_x, s_y, &xtrans, &ytrans, &ztrans, &m, &n, &v);
1327 PROTECT_INDEX xpid, ypid;
1328 PROTECT_WITH_INDEX(s_x, &xpid);
1329 PROTECT_WITH_INDEX(s_y, &ypid);
1331#define DO_S3(_A_, _TRANS_, _PID_, _ISV_) \
1333 if (TYPEOF(_A_) != OBJSXP) { \
1334 if (boolean == NA_LOGICAL || !boolean) \
1335 REPROTECT(_A_ = matrix_as_dense(_A_, ",ge", '\0', '\0', '\0', (_TRANS_ != 'N') ? 0 : 1, 2), _PID_); \
1337 REPROTECT(_A_ = matrix_as_dense(_A_, "nge", '\0', '\0', '\0', (_TRANS_ != 'N') ? 0 : 1, 2), _PID_); \
1340 SET_VECTOR_ELT(DIMNAMES(_A_, 0), \
1341 (_TRANS_ != 'N') ? 1 : 0, R_NilValue); \
1347 DO_S3(s_x, xtrans, xpid, v % 2);
1348 if (s_y != R_NilValue)
1349 DO_S3(s_y, ytrans, ypid, v > 1);
1354 const char *xclass = NULL, *yclass = NULL;
1356 if (s_y != R_NilValue)
1359 if (
boolean == NA_LOGICAL)
1360 boolean = xclass[0] ==
'n' && yclass[0] ==
'n';
1361 char kind = (boolean) ?
'n' :
1362 ((xclass[0] !=
'z' && yclass[0] !=
'z') ?
'd' :
'z');
1363 char ks = (boolean) ?
'l' : kind, kd = kind;
1365 int mg = -1,
id = -1;
1366 if (xclass[2] ==
'i') {
1368 id =
DIAG(s_x) !=
'N';
1369 }
else if (yclass[2] ==
'i') {
1371 id =
DIAG(s_y) !=
'N';
1373 Rf_error(
_(
"should never happen ..."));
1375#define DO_AS(_A_, _CLASS_, _TRANS_, _PID_) \
1377 if (_TRANS_ != 'N' && _CLASS_[1] == 's' && \
1378 (_CLASS_[0] != 'z' || TRANS(_A_) == _TRANS_)) \
1380 switch (_CLASS_[2]) { \
1382 if (!id && _CLASS_[0] != ks) { \
1383 REPROTECT(_A_ = diagonal_as_kind(_A_, _CLASS_, ks), _PID_); \
1384 _CLASS_ = Matrix_class(_A_, valid, 6, __func__); \
1390 if (_CLASS_[0] != ks) { \
1391 REPROTECT(_A_ = sparse_as_kind(_A_, _CLASS_, ks), _PID_); \
1392 _CLASS_ = Matrix_class(_A_, valid, 6, __func__); \
1394 if (!id && _CLASS_[1] == 's') { \
1395 REPROTECT(_A_ = sparse_as_general(_A_, _CLASS_), _PID_); \
1396 _CLASS_ = Matrix_class(_A_, valid, 6, __func__); \
1398 if (!id && _CLASS_[1] == 't') \
1399 REPROTECT(_A_ = sparse_diag_U2N(_A_, _CLASS_), _PID_); \
1400 if (_TRANS_ != 'N') { \
1401 REPROTECT(_A_ = sparse_transpose(_A_, _CLASS_, _TRANS_, 0), _PID_); \
1406 if (_CLASS_[0] != kd) { \
1407 REPROTECT(_A_ = dense_as_kind(_A_, _CLASS_, kd, 1), _PID_); \
1408 _CLASS_ = Matrix_class(_A_, valid, 6, __func__); \
1410 if (!id && _CLASS_[1] == 's') { \
1411 REPROTECT(_A_ = dense_as_general(_A_, _CLASS_, _A_ == _ ## _A_), _PID_); \
1412 _CLASS_ = Matrix_class(_A_, valid, 6, __func__); \
1414 if (_TRANS_ != 'N') { \
1415 REPROTECT(_A_ = dense_transpose(_A_, _CLASS_, _TRANS_), _PID_); \
1422 DO_AS(s_x, xclass, xtrans, xpid);
1423 DO_AS(s_y, yclass, ytrans, ypid);
1426 const char *zclass = (mg == 0) ? yclass : xclass;
1428 PROTECT_WITH_INDEX(z, &zpid);
1432 SEXP xdimnames = PROTECT(
DIMNAMES(s_x, 0)),
1433 ydimnames = PROTECT(
DIMNAMES(s_y, 0)),
1434 zdimnames = PROTECT(
DIMNAMES(z, 0));
1436 xdimnames, (xtrans !=
'N') ? 1 : 0,
1437 ydimnames, (ytrans !=
'N') ? 0 : 1);
1440 char ul =
'\0', nu =
'\0';
1441 if (zclass[1] !=
'g' && (ul =
UPLO((mg == 0) ? s_y : s_x)) !=
'U')
1443 if (zclass[1] ==
't' && (nu =
DIAG((mg == 0) ? s_y : s_x)) !=
'N' &&
id)
1446 if (zclass[2] ==
'C' || zclass[2] ==
'R' || zclass[2] ==
'T') {
1447 if (zclass[2] !=
'T') {
1452 if (zclass[2] !=
'R') {
1457 if (zclass[2] !=
'C') {
1465 if (
id || ((mg == 0) ? s_y != _s_y : s_x != _s_x))
1468 SEXP x1 = PROTECT(Rf_allocVector(
TYPEOF(x0), XLENGTH(x0)));
1471 memcpy(COMPLEX(x1), COMPLEX(x0),
sizeof(Rcomplex) * (
size_t) XLENGTH(x0));
1474 memcpy( REAL(x1), REAL(x0),
sizeof(
double) * (
size_t) XLENGTH(x0));
1477 memcpy(LOGICAL(x1), LOGICAL(x0),
sizeof(
int) * (
size_t) XLENGTH(x0));
1487 switch (zclass[2]) {
1516 if (
boolean && (zclass[2] ==
'C' || zclass[2] ==
'R' || zclass[2] ==
'T')) {
SEXP dense_as_kind(SEXP, const char *, char, int)
SEXP sparse_as_general(SEXP, const char *)
SEXP sparse_as_kind(SEXP, const char *, char)
#define SWAP(a, b, t, op)
const char * Matrix_class(SEXP, const char **, int, const char *)
#define DIMNAMES(x, mode)
#define GET_SLOT(x, name)
SEXP newObject(const char *)
#define SET_SLOT(x, name, value)
void symDN(SEXP dest, SEXP src, int J)
cholmod_sparse * M2CHS(SEXP obj, int values)
SEXP CHS2M(cholmod_sparse *A, int values, char shape)
cholmod_dense * M2CHD(SEXP obj, char trans)
SEXP dense_as_general(SEXP from, const char *class, int new)
void zvconj(Rcomplex *x, const Rcomplex *y, size_t n)
void ztrans2(Rcomplex *, const Rcomplex *, size_t, size_t, char)
void dtrans2(double *, const double *, size_t, size_t, char)
SEXP sparse_transpose(SEXP, const char *, char, int)
static void Tsparse_rowscale(SEXP obj, SEXP d, SEXP iSym)
SEXP R_dense_matmult(SEXP s_x, SEXP s_y, SEXP s_xtrans, SEXP s_ytrans)
static void matmultDN(SEXP dest, SEXP asrc, int ai, SEXP bsrc, int bi)
static SEXP gCgeMatrix_matmult(SEXP x, SEXP y, int xtrans, char ytrans, char ztrans, int triangular, int symmetric)
#define DO_AS(_A_, _CLASS_, _TRANS_, _PID_)
static void dense_colscale(SEXP obj, SEXP d, int m, int n, char ul, char nu)
static void Csparse_rowscale(SEXP obj, SEXP d, SEXP iSym)
SEXP sparse_dropzero(SEXP, const char *, double)
static SEXP tpMatrix_matmult(SEXP a, SEXP b, char atrans, char btrans, char aside, int triangular)
static SEXP syMatrix_matmult(SEXP a, SEXP b, char atrans, char btrans, char aside)
SEXP dense_transpose(SEXP, const char *, char)
static void Csparse_colscale(SEXP obj, SEXP d)
static void dense_rowscale(SEXP obj, SEXP d, int m, int n, char ul, char nu)
SEXP R_sparse_matmult(SEXP s_x, SEXP s_y, SEXP s_xtrans, SEXP s_ytrans, SEXP s_ztrans, SEXP s_boolean)
#define DO_S3(_A_, _TRANS_, _PID_, _ISV_)
static void matmultDim(SEXP x, SEXP y, char *xtrans, char *ytrans, char *ztrans, int *m, int *n, int *v)
#define CONJ2(_X_, _M_, _N_)
static const char * valid_matmult[]
static SEXP trMatrix_matmult(SEXP a, SEXP b, char atrans, char btrans, char aside, int triangular)
static SEXP gCgCMatrix_matmult(SEXP x, SEXP y, char xtrans, char ytrans, char ztrans, int triangular, int boolean)
SEXP sparse_diag_U2N(SEXP, const char *)
SEXP R_diagonal_matmult(SEXP s_x, SEXP s_y, SEXP s_xtrans, SEXP s_ytrans, SEXP s_boolean)
static SEXP geMatrix_matmult(SEXP a, SEXP b, char atrans, char btrans)
static SEXP spMatrix_matmult(SEXP a, SEXP b, char atrans, char btrans, char aside)