Mercurial > hg > octave-lyh
annotate liboctave/Sparse-op-defs.h @ 8181:1ebcb9872ced
fix sparse-matrix bool/cmp op instantiation problem
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Mon, 06 Oct 2008 11:07:54 -0400 |
parents | 9bcb31cc56be |
children | 23ff439ea0dd |
rev | line source |
---|---|
5164 | 1 /* |
2 | |
7344 | 3 Copyright (C) 2004, 2005, 2006, 2007, 2008 David Bateman |
7016 | 4 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Andy Adler |
7803 | 5 Copyright (C) 2008 Jaroslav Hajek |
7016 | 6 |
7 This file is part of Octave. | |
5164 | 8 |
9 Octave is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
7016 | 11 Free Software Foundation; either version 3 of the License, or (at your |
12 option) any later version. | |
5164 | 13 |
14 Octave is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
7016 | 20 along with Octave; see the file COPYING. If not, see |
21 <http://www.gnu.org/licenses/>. | |
5164 | 22 |
23 */ | |
24 | |
25 #if !defined (octave_sparse_op_defs_h) | |
26 #define octave_sparse_op_defs_h 1 | |
27 | |
28 #include "Array-util.h" | |
6221 | 29 #include "mx-ops.h" |
5164 | 30 |
6708 | 31 #define SPARSE_BIN_OP_DECL(R, OP, X, Y, API) \ |
32 extern API R OP (const X&, const Y&) | |
5164 | 33 |
6708 | 34 #define SPARSE_CMP_OP_DECL(OP, X, Y, API) \ |
35 extern API SparseBoolMatrix OP (const X&, const Y&) | |
5164 | 36 |
6708 | 37 #define SPARSE_BOOL_OP_DECL(OP, X, Y, API) \ |
38 extern API SparseBoolMatrix OP (const X&, const Y&) | |
5164 | 39 |
40 // matrix by scalar operations. | |
41 | |
6708 | 42 #define SPARSE_SMS_BIN_OP_DECLS(R1, R2, M, S, API) \ |
43 SPARSE_BIN_OP_DECL (R1, operator +, M, S, API); \ | |
44 SPARSE_BIN_OP_DECL (R1, operator -, M, S, API); \ | |
45 SPARSE_BIN_OP_DECL (R2, operator *, M, S, API); \ | |
46 SPARSE_BIN_OP_DECL (R2, operator /, M, S, API); | |
5164 | 47 |
48 #define SPARSE_SMS_BIN_OP_1(R, F, OP, M, S) \ | |
49 R \ | |
50 F (const M& m, const S& s) \ | |
51 { \ | |
5275 | 52 octave_idx_type nr = m.rows (); \ |
53 octave_idx_type nc = m.cols (); \ | |
5164 | 54 \ |
55 R r (nr, nc, (0.0 OP s)); \ | |
56 \ | |
5275 | 57 for (octave_idx_type j = 0; j < nc; j++) \ |
58 for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \ | |
5164 | 59 r.elem (m.ridx (i), j) = m.data (i) OP s; \ |
60 return r; \ | |
61 } | |
62 | |
63 #define SPARSE_SMS_BIN_OP_2(R, F, OP, M, S) \ | |
64 R \ | |
65 F (const M& m, const S& s) \ | |
66 { \ | |
5275 | 67 octave_idx_type nr = m.rows (); \ |
68 octave_idx_type nc = m.cols (); \ | |
5681 | 69 octave_idx_type nz = m.nnz (); \ |
5164 | 70 \ |
71 R r (nr, nc, nz); \ | |
72 \ | |
5275 | 73 for (octave_idx_type i = 0; i < nz; i++) \ |
5164 | 74 { \ |
75 r.data(i) = m.data(i) OP s; \ | |
76 r.ridx(i) = m.ridx(i); \ | |
77 } \ | |
5275 | 78 for (octave_idx_type i = 0; i < nc + 1; i++) \ |
5164 | 79 r.cidx(i) = m.cidx(i); \ |
80 \ | |
81 r.maybe_compress (true); \ | |
82 return r; \ | |
83 } | |
84 | |
85 #define SPARSE_SMS_BIN_OPS(R1, R2, M, S) \ | |
86 SPARSE_SMS_BIN_OP_1 (R1, operator +, +, M, S) \ | |
87 SPARSE_SMS_BIN_OP_1 (R1, operator -, -, M, S) \ | |
88 SPARSE_SMS_BIN_OP_2 (R2, operator *, *, M, S) \ | |
89 SPARSE_SMS_BIN_OP_2 (R2, operator /, /, M, S) | |
90 | |
6708 | 91 #define SPARSE_SMS_CMP_OP_DECLS(M, S, API) \ |
92 SPARSE_CMP_OP_DECL (mx_el_lt, M, S, API); \ | |
93 SPARSE_CMP_OP_DECL (mx_el_le, M, S, API); \ | |
94 SPARSE_CMP_OP_DECL (mx_el_ge, M, S, API); \ | |
95 SPARSE_CMP_OP_DECL (mx_el_gt, M, S, API); \ | |
96 SPARSE_CMP_OP_DECL (mx_el_eq, M, S, API); \ | |
97 SPARSE_CMP_OP_DECL (mx_el_ne, M, S, API); | |
5164 | 98 |
6708 | 99 #define SPARSE_SMS_EQNE_OP_DECLS(M, S, API) \ |
100 SPARSE_CMP_OP_DECL (mx_el_eq, M, S, API); \ | |
101 SPARSE_CMP_OP_DECL (mx_el_ne, M, S, API); | |
5164 | 102 |
103 #define SPARSE_SMS_CMP_OP(F, OP, M, MZ, MC, S, SZ, SC) \ | |
104 SparseBoolMatrix \ | |
105 F (const M& m, const S& s) \ | |
106 { \ | |
5275 | 107 octave_idx_type nr = m.rows (); \ |
108 octave_idx_type nc = m.cols (); \ | |
7269 | 109 SparseBoolMatrix r; \ |
5164 | 110 \ |
7269 | 111 if (MC (MZ) OP SC (s)) \ |
112 { \ | |
113 r = SparseBoolMatrix (nr, nc, true); \ | |
114 for (octave_idx_type j = 0; j < nc; j++) \ | |
115 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) \ | |
116 if (! (MC (m.data (i)) OP SC (s))) \ | |
117 r.data (m.ridx (i) + j * nr) = false; \ | |
118 r.maybe_compress (true); \ | |
119 } \ | |
120 else \ | |
5164 | 121 { \ |
7269 | 122 r = SparseBoolMatrix (nr, nc, m.nnz ()); \ |
123 r.cidx (0) = static_cast<octave_idx_type> (0); \ | |
124 octave_idx_type nel = 0; \ | |
125 for (octave_idx_type j = 0; j < nc; j++) \ | |
126 { \ | |
127 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) \ | |
128 if (MC (m.data (i)) OP SC (s)) \ | |
129 { \ | |
130 r.ridx (nel) = m.ridx (i); \ | |
131 r.data (nel++) = true; \ | |
132 } \ | |
133 r.cidx (j + 1) = nel; \ | |
134 } \ | |
135 r.maybe_compress (false); \ | |
136 } \ | |
5164 | 137 return r; \ |
138 } | |
139 | |
140 #define SPARSE_SMS_CMP_OPS(M, MZ, CM, S, SZ, CS) \ | |
141 SPARSE_SMS_CMP_OP (mx_el_lt, <, M, MZ, CM, S, SZ, CS) \ | |
142 SPARSE_SMS_CMP_OP (mx_el_le, <=, M, MZ, CM, S, SZ, CS) \ | |
143 SPARSE_SMS_CMP_OP (mx_el_ge, >=, M, MZ, CM, S, SZ, CS) \ | |
144 SPARSE_SMS_CMP_OP (mx_el_gt, >, M, MZ, CM, S, SZ, CS) \ | |
145 SPARSE_SMS_CMP_OP (mx_el_eq, ==, M, MZ, , S, SZ, ) \ | |
146 SPARSE_SMS_CMP_OP (mx_el_ne, !=, M, MZ, , S, SZ, ) | |
147 | |
148 #define SPARSE_SMS_EQNE_OPS(M, MZ, CM, S, SZ, CS) \ | |
149 SPARSE_SMS_CMP_OP (mx_el_eq, ==, M, MZ, , S, SZ, ) \ | |
150 SPARSE_SMS_CMP_OP (mx_el_ne, !=, M, MZ, , S, SZ, ) | |
151 | |
6708 | 152 #define SPARSE_SMS_BOOL_OP_DECLS(M, S, API) \ |
153 SPARSE_BOOL_OP_DECL (mx_el_and, M, S, API); \ | |
154 SPARSE_BOOL_OP_DECL (mx_el_or, M, S, API); | |
5164 | 155 |
156 #define SPARSE_SMS_BOOL_OP(F, OP, M, S, LHS_ZERO, RHS_ZERO) \ | |
157 SparseBoolMatrix \ | |
158 F (const M& m, const S& s) \ | |
159 { \ | |
5275 | 160 octave_idx_type nr = m.rows (); \ |
161 octave_idx_type nc = m.cols (); \ | |
7269 | 162 SparseBoolMatrix r; \ |
5164 | 163 \ |
164 if (nr > 0 && nc > 0) \ | |
165 { \ | |
166 if (LHS_ZERO OP (s != RHS_ZERO)) \ | |
167 { \ | |
7269 | 168 r = SparseBoolMatrix (nr, nc, true); \ |
5275 | 169 for (octave_idx_type j = 0; j < nc; j++) \ |
7269 | 170 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) \ |
171 if (! ((m.data(i) != LHS_ZERO) OP (s != RHS_ZERO))) \ | |
172 r.data (m.ridx (i) + j * nr) = false; \ | |
173 r.maybe_compress (true); \ | |
174 } \ | |
5164 | 175 else \ |
176 { \ | |
7269 | 177 r = SparseBoolMatrix (nr, nc, m.nnz ()); \ |
178 r.cidx (0) = static_cast<octave_idx_type> (0); \ | |
179 octave_idx_type nel = 0; \ | |
5275 | 180 for (octave_idx_type j = 0; j < nc; j++) \ |
7269 | 181 { \ |
182 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) \ | |
183 if ((m.data(i) != LHS_ZERO) OP (s != RHS_ZERO)) \ | |
184 { \ | |
185 r.ridx (nel) = m.ridx (i); \ | |
186 r.data (nel++) = true; \ | |
187 } \ | |
188 r.cidx (j + 1) = nel; \ | |
189 } \ | |
190 r.maybe_compress (false); \ | |
191 } \ | |
5164 | 192 } \ |
193 return r; \ | |
194 } | |
195 | |
196 #define SPARSE_SMS_BOOL_OPS2(M, S, LHS_ZERO, RHS_ZERO) \ | |
197 SPARSE_SMS_BOOL_OP (mx_el_and, &&, M, S, LHS_ZERO, RHS_ZERO) \ | |
198 SPARSE_SMS_BOOL_OP (mx_el_or, ||, M, S, LHS_ZERO, RHS_ZERO) | |
199 | |
200 #define SPARSE_SMS_BOOL_OPS(M, S, ZERO) \ | |
201 SPARSE_SMS_BOOL_OPS2(M, S, ZERO, ZERO) | |
202 | |
6708 | 203 #define SPARSE_SMS_OP_DECLS(R1, R2, M, S, API) \ |
204 SPARSE_SMS_BIN_OP_DECLS (R1, R2, M, S, API) \ | |
205 SPARSE_SMS_CMP_OP_DECLS (M, S, API) \ | |
206 SPARSE_SMS_BOOL_OP_DECLS (M, S, API) | |
5164 | 207 |
208 // scalar by matrix operations. | |
209 | |
6708 | 210 #define SPARSE_SSM_BIN_OP_DECLS(R1, R2, S, M, API) \ |
211 SPARSE_BIN_OP_DECL (R1, operator +, S, M, API); \ | |
212 SPARSE_BIN_OP_DECL (R1, operator -, S, M, API); \ | |
213 SPARSE_BIN_OP_DECL (R2, operator *, S, M, API); \ | |
214 SPARSE_BIN_OP_DECL (R2, operator /, S, M, API); | |
5164 | 215 |
216 #define SPARSE_SSM_BIN_OP_1(R, F, OP, S, M) \ | |
217 R \ | |
218 F (const S& s, const M& m) \ | |
219 { \ | |
5275 | 220 octave_idx_type nr = m.rows (); \ |
221 octave_idx_type nc = m.cols (); \ | |
5164 | 222 \ |
223 R r (nr, nc, (s OP 0.0)); \ | |
224 \ | |
5275 | 225 for (octave_idx_type j = 0; j < nc; j++) \ |
226 for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \ | |
5164 | 227 r.elem (m.ridx (i), j) = s OP m.data (i); \ |
228 \ | |
229 return r; \ | |
230 } | |
231 | |
232 #define SPARSE_SSM_BIN_OP_2(R, F, OP, S, M) \ | |
233 R \ | |
234 F (const S& s, const M& m) \ | |
235 { \ | |
5275 | 236 octave_idx_type nr = m.rows (); \ |
237 octave_idx_type nc = m.cols (); \ | |
5681 | 238 octave_idx_type nz = m.nnz (); \ |
5164 | 239 \ |
240 R r (nr, nc, nz); \ | |
241 \ | |
5275 | 242 for (octave_idx_type i = 0; i < nz; i++) \ |
5164 | 243 { \ |
244 r.data(i) = s OP m.data(i); \ | |
245 r.ridx(i) = m.ridx(i); \ | |
246 } \ | |
5275 | 247 for (octave_idx_type i = 0; i < nc + 1; i++) \ |
5164 | 248 r.cidx(i) = m.cidx(i); \ |
249 \ | |
250 r.maybe_compress(true); \ | |
251 return r; \ | |
252 } | |
253 | |
254 #define SPARSE_SSM_BIN_OPS(R1, R2, S, M) \ | |
255 SPARSE_SSM_BIN_OP_1 (R1, operator +, +, S, M) \ | |
256 SPARSE_SSM_BIN_OP_1 (R1, operator -, -, S, M) \ | |
257 SPARSE_SSM_BIN_OP_2 (R2, operator *, *, S, M) \ | |
258 SPARSE_SSM_BIN_OP_2 (R2, operator /, /, S, M) | |
259 | |
6708 | 260 #define SPARSE_SSM_CMP_OP_DECLS(S, M, API) \ |
261 SPARSE_CMP_OP_DECL (mx_el_lt, S, M, API); \ | |
262 SPARSE_CMP_OP_DECL (mx_el_le, S, M, API); \ | |
263 SPARSE_CMP_OP_DECL (mx_el_ge, S, M, API); \ | |
264 SPARSE_CMP_OP_DECL (mx_el_gt, S, M, API); \ | |
265 SPARSE_CMP_OP_DECL (mx_el_eq, S, M, API); \ | |
266 SPARSE_CMP_OP_DECL (mx_el_ne, S, M, API); | |
5164 | 267 |
6708 | 268 #define SPARSE_SSM_EQNE_OP_DECLS(S, M, API) \ |
269 SPARSE_CMP_OP_DECL (mx_el_eq, S, M, API); \ | |
270 SPARSE_CMP_OP_DECL (mx_el_ne, S, M, API); | |
5164 | 271 |
272 #define SPARSE_SSM_CMP_OP(F, OP, S, SZ, SC, M, MZ, MC) \ | |
273 SparseBoolMatrix \ | |
274 F (const S& s, const M& m) \ | |
275 { \ | |
5275 | 276 octave_idx_type nr = m.rows (); \ |
277 octave_idx_type nc = m.cols (); \ | |
7269 | 278 SparseBoolMatrix r; \ |
5164 | 279 \ |
7269 | 280 if (SC (s) OP SC (MZ)) \ |
281 { \ | |
282 r = SparseBoolMatrix (nr, nc, true); \ | |
283 for (octave_idx_type j = 0; j < nc; j++) \ | |
284 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) \ | |
285 if (! (SC (s) OP MC (m.data (i)))) \ | |
286 r.data (m.ridx (i) + j * nr) = false; \ | |
287 r.maybe_compress (true); \ | |
288 } \ | |
289 else \ | |
5164 | 290 { \ |
7269 | 291 r = SparseBoolMatrix (nr, nc, m.nnz ()); \ |
292 r.cidx (0) = static_cast<octave_idx_type> (0); \ | |
293 octave_idx_type nel = 0; \ | |
294 for (octave_idx_type j = 0; j < nc; j++) \ | |
295 { \ | |
296 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) \ | |
297 if (SC (s) OP MC (m.data (i))) \ | |
298 { \ | |
299 r.ridx (nel) = m.ridx (i); \ | |
300 r.data (nel++) = true; \ | |
301 } \ | |
302 r.cidx (j + 1) = nel; \ | |
303 } \ | |
304 r.maybe_compress (false); \ | |
305 } \ | |
5164 | 306 return r; \ |
307 } | |
308 | |
309 #define SPARSE_SSM_CMP_OPS(S, SZ, SC, M, MZ, MC) \ | |
310 SPARSE_SSM_CMP_OP (mx_el_lt, <, S, SZ, SC, M, MZ, MC) \ | |
311 SPARSE_SSM_CMP_OP (mx_el_le, <=, S, SZ, SC, M, MZ, MC) \ | |
312 SPARSE_SSM_CMP_OP (mx_el_ge, >=, S, SZ, SC, M, MZ, MC) \ | |
313 SPARSE_SSM_CMP_OP (mx_el_gt, >, S, SZ, SC, M, MZ, MC) \ | |
314 SPARSE_SSM_CMP_OP (mx_el_eq, ==, S, SZ, , M, MZ, ) \ | |
315 SPARSE_SSM_CMP_OP (mx_el_ne, !=, S, SZ, , M, MZ, ) | |
316 | |
317 #define SPARSE_SSM_EQNE_OPS(S, SZ, SC, M, MZ, MC) \ | |
318 SPARSE_SSM_CMP_OP (mx_el_eq, ==, S, SZ, , M, MZ, ) \ | |
319 SPARSE_SSM_CMP_OP (mx_el_ne, !=, S, SZ, , M, MZ, ) | |
320 | |
6708 | 321 #define SPARSE_SSM_BOOL_OP_DECLS(S, M, API) \ |
322 SPARSE_BOOL_OP_DECL (mx_el_and, S, M, API); \ | |
323 SPARSE_BOOL_OP_DECL (mx_el_or, S, M, API); \ | |
5164 | 324 |
325 #define SPARSE_SSM_BOOL_OP(F, OP, S, M, LHS_ZERO, RHS_ZERO) \ | |
326 SparseBoolMatrix \ | |
327 F (const S& s, const M& m) \ | |
328 { \ | |
5275 | 329 octave_idx_type nr = m.rows (); \ |
330 octave_idx_type nc = m.cols (); \ | |
7269 | 331 SparseBoolMatrix r; \ |
5164 | 332 \ |
333 if (nr > 0 && nc > 0) \ | |
334 { \ | |
335 if ((s != LHS_ZERO) OP RHS_ZERO) \ | |
336 { \ | |
7269 | 337 r = SparseBoolMatrix (nr, nc, true); \ |
5275 | 338 for (octave_idx_type j = 0; j < nc; j++) \ |
7269 | 339 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) \ |
340 if (! ((s != LHS_ZERO) OP (m.data(i) != RHS_ZERO))) \ | |
341 r.data (m.ridx (i) + j * nr) = false; \ | |
342 r.maybe_compress (true); \ | |
343 } \ | |
5164 | 344 else \ |
345 { \ | |
7269 | 346 r = SparseBoolMatrix (nr, nc, m.nnz ()); \ |
347 r.cidx (0) = static_cast<octave_idx_type> (0); \ | |
348 octave_idx_type nel = 0; \ | |
5275 | 349 for (octave_idx_type j = 0; j < nc; j++) \ |
7269 | 350 { \ |
351 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) \ | |
352 if ((s != LHS_ZERO) OP (m.data(i) != RHS_ZERO)) \ | |
353 { \ | |
354 r.ridx (nel) = m.ridx (i); \ | |
355 r.data (nel++) = true; \ | |
356 } \ | |
357 r.cidx (j + 1) = nel; \ | |
358 } \ | |
359 r.maybe_compress (false); \ | |
360 } \ | |
5164 | 361 } \ |
362 return r; \ | |
363 } | |
364 | |
365 #define SPARSE_SSM_BOOL_OPS2(S, M, LHS_ZERO, RHS_ZERO) \ | |
366 SPARSE_SSM_BOOL_OP (mx_el_and, &&, S, M, LHS_ZERO, RHS_ZERO) \ | |
367 SPARSE_SSM_BOOL_OP (mx_el_or, ||, S, M, LHS_ZERO, RHS_ZERO) | |
368 | |
369 #define SPARSE_SSM_BOOL_OPS(S, M, ZERO) \ | |
370 SPARSE_SSM_BOOL_OPS2(S, M, ZERO, ZERO) | |
371 | |
6708 | 372 #define SPARSE_SSM_OP_DECLS(R1, R2, S, M, API) \ |
373 SPARSE_SSM_BIN_OP_DECLS (R1, R2, S, M, API) \ | |
374 SPARSE_SSM_CMP_OP_DECLS (S, M, API) \ | |
375 SPARSE_SSM_BOOL_OP_DECLS (S, M, API) \ | |
5164 | 376 |
377 // matrix by matrix operations. | |
378 | |
6708 | 379 #define SPARSE_SMSM_BIN_OP_DECLS(R1, R2, M1, M2, API) \ |
380 SPARSE_BIN_OP_DECL (R1, operator +, M1, M2, API); \ | |
381 SPARSE_BIN_OP_DECL (R1, operator -, M1, M2, API); \ | |
382 SPARSE_BIN_OP_DECL (R2, product, M1, M2, API); \ | |
383 SPARSE_BIN_OP_DECL (R2, quotient, M1, M2, API); | |
5164 | 384 |
385 #define SPARSE_SMSM_BIN_OP_1(R, F, OP, M1, M2) \ | |
386 R \ | |
387 F (const M1& m1, const M2& m2) \ | |
388 { \ | |
389 R r; \ | |
390 \ | |
5275 | 391 octave_idx_type m1_nr = m1.rows (); \ |
392 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 393 \ |
5275 | 394 octave_idx_type m2_nr = m2.rows (); \ |
395 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 396 \ |
6221 | 397 if (m1_nr == 1 && m1_nc == 1) \ |
398 { \ | |
399 if (m1.elem(0,0) == 0.) \ | |
7342 | 400 r = OP R (m2); \ |
6221 | 401 else \ |
402 { \ | |
403 r = R (m2_nr, m2_nc, m1.data(0) OP 0.); \ | |
404 \ | |
405 for (octave_idx_type j = 0 ; j < m2_nc ; j++) \ | |
406 { \ | |
407 OCTAVE_QUIT; \ | |
408 octave_idx_type idxj = j * m2_nr; \ | |
409 for (octave_idx_type i = m2.cidx(j) ; i < m2.cidx(j+1) ; i++) \ | |
410 { \ | |
411 OCTAVE_QUIT; \ | |
412 r.data(idxj + m2.ridx(i)) = m1.data(0) OP m2.data(i); \ | |
413 } \ | |
414 } \ | |
415 r.maybe_compress (); \ | |
416 } \ | |
417 } \ | |
418 else if (m2_nr == 1 && m2_nc == 1) \ | |
419 { \ | |
420 if (m2.elem(0,0) == 0.) \ | |
421 r = R (m1); \ | |
422 else \ | |
423 { \ | |
424 r = R (m1_nr, m1_nc, 0. OP m2.data(0)); \ | |
425 \ | |
426 for (octave_idx_type j = 0 ; j < m1_nc ; j++) \ | |
427 { \ | |
428 OCTAVE_QUIT; \ | |
429 octave_idx_type idxj = j * m1_nr; \ | |
430 for (octave_idx_type i = m1.cidx(j) ; i < m1.cidx(j+1) ; i++) \ | |
431 { \ | |
432 OCTAVE_QUIT; \ | |
433 r.data(idxj + m1.ridx(i)) = m1.data(i) OP m2.data(0); \ | |
434 } \ | |
435 } \ | |
436 r.maybe_compress (); \ | |
437 } \ | |
438 } \ | |
439 else if (m1_nr != m2_nr || m1_nc != m2_nc) \ | |
5164 | 440 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ |
441 else \ | |
442 { \ | |
5681 | 443 r = R (m1_nr, m1_nc, (m1.nnz () + m2.nnz ())); \ |
5164 | 444 \ |
5275 | 445 octave_idx_type jx = 0; \ |
5164 | 446 r.cidx (0) = 0; \ |
5275 | 447 for (octave_idx_type i = 0 ; i < m1_nc ; i++) \ |
5164 | 448 { \ |
5275 | 449 octave_idx_type ja = m1.cidx(i); \ |
450 octave_idx_type ja_max = m1.cidx(i+1); \ | |
5164 | 451 bool ja_lt_max= ja < ja_max; \ |
452 \ | |
5275 | 453 octave_idx_type jb = m2.cidx(i); \ |
454 octave_idx_type jb_max = m2.cidx(i+1); \ | |
5164 | 455 bool jb_lt_max = jb < jb_max; \ |
456 \ | |
457 while (ja_lt_max || jb_lt_max ) \ | |
458 { \ | |
459 OCTAVE_QUIT; \ | |
460 if ((! jb_lt_max) || \ | |
461 (ja_lt_max && (m1.ridx(ja) < m2.ridx(jb)))) \ | |
462 { \ | |
463 r.ridx(jx) = m1.ridx(ja); \ | |
464 r.data(jx) = m1.data(ja) OP 0.; \ | |
465 jx++; \ | |
466 ja++; \ | |
467 ja_lt_max= ja < ja_max; \ | |
468 } \ | |
469 else if (( !ja_lt_max ) || \ | |
470 (jb_lt_max && (m2.ridx(jb) < m1.ridx(ja)) ) ) \ | |
471 { \ | |
472 r.ridx(jx) = m2.ridx(jb); \ | |
473 r.data(jx) = 0. OP m2.data(jb); \ | |
474 jx++; \ | |
475 jb++; \ | |
476 jb_lt_max= jb < jb_max; \ | |
477 } \ | |
478 else \ | |
479 { \ | |
480 if ((m1.data(ja) OP m2.data(jb)) != 0.) \ | |
481 { \ | |
482 r.data(jx) = m1.data(ja) OP m2.data(jb); \ | |
483 r.ridx(jx) = m1.ridx(ja); \ | |
484 jx++; \ | |
485 } \ | |
486 ja++; \ | |
487 ja_lt_max= ja < ja_max; \ | |
488 jb++; \ | |
489 jb_lt_max= jb < jb_max; \ | |
490 } \ | |
491 } \ | |
492 r.cidx(i+1) = jx; \ | |
493 } \ | |
494 \ | |
495 r.maybe_compress (); \ | |
496 } \ | |
497 \ | |
498 return r; \ | |
499 } | |
500 | |
501 #define SPARSE_SMSM_BIN_OP_2(R, F, OP, M1, M2) \ | |
502 R \ | |
503 F (const M1& m1, const M2& m2) \ | |
504 { \ | |
505 R r; \ | |
506 \ | |
5275 | 507 octave_idx_type m1_nr = m1.rows (); \ |
508 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 509 \ |
5275 | 510 octave_idx_type m2_nr = m2.rows (); \ |
511 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 512 \ |
6221 | 513 if (m1_nr == 1 && m1_nc == 1) \ |
514 { \ | |
515 if (m1.elem(0,0) == 0.) \ | |
516 r = R (m2_nr, m2_nc); \ | |
517 else \ | |
518 { \ | |
519 r = R (m2); \ | |
520 octave_idx_type m2_nnz = m2.nnz(); \ | |
521 \ | |
522 for (octave_idx_type i = 0 ; i < m2_nnz ; i++) \ | |
523 { \ | |
524 OCTAVE_QUIT; \ | |
525 r.data (i) = m1.data(0) OP r.data(i); \ | |
526 } \ | |
527 r.maybe_compress (); \ | |
528 } \ | |
529 } \ | |
530 else if (m2_nr == 1 && m2_nc == 1) \ | |
531 { \ | |
532 if (m2.elem(0,0) == 0.) \ | |
533 r = R (m1_nr, m1_nc); \ | |
534 else \ | |
535 { \ | |
536 r = R (m1); \ | |
537 octave_idx_type m1_nnz = m1.nnz(); \ | |
538 \ | |
539 for (octave_idx_type i = 0 ; i < m1_nnz ; i++) \ | |
540 { \ | |
541 OCTAVE_QUIT; \ | |
542 r.data (i) = r.data(i) OP m2.data(0); \ | |
543 } \ | |
544 r.maybe_compress (); \ | |
545 } \ | |
546 } \ | |
547 else if (m1_nr != m2_nr || m1_nc != m2_nc) \ | |
5164 | 548 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ |
549 else \ | |
550 { \ | |
5681 | 551 r = R (m1_nr, m1_nc, (m1.nnz () > m2.nnz () ? m1.nnz () : m2.nnz ())); \ |
5164 | 552 \ |
5275 | 553 octave_idx_type jx = 0; \ |
5164 | 554 r.cidx (0) = 0; \ |
5275 | 555 for (octave_idx_type i = 0 ; i < m1_nc ; i++) \ |
5164 | 556 { \ |
5275 | 557 octave_idx_type ja = m1.cidx(i); \ |
558 octave_idx_type ja_max = m1.cidx(i+1); \ | |
5164 | 559 bool ja_lt_max= ja < ja_max; \ |
560 \ | |
5275 | 561 octave_idx_type jb = m2.cidx(i); \ |
562 octave_idx_type jb_max = m2.cidx(i+1); \ | |
5164 | 563 bool jb_lt_max = jb < jb_max; \ |
564 \ | |
565 while (ja_lt_max || jb_lt_max ) \ | |
566 { \ | |
567 OCTAVE_QUIT; \ | |
568 if ((! jb_lt_max) || \ | |
569 (ja_lt_max && (m1.ridx(ja) < m2.ridx(jb)))) \ | |
570 { \ | |
571 ja++; ja_lt_max= ja < ja_max; \ | |
572 } \ | |
573 else if (( !ja_lt_max ) || \ | |
574 (jb_lt_max && (m2.ridx(jb) < m1.ridx(ja)) ) ) \ | |
575 { \ | |
576 jb++; jb_lt_max= jb < jb_max; \ | |
577 } \ | |
578 else \ | |
579 { \ | |
580 if ((m1.data(ja) OP m2.data(jb)) != 0.) \ | |
581 { \ | |
582 r.data(jx) = m1.data(ja) OP m2.data(jb); \ | |
583 r.ridx(jx) = m1.ridx(ja); \ | |
584 jx++; \ | |
585 } \ | |
586 ja++; ja_lt_max= ja < ja_max; \ | |
587 jb++; jb_lt_max= jb < jb_max; \ | |
588 } \ | |
589 } \ | |
590 r.cidx(i+1) = jx; \ | |
591 } \ | |
592 \ | |
593 r.maybe_compress (); \ | |
594 } \ | |
595 \ | |
596 return r; \ | |
597 } | |
598 | |
599 #define SPARSE_SMSM_BIN_OP_3(R, F, OP, M1, M2) \ | |
600 R \ | |
601 F (const M1& m1, const M2& m2) \ | |
602 { \ | |
603 R r; \ | |
604 \ | |
5275 | 605 octave_idx_type m1_nr = m1.rows (); \ |
606 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 607 \ |
5275 | 608 octave_idx_type m2_nr = m2.rows (); \ |
609 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 610 \ |
6221 | 611 if (m1_nr == 1 && m1_nc == 1) \ |
612 { \ | |
613 if ((m1.elem (0,0) OP Complex()) == Complex()) \ | |
614 { \ | |
615 octave_idx_type m2_nnz = m2.nnz(); \ | |
616 r = R (m2); \ | |
617 for (octave_idx_type i = 0 ; i < m2_nnz ; i++) \ | |
618 r.data (i) = m1.elem(0,0) OP r.data(i); \ | |
619 r.maybe_compress (); \ | |
620 } \ | |
621 else \ | |
622 { \ | |
623 r = R (m2_nr, m2_nc, m1.elem(0,0) OP Complex ()); \ | |
624 for (octave_idx_type j = 0 ; j < m2_nc ; j++) \ | |
625 { \ | |
626 OCTAVE_QUIT; \ | |
627 octave_idx_type idxj = j * m2_nr; \ | |
628 for (octave_idx_type i = m2.cidx(j) ; i < m2.cidx(j+1) ; i++) \ | |
629 { \ | |
630 OCTAVE_QUIT; \ | |
631 r.data(idxj + m2.ridx(i)) = m1.elem(0,0) OP m2.data(i); \ | |
632 } \ | |
633 } \ | |
634 r.maybe_compress (); \ | |
635 } \ | |
636 } \ | |
637 else if (m2_nr == 1 && m2_nc == 1) \ | |
638 { \ | |
639 if ((Complex() OP m1.elem (0,0)) == Complex()) \ | |
640 { \ | |
641 octave_idx_type m1_nnz = m1.nnz(); \ | |
642 r = R (m1); \ | |
643 for (octave_idx_type i = 0 ; i < m1_nnz ; i++) \ | |
644 r.data (i) = r.data(i) OP m2.elem(0,0); \ | |
645 r.maybe_compress (); \ | |
646 } \ | |
647 else \ | |
648 { \ | |
649 r = R (m1_nr, m1_nc, Complex() OP m2.elem(0,0)); \ | |
650 for (octave_idx_type j = 0 ; j < m1_nc ; j++) \ | |
651 { \ | |
652 OCTAVE_QUIT; \ | |
653 octave_idx_type idxj = j * m1_nr; \ | |
654 for (octave_idx_type i = m1.cidx(j) ; i < m1.cidx(j+1) ; i++) \ | |
655 { \ | |
656 OCTAVE_QUIT; \ | |
657 r.data(idxj + m1.ridx(i)) = m1.data(i) OP m2.elem(0,0); \ | |
658 } \ | |
659 } \ | |
660 r.maybe_compress (); \ | |
661 } \ | |
662 } \ | |
663 else if (m1_nr != m2_nr || m1_nc != m2_nc) \ | |
5164 | 664 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ |
665 else \ | |
666 { \ | |
667 \ | |
5775 | 668 /* FIXME Kludge... Always double/Complex, so Complex () */ \ |
5164 | 669 r = R (m1_nr, m1_nc, (Complex () OP Complex ())); \ |
670 \ | |
5275 | 671 for (octave_idx_type i = 0 ; i < m1_nc ; i++) \ |
5164 | 672 { \ |
5275 | 673 octave_idx_type ja = m1.cidx(i); \ |
674 octave_idx_type ja_max = m1.cidx(i+1); \ | |
5164 | 675 bool ja_lt_max= ja < ja_max; \ |
676 \ | |
5275 | 677 octave_idx_type jb = m2.cidx(i); \ |
678 octave_idx_type jb_max = m2.cidx(i+1); \ | |
5164 | 679 bool jb_lt_max = jb < jb_max; \ |
680 \ | |
681 while (ja_lt_max || jb_lt_max ) \ | |
682 { \ | |
683 OCTAVE_QUIT; \ | |
684 if ((! jb_lt_max) || \ | |
685 (ja_lt_max && (m1.ridx(ja) < m2.ridx(jb)))) \ | |
686 { \ | |
687 /* keep those kludges coming */ \ | |
688 r.elem(m1.ridx(ja),i) = m1.data(ja) OP Complex (); \ | |
689 ja++; \ | |
690 ja_lt_max= ja < ja_max; \ | |
691 } \ | |
692 else if (( !ja_lt_max ) || \ | |
693 (jb_lt_max && (m2.ridx(jb) < m1.ridx(ja)) ) ) \ | |
694 { \ | |
695 /* keep those kludges coming */ \ | |
696 r.elem(m2.ridx(jb),i) = Complex () OP m2.data(jb); \ | |
697 jb++; \ | |
698 jb_lt_max= jb < jb_max; \ | |
699 } \ | |
700 else \ | |
701 { \ | |
702 r.elem(m1.ridx(ja),i) = m1.data(ja) OP m2.data(jb); \ | |
703 ja++; \ | |
704 ja_lt_max= ja < ja_max; \ | |
705 jb++; \ | |
706 jb_lt_max= jb < jb_max; \ | |
707 } \ | |
708 } \ | |
709 } \ | |
710 r.maybe_compress (true); \ | |
711 } \ | |
712 \ | |
713 return r; \ | |
714 } | |
715 | |
716 // Note that SM ./ SM needs to take into account the NaN and Inf values | |
717 // implied by the division by zero. | |
5775 | 718 // FIXME Are the NaNs double(NaN) or Complex(NaN,Nan) in the complex |
5164 | 719 // case? |
720 #define SPARSE_SMSM_BIN_OPS(R1, R2, M1, M2) \ | |
721 SPARSE_SMSM_BIN_OP_1 (R1, operator +, +, M1, M2) \ | |
722 SPARSE_SMSM_BIN_OP_1 (R1, operator -, -, M1, M2) \ | |
723 SPARSE_SMSM_BIN_OP_2 (R2, product, *, M1, M2) \ | |
724 SPARSE_SMSM_BIN_OP_3 (R2, quotient, /, M1, M2) | |
725 | |
6708 | 726 #define SPARSE_SMSM_CMP_OP_DECLS(M1, M2, API) \ |
727 SPARSE_CMP_OP_DECL (mx_el_lt, M1, M2, API); \ | |
728 SPARSE_CMP_OP_DECL (mx_el_le, M1, M2, API); \ | |
729 SPARSE_CMP_OP_DECL (mx_el_ge, M1, M2, API); \ | |
730 SPARSE_CMP_OP_DECL (mx_el_gt, M1, M2, API); \ | |
731 SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \ | |
732 SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API); | |
5164 | 733 |
6708 | 734 #define SPARSE_SMSM_EQNE_OP_DECLS(M1, M2, API) \ |
735 SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \ | |
736 SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API); | |
5164 | 737 |
7269 | 738 #define SPARSE_SMSM_CMP_OP(F, OP, M1, Z1, C1, M2, Z2, C2) \ |
5164 | 739 SparseBoolMatrix \ |
740 F (const M1& m1, const M2& m2) \ | |
741 { \ | |
742 SparseBoolMatrix r; \ | |
743 \ | |
5275 | 744 octave_idx_type m1_nr = m1.rows (); \ |
745 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 746 \ |
5275 | 747 octave_idx_type m2_nr = m2.rows (); \ |
748 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 749 \ |
6221 | 750 if (m1_nr == 1 && m1_nc == 1) \ |
751 { \ | |
8181
1ebcb9872ced
fix sparse-matrix bool/cmp op instantiation problem
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
752 r = F (m1.elem(0,0) != M1::elt_type (), m2); \ |
6221 | 753 } \ |
754 else if (m2_nr == 1 && m2_nc == 1) \ | |
755 { \ | |
8181
1ebcb9872ced
fix sparse-matrix bool/cmp op instantiation problem
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
756 r = F (m1, m2.elem(0,0) != M2::elt_type ()); \ |
6221 | 757 } \ |
758 else if (m1_nr == m2_nr && m1_nc == m2_nc) \ | |
5164 | 759 { \ |
760 if (m1_nr != 0 || m1_nc != 0) \ | |
761 { \ | |
7269 | 762 if (C1 (Z1) OP C2 (Z2)) \ |
5164 | 763 { \ |
7269 | 764 r = SparseBoolMatrix (m1_nr, m1_nc, true); \ |
765 for (octave_idx_type j = 0; j < m1_nc; j++) \ | |
766 { \ | |
767 octave_idx_type i1 = m1.cidx (j); \ | |
768 octave_idx_type e1 = m1.cidx (j+1); \ | |
769 octave_idx_type i2 = m2.cidx (j); \ | |
770 octave_idx_type e2 = m2.cidx (j+1); \ | |
771 while (i1 < e1 || i2 < e2) \ | |
772 { \ | |
773 if (i1 == e1 || (i2 < e2 && m1.ridx(i1) > m2.ridx(i2))) \ | |
774 { \ | |
775 if (! (C1 (Z1) OP C2 (m2.data (i2)))) \ | |
776 r.data (m2.ridx (i2) + j * m1_nr) = false; \ | |
777 i2++; \ | |
778 } \ | |
779 else if (i2 == e2 || m1.ridx(i1) < m2.ridx(i2)) \ | |
780 { \ | |
781 if (! (C1 (m1.data (i1)) OP C2 (Z2))) \ | |
782 r.data (m1.ridx (i1) + j * m1_nr) = false; \ | |
783 i1++; \ | |
784 } \ | |
785 else \ | |
786 { \ | |
787 if (! (C1 (m1.data (i1)) OP C2 (m2.data (i2)))) \ | |
788 r.data (m1.ridx (i1) + j * m1_nr) = false; \ | |
789 i1++; \ | |
790 i2++; \ | |
791 } \ | |
792 } \ | |
793 } \ | |
794 r.maybe_compress (true); \ | |
795 } \ | |
796 else \ | |
797 { \ | |
798 r = SparseBoolMatrix (m1_nr, m1_nc, m1.nnz () + m2.nnz ()); \ | |
799 r.cidx (0) = static_cast<octave_idx_type> (0); \ | |
800 octave_idx_type nel = 0; \ | |
801 for (octave_idx_type j = 0; j < m1_nc; j++) \ | |
802 { \ | |
803 octave_idx_type i1 = m1.cidx (j); \ | |
804 octave_idx_type e1 = m1.cidx (j+1); \ | |
805 octave_idx_type i2 = m2.cidx (j); \ | |
806 octave_idx_type e2 = m2.cidx (j+1); \ | |
807 while (i1 < e1 || i2 < e2) \ | |
808 { \ | |
809 if (i1 == e1 || (i2 < e2 && m1.ridx(i1) > m2.ridx(i2))) \ | |
810 { \ | |
811 if (C1 (Z1) OP C2 (m2.data (i2))) \ | |
812 { \ | |
813 r.ridx (nel) = m2.ridx (i2); \ | |
814 r.data (nel++) = true; \ | |
815 } \ | |
816 i2++; \ | |
817 } \ | |
818 else if (i2 == e2 || m1.ridx(i1) < m2.ridx(i2)) \ | |
819 { \ | |
820 if (C1 (m1.data (i1)) OP C2 (Z2)) \ | |
821 { \ | |
822 r.ridx (nel) = m1.ridx (i1); \ | |
823 r.data (nel++) = true; \ | |
824 } \ | |
825 i1++; \ | |
826 } \ | |
827 else \ | |
828 { \ | |
829 if (C1 (m1.data (i1)) OP C2 (m2.data (i2))) \ | |
830 { \ | |
831 r.ridx (nel) = m1.ridx (i1); \ | |
832 r.data (nel++) = true; \ | |
833 } \ | |
834 i1++; \ | |
835 i2++; \ | |
836 } \ | |
837 } \ | |
838 r.cidx (j + 1) = nel; \ | |
839 } \ | |
840 r.maybe_compress (false); \ | |
841 } \ | |
5164 | 842 } \ |
843 } \ | |
844 else \ | |
845 { \ | |
846 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ | |
847 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ | |
848 } \ | |
849 return r; \ | |
850 } | |
851 | |
852 #define SPARSE_SMSM_CMP_OPS(M1, Z1, C1, M2, Z2, C2) \ | |
7269 | 853 SPARSE_SMSM_CMP_OP (mx_el_lt, <, M1, Z1, C1, M2, Z2, C2) \ |
854 SPARSE_SMSM_CMP_OP (mx_el_le, <=, M1, Z1, C1, M2, Z2, C2) \ | |
855 SPARSE_SMSM_CMP_OP (mx_el_ge, >=, M1, Z1, C1, M2, Z2, C2) \ | |
856 SPARSE_SMSM_CMP_OP (mx_el_gt, >, M1, Z1, C1, M2, Z2, C2) \ | |
857 SPARSE_SMSM_CMP_OP (mx_el_eq, ==, M1, Z1, , M2, Z2, ) \ | |
858 SPARSE_SMSM_CMP_OP (mx_el_ne, !=, M1, Z1, , M2, Z2, ) | |
5164 | 859 |
860 #define SPARSE_SMSM_EQNE_OPS(M1, Z1, C1, M2, Z2, C2) \ | |
7269 | 861 SPARSE_SMSM_CMP_OP (mx_el_eq, ==, M1, Z1, , M2, Z2, ) \ |
862 SPARSE_SMSM_CMP_OP (mx_el_ne, !=, M1, Z1, , M2, Z2, ) | |
5164 | 863 |
6708 | 864 #define SPARSE_SMSM_BOOL_OP_DECLS(M1, M2, API) \ |
865 SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2, API); \ | |
866 SPARSE_BOOL_OP_DECL (mx_el_or, M1, M2, API); | |
5164 | 867 |
868 #define SPARSE_SMSM_BOOL_OP(F, OP, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
869 SparseBoolMatrix \ | |
870 F (const M1& m1, const M2& m2) \ | |
871 { \ | |
872 SparseBoolMatrix r; \ | |
873 \ | |
5275 | 874 octave_idx_type m1_nr = m1.rows (); \ |
875 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 876 \ |
5275 | 877 octave_idx_type m2_nr = m2.rows (); \ |
878 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 879 \ |
6221 | 880 if (m1_nr == 1 && m1_nc == 1) \ |
881 { \ | |
8181
1ebcb9872ced
fix sparse-matrix bool/cmp op instantiation problem
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
882 r = F (m1.elem(0,0) != M1::elt_type (), m2); \ |
6221 | 883 } \ |
884 else if (m2_nr == 1 && m2_nc == 1) \ | |
885 { \ | |
8181
1ebcb9872ced
fix sparse-matrix bool/cmp op instantiation problem
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
886 r = F (m1, m2.elem(0,0) != M2::elt_type ()); \ |
6221 | 887 } \ |
888 else if (m1_nr == m2_nr && m1_nc == m2_nc) \ | |
5164 | 889 { \ |
890 if (m1_nr != 0 || m1_nc != 0) \ | |
891 { \ | |
7269 | 892 r = SparseBoolMatrix (m1_nr, m1_nc, m1.nnz () + m2.nnz ()); \ |
893 r.cidx (0) = static_cast<octave_idx_type> (0); \ | |
894 octave_idx_type nel = 0; \ | |
5275 | 895 for (octave_idx_type j = 0; j < m1_nc; j++) \ |
7269 | 896 { \ |
897 octave_idx_type i1 = m1.cidx (j); \ | |
898 octave_idx_type e1 = m1.cidx (j+1); \ | |
899 octave_idx_type i2 = m2.cidx (j); \ | |
900 octave_idx_type e2 = m2.cidx (j+1); \ | |
901 while (i1 < e1 || i2 < e2) \ | |
902 { \ | |
903 if (i1 == e1 || (i2 < e2 && m1.ridx(i1) > m2.ridx(i2))) \ | |
904 { \ | |
905 if (LHS_ZERO OP m2.data (i2) != RHS_ZERO) \ | |
906 { \ | |
907 r.ridx (nel) = m2.ridx (i2); \ | |
908 r.data (nel++) = true; \ | |
909 } \ | |
910 i2++; \ | |
911 } \ | |
912 else if (i2 == e2 || m1.ridx(i1) < m2.ridx(i2)) \ | |
913 { \ | |
914 if (m1.data (i1) != LHS_ZERO OP RHS_ZERO) \ | |
915 { \ | |
916 r.ridx (nel) = m1.ridx (i1); \ | |
917 r.data (nel++) = true; \ | |
918 } \ | |
919 i1++; \ | |
920 } \ | |
921 else \ | |
922 { \ | |
923 if (m1.data (i1) != LHS_ZERO OP m2.data(i2) != RHS_ZERO) \ | |
924 { \ | |
925 r.ridx (nel) = m1.ridx (i1); \ | |
926 r.data (nel++) = true; \ | |
927 } \ | |
928 i1++; \ | |
929 i2++; \ | |
930 } \ | |
931 } \ | |
932 r.cidx (j + 1) = nel; \ | |
933 } \ | |
934 r.maybe_compress (false); \ | |
5164 | 935 } \ |
936 } \ | |
937 else \ | |
938 { \ | |
939 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ | |
940 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ | |
941 } \ | |
942 return r; \ | |
943 } | |
944 | |
945 #define SPARSE_SMSM_BOOL_OPS2(M1, M2, LHS_ZERO, RHS_ZERO) \ | |
946 SPARSE_SMSM_BOOL_OP (mx_el_and, &&, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
947 SPARSE_SMSM_BOOL_OP (mx_el_or, ||, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
948 | |
949 #define SPARSE_SMSM_BOOL_OPS(M1, M2, ZERO) \ | |
950 SPARSE_SMSM_BOOL_OPS2(M1, M2, ZERO, ZERO) | |
951 | |
6708 | 952 #define SPARSE_SMSM_OP_DECLS(R1, R2, M1, M2, API) \ |
953 SPARSE_SMSM_BIN_OP_DECLS (R1, R2, M1, M2, API) \ | |
954 SPARSE_SMSM_CMP_OP_DECLS (M1, M2, API) \ | |
955 SPARSE_SMSM_BOOL_OP_DECLS (M1, M2, API) | |
5164 | 956 |
957 // matrix by matrix operations. | |
958 | |
6708 | 959 #define SPARSE_MSM_BIN_OP_DECLS(R1, R2, M1, M2, API) \ |
960 SPARSE_BIN_OP_DECL (R1, operator +, M1, M2, API); \ | |
961 SPARSE_BIN_OP_DECL (R1, operator -, M1, M2, API); \ | |
962 SPARSE_BIN_OP_DECL (R2, product, M1, M2, API); \ | |
963 SPARSE_BIN_OP_DECL (R2, quotient, M1, M2, API); | |
5164 | 964 |
965 #define SPARSE_MSM_BIN_OP_1(R, F, OP, M1, M2) \ | |
966 R \ | |
967 F (const M1& m1, const M2& m2) \ | |
968 { \ | |
969 R r; \ | |
970 \ | |
5275 | 971 octave_idx_type m1_nr = m1.rows (); \ |
972 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 973 \ |
5275 | 974 octave_idx_type m2_nr = m2.rows (); \ |
975 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 976 \ |
6221 | 977 if (m2_nr == 1 && m2_nc == 1) \ |
978 r = R (m1 OP m2.elem(0,0)); \ | |
979 else if (m1_nr != m2_nr || m1_nc != m2_nc) \ | |
5164 | 980 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ |
981 else \ | |
982 { \ | |
983 r = R (m1_nr, m1_nc); \ | |
984 \ | |
5275 | 985 for (octave_idx_type j = 0; j < m1_nc; j++) \ |
986 for (octave_idx_type i = 0; i < m1_nr; i++) \ | |
5164 | 987 r.elem (i, j) = m1.elem (i, j) OP m2.elem (i, j); \ |
988 } \ | |
989 return r; \ | |
990 } | |
991 | |
992 #define SPARSE_MSM_BIN_OP_2(R, F, OP, M1, M2, ZERO) \ | |
993 R \ | |
994 F (const M1& m1, const M2& m2) \ | |
995 { \ | |
996 R r; \ | |
997 \ | |
5275 | 998 octave_idx_type m1_nr = m1.rows (); \ |
999 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 1000 \ |
5275 | 1001 octave_idx_type m2_nr = m2.rows (); \ |
1002 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 1003 \ |
6221 | 1004 if (m2_nr == 1 && m2_nc == 1) \ |
1005 r = R (m1 OP m2.elem(0,0)); \ | |
1006 else if (m1_nr != m2_nr || m1_nc != m2_nc) \ | |
5164 | 1007 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ |
1008 else \ | |
1009 { \ | |
1010 /* Count num of non-zero elements */ \ | |
5275 | 1011 octave_idx_type nel = 0; \ |
1012 for (octave_idx_type j = 0; j < m1_nc; j++) \ | |
1013 for (octave_idx_type i = 0; i < m1_nr; i++) \ | |
5164 | 1014 if ((m1.elem(i, j) OP m2.elem(i, j)) != ZERO) \ |
1015 nel++; \ | |
1016 \ | |
1017 r = R (m1_nr, m1_nc, nel); \ | |
1018 \ | |
5275 | 1019 octave_idx_type ii = 0; \ |
5164 | 1020 r.cidx (0) = 0; \ |
5275 | 1021 for (octave_idx_type j = 0 ; j < m1_nc ; j++) \ |
5164 | 1022 { \ |
5275 | 1023 for (octave_idx_type i = 0 ; i < m1_nr ; i++) \ |
5164 | 1024 { \ |
1025 if ((m1.elem(i, j) OP m2.elem(i, j)) != ZERO) \ | |
1026 { \ | |
1027 r.data (ii) = m1.elem(i, j) OP m2.elem(i,j); \ | |
1028 r.ridx (ii++) = i; \ | |
1029 } \ | |
1030 } \ | |
1031 r.cidx(j+1) = ii; \ | |
1032 } \ | |
1033 } \ | |
1034 \ | |
1035 return r; \ | |
1036 } | |
1037 | |
5775 | 1038 // FIXME Pass a specific ZERO value |
5164 | 1039 #define SPARSE_MSM_BIN_OPS(R1, R2, M1, M2) \ |
1040 SPARSE_MSM_BIN_OP_1 (R1, operator +, +, M1, M2) \ | |
1041 SPARSE_MSM_BIN_OP_1 (R1, operator -, -, M1, M2) \ | |
1042 SPARSE_MSM_BIN_OP_2 (R2, product, *, M1, M2, 0.0) \ | |
1043 SPARSE_MSM_BIN_OP_2 (R2, quotient, /, M1, M2, 0.0) | |
1044 | |
6708 | 1045 #define SPARSE_MSM_CMP_OP_DECLS(M1, M2, API) \ |
1046 SPARSE_CMP_OP_DECL (mx_el_lt, M1, M2, API); \ | |
1047 SPARSE_CMP_OP_DECL (mx_el_le, M1, M2, API); \ | |
1048 SPARSE_CMP_OP_DECL (mx_el_ge, M1, M2, API); \ | |
1049 SPARSE_CMP_OP_DECL (mx_el_gt, M1, M2, API); \ | |
1050 SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \ | |
1051 SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API); | |
5164 | 1052 |
6708 | 1053 #define SPARSE_MSM_EQNE_OP_DECLS(M1, M2, API) \ |
1054 SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \ | |
1055 SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API); | |
5164 | 1056 |
1057 #define SPARSE_MSM_CMP_OP(F, OP, M1, C1, M2, C2) \ | |
1058 SparseBoolMatrix \ | |
1059 F (const M1& m1, const M2& m2) \ | |
1060 { \ | |
1061 SparseBoolMatrix r; \ | |
1062 \ | |
5275 | 1063 octave_idx_type m1_nr = m1.rows (); \ |
1064 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 1065 \ |
5275 | 1066 octave_idx_type m2_nr = m2.rows (); \ |
1067 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 1068 \ |
6221 | 1069 if (m2_nr == 1 && m2_nc == 1) \ |
1070 r = SparseBoolMatrix (F (m1, m2.elem(0,0))); \ | |
1071 else if (m1_nr == m2_nr && m1_nc == m2_nc) \ | |
5164 | 1072 { \ |
1073 if (m1_nr != 0 || m1_nc != 0) \ | |
1074 { \ | |
1075 /* Count num of non-zero elements */ \ | |
5275 | 1076 octave_idx_type nel = 0; \ |
1077 for (octave_idx_type j = 0; j < m1_nc; j++) \ | |
1078 for (octave_idx_type i = 0; i < m1_nr; i++) \ | |
5164 | 1079 if (C1 (m1.elem(i, j)) OP C2 (m2.elem(i, j))) \ |
1080 nel++; \ | |
1081 \ | |
1082 r = SparseBoolMatrix (m1_nr, m1_nc, nel); \ | |
1083 \ | |
5275 | 1084 octave_idx_type ii = 0; \ |
5164 | 1085 r.cidx (0) = 0; \ |
5275 | 1086 for (octave_idx_type j = 0; j < m1_nc; j++) \ |
5164 | 1087 { \ |
5275 | 1088 for (octave_idx_type i = 0; i < m1_nr; i++) \ |
5164 | 1089 { \ |
1090 bool el = C1 (m1.elem(i, j)) OP C2 (m2.elem(i, j)); \ | |
1091 if (el) \ | |
1092 { \ | |
1093 r.data(ii) = el; \ | |
1094 r.ridx(ii++) = i; \ | |
1095 } \ | |
1096 } \ | |
1097 r.cidx(j+1) = ii; \ | |
1098 } \ | |
1099 } \ | |
1100 } \ | |
1101 else \ | |
1102 { \ | |
1103 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ | |
1104 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ | |
1105 } \ | |
1106 return r; \ | |
1107 } | |
1108 | |
1109 #define SPARSE_MSM_CMP_OPS(M1, Z1, C1, M2, Z2, C2) \ | |
1110 SPARSE_MSM_CMP_OP (mx_el_lt, <, M1, C1, M2, C2) \ | |
1111 SPARSE_MSM_CMP_OP (mx_el_le, <=, M1, C1, M2, C2) \ | |
1112 SPARSE_MSM_CMP_OP (mx_el_ge, >=, M1, C1, M2, C2) \ | |
1113 SPARSE_MSM_CMP_OP (mx_el_gt, >, M1, C1, M2, C2) \ | |
1114 SPARSE_MSM_CMP_OP (mx_el_eq, ==, M1, , M2, ) \ | |
1115 SPARSE_MSM_CMP_OP (mx_el_ne, !=, M1, , M2, ) | |
1116 | |
1117 #define SPARSE_MSM_EQNE_OPS(M1, Z1, C1, M2, Z2, C2) \ | |
1118 SPARSE_MSM_CMP_OP (mx_el_eq, ==, M1, , M2, ) \ | |
1119 SPARSE_MSM_CMP_OP (mx_el_ne, !=, M1, , M2, ) | |
1120 | |
6708 | 1121 #define SPARSE_MSM_BOOL_OP_DECLS(M1, M2, API) \ |
1122 SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2, API); \ | |
1123 SPARSE_BOOL_OP_DECL (mx_el_or, M1, M2, API); | |
5164 | 1124 |
1125 #define SPARSE_MSM_BOOL_OP(F, OP, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
1126 SparseBoolMatrix \ | |
1127 F (const M1& m1, const M2& m2) \ | |
1128 { \ | |
1129 SparseBoolMatrix r; \ | |
1130 \ | |
5275 | 1131 octave_idx_type m1_nr = m1.rows (); \ |
1132 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 1133 \ |
5275 | 1134 octave_idx_type m2_nr = m2.rows (); \ |
1135 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 1136 \ |
6221 | 1137 if (m2_nr == 1 && m2_nc == 1) \ |
1138 r = SparseBoolMatrix (F (m1, m2.elem(0,0))); \ | |
1139 else if (m1_nr == m2_nr && m1_nc == m2_nc) \ | |
5164 | 1140 { \ |
1141 if (m1_nr != 0 || m1_nc != 0) \ | |
1142 { \ | |
1143 /* Count num of non-zero elements */ \ | |
5275 | 1144 octave_idx_type nel = 0; \ |
1145 for (octave_idx_type j = 0; j < m1_nc; j++) \ | |
1146 for (octave_idx_type i = 0; i < m1_nr; i++) \ | |
5164 | 1147 if ((m1.elem(i, j) != LHS_ZERO) \ |
1148 OP (m2.elem(i, j) != RHS_ZERO)) \ | |
1149 nel++; \ | |
1150 \ | |
1151 r = SparseBoolMatrix (m1_nr, m1_nc, nel); \ | |
1152 \ | |
5275 | 1153 octave_idx_type ii = 0; \ |
5164 | 1154 r.cidx (0) = 0; \ |
5275 | 1155 for (octave_idx_type j = 0; j < m1_nc; j++) \ |
5164 | 1156 { \ |
5275 | 1157 for (octave_idx_type i = 0; i < m1_nr; i++) \ |
5164 | 1158 { \ |
1159 bool el = (m1.elem(i, j) != LHS_ZERO) \ | |
1160 OP (m2.elem(i, j) != RHS_ZERO); \ | |
1161 if (el) \ | |
1162 { \ | |
1163 r.data(ii) = el; \ | |
1164 r.ridx(ii++) = i; \ | |
1165 } \ | |
1166 } \ | |
1167 r.cidx(j+1) = ii; \ | |
1168 } \ | |
1169 } \ | |
1170 } \ | |
1171 else \ | |
1172 { \ | |
1173 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ | |
1174 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ | |
1175 } \ | |
1176 return r; \ | |
1177 } | |
1178 | |
1179 #define SPARSE_MSM_BOOL_OPS2(M1, M2, LHS_ZERO, RHS_ZERO) \ | |
1180 SPARSE_MSM_BOOL_OP (mx_el_and, &&, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
1181 SPARSE_MSM_BOOL_OP (mx_el_or, ||, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
1182 | |
1183 #define SPARSE_MSM_BOOL_OPS(M1, M2, ZERO) \ | |
1184 SPARSE_MSM_BOOL_OPS2(M1, M2, ZERO, ZERO) | |
1185 | |
6708 | 1186 #define SPARSE_MSM_OP_DECLS(R1, R2, M1, M2, API) \ |
1187 SPARSE_MSM_BIN_OP_DECLS (R1, R2, M1, M2, API) \ | |
1188 SPARSE_MSM_CMP_OP_DECLS (M1, M2, API) \ | |
1189 SPARSE_MSM_BOOL_OP_DECLS (M1, M2, API) | |
5164 | 1190 |
1191 // matrix by matrix operations. | |
1192 | |
6708 | 1193 #define SPARSE_SMM_BIN_OP_DECLS(R1, R2, M1, M2, API) \ |
1194 SPARSE_BIN_OP_DECL (R1, operator +, M1, M2, API); \ | |
1195 SPARSE_BIN_OP_DECL (R1, operator -, M1, M2, API); \ | |
1196 SPARSE_BIN_OP_DECL (R2, product, M1, M2, API); \ | |
1197 SPARSE_BIN_OP_DECL (R2, quotient, M1, M2, API); | |
5164 | 1198 |
1199 #define SPARSE_SMM_BIN_OP_1(R, F, OP, M1, M2) \ | |
1200 R \ | |
1201 F (const M1& m1, const M2& m2) \ | |
1202 { \ | |
1203 R r; \ | |
1204 \ | |
5275 | 1205 octave_idx_type m1_nr = m1.rows (); \ |
1206 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 1207 \ |
5275 | 1208 octave_idx_type m2_nr = m2.rows (); \ |
1209 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 1210 \ |
6221 | 1211 if (m1_nr == 1 && m1_nc == 1) \ |
1212 r = R (m1.elem(0,0) OP m2); \ | |
1213 else if (m1_nr != m2_nr || m1_nc != m2_nc) \ | |
5164 | 1214 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ |
1215 else \ | |
1216 { \ | |
1217 r = R (m1_nr, m1_nc); \ | |
1218 \ | |
5275 | 1219 for (octave_idx_type j = 0; j < m1_nc; j++) \ |
1220 for (octave_idx_type i = 0; i < m1_nr; i++) \ | |
5164 | 1221 r.elem (i, j) = m1.elem (i, j) OP m2.elem (i, j); \ |
1222 } \ | |
1223 return r; \ | |
1224 } | |
1225 | |
1226 #define SPARSE_SMM_BIN_OP_2(R, F, OP, M1, M2, ZERO) \ | |
1227 R \ | |
1228 F (const M1& m1, const M2& m2) \ | |
1229 { \ | |
1230 R r; \ | |
1231 \ | |
5275 | 1232 octave_idx_type m1_nr = m1.rows (); \ |
1233 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 1234 \ |
5275 | 1235 octave_idx_type m2_nr = m2.rows (); \ |
1236 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 1237 \ |
6221 | 1238 if (m1_nr == 1 && m1_nc == 1) \ |
1239 r = R (m1.elem(0,0) OP m2); \ | |
1240 else if (m1_nr != m2_nr || m1_nc != m2_nc) \ | |
5164 | 1241 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ |
1242 else \ | |
1243 { \ | |
1244 /* Count num of non-zero elements */ \ | |
5275 | 1245 octave_idx_type nel = 0; \ |
1246 for (octave_idx_type j = 0; j < m1_nc; j++) \ | |
1247 for (octave_idx_type i = 0; i < m1_nr; i++) \ | |
5164 | 1248 if ((m1.elem(i, j) OP m2.elem(i, j)) != ZERO) \ |
1249 nel++; \ | |
1250 \ | |
1251 r = R (m1_nr, m1_nc, nel); \ | |
1252 \ | |
5275 | 1253 octave_idx_type ii = 0; \ |
5164 | 1254 r.cidx (0) = 0; \ |
5275 | 1255 for (octave_idx_type j = 0 ; j < m1_nc ; j++) \ |
5164 | 1256 { \ |
5275 | 1257 for (octave_idx_type i = 0 ; i < m1_nr ; i++) \ |
5164 | 1258 { \ |
1259 if ((m1.elem(i, j) OP m2.elem(i, j)) != ZERO) \ | |
1260 { \ | |
1261 r.data (ii) = m1.elem(i, j) OP m2.elem(i,j); \ | |
1262 r.ridx (ii++) = i; \ | |
1263 } \ | |
1264 } \ | |
1265 r.cidx(j+1) = ii; \ | |
1266 } \ | |
1267 } \ | |
1268 \ | |
1269 return r; \ | |
1270 } | |
1271 | |
5775 | 1272 // FIXME Pass a specific ZERO value |
5164 | 1273 #define SPARSE_SMM_BIN_OPS(R1, R2, M1, M2) \ |
1274 SPARSE_SMM_BIN_OP_1 (R1, operator +, +, M1, M2) \ | |
1275 SPARSE_SMM_BIN_OP_1 (R1, operator -, -, M1, M2) \ | |
1276 SPARSE_SMM_BIN_OP_2 (R2, product, *, M1, M2, 0.0) \ | |
1277 SPARSE_SMM_BIN_OP_2 (R2, quotient, /, M1, M2, 0.0) | |
1278 | |
6708 | 1279 #define SPARSE_SMM_CMP_OP_DECLS(M1, M2, API) \ |
1280 SPARSE_CMP_OP_DECL (mx_el_lt, M1, M2, API); \ | |
1281 SPARSE_CMP_OP_DECL (mx_el_le, M1, M2, API); \ | |
1282 SPARSE_CMP_OP_DECL (mx_el_ge, M1, M2, API); \ | |
1283 SPARSE_CMP_OP_DECL (mx_el_gt, M1, M2, API); \ | |
1284 SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \ | |
1285 SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API); | |
5164 | 1286 |
6708 | 1287 #define SPARSE_SMM_EQNE_OP_DECLS(M1, M2, API) \ |
1288 SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \ | |
1289 SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API); | |
5164 | 1290 |
1291 #define SPARSE_SMM_CMP_OP(F, OP, M1, C1, M2, C2) \ | |
1292 SparseBoolMatrix \ | |
1293 F (const M1& m1, const M2& m2) \ | |
1294 { \ | |
1295 SparseBoolMatrix r; \ | |
1296 \ | |
5275 | 1297 octave_idx_type m1_nr = m1.rows (); \ |
1298 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 1299 \ |
5275 | 1300 octave_idx_type m2_nr = m2.rows (); \ |
1301 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 1302 \ |
6221 | 1303 if (m1_nr == 1 && m1_nc == 1) \ |
1304 r = SparseBoolMatrix (F (m1.elem(0,0), m2)); \ | |
1305 else if (m1_nr == m2_nr && m1_nc == m2_nc) \ | |
5164 | 1306 { \ |
1307 if (m1_nr != 0 || m1_nc != 0) \ | |
1308 { \ | |
1309 /* Count num of non-zero elements */ \ | |
5275 | 1310 octave_idx_type nel = 0; \ |
1311 for (octave_idx_type j = 0; j < m1_nc; j++) \ | |
1312 for (octave_idx_type i = 0; i < m1_nr; i++) \ | |
5164 | 1313 if (C1 (m1.elem(i, j)) OP C2 (m2.elem(i, j))) \ |
1314 nel++; \ | |
1315 \ | |
1316 r = SparseBoolMatrix (m1_nr, m1_nc, nel); \ | |
1317 \ | |
5275 | 1318 octave_idx_type ii = 0; \ |
5164 | 1319 r.cidx (0) = 0; \ |
5275 | 1320 for (octave_idx_type j = 0; j < m1_nc; j++) \ |
5164 | 1321 { \ |
5275 | 1322 for (octave_idx_type i = 0; i < m1_nr; i++) \ |
5164 | 1323 { \ |
1324 bool el = C1 (m1.elem(i, j)) OP C2 (m2.elem(i, j)); \ | |
1325 if (el) \ | |
1326 { \ | |
1327 r.data(ii) = el; \ | |
1328 r.ridx(ii++) = i; \ | |
1329 } \ | |
1330 } \ | |
1331 r.cidx(j+1) = ii; \ | |
1332 } \ | |
1333 } \ | |
1334 } \ | |
1335 else \ | |
1336 { \ | |
1337 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ | |
1338 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ | |
1339 } \ | |
1340 return r; \ | |
1341 } | |
1342 | |
1343 #define SPARSE_SMM_CMP_OPS(M1, Z1, C1, M2, Z2, C2) \ | |
1344 SPARSE_SMM_CMP_OP (mx_el_lt, <, M1, C1, M2, C2) \ | |
1345 SPARSE_SMM_CMP_OP (mx_el_le, <=, M1, C1, M2, C2) \ | |
1346 SPARSE_SMM_CMP_OP (mx_el_ge, >=, M1, C1, M2, C2) \ | |
1347 SPARSE_SMM_CMP_OP (mx_el_gt, >, M1, C1, M2, C2) \ | |
1348 SPARSE_SMM_CMP_OP (mx_el_eq, ==, M1, , M2, ) \ | |
1349 SPARSE_SMM_CMP_OP (mx_el_ne, !=, M1, , M2, ) | |
1350 | |
1351 #define SPARSE_SMM_EQNE_OPS(M1, Z1, C1, M2, Z2, C2) \ | |
1352 SPARSE_SMM_CMP_OP (mx_el_eq, ==, M1, , M2, ) \ | |
1353 SPARSE_SMM_CMP_OP (mx_el_ne, !=, M1, , M2, ) | |
1354 | |
6708 | 1355 #define SPARSE_SMM_BOOL_OP_DECLS(M1, M2, API) \ |
1356 SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2, API); \ | |
1357 SPARSE_BOOL_OP_DECL (mx_el_or, M1, M2, API); | |
5164 | 1358 |
1359 #define SPARSE_SMM_BOOL_OP(F, OP, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
1360 SparseBoolMatrix \ | |
1361 F (const M1& m1, const M2& m2) \ | |
1362 { \ | |
1363 SparseBoolMatrix r; \ | |
1364 \ | |
5275 | 1365 octave_idx_type m1_nr = m1.rows (); \ |
1366 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 1367 \ |
5275 | 1368 octave_idx_type m2_nr = m2.rows (); \ |
1369 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 1370 \ |
6221 | 1371 if (m1_nr == 1 && m1_nc == 1) \ |
1372 r = SparseBoolMatrix (F (m1.elem(0,0), m2)); \ | |
1373 else if (m1_nr == m2_nr && m1_nc == m2_nc) \ | |
5164 | 1374 { \ |
1375 if (m1_nr != 0 || m1_nc != 0) \ | |
1376 { \ | |
1377 /* Count num of non-zero elements */ \ | |
5275 | 1378 octave_idx_type nel = 0; \ |
1379 for (octave_idx_type j = 0; j < m1_nc; j++) \ | |
1380 for (octave_idx_type i = 0; i < m1_nr; i++) \ | |
5164 | 1381 if ((m1.elem(i, j) != LHS_ZERO) \ |
1382 OP (m2.elem(i, j) != RHS_ZERO)) \ | |
1383 nel++; \ | |
1384 \ | |
1385 r = SparseBoolMatrix (m1_nr, m1_nc, nel); \ | |
1386 \ | |
5275 | 1387 octave_idx_type ii = 0; \ |
5164 | 1388 r.cidx (0) = 0; \ |
5275 | 1389 for (octave_idx_type j = 0; j < m1_nc; j++) \ |
5164 | 1390 { \ |
5275 | 1391 for (octave_idx_type i = 0; i < m1_nr; i++) \ |
5164 | 1392 { \ |
1393 bool el = (m1.elem(i, j) != LHS_ZERO) \ | |
1394 OP (m2.elem(i, j) != RHS_ZERO); \ | |
1395 if (el) \ | |
1396 { \ | |
1397 r.data(ii) = el; \ | |
1398 r.ridx(ii++) = i; \ | |
1399 } \ | |
1400 } \ | |
1401 r.cidx(j+1) = ii; \ | |
1402 } \ | |
1403 } \ | |
1404 } \ | |
1405 else \ | |
1406 { \ | |
1407 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ | |
1408 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ | |
1409 } \ | |
1410 return r; \ | |
1411 } | |
1412 | |
1413 #define SPARSE_SMM_BOOL_OPS2(M1, M2, LHS_ZERO, RHS_ZERO) \ | |
1414 SPARSE_SMM_BOOL_OP (mx_el_and, &&, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
1415 SPARSE_SMM_BOOL_OP (mx_el_or, ||, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
1416 | |
1417 #define SPARSE_SMM_BOOL_OPS(M1, M2, ZERO) \ | |
1418 SPARSE_SMM_BOOL_OPS2(M1, M2, ZERO, ZERO) | |
1419 | |
6708 | 1420 #define SPARSE_SMM_OP_DECLS(R1, R2, M1, M2, API) \ |
1421 SPARSE_SMM_BIN_OP_DECLS (R1, R2, M1, M2, API) \ | |
1422 SPARSE_SMM_CMP_OP_DECLS (M1, M2, API) \ | |
1423 SPARSE_SMM_BOOL_OP_DECLS (M1, M2, API) | |
5164 | 1424 |
1425 // Avoid some code duplication. Maybe we should use templates. | |
1426 | |
1427 #define SPARSE_CUMSUM(RET_TYPE, ELT_TYPE, FCN) \ | |
1428 \ | |
5275 | 1429 octave_idx_type nr = rows (); \ |
1430 octave_idx_type nc = cols (); \ | |
5164 | 1431 \ |
1432 RET_TYPE retval; \ | |
1433 \ | |
1434 if (nr > 0 && nc > 0) \ | |
1435 { \ | |
1436 if ((nr == 1 && dim == -1) || dim == 1) \ | |
1437 /* Ugly!! Is there a better way? */ \ | |
1438 retval = transpose (). FCN (0) .transpose (); \ | |
1439 else \ | |
1440 { \ | |
5275 | 1441 octave_idx_type nel = 0; \ |
1442 for (octave_idx_type i = 0; i < nc; i++) \ | |
5164 | 1443 { \ |
1444 ELT_TYPE t = ELT_TYPE (); \ | |
5275 | 1445 for (octave_idx_type j = cidx (i); j < cidx (i+1); j++) \ |
5164 | 1446 { \ |
1447 t += data(j); \ | |
1448 if (t != ELT_TYPE ()) \ | |
6482 | 1449 { \ |
1450 if (j == cidx(i+1) - 1) \ | |
1451 nel += nr - ridx(j); \ | |
1452 else \ | |
1453 nel += ridx(j+1) - ridx(j); \ | |
1454 } \ | |
5164 | 1455 } \ |
1456 } \ | |
1457 retval = RET_TYPE (nr, nc, nel); \ | |
1458 retval.cidx(0) = 0; \ | |
5275 | 1459 octave_idx_type ii = 0; \ |
1460 for (octave_idx_type i = 0; i < nc; i++) \ | |
5164 | 1461 { \ |
1462 ELT_TYPE t = ELT_TYPE (); \ | |
5275 | 1463 for (octave_idx_type j = cidx (i); j < cidx (i+1); j++) \ |
5164 | 1464 { \ |
1465 t += data(j); \ | |
1466 if (t != ELT_TYPE ()) \ | |
1467 { \ | |
1468 if (j == cidx(i+1) - 1) \ | |
1469 { \ | |
5275 | 1470 for (octave_idx_type k = ridx(j); k < nr; k++) \ |
5164 | 1471 { \ |
1472 retval.data (ii) = t; \ | |
1473 retval.ridx (ii++) = k; \ | |
1474 } \ | |
1475 } \ | |
1476 else \ | |
1477 { \ | |
5275 | 1478 for (octave_idx_type k = ridx(j); k < ridx(j+1); k++) \ |
5164 | 1479 { \ |
1480 retval.data (ii) = t; \ | |
1481 retval.ridx (ii++) = k; \ | |
1482 } \ | |
1483 } \ | |
1484 } \ | |
1485 } \ | |
1486 retval.cidx(i+1) = ii; \ | |
1487 } \ | |
1488 } \ | |
1489 } \ | |
1490 else \ | |
1491 retval = RET_TYPE (nr,nc); \ | |
1492 \ | |
1493 return retval | |
1494 | |
1495 | |
1496 #define SPARSE_CUMPROD(RET_TYPE, ELT_TYPE, FCN) \ | |
1497 \ | |
5275 | 1498 octave_idx_type nr = rows (); \ |
1499 octave_idx_type nc = cols (); \ | |
5164 | 1500 \ |
1501 RET_TYPE retval; \ | |
1502 \ | |
1503 if (nr > 0 && nc > 0) \ | |
1504 { \ | |
1505 if ((nr == 1 && dim == -1) || dim == 1) \ | |
1506 /* Ugly!! Is there a better way? */ \ | |
1507 retval = transpose (). FCN (0) .transpose (); \ | |
1508 else \ | |
1509 { \ | |
5275 | 1510 octave_idx_type nel = 0; \ |
1511 for (octave_idx_type i = 0; i < nc; i++) \ | |
5164 | 1512 { \ |
5275 | 1513 octave_idx_type jj = 0; \ |
1514 for (octave_idx_type j = cidx (i); j < cidx (i+1); j++) \ | |
5164 | 1515 { \ |
1516 if (jj == ridx(j)) \ | |
1517 { \ | |
1518 nel++; \ | |
1519 jj++; \ | |
1520 } \ | |
1521 else \ | |
1522 break; \ | |
1523 } \ | |
1524 } \ | |
1525 retval = RET_TYPE (nr, nc, nel); \ | |
1526 retval.cidx(0) = 0; \ | |
5275 | 1527 octave_idx_type ii = 0; \ |
1528 for (octave_idx_type i = 0; i < nc; i++) \ | |
5164 | 1529 { \ |
1530 ELT_TYPE t = ELT_TYPE (1.); \ | |
5275 | 1531 octave_idx_type jj = 0; \ |
1532 for (octave_idx_type j = cidx (i); j < cidx (i+1); j++) \ | |
5164 | 1533 { \ |
1534 if (jj == ridx(j)) \ | |
1535 { \ | |
1536 t *= data(j); \ | |
1537 retval.data(ii) = t; \ | |
1538 retval.ridx(ii++) = jj++; \ | |
1539 } \ | |
1540 else \ | |
1541 break; \ | |
1542 } \ | |
1543 retval.cidx(i+1) = ii; \ | |
1544 } \ | |
1545 } \ | |
1546 } \ | |
1547 else \ | |
1548 retval = RET_TYPE (nr,nc); \ | |
1549 \ | |
1550 return retval | |
1551 | |
1552 #define SPARSE_BASE_REDUCTION_OP(RET_TYPE, EL_TYPE, ROW_EXPR, COL_EXPR, \ | |
1553 INIT_VAL, MT_RESULT) \ | |
1554 \ | |
5275 | 1555 octave_idx_type nr = rows (); \ |
1556 octave_idx_type nc = cols (); \ | |
5164 | 1557 \ |
1558 RET_TYPE retval; \ | |
1559 \ | |
1560 if (nr > 0 && nc > 0) \ | |
1561 { \ | |
1562 if ((nr == 1 && dim == -1) || dim == 1) \ | |
1563 { \ | |
7269 | 1564 /* Define j here to allow fancy definition for prod method */ \ |
1565 octave_idx_type j = 0; \ | |
5164 | 1566 OCTAVE_LOCAL_BUFFER (EL_TYPE, tmp, nr); \ |
1567 \ | |
5275 | 1568 for (octave_idx_type i = 0; i < nr; i++) \ |
7269 | 1569 tmp[i] = INIT_VAL; \ |
1570 for (j = 0; j < nc; j++) \ | |
1571 { \ | |
1572 for (octave_idx_type i = cidx(j); i < cidx(j + 1); i++) \ | |
1573 { \ | |
1574 ROW_EXPR; \ | |
1575 } \ | |
5164 | 1576 } \ |
5275 | 1577 octave_idx_type nel = 0; \ |
1578 for (octave_idx_type i = 0; i < nr; i++) \ | |
5164 | 1579 if (tmp[i] != EL_TYPE ()) \ |
1580 nel++ ; \ | |
5275 | 1581 retval = RET_TYPE (nr, static_cast<octave_idx_type> (1), nel); \ |
5164 | 1582 retval.cidx(0) = 0; \ |
1583 retval.cidx(1) = nel; \ | |
1584 nel = 0; \ | |
5275 | 1585 for (octave_idx_type i = 0; i < nr; i++) \ |
5164 | 1586 if (tmp[i] != EL_TYPE ()) \ |
1587 { \ | |
1588 retval.data(nel) = tmp[i]; \ | |
1589 retval.ridx(nel++) = i; \ | |
1590 } \ | |
1591 } \ | |
1592 else \ | |
1593 { \ | |
1594 OCTAVE_LOCAL_BUFFER (EL_TYPE, tmp, nc); \ | |
1595 \ | |
5275 | 1596 for (octave_idx_type j = 0; j < nc; j++) \ |
5164 | 1597 { \ |
1598 tmp[j] = INIT_VAL; \ | |
7269 | 1599 for (octave_idx_type i = cidx(j); i < cidx(j + 1); i++) \ |
1600 { \ | |
5164 | 1601 COL_EXPR; \ |
7269 | 1602 } \ |
5164 | 1603 } \ |
5275 | 1604 octave_idx_type nel = 0; \ |
1605 for (octave_idx_type i = 0; i < nc; i++) \ | |
5164 | 1606 if (tmp[i] != EL_TYPE ()) \ |
1607 nel++ ; \ | |
5275 | 1608 retval = RET_TYPE (static_cast<octave_idx_type> (1), nc, nel); \ |
5164 | 1609 retval.cidx(0) = 0; \ |
1610 nel = 0; \ | |
5275 | 1611 for (octave_idx_type i = 0; i < nc; i++) \ |
5164 | 1612 if (tmp[i] != EL_TYPE ()) \ |
1613 { \ | |
1614 retval.data(nel) = tmp[i]; \ | |
1615 retval.ridx(nel++) = 0; \ | |
1616 retval.cidx(i+1) = retval.cidx(i) + 1; \ | |
1617 } \ | |
1618 else \ | |
1619 retval.cidx(i+1) = retval.cidx(i); \ | |
1620 } \ | |
1621 } \ | |
1622 else if (nc == 0 && (nr == 0 || (nr == 1 && dim == -1))) \ | |
1623 { \ | |
7197 | 1624 if (MT_RESULT) \ |
1625 { \ | |
1626 retval = RET_TYPE (static_cast<octave_idx_type> (1), \ | |
1627 static_cast<octave_idx_type> (1), \ | |
1628 static_cast<octave_idx_type> (1)); \ | |
1629 retval.cidx(0) = 0; \ | |
1630 retval.cidx(1) = 1; \ | |
1631 retval.ridx(0) = 0; \ | |
1632 retval.data(0) = MT_RESULT; \ | |
1633 } \ | |
1634 else \ | |
1635 retval = RET_TYPE (static_cast<octave_idx_type> (1), \ | |
1636 static_cast<octave_idx_type> (1), \ | |
1637 static_cast<octave_idx_type> (0)); \ | |
5164 | 1638 } \ |
1639 else if (nr == 0 && (dim == 0 || dim == -1)) \ | |
1640 { \ | |
7197 | 1641 if (MT_RESULT) \ |
5164 | 1642 { \ |
7197 | 1643 retval = RET_TYPE (static_cast<octave_idx_type> (1), nc, nc); \ |
1644 retval.cidx (0) = 0; \ | |
1645 for (octave_idx_type i = 0; i < nc ; i++) \ | |
1646 { \ | |
1647 retval.ridx (i) = 0; \ | |
1648 retval.cidx (i+1) = i; \ | |
1649 retval.data (i) = MT_RESULT; \ | |
1650 } \ | |
1651 } \ | |
1652 else \ | |
1653 retval = RET_TYPE (static_cast<octave_idx_type> (1), nc, \ | |
1654 static_cast<octave_idx_type> (0)); \ | |
5164 | 1655 } \ |
1656 else if (nc == 0 && dim == 1) \ | |
1657 { \ | |
7197 | 1658 if (MT_RESULT) \ |
1659 { \ | |
1660 retval = RET_TYPE (nr, static_cast<octave_idx_type> (1), nr); \ | |
1661 retval.cidx(0) = 0; \ | |
1662 retval.cidx(1) = nr; \ | |
1663 for (octave_idx_type i = 0; i < nr; i++) \ | |
1664 { \ | |
1665 retval.ridx(i) = i; \ | |
1666 retval.data(i) = MT_RESULT; \ | |
1667 } \ | |
1668 } \ | |
1669 else \ | |
1670 retval = RET_TYPE (nr, static_cast<octave_idx_type> (1), \ | |
1671 static_cast<octave_idx_type> (0)); \ | |
5164 | 1672 } \ |
1673 else \ | |
1674 retval.resize (nr > 0, nc > 0); \ | |
1675 \ | |
1676 return retval | |
1677 | |
1678 #define SPARSE_REDUCTION_OP_ROW_EXPR(OP) \ | |
7269 | 1679 tmp[ridx(i)] OP data (i) |
5164 | 1680 |
1681 #define SPARSE_REDUCTION_OP_COL_EXPR(OP) \ | |
7269 | 1682 tmp[j] OP data (i) |
5164 | 1683 |
1684 #define SPARSE_REDUCTION_OP(RET_TYPE, EL_TYPE, OP, INIT_VAL, MT_RESULT) \ | |
1685 SPARSE_BASE_REDUCTION_OP (RET_TYPE, EL_TYPE, \ | |
1686 SPARSE_REDUCTION_OP_ROW_EXPR (OP), \ | |
1687 SPARSE_REDUCTION_OP_COL_EXPR (OP), \ | |
1688 INIT_VAL, MT_RESULT) | |
1689 | |
7350 | 1690 |
1691 // Don't break from this loop if the test succeeds because | |
1692 // we are looping over the rows and not the columns in the inner | |
1693 // loop. | |
5164 | 1694 #define SPARSE_ANY_ALL_OP_ROW_CODE(TEST_OP, TEST_TRUE_VAL) \ |
7269 | 1695 if (data (i) TEST_OP 0.0) \ |
7350 | 1696 tmp[ridx(i)] = TEST_TRUE_VAL; \ |
5164 | 1697 |
1698 #define SPARSE_ANY_ALL_OP_COL_CODE(TEST_OP, TEST_TRUE_VAL) \ | |
7269 | 1699 if (data (i) TEST_OP 0.0) \ |
5164 | 1700 { \ |
1701 tmp[j] = TEST_TRUE_VAL; \ | |
1702 break; \ | |
1703 } | |
1704 | |
7269 | 1705 #define SPARSE_ANY_ALL_OP(DIM, INIT_VAL, MT_RESULT, TEST_OP, TEST_TRUE_VAL) \ |
5164 | 1706 SPARSE_BASE_REDUCTION_OP (SparseBoolMatrix, char, \ |
1707 SPARSE_ANY_ALL_OP_ROW_CODE (TEST_OP, TEST_TRUE_VAL), \ | |
1708 SPARSE_ANY_ALL_OP_COL_CODE (TEST_OP, TEST_TRUE_VAL), \ | |
7269 | 1709 INIT_VAL, MT_RESULT) |
5164 | 1710 |
7269 | 1711 #define SPARSE_ALL_OP(DIM) \ |
1712 if ((rows() == 1 && dim == -1) || dim == 1) \ | |
1713 return transpose (). all (0). transpose(); \ | |
1714 else \ | |
1715 { \ | |
1716 SPARSE_ANY_ALL_OP (DIM, (cidx(j+1) - cidx(j) < nc ? false : true), \ | |
1717 true, ==, false); \ | |
1718 } | |
5164 | 1719 |
7269 | 1720 #define SPARSE_ANY_OP(DIM) SPARSE_ANY_ALL_OP (DIM, false, false, !=, true) |
5164 | 1721 |
5681 | 1722 #define SPARSE_SPARSE_MUL( RET_TYPE, RET_EL_TYPE, EL_TYPE ) \ |
5275 | 1723 octave_idx_type nr = m.rows (); \ |
1724 octave_idx_type nc = m.cols (); \ | |
5164 | 1725 \ |
5275 | 1726 octave_idx_type a_nr = a.rows (); \ |
1727 octave_idx_type a_nc = a.cols (); \ | |
5164 | 1728 \ |
6221 | 1729 if (nr == 1 && nc == 1) \ |
1730 { \ | |
1731 RET_EL_TYPE s = m.elem(0,0); \ | |
1732 octave_idx_type nz = a.nnz(); \ | |
1733 RET_TYPE r (a_nr, a_nc, nz); \ | |
1734 \ | |
1735 for (octave_idx_type i = 0; i < nz; i++) \ | |
1736 { \ | |
1737 OCTAVE_QUIT; \ | |
1738 r.data(i) = s * a.data(i); \ | |
1739 r.ridx(i) = a.ridx(i); \ | |
1740 } \ | |
1741 for (octave_idx_type i = 0; i < a_nc + 1; i++) \ | |
1742 { \ | |
1743 OCTAVE_QUIT; \ | |
1744 r.cidx(i) = a.cidx(i); \ | |
1745 } \ | |
1746 \ | |
1747 r.maybe_compress (true); \ | |
1748 return r; \ | |
1749 } \ | |
1750 else if (a_nr == 1 && a_nc == 1) \ | |
1751 { \ | |
1752 RET_EL_TYPE s = a.elem(0,0); \ | |
1753 octave_idx_type nz = m.nnz(); \ | |
1754 RET_TYPE r (nr, nc, nz); \ | |
1755 \ | |
1756 for (octave_idx_type i = 0; i < nz; i++) \ | |
1757 { \ | |
1758 OCTAVE_QUIT; \ | |
1759 r.data(i) = m.data(i) * s; \ | |
1760 r.ridx(i) = m.ridx(i); \ | |
1761 } \ | |
1762 for (octave_idx_type i = 0; i < nc + 1; i++) \ | |
1763 { \ | |
1764 OCTAVE_QUIT; \ | |
1765 r.cidx(i) = m.cidx(i); \ | |
1766 } \ | |
1767 \ | |
1768 r.maybe_compress (true); \ | |
1769 return r; \ | |
1770 } \ | |
1771 else if (nc != a_nr) \ | |
5164 | 1772 { \ |
1773 gripe_nonconformant ("operator *", nr, nc, a_nr, a_nc); \ | |
1774 return RET_TYPE (); \ | |
1775 } \ | |
1776 else \ | |
1777 { \ | |
5586 | 1778 OCTAVE_LOCAL_BUFFER (octave_idx_type, w, nr); \ |
5876 | 1779 RET_TYPE retval (nr, a_nc, static_cast<octave_idx_type> (0)); \ |
5586 | 1780 for (octave_idx_type i = 0; i < nr; i++) \ |
1781 w[i] = 0; \ | |
5795 | 1782 retval.xcidx(0) = 0; \ |
5164 | 1783 \ |
5275 | 1784 octave_idx_type nel = 0; \ |
5164 | 1785 \ |
5275 | 1786 for (octave_idx_type i = 0; i < a_nc; i++) \ |
5164 | 1787 { \ |
5275 | 1788 for (octave_idx_type j = a.cidx(i); j < a.cidx(i+1); j++) \ |
5164 | 1789 { \ |
5275 | 1790 octave_idx_type col = a.ridx(j); \ |
1791 for (octave_idx_type k = m.cidx(col) ; k < m.cidx(col+1); k++) \ | |
5586 | 1792 { \ |
1793 if (w[m.ridx(k)] < i + 1) \ | |
1794 { \ | |
1795 w[m.ridx(k)] = i + 1; \ | |
1796 nel++; \ | |
1797 } \ | |
5587 | 1798 OCTAVE_QUIT; \ |
5586 | 1799 } \ |
5164 | 1800 } \ |
5795 | 1801 retval.xcidx(i+1) = nel; \ |
5164 | 1802 } \ |
1803 \ | |
1804 if (nel == 0) \ | |
1805 return RET_TYPE (nr, a_nc); \ | |
1806 else \ | |
1807 { \ | |
5586 | 1808 for (octave_idx_type i = 0; i < nr; i++) \ |
1809 w[i] = 0; \ | |
1810 \ | |
5681 | 1811 OCTAVE_LOCAL_BUFFER (RET_EL_TYPE, Xcol, nr); \ |
5586 | 1812 \ |
5795 | 1813 retval.change_capacity (nel); \ |
5587 | 1814 /* The optimal break-point as estimated from simulations */ \ |
1815 /* Note that Mergesort is O(nz log(nz)) while searching all */ \ | |
1816 /* values is O(nr), where nz here is non-zero per row of */ \ | |
1817 /* length nr. The test itself was then derived from the */ \ | |
1818 /* simulation with random square matrices and the observation */ \ | |
1819 /* of the number of non-zero elements in the output matrix */ \ | |
1820 /* it was found that the breakpoints were */ \ | |
1821 /* nr: 500 1000 2000 5000 10000 */ \ | |
1822 /* nz: 6 25 97 585 2202 */ \ | |
1823 /* The below is a simplication of the 'polyfit'-ed parameters */ \ | |
1824 /* to these breakpoints */ \ | |
5795 | 1825 octave_idx_type n_per_col = (a_nc > 43000 ? 43000 : \ |
1826 (a_nc * a_nc) / 43000); \ | |
1827 octave_idx_type ii = 0; \ | |
1828 octave_idx_type *ri = retval.xridx(); \ | |
1829 octave_sort<octave_idx_type> sort; \ | |
1830 \ | |
1831 for (octave_idx_type i = 0; i < a_nc ; i++) \ | |
5164 | 1832 { \ |
5795 | 1833 if (retval.xcidx(i+1) - retval.xcidx(i) > n_per_col) \ |
5587 | 1834 { \ |
1835 for (octave_idx_type j = a.cidx(i); j < a.cidx(i+1); j++) \ | |
1836 { \ | |
1837 octave_idx_type col = a.ridx(j); \ | |
1838 EL_TYPE tmpval = a.data(j); \ | |
1839 for (octave_idx_type k = m.cidx(col) ; \ | |
1840 k < m.cidx(col+1); k++) \ | |
1841 { \ | |
1842 OCTAVE_QUIT; \ | |
1843 octave_idx_type row = m.ridx(k); \ | |
1844 if (w[row] < i + 1) \ | |
1845 { \ | |
1846 w[row] = i + 1; \ | |
1847 Xcol[row] = tmpval * m.data(k); \ | |
1848 } \ | |
1849 else \ | |
1850 Xcol[row] += tmpval * m.data(k); \ | |
1851 } \ | |
1852 } \ | |
1853 for (octave_idx_type k = 0; k < nr; k++) \ | |
5813 | 1854 if (w[k] == i + 1) \ |
5587 | 1855 { \ |
1856 retval.xdata(ii) = Xcol[k]; \ | |
1857 retval.xridx(ii++) = k; \ | |
1858 } \ | |
5795 | 1859 } \ |
1860 else \ | |
1861 { \ | |
1862 for (octave_idx_type j = a.cidx(i); j < a.cidx(i+1); j++) \ | |
1863 { \ | |
1864 octave_idx_type col = a.ridx(j); \ | |
1865 EL_TYPE tmpval = a.data(j); \ | |
1866 for (octave_idx_type k = m.cidx(col) ; \ | |
1867 k < m.cidx(col+1); k++) \ | |
1868 { \ | |
1869 OCTAVE_QUIT; \ | |
1870 octave_idx_type row = m.ridx(k); \ | |
1871 if (w[row] < i + 1) \ | |
1872 { \ | |
1873 w[row] = i + 1; \ | |
1874 retval.xridx(ii++) = row;\ | |
1875 Xcol[row] = tmpval * m.data(k); \ | |
1876 } \ | |
1877 else \ | |
1878 Xcol[row] += tmpval * m.data(k); \ | |
1879 } \ | |
1880 } \ | |
1881 sort.sort (ri + retval.xcidx(i), ii - retval.xcidx(i)); \ | |
1882 for (octave_idx_type k = retval.xcidx(i); k < ii; k++) \ | |
1883 retval.xdata(k) = Xcol[retval.xridx(k)]; \ | |
5587 | 1884 } \ |
5164 | 1885 } \ |
5813 | 1886 retval.maybe_compress (true);\ |
5164 | 1887 return retval; \ |
1888 } \ | |
1889 } | |
1890 | |
5681 | 1891 #define SPARSE_FULL_MUL( RET_TYPE, EL_TYPE, ZERO ) \ |
5429 | 1892 octave_idx_type nr = m.rows (); \ |
1893 octave_idx_type nc = m.cols (); \ | |
1894 \ | |
1895 octave_idx_type a_nr = a.rows (); \ | |
1896 octave_idx_type a_nc = a.cols (); \ | |
1897 \ | |
6221 | 1898 if (nr == 1 && nc == 1) \ |
1899 { \ | |
7802
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1900 RET_TYPE retval = m.elem (0,0) * a; \ |
6221 | 1901 return retval; \ |
1902 } \ | |
1903 else if (nc != a_nr) \ | |
5429 | 1904 { \ |
1905 gripe_nonconformant ("operator *", nr, nc, a_nr, a_nc); \ | |
1906 return RET_TYPE (); \ | |
1907 } \ | |
1908 else \ | |
1909 { \ | |
5681 | 1910 RET_TYPE retval (nr, a_nc, ZERO); \ |
5429 | 1911 \ |
1912 for (octave_idx_type i = 0; i < a_nc ; i++) \ | |
7802
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1913 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1914 for (octave_idx_type j = 0; j < a_nr; j++) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1915 { \ |
5429 | 1916 OCTAVE_QUIT; \ |
7802
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1917 \ |
5429 | 1918 EL_TYPE tmpval = a.elem(j,i); \ |
7802
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1919 for (octave_idx_type k = m.cidx(j) ; k < m.cidx(j+1); k++) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1920 retval.elem (m.ridx(k),i) += tmpval * m.data(k); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1921 } \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1922 } \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1923 return retval; \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1924 } |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1925 |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1926 #define SPARSE_FULL_TRANS_MUL( RET_TYPE, EL_TYPE, ZERO, CONJ_OP ) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1927 octave_idx_type nr = m.rows (); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1928 octave_idx_type nc = m.cols (); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1929 \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1930 octave_idx_type a_nr = a.rows (); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1931 octave_idx_type a_nc = a.cols (); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1932 \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1933 if (nr == 1 && nc == 1) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1934 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1935 RET_TYPE retval = CONJ_OP (m.elem(0,0)) * a; \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1936 return retval; \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1937 } \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1938 else if (nr != a_nr) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1939 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1940 gripe_nonconformant ("operator *", nc, nr, a_nr, a_nc); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1941 return RET_TYPE (); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1942 } \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1943 else \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1944 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1945 RET_TYPE retval (nc, a_nc); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1946 \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1947 for (octave_idx_type i = 0; i < a_nc ; i++) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1948 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1949 for (octave_idx_type j = 0; j < nc; j++) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1950 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1951 OCTAVE_QUIT; \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1952 \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1953 EL_TYPE acc = ZERO; \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1954 for (octave_idx_type k = m.cidx(j) ; k < m.cidx(j+1); k++) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1955 acc += a.elem (m.ridx(k),i) * CONJ_OP (m.data(k)); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1956 retval.xelem (j,i) = acc; \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1957 } \ |
5429 | 1958 } \ |
1959 return retval; \ | |
1960 } | |
1961 | |
5681 | 1962 #define FULL_SPARSE_MUL( RET_TYPE, EL_TYPE, ZERO ) \ |
5429 | 1963 octave_idx_type nr = m.rows (); \ |
1964 octave_idx_type nc = m.cols (); \ | |
1965 \ | |
1966 octave_idx_type a_nr = a.rows (); \ | |
1967 octave_idx_type a_nc = a.cols (); \ | |
1968 \ | |
6221 | 1969 if (a_nr == 1 && a_nc == 1) \ |
1970 { \ | |
7802
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1971 RET_TYPE retval = m * a.elem (0,0); \ |
6221 | 1972 return retval; \ |
1973 } \ | |
1974 else if (nc != a_nr) \ | |
5429 | 1975 { \ |
1976 gripe_nonconformant ("operator *", nr, nc, a_nr, a_nc); \ | |
1977 return RET_TYPE (); \ | |
1978 } \ | |
1979 else \ | |
1980 { \ | |
5681 | 1981 RET_TYPE retval (nr, a_nc, ZERO); \ |
5429 | 1982 \ |
1983 for (octave_idx_type i = 0; i < a_nc ; i++) \ | |
7802
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1984 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1985 OCTAVE_QUIT; \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1986 for (octave_idx_type j = a.cidx(i); j < a.cidx(i+1); j++) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1987 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1988 octave_idx_type col = a.ridx(j); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1989 EL_TYPE tmpval = a.data(j); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1990 \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1991 for (octave_idx_type k = 0 ; k < nr; k++) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1992 retval.xelem (k,i) += tmpval * m.elem(k,col); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1993 } \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1994 } \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1995 return retval; \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1996 } |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1997 |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1998 #define FULL_SPARSE_MUL_TRANS( RET_TYPE, EL_TYPE, ZERO, CONJ_OP ) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1999 octave_idx_type nr = m.rows (); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2000 octave_idx_type nc = m.cols (); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2001 \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2002 octave_idx_type a_nr = a.rows (); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2003 octave_idx_type a_nc = a.cols (); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2004 \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2005 if (a_nr == 1 && a_nc == 1) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2006 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2007 RET_TYPE retval = m * CONJ_OP (a.elem(0,0)); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2008 return retval; \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2009 } \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2010 else if (nc != a_nc) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2011 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2012 gripe_nonconformant ("operator *", nr, nc, a_nc, a_nr); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2013 return RET_TYPE (); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2014 } \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2015 else \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2016 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2017 RET_TYPE retval (nr, a_nr, ZERO); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2018 \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2019 for (octave_idx_type i = 0; i < a_nc ; i++) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2020 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2021 OCTAVE_QUIT; \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2022 for (octave_idx_type j = a.cidx(i); j < a.cidx(i+1); j++) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2023 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2024 octave_idx_type col = a.ridx(j); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2025 EL_TYPE tmpval = CONJ_OP (a.data(j)); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2026 for (octave_idx_type k = 0 ; k < nr; k++) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2027 retval.xelem (k,col) += tmpval * m.elem(k,i); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2028 } \ |
5429 | 2029 } \ |
2030 return retval; \ | |
2031 } | |
2032 | |
5164 | 2033 #endif |
2034 | |
2035 /* | |
2036 ;;; Local Variables: *** | |
2037 ;;; mode: C++ *** | |
2038 ;;; End: *** | |
2039 */ |