26 #if ! defined (octave_Sparse_op_defs_h)
27 #define octave_Sparse_op_defs_h 1
29 #include "octave-config.h"
38 #define SPARSE_SMS_BIN_OP_1(R, F, OP, M, S) \
40 F (const M& m, const S& s) \
42 octave_idx_type nr = m.rows (); \
43 octave_idx_type nc = m.cols (); \
45 R r (nr, nc, (0.0 OP s)); \
47 for (octave_idx_type j = 0; j < nc; j++) \
48 for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
49 r.xelem (m.ridx (i), j) = m.data (i) OP s; \
53 #define SPARSE_SMS_BIN_OP_2(R, F, OP, M, S) \
55 F (const M& m, const S& s) \
57 octave_idx_type nr = m.rows (); \
58 octave_idx_type nc = m.cols (); \
59 octave_idx_type nz = m.nnz (); \
63 for (octave_idx_type i = 0; i < nz; i++) \
65 r.xdata (i) = m.data (i) OP s; \
66 r.xridx (i) = m.ridx (i); \
68 for (octave_idx_type i = 0; i < nc + 1; i++) \
69 r.xcidx (i) = m.cidx (i); \
71 r.maybe_compress (true); \
75 #define SPARSE_SMS_BIN_OPS(R1, R2, M, S) \
76 SPARSE_SMS_BIN_OP_1 (R1, operator +, +, M, S) \
77 SPARSE_SMS_BIN_OP_1 (R1, operator -, -, M, S) \
78 SPARSE_SMS_BIN_OP_2 (R2, operator *, *, M, S) \
79 SPARSE_SMS_BIN_OP_2 (R2, operator /, /, M, S)
81 #define SPARSE_SMS_CMP_OP(F, OP, M, S) \
83 F (const M& m, const S& s) \
85 octave_idx_type nr = m.rows (); \
86 octave_idx_type nc = m.cols (); \
89 M::element_type m_zero = M::element_type (); \
93 r = SparseBoolMatrix (nr, nc, true); \
94 for (octave_idx_type j = 0; j < nc; j++) \
95 for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
96 if (! (m.data (i) OP s)) \
97 r.data (m.ridx (i) + j * nr) = false; \
98 r.maybe_compress (true); \
102 r = SparseBoolMatrix (nr, nc, m.nnz ()); \
103 r.cidx (0) = static_cast<octave_idx_type> (0); \
104 octave_idx_type nel = 0; \
105 for (octave_idx_type j = 0; j < nc; j++) \
107 for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
108 if (m.data (i) OP s) \
110 r.ridx (nel) = m.ridx (i); \
111 r.data (nel++) = true; \
113 r.cidx (j + 1) = nel; \
115 r.maybe_compress (false); \
120 #define SPARSE_SMS_CMP_OPS(M, S) \
121 SPARSE_SMS_CMP_OP (mx_el_lt, <, M, S) \
122 SPARSE_SMS_CMP_OP (mx_el_le, <=, M, S) \
123 SPARSE_SMS_CMP_OP (mx_el_ge, >=, M, S) \
124 SPARSE_SMS_CMP_OP (mx_el_gt, >, M, S) \
125 SPARSE_SMS_CMP_OP (mx_el_eq, ==, M, S) \
126 SPARSE_SMS_CMP_OP (mx_el_ne, !=, M, S)
128 #define SPARSE_SMS_EQNE_OPS(M, S) \
129 SPARSE_SMS_CMP_OP (mx_el_eq, ==, M, S) \
130 SPARSE_SMS_CMP_OP (mx_el_ne, !=, M, S)
132 #define SPARSE_SMS_BOOL_OR_OP(M, S) \
134 mx_el_or (const M& m, const S& s) \
136 octave_idx_type nr = m.rows (); \
137 octave_idx_type nc = m.cols (); \
138 SparseBoolMatrix r; \
140 M::element_type lhs_zero = M::element_type (); \
143 if (nr > 0 && nc > 0) \
146 r = SparseBoolMatrix (nr, nc, true); \
149 r = SparseBoolMatrix (nr, nc, m.nnz ()); \
150 r.cidx (0) = static_cast<octave_idx_type> (0); \
151 octave_idx_type nel = 0; \
152 for (octave_idx_type j = 0; j < nc; j++) \
154 for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
155 if (m.data (i) != lhs_zero) \
157 r.ridx (nel) = m.ridx (i); \
158 r.data (nel++) = true; \
160 r.cidx (j + 1) = nel; \
162 r.maybe_compress (false); \
168 #define SPARSE_SMS_BOOL_AND_OP(M, S) \
170 mx_el_and (const M& m, const S& s) \
172 octave_idx_type nr = m.rows (); \
173 octave_idx_type nc = m.cols (); \
174 SparseBoolMatrix r; \
176 M::element_type lhs_zero = M::element_type (); \
179 if (nr > 0 && nc > 0) \
183 r = SparseBoolMatrix (nr, nc, m.nnz ()); \
184 r.cidx (0) = static_cast<octave_idx_type> (0); \
185 octave_idx_type nel = 0; \
186 for (octave_idx_type j = 0; j < nc; j++) \
188 for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
189 if (m.data (i) != lhs_zero) \
191 r.ridx (nel) = m.ridx (i); \
192 r.data (nel++) = true; \
194 r.cidx (j + 1) = nel; \
196 r.maybe_compress (false); \
199 r = SparseBoolMatrix (nr, nc); \
204 #define SPARSE_SMS_BOOL_OPS(M, S) \
205 SPARSE_SMS_BOOL_AND_OP (M, S) \
206 SPARSE_SMS_BOOL_OR_OP (M, S)
210 #define SPARSE_SSM_BIN_OP_1(R, F, OP, S, M) \
212 F (const S& s, const M& m) \
214 octave_idx_type nr = m.rows (); \
215 octave_idx_type nc = m.cols (); \
217 R r (nr, nc, (s OP 0.0)); \
219 for (octave_idx_type j = 0; j < nc; j++) \
220 for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
221 r.xelem (m.ridx (i), j) = s OP m.data (i); \
226 #define SPARSE_SSM_BIN_OP_2(R, F, OP, S, M) \
228 F (const S& s, const M& m) \
230 octave_idx_type nr = m.rows (); \
231 octave_idx_type nc = m.cols (); \
232 octave_idx_type nz = m.nnz (); \
236 for (octave_idx_type i = 0; i < nz; i++) \
238 r.xdata (i) = s OP m.data (i); \
239 r.xridx (i) = m.ridx (i); \
241 for (octave_idx_type i = 0; i < nc + 1; i++) \
242 r.xcidx (i) = m.cidx (i); \
244 r.maybe_compress(true); \
248 #define SPARSE_SSM_BIN_OPS(R1, R2, S, M) \
249 SPARSE_SSM_BIN_OP_1 (R1, operator +, +, S, M) \
250 SPARSE_SSM_BIN_OP_1 (R1, operator -, -, S, M) \
251 SPARSE_SSM_BIN_OP_2 (R2, operator *, *, S, M) \
252 SPARSE_SSM_BIN_OP_2 (R2, operator /, /, S, M)
254 #define SPARSE_SSM_CMP_OP(F, OP, S, M) \
256 F (const S& s, const M& m) \
258 octave_idx_type nr = m.rows (); \
259 octave_idx_type nc = m.cols (); \
260 SparseBoolMatrix r; \
262 M::element_type m_zero = M::element_type (); \
266 r = SparseBoolMatrix (nr, nc, true); \
267 for (octave_idx_type j = 0; j < nc; j++) \
268 for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
269 if (! (s OP m.data (i))) \
270 r.data (m.ridx (i) + j * nr) = false; \
271 r.maybe_compress (true); \
275 r = SparseBoolMatrix (nr, nc, m.nnz ()); \
276 r.cidx (0) = static_cast<octave_idx_type> (0); \
277 octave_idx_type nel = 0; \
278 for (octave_idx_type j = 0; j < nc; j++) \
280 for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
281 if (s OP m.data (i)) \
283 r.ridx (nel) = m.ridx (i); \
284 r.data (nel++) = true; \
286 r.cidx (j + 1) = nel; \
288 r.maybe_compress (false); \
293 #define SPARSE_SSM_CMP_OPS(S, M) \
294 SPARSE_SSM_CMP_OP (mx_el_lt, <, S, M) \
295 SPARSE_SSM_CMP_OP (mx_el_le, <=, S, M) \
296 SPARSE_SSM_CMP_OP (mx_el_ge, >=, S, M) \
297 SPARSE_SSM_CMP_OP (mx_el_gt, >, S, M) \
298 SPARSE_SSM_CMP_OP (mx_el_eq, ==, S, M) \
299 SPARSE_SSM_CMP_OP (mx_el_ne, !=, S, M)
301 #define SPARSE_SSM_EQNE_OPS(S, M) \
302 SPARSE_SSM_CMP_OP (mx_el_eq, ==, S, M) \
303 SPARSE_SSM_CMP_OP (mx_el_ne, !=, S, M)
305 #define SPARSE_SSM_BOOL_OR_OP(S, M) \
307 mx_el_or (const S& s, const M& m) \
309 octave_idx_type nr = m.rows (); \
310 octave_idx_type nc = m.cols (); \
311 SparseBoolMatrix r; \
314 M::element_type rhs_zero = M::element_type (); \
316 if (nr > 0 && nc > 0) \
319 r = SparseBoolMatrix (nr, nc, true); \
322 r = SparseBoolMatrix (nr, nc, m.nnz ()); \
323 r.cidx (0) = static_cast<octave_idx_type> (0); \
324 octave_idx_type nel = 0; \
325 for (octave_idx_type j = 0; j < nc; j++) \
327 for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
328 if (m.data (i) != rhs_zero) \
330 r.ridx (nel) = m.ridx (i); \
331 r.data (nel++) = true; \
333 r.cidx (j + 1) = nel; \
335 r.maybe_compress (false); \
341 #define SPARSE_SSM_BOOL_AND_OP(S, M) \
343 mx_el_and (const S& s, const M& m) \
345 octave_idx_type nr = m.rows (); \
346 octave_idx_type nc = m.cols (); \
347 SparseBoolMatrix r; \
350 M::element_type rhs_zero = M::element_type (); \
352 if (nr > 0 && nc > 0) \
356 r = SparseBoolMatrix (nr, nc, m.nnz ()); \
357 r.cidx (0) = static_cast<octave_idx_type> (0); \
358 octave_idx_type nel = 0; \
359 for (octave_idx_type j = 0; j < nc; j++) \
361 for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
362 if (m.data (i) != rhs_zero) \
364 r.ridx (nel) = m.ridx (i); \
365 r.data (nel++) = true; \
367 r.cidx (j + 1) = nel; \
369 r.maybe_compress (false); \
372 r = SparseBoolMatrix (nr, nc); \
377 #define SPARSE_SSM_BOOL_OPS(S, M) \
378 SPARSE_SSM_BOOL_AND_OP (S, M) \
379 SPARSE_SSM_BOOL_OR_OP (S, M)
383 #define SPARSE_SMSM_BIN_OP_1(R, F, OP, M1, M2) \
385 F (const M1& m1, const M2& m2) \
389 octave_idx_type m1_nr = m1.rows (); \
390 octave_idx_type m1_nc = m1.cols (); \
392 octave_idx_type m2_nr = m2.rows (); \
393 octave_idx_type m2_nc = m2.cols (); \
395 if (m1_nr == 1 && m1_nc == 1) \
397 if (m1.elem (0,0) == 0.) \
401 r = R (m2_nr, m2_nc, m1.data (0) OP 0.); \
403 for (octave_idx_type j = 0 ; j < m2_nc ; j++) \
406 octave_idx_type idxj = j * m2_nr; \
407 for (octave_idx_type i = m2.cidx (j) ; i < m2.cidx (j+1) ; i++) \
410 r.data (idxj + m2.ridx (i)) = m1.data (0) OP m2.data (i); \
413 r.maybe_compress (); \
416 else if (m2_nr == 1 && m2_nc == 1) \
418 if (m2.elem (0,0) == 0.) \
422 r = R (m1_nr, m1_nc, 0. OP m2.data (0)); \
424 for (octave_idx_type j = 0 ; j < m1_nc ; j++) \
427 octave_idx_type idxj = j * m1_nr; \
428 for (octave_idx_type i = m1.cidx (j) ; i < m1.cidx (j+1) ; i++) \
431 r.data (idxj + m1.ridx (i)) = m1.data (i) OP m2.data (0); \
434 r.maybe_compress (); \
437 else if (m1_nr != m2_nr || m1_nc != m2_nc) \
438 octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \
441 r = R (m1_nr, m1_nc, (m1.nnz () + m2.nnz ())); \
443 octave_idx_type jx = 0; \
445 for (octave_idx_type i = 0 ; i < m1_nc ; i++) \
447 octave_idx_type ja = m1.cidx (i); \
448 octave_idx_type ja_max = m1.cidx (i+1); \
449 bool ja_lt_max = ja < ja_max; \
451 octave_idx_type jb = m2.cidx (i); \
452 octave_idx_type jb_max = m2.cidx (i+1); \
453 bool jb_lt_max = jb < jb_max; \
455 while (ja_lt_max || jb_lt_max) \
458 if ((! jb_lt_max) || \
459 (ja_lt_max && (m1.ridx (ja) < m2.ridx (jb)))) \
461 r.ridx (jx) = m1.ridx (ja); \
462 r.data (jx) = m1.data (ja) OP 0.; \
465 ja_lt_max= ja < ja_max; \
467 else if ((! ja_lt_max) || \
468 (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)))) \
470 r.ridx (jx) = m2.ridx (jb); \
471 r.data (jx) = 0. OP m2.data (jb); \
474 jb_lt_max= jb < jb_max; \
478 if ((m1.data (ja) OP m2.data (jb)) != 0.) \
480 r.data (jx) = m1.data (ja) OP m2.data (jb); \
481 r.ridx (jx) = m1.ridx (ja); \
485 ja_lt_max= ja < ja_max; \
487 jb_lt_max= jb < jb_max; \
493 r.maybe_compress (); \
499 #define SPARSE_SMSM_BIN_OP_2(R, F, OP, M1, M2) \
501 F (const M1& m1, const M2& m2) \
505 octave_idx_type m1_nr = m1.rows (); \
506 octave_idx_type m1_nc = m1.cols (); \
508 octave_idx_type m2_nr = m2.rows (); \
509 octave_idx_type m2_nc = m2.cols (); \
511 if (m1_nr == 1 && m1_nc == 1) \
513 if (m1.elem (0,0) == 0.) \
514 r = R (m2_nr, m2_nc); \
518 octave_idx_type m2_nnz = m2.nnz (); \
520 for (octave_idx_type i = 0 ; i < m2_nnz ; i++) \
523 r.data (i) = m1.data (0) OP r.data (i); \
525 r.maybe_compress (); \
528 else if (m2_nr == 1 && m2_nc == 1) \
530 if (m2.elem (0,0) == 0.) \
531 r = R (m1_nr, m1_nc); \
535 octave_idx_type m1_nnz = m1.nnz (); \
537 for (octave_idx_type i = 0 ; i < m1_nnz ; i++) \
540 r.data (i) = r.data (i) OP m2.data (0); \
542 r.maybe_compress (); \
545 else if (m1_nr != m2_nr || m1_nc != m2_nc) \
546 octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \
549 r = R (m1_nr, m1_nc, (m1.nnz () > m2.nnz () ? m1.nnz () : m2.nnz ())); \
551 octave_idx_type jx = 0; \
553 for (octave_idx_type i = 0 ; i < m1_nc ; i++) \
555 octave_idx_type ja = m1.cidx (i); \
556 octave_idx_type ja_max = m1.cidx (i+1); \
557 bool ja_lt_max = ja < ja_max; \
559 octave_idx_type jb = m2.cidx (i); \
560 octave_idx_type jb_max = m2.cidx (i+1); \
561 bool jb_lt_max = jb < jb_max; \
563 while (ja_lt_max || jb_lt_max) \
566 if ((! jb_lt_max) || \
567 (ja_lt_max && (m1.ridx (ja) < m2.ridx (jb)))) \
569 ja++; ja_lt_max= ja < ja_max; \
571 else if ((! ja_lt_max) || \
572 (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)))) \
574 jb++; jb_lt_max= jb < jb_max; \
578 if ((m1.data (ja) OP m2.data (jb)) != 0.) \
580 r.data (jx) = m1.data (ja) OP m2.data (jb); \
581 r.ridx (jx) = m1.ridx (ja); \
584 ja++; ja_lt_max= ja < ja_max; \
585 jb++; jb_lt_max= jb < jb_max; \
591 r.maybe_compress (); \
597 #define SPARSE_SMSM_BIN_OP_3(R, F, OP, M1, M2) \
599 F (const M1& m1, const M2& m2) \
603 octave_idx_type m1_nr = m1.rows (); \
604 octave_idx_type m1_nc = m1.cols (); \
606 octave_idx_type m2_nr = m2.rows (); \
607 octave_idx_type m2_nc = m2.cols (); \
609 if (m1_nr == 1 && m1_nc == 1) \
611 if ((m1.elem (0,0) OP Complex ()) == Complex ()) \
613 octave_idx_type m2_nnz = m2.nnz (); \
615 for (octave_idx_type i = 0 ; i < m2_nnz ; i++) \
616 r.data (i) = m1.elem (0,0) OP r.data (i); \
617 r.maybe_compress (); \
621 r = R (m2_nr, m2_nc, m1.elem (0,0) OP Complex ()); \
622 for (octave_idx_type j = 0 ; j < m2_nc ; j++) \
625 octave_idx_type idxj = j * m2_nr; \
626 for (octave_idx_type i = m2.cidx (j) ; i < m2.cidx (j+1) ; i++) \
629 r.data (idxj + m2.ridx (i)) = m1.elem (0,0) OP m2.data (i); \
632 r.maybe_compress (); \
635 else if (m2_nr == 1 && m2_nc == 1) \
637 if ((Complex () OP m1.elem (0,0)) == Complex ()) \
639 octave_idx_type m1_nnz = m1.nnz (); \
641 for (octave_idx_type i = 0 ; i < m1_nnz ; i++) \
642 r.data (i) = r.data (i) OP m2.elem (0,0); \
643 r.maybe_compress (); \
647 r = R (m1_nr, m1_nc, Complex () OP m2.elem (0,0)); \
648 for (octave_idx_type j = 0 ; j < m1_nc ; j++) \
651 octave_idx_type idxj = j * m1_nr; \
652 for (octave_idx_type i = m1.cidx (j) ; i < m1.cidx (j+1) ; i++) \
655 r.data (idxj + m1.ridx (i)) = m1.data (i) OP m2.elem (0,0); \
658 r.maybe_compress (); \
661 else if (m1_nr != m2_nr || m1_nc != m2_nc) \
662 octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \
667 r = R (m1_nr, m1_nc, (Complex () OP Complex ())); \
669 for (octave_idx_type i = 0 ; i < m1_nc ; i++) \
671 octave_idx_type ja = m1.cidx (i); \
672 octave_idx_type ja_max = m1.cidx (i+1); \
673 bool ja_lt_max = ja < ja_max; \
675 octave_idx_type jb = m2.cidx (i); \
676 octave_idx_type jb_max = m2.cidx (i+1); \
677 bool jb_lt_max = jb < jb_max; \
679 while (ja_lt_max || jb_lt_max) \
682 if ((! jb_lt_max) || \
683 (ja_lt_max && (m1.ridx (ja) < m2.ridx (jb)))) \
686 r.elem (m1.ridx (ja),i) = m1.data (ja) OP Complex (); \
688 ja_lt_max= ja < ja_max; \
690 else if ((! ja_lt_max) || \
691 (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)))) \
694 r.elem (m2.ridx (jb),i) = Complex () OP m2.data (jb); \
696 jb_lt_max= jb < jb_max; \
700 r.elem (m1.ridx (ja),i) = m1.data (ja) OP m2.data (jb); \
702 ja_lt_max= ja < ja_max; \
704 jb_lt_max= jb < jb_max; \
708 r.maybe_compress (true); \
717 #define SPARSE_SMSM_BIN_OPS(R1, R2, M1, M2) \
718 SPARSE_SMSM_BIN_OP_1 (R1, operator +, +, M1, M2) \
719 SPARSE_SMSM_BIN_OP_1 (R1, operator -, -, M1, M2) \
720 SPARSE_SMSM_BIN_OP_2 (R2, product, *, M1, M2) \
721 SPARSE_SMSM_BIN_OP_3 (R2, quotient, /, M1, M2)
726 #define SPARSE_SMSM_CMP_OP(F, OP, M1, M2) \
728 F (const M1& m1, const M2& m2) \
730 SparseBoolMatrix r; \
732 octave_idx_type m1_nr = m1.rows (); \
733 octave_idx_type m1_nc = m1.cols (); \
735 octave_idx_type m2_nr = m2.rows (); \
736 octave_idx_type m2_nc = m2.cols (); \
738 M1::element_type Z1 = M1::element_type (); \
739 M2::element_type Z2 = M2::element_type (); \
741 if (m1_nr == 1 && m1_nc == 1) \
743 if (m1.elem (0,0) OP Z2) \
745 r = SparseBoolMatrix (m2_nr, m2_nc, true); \
746 for (octave_idx_type j = 0; j < m2_nc; j++) \
747 for (octave_idx_type i = m2.cidx (j); i < m2.cidx (j+1); i++) \
748 if (! (m1.elem (0,0) OP m2.data (i))) \
749 r.data (m2.ridx (i) + j * m2_nr) = false; \
750 r.maybe_compress (true); \
754 r = SparseBoolMatrix (m2_nr, m2_nc, m2.nnz ()); \
755 r.cidx (0) = static_cast<octave_idx_type> (0); \
756 octave_idx_type nel = 0; \
757 for (octave_idx_type j = 0; j < m2_nc; j++) \
759 for (octave_idx_type i = m2.cidx (j); i < m2.cidx (j+1); i++) \
760 if (m1.elem (0,0) OP m2.data (i)) \
762 r.ridx (nel) = m2.ridx (i); \
763 r.data (nel++) = true; \
765 r.cidx (j + 1) = nel; \
767 r.maybe_compress (false); \
770 else if (m2_nr == 1 && m2_nc == 1) \
772 if (Z1 OP m2.elem (0,0)) \
774 r = SparseBoolMatrix (m1_nr, m1_nc, true); \
775 for (octave_idx_type j = 0; j < m1_nc; j++) \
776 for (octave_idx_type i = m1.cidx (j); i < m1.cidx (j+1); i++) \
777 if (! (m1.data (i) OP m2.elem (0,0))) \
778 r.data (m1.ridx (i) + j * m1_nr) = false; \
779 r.maybe_compress (true); \
783 r = SparseBoolMatrix (m1_nr, m1_nc, m1.nnz ()); \
784 r.cidx (0) = static_cast<octave_idx_type> (0); \
785 octave_idx_type nel = 0; \
786 for (octave_idx_type j = 0; j < m1_nc; j++) \
788 for (octave_idx_type i = m1.cidx (j); i < m1.cidx (j+1); i++) \
789 if (m1.data (i) OP m2.elem (0,0)) \
791 r.ridx (nel) = m1.ridx (i); \
792 r.data (nel++) = true; \
794 r.cidx (j + 1) = nel; \
796 r.maybe_compress (false); \
799 else if (m1_nr == m2_nr && m1_nc == m2_nc) \
801 if (m1_nr != 0 || m1_nc != 0) \
805 r = SparseBoolMatrix (m1_nr, m1_nc, true); \
806 for (octave_idx_type j = 0; j < m1_nc; j++) \
808 octave_idx_type i1 = m1.cidx (j); \
809 octave_idx_type e1 = m1.cidx (j+1); \
810 octave_idx_type i2 = m2.cidx (j); \
811 octave_idx_type e2 = m2.cidx (j+1); \
812 while (i1 < e1 || i2 < e2) \
814 if (i1 == e1 || (i2 < e2 && m1.ridx (i1) > m2.ridx (i2))) \
816 if (! (Z1 OP m2.data (i2))) \
817 r.data (m2.ridx (i2) + j * m1_nr) = false; \
820 else if (i2 == e2 || m1.ridx (i1) < m2.ridx (i2)) \
822 if (! (m1.data (i1) OP Z2)) \
823 r.data (m1.ridx (i1) + j * m1_nr) = false; \
828 if (! (m1.data (i1) OP m2.data (i2))) \
829 r.data (m1.ridx (i1) + j * m1_nr) = false; \
835 r.maybe_compress (true); \
839 r = SparseBoolMatrix (m1_nr, m1_nc, m1.nnz () + m2.nnz ()); \
840 r.cidx (0) = static_cast<octave_idx_type> (0); \
841 octave_idx_type nel = 0; \
842 for (octave_idx_type j = 0; j < m1_nc; j++) \
844 octave_idx_type i1 = m1.cidx (j); \
845 octave_idx_type e1 = m1.cidx (j+1); \
846 octave_idx_type i2 = m2.cidx (j); \
847 octave_idx_type e2 = m2.cidx (j+1); \
848 while (i1 < e1 || i2 < e2) \
850 if (i1 == e1 || (i2 < e2 && m1.ridx (i1) > m2.ridx (i2))) \
852 if (Z1 OP m2.data (i2)) \
854 r.ridx (nel) = m2.ridx (i2); \
855 r.data (nel++) = true; \
859 else if (i2 == e2 || m1.ridx (i1) < m2.ridx (i2)) \
861 if (m1.data (i1) OP Z2) \
863 r.ridx (nel) = m1.ridx (i1); \
864 r.data (nel++) = true; \
870 if (m1.data (i1) OP m2.data (i2)) \
872 r.ridx (nel) = m1.ridx (i1); \
873 r.data (nel++) = true; \
879 r.cidx (j + 1) = nel; \
881 r.maybe_compress (false); \
887 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \
888 octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \
893 #define SPARSE_SMSM_CMP_OPS(M1, M2) \
894 SPARSE_SMSM_CMP_OP (mx_el_lt, <, M1, M2) \
895 SPARSE_SMSM_CMP_OP (mx_el_le, <=, M1, M2) \
896 SPARSE_SMSM_CMP_OP (mx_el_ge, >=, M1, M2) \
897 SPARSE_SMSM_CMP_OP (mx_el_gt, >, M1, M2) \
898 SPARSE_SMSM_CMP_OP (mx_el_eq, ==, M1, M2) \
899 SPARSE_SMSM_CMP_OP (mx_el_ne, !=, M1, M2)
901 #define SPARSE_SMSM_EQNE_OPS(M1, M2) \
902 SPARSE_SMSM_CMP_OP (mx_el_eq, ==, M1, M2) \
903 SPARSE_SMSM_CMP_OP (mx_el_ne, !=, M1, M2)
905 #define SPARSE_SMSM_BOOL_AND_OP(M1, M2) \
906 extern SparseBoolMatrix mx_el_and (const M1&, const M2::element_type&); \
907 extern SparseBoolMatrix mx_el_and (const M1::element_type&, const M2&); \
909 mx_el_and (const M1& m1, const M2& m2) \
911 SparseBoolMatrix r; \
913 octave_idx_type m1_nr = m1.rows (); \
914 octave_idx_type m1_nc = m1.cols (); \
916 octave_idx_type m2_nr = m2.rows (); \
917 octave_idx_type m2_nc = m2.cols (); \
919 M1::element_type lhs_zero = M1::element_type (); \
920 M2::element_type rhs_zero = M2::element_type (); \
922 if (m1_nr == 1 && m1_nc == 1) \
923 return mx_el_and (m1.elem (0,0), m2); \
924 else if (m2_nr == 1 && m2_nc == 1) \
925 return mx_el_and (m1, m2.elem (0,0)); \
926 else if (m1_nr == m2_nr && m1_nc == m2_nc) \
928 if (m1_nr != 0 || m1_nc != 0) \
930 r = SparseBoolMatrix (m1_nr, m1_nc, m1.nnz () + m2.nnz ()); \
931 r.cidx (0) = static_cast<octave_idx_type> (0); \
932 octave_idx_type nel = 0; \
933 for (octave_idx_type j = 0; j < m1_nc; j++) \
935 octave_idx_type i1 = m1.cidx (j); \
936 octave_idx_type e1 = m1.cidx (j+1); \
937 octave_idx_type i2 = m2.cidx (j); \
938 octave_idx_type e2 = m2.cidx (j+1); \
939 while (i1 < e1 || i2 < e2) \
941 if (i1 == e1 || (i2 < e2 && m1.ridx (i1) > m2.ridx (i2))) \
943 else if (i2 == e2 || m1.ridx (i1) < m2.ridx (i2)) \
947 if (m1.data (i1) != lhs_zero && m2.data (i2) != rhs_zero) \
949 r.ridx (nel) = m1.ridx (i1); \
950 r.data (nel++) = true; \
956 r.cidx (j + 1) = nel; \
958 r.maybe_compress (false); \
963 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \
964 octave::err_nonconformant ("mx_el_and_", m1_nr, m1_nc, m2_nr, m2_nc); \
969 #define SPARSE_SMSM_BOOL_OR_OP(M1, M2) \
970 extern SparseBoolMatrix mx_el_or (const M1&, const M2::element_type&); \
971 extern SparseBoolMatrix mx_el_or (const M1::element_type&, const M2&); \
973 mx_el_or (const M1& m1, const M2& m2) \
975 SparseBoolMatrix r; \
977 octave_idx_type m1_nr = m1.rows (); \
978 octave_idx_type m1_nc = m1.cols (); \
980 octave_idx_type m2_nr = m2.rows (); \
981 octave_idx_type m2_nc = m2.cols (); \
983 M1::element_type lhs_zero = M1::element_type (); \
984 M2::element_type rhs_zero = M2::element_type (); \
986 if (m1_nr == 1 && m1_nc == 1) \
987 return mx_el_or (m1.elem (0,0), m2); \
988 else if (m2_nr == 1 && m2_nc == 1) \
989 return mx_el_or (m1, m2.elem (0,0)); \
990 else if (m1_nr == m2_nr && m1_nc == m2_nc) \
992 if (m1_nr != 0 || m1_nc != 0) \
994 r = SparseBoolMatrix (m1_nr, m1_nc, m1.nnz () + m2.nnz ()); \
995 r.cidx (0) = static_cast<octave_idx_type> (0); \
996 octave_idx_type nel = 0; \
997 for (octave_idx_type j = 0; j < m1_nc; j++) \
999 octave_idx_type i1 = m1.cidx (j); \
1000 octave_idx_type e1 = m1.cidx (j+1); \
1001 octave_idx_type i2 = m2.cidx (j); \
1002 octave_idx_type e2 = m2.cidx (j+1); \
1003 while (i1 < e1 || i2 < e2) \
1005 if (i1 == e1 || (i2 < e2 && m1.ridx (i1) > m2.ridx (i2))) \
1007 if (m2.data (i2) != rhs_zero) \
1009 r.ridx (nel) = m2.ridx (i2); \
1010 r.data (nel++) = true; \
1014 else if (i2 == e2 || m1.ridx (i1) < m2.ridx (i2)) \
1016 if (m1.data (i1) != lhs_zero) \
1018 r.ridx (nel) = m1.ridx (i1); \
1019 r.data (nel++) = true; \
1025 if (m1.data (i1) != lhs_zero || m2.data (i2) != rhs_zero) \
1027 r.ridx (nel) = m1.ridx (i1); \
1028 r.data (nel++) = true; \
1034 r.cidx (j + 1) = nel; \
1036 r.maybe_compress (false); \
1041 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \
1042 octave::err_nonconformant ("mx_el_or", m1_nr, m1_nc, m2_nr, m2_nc); \
1047 #define SPARSE_SMSM_BOOL_OPS(M1, M2) \
1048 SPARSE_SMSM_BOOL_AND_OP (M1, M2) \
1049 SPARSE_SMSM_BOOL_OR_OP (M1, M2)
1053 #define SPARSE_MSM_BIN_OP_1(R, F, OP, M1, M2) \
1055 F (const M1& m1, const M2& m2) \
1059 octave_idx_type m1_nr = m1.rows (); \
1060 octave_idx_type m1_nc = m1.cols (); \
1062 octave_idx_type m2_nr = m2.rows (); \
1063 octave_idx_type m2_nc = m2.cols (); \
1065 if (m2_nr == 1 && m2_nc == 1) \
1066 r = R (m1 OP m2.elem (0,0)); \
1067 else if (m1_nr != m2_nr || m1_nc != m2_nc) \
1068 octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \
1071 r = R (F (m1, m2.matrix_value ())); \
1076 #define SPARSE_MSM_BIN_OP_2(R, F, OP, M1, M2) \
1078 F (const M1& m1, const M2& m2) \
1082 octave_idx_type m1_nr = m1.rows (); \
1083 octave_idx_type m1_nc = m1.cols (); \
1085 octave_idx_type m2_nr = m2.rows (); \
1086 octave_idx_type m2_nc = m2.cols (); \
1088 if (m2_nr == 1 && m2_nc == 1) \
1089 r = R (m1 OP m2.elem (0,0)); \
1090 else if (m1_nr != m2_nr || m1_nc != m2_nc) \
1091 octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \
1094 if (do_mx_check (m1, mx_inline_all_finite<M1::element_type>)) \
1097 octave_idx_type m2_nz = m2.nnz (); \
1098 r = R (m2_nr, m2_nc, m2_nz); \
1099 for (octave_idx_type j = 0, k = 0; j < m2_nc; j++) \
1102 for (octave_idx_type i = m2.cidx (j); i < m2.cidx (j+1); i++) \
1104 octave_idx_type mri = m2.ridx (i); \
1105 R::element_type x = m1(mri, j) OP m2.data (i); \
1109 r.xridx (k) = m2.ridx (i); \
1113 r.xcidx (j+1) = k; \
1115 r.maybe_compress (false); \
1119 r = R (F (m1, m2.matrix_value ())); \
1125 #define SPARSE_MSM_BIN_OPS(R1, R2, M1, M2) \
1126 SPARSE_MSM_BIN_OP_1 (R1, operator +, +, M1, M2) \
1127 SPARSE_MSM_BIN_OP_1 (R1, operator -, -, M1, M2) \
1128 SPARSE_MSM_BIN_OP_2 (R2, product, *, M1, M2) \
1129 SPARSE_MSM_BIN_OP_1 (R2, quotient, /, M1, M2)
1131 #define SPARSE_MSM_CMP_OP(F, OP, M1, M2) \
1133 F (const M1& m1, const M2& m2) \
1135 SparseBoolMatrix r; \
1137 octave_idx_type m1_nr = m1.rows (); \
1138 octave_idx_type m1_nc = m1.cols (); \
1140 octave_idx_type m2_nr = m2.rows (); \
1141 octave_idx_type m2_nc = m2.cols (); \
1143 if (m2_nr == 1 && m2_nc == 1) \
1144 r = SparseBoolMatrix (F (m1, m2.elem (0,0))); \
1145 else if (m1_nr == m2_nr && m1_nc == m2_nc) \
1147 if (m1_nr != 0 || m1_nc != 0) \
1150 octave_idx_type nel = 0; \
1151 for (octave_idx_type j = 0; j < m1_nc; j++) \
1152 for (octave_idx_type i = 0; i < m1_nr; i++) \
1153 if (m1.elem (i, j) OP m2.elem (i, j)) \
1156 r = SparseBoolMatrix (m1_nr, m1_nc, nel); \
1158 octave_idx_type ii = 0; \
1160 for (octave_idx_type j = 0; j < m1_nc; j++) \
1162 for (octave_idx_type i = 0; i < m1_nr; i++) \
1164 bool el = m1.elem (i, j) OP m2.elem (i, j); \
1168 r.ridx (ii++) = i; \
1171 r.cidx (j+1) = ii; \
1177 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \
1178 octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \
1183 #define SPARSE_MSM_CMP_OPS(M1, M2) \
1184 SPARSE_MSM_CMP_OP (mx_el_lt, <, M1, M2) \
1185 SPARSE_MSM_CMP_OP (mx_el_le, <=, M1, M2) \
1186 SPARSE_MSM_CMP_OP (mx_el_ge, >=, M1, M2) \
1187 SPARSE_MSM_CMP_OP (mx_el_gt, >, M1, M2) \
1188 SPARSE_MSM_CMP_OP (mx_el_eq, ==, M1, M2) \
1189 SPARSE_MSM_CMP_OP (mx_el_ne, !=, M1, M2)
1191 #define SPARSE_MSM_EQNE_OPS(M1, M2) \
1192 SPARSE_MSM_CMP_OP (mx_el_eq, ==, M1, M2) \
1193 SPARSE_MSM_CMP_OP (mx_el_ne, !=, M1, M2)
1195 #define SPARSE_MSM_BOOL_OP(F, OP, M1, M2) \
1197 F (const M1& m1, const M2& m2) \
1199 SparseBoolMatrix r; \
1201 octave_idx_type m1_nr = m1.rows (); \
1202 octave_idx_type m1_nc = m1.cols (); \
1204 octave_idx_type m2_nr = m2.rows (); \
1205 octave_idx_type m2_nc = m2.cols (); \
1207 M1::element_type lhs_zero = M1::element_type (); \
1208 M2::element_type rhs_zero = M2::element_type (); \
1210 if (m2_nr == 1 && m2_nc == 1) \
1211 r = SparseBoolMatrix (F (m1, m2.elem (0,0))); \
1212 else if (m1_nr == m2_nr && m1_nc == m2_nc) \
1214 if (m1_nr != 0 || m1_nc != 0) \
1217 octave_idx_type nel = 0; \
1218 for (octave_idx_type j = 0; j < m1_nc; j++) \
1219 for (octave_idx_type i = 0; i < m1_nr; i++) \
1220 if ((m1.elem (i, j) != lhs_zero) \
1221 OP (m2.elem (i, j) != rhs_zero)) \
1224 r = SparseBoolMatrix (m1_nr, m1_nc, nel); \
1226 octave_idx_type ii = 0; \
1228 for (octave_idx_type j = 0; j < m1_nc; j++) \
1230 for (octave_idx_type i = 0; i < m1_nr; i++) \
1232 bool el = (m1.elem (i, j) != lhs_zero) \
1233 OP (m2.elem (i, j) != rhs_zero); \
1237 r.ridx (ii++) = i; \
1240 r.cidx (j+1) = ii; \
1246 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \
1247 octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \
1252 #define SPARSE_MSM_BOOL_OPS(M1, M2) \
1253 SPARSE_MSM_BOOL_OP (mx_el_and, &&, M1, M2) \
1254 SPARSE_MSM_BOOL_OP (mx_el_or, ||, M1, M2)
1258 #define SPARSE_SMM_BIN_OP_1(R, F, OP, M1, M2) \
1260 F (const M1& m1, const M2& m2) \
1264 octave_idx_type m1_nr = m1.rows (); \
1265 octave_idx_type m1_nc = m1.cols (); \
1267 octave_idx_type m2_nr = m2.rows (); \
1268 octave_idx_type m2_nc = m2.cols (); \
1270 if (m1_nr == 1 && m1_nc == 1) \
1271 r = R (m1.elem (0,0) OP m2); \
1272 else if (m1_nr != m2_nr || m1_nc != m2_nc) \
1273 octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \
1276 r = R (m1.matrix_value () OP m2); \
1282 #define SPARSE_SMM_BIN_OP_2_CHECK_product(ET) \
1283 do_mx_check (m2, mx_inline_all_finite<ET>)
1286 #define SPARSE_SMM_BIN_OP_2_CHECK_quotient(ET) \
1287 ! do_mx_check (m2, mx_inline_any_nan<ET>) && m2.nnz () == m2.numel ()
1289 #define SPARSE_SMM_BIN_OP_2(R, F, OP, M1, M2) \
1291 F (const M1& m1, const M2& m2) \
1295 octave_idx_type m1_nr = m1.rows (); \
1296 octave_idx_type m1_nc = m1.cols (); \
1298 octave_idx_type m2_nr = m2.rows (); \
1299 octave_idx_type m2_nc = m2.cols (); \
1301 if (m1_nr == 1 && m1_nc == 1) \
1302 r = R (m1.elem (0,0) OP m2); \
1303 else if (m1_nr != m2_nr || m1_nc != m2_nc) \
1304 octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \
1307 if (SPARSE_SMM_BIN_OP_2_CHECK_ ## F(M2::element_type)) \
1310 octave_idx_type m1_nz = m1.nnz (); \
1311 r = R (m1_nr, m1_nc, m1_nz); \
1312 for (octave_idx_type j = 0, k = 0; j < m1_nc; j++) \
1315 for (octave_idx_type i = m1.cidx (j); i < m1.cidx (j+1); i++) \
1317 octave_idx_type mri = m1.ridx (i); \
1318 R::element_type x = m1.data (i) OP m2 (mri, j); \
1322 r.xridx (k) = m1.ridx (i); \
1326 r.xcidx (j+1) = k; \
1328 r.maybe_compress (false); \
1332 r = R (F (m1.matrix_value (), m2)); \
1338 #define SPARSE_SMM_BIN_OPS(R1, R2, M1, M2) \
1339 SPARSE_SMM_BIN_OP_1 (R1, operator +, +, M1, M2) \
1340 SPARSE_SMM_BIN_OP_1 (R1, operator -, -, M1, M2) \
1341 SPARSE_SMM_BIN_OP_2 (R2, product, *, M1, M2) \
1342 SPARSE_SMM_BIN_OP_2 (R2, quotient, /, M1, M2)
1344 #define SPARSE_SMM_CMP_OP(F, OP, M1, M2) \
1346 F (const M1& m1, const M2& m2) \
1348 SparseBoolMatrix r; \
1350 octave_idx_type m1_nr = m1.rows (); \
1351 octave_idx_type m1_nc = m1.cols (); \
1353 octave_idx_type m2_nr = m2.rows (); \
1354 octave_idx_type m2_nc = m2.cols (); \
1356 if (m1_nr == 1 && m1_nc == 1) \
1357 r = SparseBoolMatrix (F (m1.elem (0,0), m2)); \
1358 else if (m1_nr == m2_nr && m1_nc == m2_nc) \
1360 if (m1_nr != 0 || m1_nc != 0) \
1363 octave_idx_type nel = 0; \
1364 for (octave_idx_type j = 0; j < m1_nc; j++) \
1365 for (octave_idx_type i = 0; i < m1_nr; i++) \
1366 if (m1.elem (i, j) OP m2.elem (i, j)) \
1369 r = SparseBoolMatrix (m1_nr, m1_nc, nel); \
1371 octave_idx_type ii = 0; \
1373 for (octave_idx_type j = 0; j < m1_nc; j++) \
1375 for (octave_idx_type i = 0; i < m1_nr; i++) \
1377 bool el = m1.elem (i, j) OP m2.elem (i, j); \
1381 r.ridx (ii++) = i; \
1384 r.cidx (j+1) = ii; \
1390 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \
1391 octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \
1396 #define SPARSE_SMM_CMP_OPS(M1, M2) \
1397 SPARSE_SMM_CMP_OP (mx_el_lt, <, M1, M2) \
1398 SPARSE_SMM_CMP_OP (mx_el_le, <=, M1, M2) \
1399 SPARSE_SMM_CMP_OP (mx_el_ge, >=, M1, M2) \
1400 SPARSE_SMM_CMP_OP (mx_el_gt, >, M1, M2) \
1401 SPARSE_SMM_CMP_OP (mx_el_eq, ==, M1, M2) \
1402 SPARSE_SMM_CMP_OP (mx_el_ne, !=, M1, M2)
1404 #define SPARSE_SMM_EQNE_OPS(M1, M2) \
1405 SPARSE_SMM_CMP_OP (mx_el_eq, ==, M1, M2) \
1406 SPARSE_SMM_CMP_OP (mx_el_ne, !=, M1, M2)
1408 #define SPARSE_SMM_BOOL_OP(F, OP, M1, M2) \
1410 F (const M1& m1, const M2& m2) \
1412 SparseBoolMatrix r; \
1414 octave_idx_type m1_nr = m1.rows (); \
1415 octave_idx_type m1_nc = m1.cols (); \
1417 octave_idx_type m2_nr = m2.rows (); \
1418 octave_idx_type m2_nc = m2.cols (); \
1420 M1::element_type lhs_zero = M1::element_type (); \
1421 M2::element_type rhs_zero = M2::element_type (); \
1423 if (m1_nr == 1 && m1_nc == 1) \
1424 r = SparseBoolMatrix (F (m1.elem (0,0), m2)); \
1425 else if (m1_nr == m2_nr && m1_nc == m2_nc) \
1427 if (m1_nr != 0 || m1_nc != 0) \
1430 octave_idx_type nel = 0; \
1431 for (octave_idx_type j = 0; j < m1_nc; j++) \
1432 for (octave_idx_type i = 0; i < m1_nr; i++) \
1433 if ((m1.elem (i, j) != lhs_zero) \
1434 OP (m2.elem (i, j) != rhs_zero)) \
1437 r = SparseBoolMatrix (m1_nr, m1_nc, nel); \
1439 octave_idx_type ii = 0; \
1441 for (octave_idx_type j = 0; j < m1_nc; j++) \
1443 for (octave_idx_type i = 0; i < m1_nr; i++) \
1445 bool el = (m1.elem (i, j) != lhs_zero) \
1446 OP (m2.elem (i, j) != rhs_zero); \
1450 r.ridx (ii++) = i; \
1453 r.cidx (j+1) = ii; \
1459 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \
1460 octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \
1465 #define SPARSE_SMM_BOOL_OPS(M1, M2) \
1466 SPARSE_SMM_BOOL_OP (mx_el_and, &&, M1, M2) \
1467 SPARSE_SMM_BOOL_OP (mx_el_or, ||, M1, M2)
1471 #define SPARSE_CUMSUM(RET_TYPE, ELT_TYPE, FCN) \
1473 octave_idx_type nr = rows (); \
1474 octave_idx_type nc = cols (); \
1478 if (nr > 0 && nc > 0) \
1480 if ((nr == 1 && dim == -1) || dim == 1) \
1482 retval = transpose (). FCN (0) .transpose (); \
1485 octave_idx_type nel = 0; \
1486 for (octave_idx_type i = 0; i < nc; i++) \
1488 ELT_TYPE t = ELT_TYPE (); \
1489 for (octave_idx_type j = cidx (i); j < cidx (i+1); j++) \
1492 if (t != ELT_TYPE ()) \
1494 if (j == cidx (i+1) - 1) \
1495 nel += nr - ridx (j); \
1497 nel += ridx (j+1) - ridx (j); \
1501 retval = RET_TYPE (nr, nc, nel); \
1502 retval.cidx (0) = 0; \
1503 octave_idx_type ii = 0; \
1504 for (octave_idx_type i = 0; i < nc; i++) \
1506 ELT_TYPE t = ELT_TYPE (); \
1507 for (octave_idx_type j = cidx (i); j < cidx (i+1); j++) \
1510 if (t != ELT_TYPE ()) \
1512 if (j == cidx (i+1) - 1) \
1514 for (octave_idx_type k = ridx (j); k < nr; k++) \
1516 retval.data (ii) = t; \
1517 retval.ridx (ii++) = k; \
1522 for (octave_idx_type k = ridx (j); k < ridx (j+1); k++) \
1524 retval.data (ii) = t; \
1525 retval.ridx (ii++) = k; \
1530 retval.cidx (i+1) = ii; \
1535 retval = RET_TYPE (nr,nc); \
1539 #define SPARSE_CUMPROD(RET_TYPE, ELT_TYPE, FCN) \
1541 octave_idx_type nr = rows (); \
1542 octave_idx_type nc = cols (); \
1546 if (nr > 0 && nc > 0) \
1548 if ((nr == 1 && dim == -1) || dim == 1) \
1550 retval = transpose (). FCN (0) .transpose (); \
1553 octave_idx_type nel = 0; \
1554 for (octave_idx_type i = 0; i < nc; i++) \
1556 octave_idx_type jj = 0; \
1557 for (octave_idx_type j = cidx (i); j < cidx (i+1); j++) \
1559 if (jj == ridx (j)) \
1568 retval = RET_TYPE (nr, nc, nel); \
1569 retval.cidx (0) = 0; \
1570 octave_idx_type ii = 0; \
1571 for (octave_idx_type i = 0; i < nc; i++) \
1573 ELT_TYPE t = ELT_TYPE (1.); \
1574 octave_idx_type jj = 0; \
1575 for (octave_idx_type j = cidx (i); j < cidx (i+1); j++) \
1577 if (jj == ridx (j)) \
1580 retval.data (ii) = t; \
1581 retval.ridx (ii++) = jj++; \
1586 retval.cidx (i+1) = ii; \
1591 retval = RET_TYPE (nr,nc); \
1595 #define SPARSE_BASE_REDUCTION_OP(RET_TYPE, EL_TYPE, ROW_EXPR, COL_EXPR, \
1596 INIT_VAL, MT_RESULT) \
1598 octave_idx_type nr = rows (); \
1599 octave_idx_type nc = cols (); \
1603 if (nr > 0 && nc > 0) \
1605 if ((nr == 1 && dim == -1) || dim == 1) \
1608 octave_idx_type j = 0; \
1609 OCTAVE_LOCAL_BUFFER (EL_TYPE, tmp, nr); \
1611 for (octave_idx_type i = 0; i < nr; i++) \
1612 tmp[i] = INIT_VAL; \
1613 for (j = 0; j < nc; j++) \
1615 for (octave_idx_type i = cidx (j); i < cidx (j + 1); i++) \
1620 octave_idx_type nel = 0; \
1621 for (octave_idx_type i = 0; i < nr; i++) \
1622 if (tmp[i] != EL_TYPE ()) \
1624 retval = RET_TYPE (nr, static_cast<octave_idx_type> (1), nel); \
1625 retval.cidx (0) = 0; \
1626 retval.cidx (1) = nel; \
1628 for (octave_idx_type i = 0; i < nr; i++) \
1629 if (tmp[i] != EL_TYPE ()) \
1631 retval.data (nel) = tmp[i]; \
1632 retval.ridx (nel++) = i; \
1637 OCTAVE_LOCAL_BUFFER (EL_TYPE, tmp, nc); \
1639 for (octave_idx_type j = 0; j < nc; j++) \
1641 tmp[j] = INIT_VAL; \
1642 for (octave_idx_type i = cidx (j); i < cidx (j + 1); i++) \
1647 octave_idx_type nel = 0; \
1648 for (octave_idx_type i = 0; i < nc; i++) \
1649 if (tmp[i] != EL_TYPE ()) \
1651 retval = RET_TYPE (static_cast<octave_idx_type> (1), nc, nel); \
1652 retval.cidx (0) = 0; \
1654 for (octave_idx_type i = 0; i < nc; i++) \
1655 if (tmp[i] != EL_TYPE ()) \
1657 retval.data (nel) = tmp[i]; \
1658 retval.ridx (nel++) = 0; \
1659 retval.cidx (i+1) = retval.cidx (i) + 1; \
1662 retval.cidx (i+1) = retval.cidx (i); \
1665 else if (nc == 0 && (nr == 0 || (nr == 1 && dim == -1))) \
1669 retval = RET_TYPE (static_cast<octave_idx_type> (1), \
1670 static_cast<octave_idx_type> (1), \
1671 static_cast<octave_idx_type> (1)); \
1672 retval.cidx (0) = 0; \
1673 retval.cidx (1) = 1; \
1674 retval.ridx (0) = 0; \
1675 retval.data (0) = MT_RESULT; \
1678 retval = RET_TYPE (static_cast<octave_idx_type> (1), \
1679 static_cast<octave_idx_type> (1), \
1680 static_cast<octave_idx_type> (0)); \
1682 else if (nr == 0 && (dim == 0 || dim == -1)) \
1686 retval = RET_TYPE (static_cast<octave_idx_type> (1), nc, nc); \
1687 retval.cidx (0) = 0; \
1688 for (octave_idx_type i = 0; i < nc ; i++) \
1690 retval.ridx (i) = 0; \
1691 retval.cidx (i+1) = i+1; \
1692 retval.data (i) = MT_RESULT; \
1696 retval = RET_TYPE (static_cast<octave_idx_type> (1), nc, \
1697 static_cast<octave_idx_type> (0)); \
1699 else if (nc == 0 && dim == 1) \
1703 retval = RET_TYPE (nr, static_cast<octave_idx_type> (1), nr); \
1704 retval.cidx (0) = 0; \
1705 retval.cidx (1) = nr; \
1706 for (octave_idx_type i = 0; i < nr; i++) \
1708 retval.ridx (i) = i; \
1709 retval.data (i) = MT_RESULT; \
1713 retval = RET_TYPE (nr, static_cast<octave_idx_type> (1), \
1714 static_cast<octave_idx_type> (0)); \
1717 retval.resize (nr > 0, nc > 0); \
1721 #define SPARSE_REDUCTION_OP_ROW_EXPR(OP) \
1722 tmp[ridx (i)] OP data (i)
1724 #define SPARSE_REDUCTION_OP_COL_EXPR(OP) \
1727 #define SPARSE_REDUCTION_OP(RET_TYPE, EL_TYPE, OP, INIT_VAL, MT_RESULT) \
1728 SPARSE_BASE_REDUCTION_OP (RET_TYPE, EL_TYPE, \
1729 SPARSE_REDUCTION_OP_ROW_EXPR (OP), \
1730 SPARSE_REDUCTION_OP_COL_EXPR (OP), \
1731 INIT_VAL, MT_RESULT)
1735 #define SPARSE_ANY_ALL_OP_ROW_CODE(TEST_OP, TEST_TRUE_VAL) \
1736 if (data (i) TEST_OP 0.0) \
1737 tmp[ridx (i)] = TEST_TRUE_VAL;
1739 #define SPARSE_ANY_ALL_OP_COL_CODE(TEST_OP, TEST_TRUE_VAL) \
1740 if (data (i) TEST_OP 0.0) \
1742 tmp[j] = TEST_TRUE_VAL; \
1746 #define SPARSE_ANY_ALL_OP(DIM, INIT_VAL, MT_RESULT, TEST_OP, TEST_TRUE_VAL) \
1747 SPARSE_BASE_REDUCTION_OP (SparseBoolMatrix, char, \
1748 SPARSE_ANY_ALL_OP_ROW_CODE (TEST_OP, TEST_TRUE_VAL), \
1749 SPARSE_ANY_ALL_OP_COL_CODE (TEST_OP, TEST_TRUE_VAL), \
1750 INIT_VAL, MT_RESULT)
1752 #define SPARSE_ALL_OP(DIM) \
1753 if ((rows () == 1 && dim == -1) || dim == 1) \
1754 return transpose (). all (0). transpose (); \
1757 SPARSE_ANY_ALL_OP (DIM, (cidx (j+1) - cidx (j) < nr ? false : true), \
1761 #define SPARSE_ANY_OP(DIM) SPARSE_ANY_ALL_OP (DIM, false, false, !=, true)
1763 #define SPARSE_SPARSE_MUL(RET_TYPE, RET_EL_TYPE, EL_TYPE) \
1764 octave_idx_type nr = m.rows (); \
1765 octave_idx_type nc = m.cols (); \
1767 octave_idx_type a_nr = a.rows (); \
1768 octave_idx_type a_nc = a.cols (); \
1770 if (nr == 1 && nc == 1) \
1772 RET_EL_TYPE s = m.elem (0,0); \
1773 octave_idx_type nz = a.nnz (); \
1774 RET_TYPE r (a_nr, a_nc, nz); \
1776 for (octave_idx_type i = 0; i < nz; i++) \
1779 r.data (i) = s * a.data (i); \
1780 r.ridx (i) = a.ridx (i); \
1782 for (octave_idx_type i = 0; i < a_nc + 1; i++) \
1785 r.cidx (i) = a.cidx (i); \
1788 r.maybe_compress (true); \
1791 else if (a_nr == 1 && a_nc == 1) \
1793 RET_EL_TYPE s = a.elem (0,0); \
1794 octave_idx_type nz = m.nnz (); \
1795 RET_TYPE r (nr, nc, nz); \
1797 for (octave_idx_type i = 0; i < nz; i++) \
1800 r.data (i) = m.data (i) * s; \
1801 r.ridx (i) = m.ridx (i); \
1803 for (octave_idx_type i = 0; i < nc + 1; i++) \
1806 r.cidx (i) = m.cidx (i); \
1809 r.maybe_compress (true); \
1812 else if (nc != a_nr) \
1813 octave::err_nonconformant ("operator *", nr, nc, a_nr, a_nc); \
1816 OCTAVE_LOCAL_BUFFER (octave_idx_type, w, nr); \
1817 RET_TYPE retval (nr, a_nc, static_cast<octave_idx_type> (0)); \
1818 for (octave_idx_type i = 0; i < nr; i++) \
1820 retval.xcidx (0) = 0; \
1822 octave_idx_type nel = 0; \
1824 for (octave_idx_type i = 0; i < a_nc; i++) \
1826 for (octave_idx_type j = a.cidx (i); j < a.cidx (i+1); j++) \
1828 octave_idx_type col = a.ridx (j); \
1829 for (octave_idx_type k = m.cidx (col) ; k < m.cidx (col+1); k++) \
1831 if (w[m.ridx (k)] < i + 1) \
1833 w[m.ridx (k)] = i + 1; \
1839 retval.xcidx (i+1) = nel; \
1843 return RET_TYPE (nr, a_nc); \
1846 for (octave_idx_type i = 0; i < nr; i++) \
1849 OCTAVE_LOCAL_BUFFER (RET_EL_TYPE, Xcol, nr); \
1851 retval.change_capacity (nel); \
1863 octave_idx_type n_per_col = (a_nc > 43000 ? 43000 : \
1864 (a_nc * a_nc) / 43000); \
1865 octave_idx_type ii = 0; \
1866 octave_idx_type *ri = retval.xridx (); \
1867 octave_sort<octave_idx_type> sort; \
1869 for (octave_idx_type i = 0; i < a_nc ; i++) \
1871 if (retval.xcidx (i+1) - retval.xcidx (i) > n_per_col) \
1873 for (octave_idx_type j = a.cidx (i); j < a.cidx (i+1); j++) \
1875 octave_idx_type col = a.ridx (j); \
1876 EL_TYPE tmpval = a.data (j); \
1877 for (octave_idx_type k = m.cidx (col) ; \
1878 k < m.cidx (col+1); k++) \
1881 octave_idx_type row = m.ridx (k); \
1882 if (w[row] < i + 1) \
1885 Xcol[row] = tmpval * m.data (k); \
1888 Xcol[row] += tmpval * m.data (k); \
1891 for (octave_idx_type k = 0; k < nr; k++) \
1892 if (w[k] == i + 1) \
1894 retval.xdata (ii) = Xcol[k]; \
1895 retval.xridx (ii++) = k; \
1900 for (octave_idx_type j = a.cidx (i); j < a.cidx (i+1); j++) \
1902 octave_idx_type col = a.ridx (j); \
1903 EL_TYPE tmpval = a.data (j); \
1904 for (octave_idx_type k = m.cidx (col) ; \
1905 k < m.cidx (col+1); k++) \
1908 octave_idx_type row = m.ridx (k); \
1909 if (w[row] < i + 1) \
1912 retval.xridx (ii++) = row; \
1913 Xcol[row] = tmpval * m.data (k); \
1916 Xcol[row] += tmpval * m.data (k); \
1919 sort.sort (ri + retval.xcidx (i), ii - retval.xcidx (i)); \
1920 for (octave_idx_type k = retval.xcidx (i); k < ii; k++) \
1921 retval.xdata (k) = Xcol[retval.xridx (k)]; \
1924 retval.maybe_compress (true); \
1929 #define SPARSE_FULL_MUL(RET_TYPE, EL_TYPE) \
1930 octave_idx_type nr = m.rows (); \
1931 octave_idx_type nc = m.cols (); \
1933 octave_idx_type a_nr = a.rows (); \
1934 octave_idx_type a_nc = a.cols (); \
1936 if (nr == 1 && nc == 1) \
1938 RET_TYPE retval = m.elem (0,0) * a; \
1941 else if (nc != a_nr) \
1942 octave::err_nonconformant ("operator *", nr, nc, a_nr, a_nc); \
1945 RET_TYPE::element_type zero = RET_TYPE::element_type (); \
1947 RET_TYPE retval (nr, a_nc, zero); \
1949 for (octave_idx_type i = 0; i < a_nc ; i++) \
1951 for (octave_idx_type j = 0; j < a_nr; j++) \
1955 EL_TYPE tmpval = a.elem (j,i); \
1956 for (octave_idx_type k = m.cidx (j) ; k < m.cidx (j+1); k++) \
1957 retval.elem (m.ridx (k),i) += tmpval * m.data (k); \
1963 #define SPARSE_FULL_TRANS_MUL(RET_TYPE, EL_TYPE, CONJ_OP) \
1964 octave_idx_type nr = m.rows (); \
1965 octave_idx_type nc = m.cols (); \
1967 octave_idx_type a_nr = a.rows (); \
1968 octave_idx_type a_nc = a.cols (); \
1970 if (nr == 1 && nc == 1) \
1972 RET_TYPE retval = CONJ_OP (m.elem (0,0)) * a; \
1975 else if (nr != a_nr) \
1976 octave::err_nonconformant ("operator *", nc, nr, a_nr, a_nc); \
1979 RET_TYPE retval (nc, a_nc); \
1981 for (octave_idx_type i = 0; i < a_nc ; i++) \
1983 for (octave_idx_type j = 0; j < nc; j++) \
1987 EL_TYPE acc = EL_TYPE (); \
1988 for (octave_idx_type k = m.cidx (j) ; k < m.cidx (j+1); k++) \
1989 acc += a.elem (m.ridx (k),i) * CONJ_OP (m.data (k)); \
1990 retval.xelem (j,i) = acc; \
1996 #define FULL_SPARSE_MUL(RET_TYPE, EL_TYPE) \
1997 octave_idx_type nr = m.rows (); \
1998 octave_idx_type nc = m.cols (); \
2000 octave_idx_type a_nr = a.rows (); \
2001 octave_idx_type a_nc = a.cols (); \
2003 if (a_nr == 1 && a_nc == 1) \
2005 RET_TYPE retval = m * a.elem (0,0); \
2008 else if (nc != a_nr) \
2009 octave::err_nonconformant ("operator *", nr, nc, a_nr, a_nc); \
2012 RET_TYPE::element_type zero = RET_TYPE::element_type (); \
2014 RET_TYPE retval (nr, a_nc, zero); \
2016 for (octave_idx_type i = 0; i < a_nc ; i++) \
2019 for (octave_idx_type j = a.cidx (i); j < a.cidx (i+1); j++) \
2021 octave_idx_type col = a.ridx (j); \
2022 EL_TYPE tmpval = a.data (j); \
2024 for (octave_idx_type k = 0 ; k < nr; k++) \
2025 retval.xelem (k,i) += tmpval * m.elem (k,col); \
2031 #define FULL_SPARSE_MUL_TRANS(RET_TYPE, EL_TYPE, CONJ_OP) \
2032 octave_idx_type nr = m.rows (); \
2033 octave_idx_type nc = m.cols (); \
2035 octave_idx_type a_nr = a.rows (); \
2036 octave_idx_type a_nc = a.cols (); \
2038 if (a_nr == 1 && a_nc == 1) \
2040 RET_TYPE retval = m * CONJ_OP (a.elem (0,0)); \
2043 else if (nc != a_nc) \
2044 octave::err_nonconformant ("operator *", nr, nc, a_nc, a_nr); \
2047 RET_TYPE::element_type zero = RET_TYPE::element_type (); \
2049 RET_TYPE retval (nr, a_nr, zero); \
2051 for (octave_idx_type i = 0; i < a_nc ; i++) \
2054 for (octave_idx_type j = a.cidx (i); j < a.cidx (i+1); j++) \
2056 octave_idx_type col = a.ridx (j); \
2057 EL_TYPE tmpval = CONJ_OP (a.data (j)); \
2058 for (octave_idx_type k = 0 ; k < nr; k++) \
2059 retval.xelem (k,col) += tmpval * m.elem (k,i); \