Mercurial > hg > octave-lyh
annotate liboctave/Sparse-op-defs.h @ 7820:cb4838d70ab2
Fix default value for axes gridlinestyle and minorgridlinestyle.
author | Michael Goffioul <michael.goffioul@gmail.com> |
---|---|
date | Thu, 07 Feb 2008 16:21:03 +0100 |
parents | 9bcb31cc56be |
children | 1ebcb9872ced |
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 { \ | |
752 extern OCTAVE_API SparseBoolMatrix F (const double&, const M2&); \ | |
753 extern OCTAVE_API SparseBoolMatrix F (const Complex&, const M2&); \ | |
754 r = F (m1.elem(0,0), m2); \ | |
755 } \ | |
756 else if (m2_nr == 1 && m2_nc == 1) \ | |
757 { \ | |
758 extern OCTAVE_API SparseBoolMatrix F (const M1&, const double&); \ | |
759 extern OCTAVE_API SparseBoolMatrix F (const M1&, const Complex&); \ | |
760 r = F (m1, m2.elem(0,0)); \ | |
761 } \ | |
762 else if (m1_nr == m2_nr && m1_nc == m2_nc) \ | |
5164 | 763 { \ |
764 if (m1_nr != 0 || m1_nc != 0) \ | |
765 { \ | |
7269 | 766 if (C1 (Z1) OP C2 (Z2)) \ |
5164 | 767 { \ |
7269 | 768 r = SparseBoolMatrix (m1_nr, m1_nc, true); \ |
769 for (octave_idx_type j = 0; j < m1_nc; j++) \ | |
770 { \ | |
771 octave_idx_type i1 = m1.cidx (j); \ | |
772 octave_idx_type e1 = m1.cidx (j+1); \ | |
773 octave_idx_type i2 = m2.cidx (j); \ | |
774 octave_idx_type e2 = m2.cidx (j+1); \ | |
775 while (i1 < e1 || i2 < e2) \ | |
776 { \ | |
777 if (i1 == e1 || (i2 < e2 && m1.ridx(i1) > m2.ridx(i2))) \ | |
778 { \ | |
779 if (! (C1 (Z1) OP C2 (m2.data (i2)))) \ | |
780 r.data (m2.ridx (i2) + j * m1_nr) = false; \ | |
781 i2++; \ | |
782 } \ | |
783 else if (i2 == e2 || m1.ridx(i1) < m2.ridx(i2)) \ | |
784 { \ | |
785 if (! (C1 (m1.data (i1)) OP C2 (Z2))) \ | |
786 r.data (m1.ridx (i1) + j * m1_nr) = false; \ | |
787 i1++; \ | |
788 } \ | |
789 else \ | |
790 { \ | |
791 if (! (C1 (m1.data (i1)) OP C2 (m2.data (i2)))) \ | |
792 r.data (m1.ridx (i1) + j * m1_nr) = false; \ | |
793 i1++; \ | |
794 i2++; \ | |
795 } \ | |
796 } \ | |
797 } \ | |
798 r.maybe_compress (true); \ | |
799 } \ | |
800 else \ | |
801 { \ | |
802 r = SparseBoolMatrix (m1_nr, m1_nc, m1.nnz () + m2.nnz ()); \ | |
803 r.cidx (0) = static_cast<octave_idx_type> (0); \ | |
804 octave_idx_type nel = 0; \ | |
805 for (octave_idx_type j = 0; j < m1_nc; j++) \ | |
806 { \ | |
807 octave_idx_type i1 = m1.cidx (j); \ | |
808 octave_idx_type e1 = m1.cidx (j+1); \ | |
809 octave_idx_type i2 = m2.cidx (j); \ | |
810 octave_idx_type e2 = m2.cidx (j+1); \ | |
811 while (i1 < e1 || i2 < e2) \ | |
812 { \ | |
813 if (i1 == e1 || (i2 < e2 && m1.ridx(i1) > m2.ridx(i2))) \ | |
814 { \ | |
815 if (C1 (Z1) OP C2 (m2.data (i2))) \ | |
816 { \ | |
817 r.ridx (nel) = m2.ridx (i2); \ | |
818 r.data (nel++) = true; \ | |
819 } \ | |
820 i2++; \ | |
821 } \ | |
822 else if (i2 == e2 || m1.ridx(i1) < m2.ridx(i2)) \ | |
823 { \ | |
824 if (C1 (m1.data (i1)) OP C2 (Z2)) \ | |
825 { \ | |
826 r.ridx (nel) = m1.ridx (i1); \ | |
827 r.data (nel++) = true; \ | |
828 } \ | |
829 i1++; \ | |
830 } \ | |
831 else \ | |
832 { \ | |
833 if (C1 (m1.data (i1)) OP C2 (m2.data (i2))) \ | |
834 { \ | |
835 r.ridx (nel) = m1.ridx (i1); \ | |
836 r.data (nel++) = true; \ | |
837 } \ | |
838 i1++; \ | |
839 i2++; \ | |
840 } \ | |
841 } \ | |
842 r.cidx (j + 1) = nel; \ | |
843 } \ | |
844 r.maybe_compress (false); \ | |
845 } \ | |
5164 | 846 } \ |
847 } \ | |
848 else \ | |
849 { \ | |
850 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ | |
851 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ | |
852 } \ | |
853 return r; \ | |
854 } | |
855 | |
856 #define SPARSE_SMSM_CMP_OPS(M1, Z1, C1, M2, Z2, C2) \ | |
7269 | 857 SPARSE_SMSM_CMP_OP (mx_el_lt, <, M1, Z1, C1, M2, Z2, C2) \ |
858 SPARSE_SMSM_CMP_OP (mx_el_le, <=, M1, Z1, C1, M2, Z2, C2) \ | |
859 SPARSE_SMSM_CMP_OP (mx_el_ge, >=, M1, Z1, C1, M2, Z2, C2) \ | |
860 SPARSE_SMSM_CMP_OP (mx_el_gt, >, M1, Z1, C1, M2, Z2, C2) \ | |
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 |
864 #define SPARSE_SMSM_EQNE_OPS(M1, Z1, C1, M2, Z2, C2) \ | |
7269 | 865 SPARSE_SMSM_CMP_OP (mx_el_eq, ==, M1, Z1, , M2, Z2, ) \ |
866 SPARSE_SMSM_CMP_OP (mx_el_ne, !=, M1, Z1, , M2, Z2, ) | |
5164 | 867 |
6708 | 868 #define SPARSE_SMSM_BOOL_OP_DECLS(M1, M2, API) \ |
869 SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2, API); \ | |
870 SPARSE_BOOL_OP_DECL (mx_el_or, M1, M2, API); | |
5164 | 871 |
872 #define SPARSE_SMSM_BOOL_OP(F, OP, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
873 SparseBoolMatrix \ | |
874 F (const M1& m1, const M2& m2) \ | |
875 { \ | |
876 SparseBoolMatrix r; \ | |
877 \ | |
5275 | 878 octave_idx_type m1_nr = m1.rows (); \ |
879 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 880 \ |
5275 | 881 octave_idx_type m2_nr = m2.rows (); \ |
882 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 883 \ |
6221 | 884 if (m1_nr == 1 && m1_nc == 1) \ |
885 { \ | |
886 extern OCTAVE_API SparseBoolMatrix F (const double&, const M2&); \ | |
887 extern OCTAVE_API SparseBoolMatrix F (const Complex&, const M2&); \ | |
888 r = F (m1.elem(0,0), m2); \ | |
889 } \ | |
890 else if (m2_nr == 1 && m2_nc == 1) \ | |
891 { \ | |
892 extern OCTAVE_API SparseBoolMatrix F (const M1&, const double&); \ | |
893 extern OCTAVE_API SparseBoolMatrix F (const M1&, const Complex&); \ | |
894 r = F (m1, m2.elem(0,0)); \ | |
895 } \ | |
896 else if (m1_nr == m2_nr && m1_nc == m2_nc) \ | |
5164 | 897 { \ |
898 if (m1_nr != 0 || m1_nc != 0) \ | |
899 { \ | |
7269 | 900 r = SparseBoolMatrix (m1_nr, m1_nc, m1.nnz () + m2.nnz ()); \ |
901 r.cidx (0) = static_cast<octave_idx_type> (0); \ | |
902 octave_idx_type nel = 0; \ | |
5275 | 903 for (octave_idx_type j = 0; j < m1_nc; j++) \ |
7269 | 904 { \ |
905 octave_idx_type i1 = m1.cidx (j); \ | |
906 octave_idx_type e1 = m1.cidx (j+1); \ | |
907 octave_idx_type i2 = m2.cidx (j); \ | |
908 octave_idx_type e2 = m2.cidx (j+1); \ | |
909 while (i1 < e1 || i2 < e2) \ | |
910 { \ | |
911 if (i1 == e1 || (i2 < e2 && m1.ridx(i1) > m2.ridx(i2))) \ | |
912 { \ | |
913 if (LHS_ZERO OP m2.data (i2) != RHS_ZERO) \ | |
914 { \ | |
915 r.ridx (nel) = m2.ridx (i2); \ | |
916 r.data (nel++) = true; \ | |
917 } \ | |
918 i2++; \ | |
919 } \ | |
920 else if (i2 == e2 || m1.ridx(i1) < m2.ridx(i2)) \ | |
921 { \ | |
922 if (m1.data (i1) != LHS_ZERO OP RHS_ZERO) \ | |
923 { \ | |
924 r.ridx (nel) = m1.ridx (i1); \ | |
925 r.data (nel++) = true; \ | |
926 } \ | |
927 i1++; \ | |
928 } \ | |
929 else \ | |
930 { \ | |
931 if (m1.data (i1) != LHS_ZERO OP m2.data(i2) != RHS_ZERO) \ | |
932 { \ | |
933 r.ridx (nel) = m1.ridx (i1); \ | |
934 r.data (nel++) = true; \ | |
935 } \ | |
936 i1++; \ | |
937 i2++; \ | |
938 } \ | |
939 } \ | |
940 r.cidx (j + 1) = nel; \ | |
941 } \ | |
942 r.maybe_compress (false); \ | |
5164 | 943 } \ |
944 } \ | |
945 else \ | |
946 { \ | |
947 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ | |
948 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ | |
949 } \ | |
950 return r; \ | |
951 } | |
952 | |
953 #define SPARSE_SMSM_BOOL_OPS2(M1, M2, LHS_ZERO, RHS_ZERO) \ | |
954 SPARSE_SMSM_BOOL_OP (mx_el_and, &&, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
955 SPARSE_SMSM_BOOL_OP (mx_el_or, ||, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
956 | |
957 #define SPARSE_SMSM_BOOL_OPS(M1, M2, ZERO) \ | |
958 SPARSE_SMSM_BOOL_OPS2(M1, M2, ZERO, ZERO) | |
959 | |
6708 | 960 #define SPARSE_SMSM_OP_DECLS(R1, R2, M1, M2, API) \ |
961 SPARSE_SMSM_BIN_OP_DECLS (R1, R2, M1, M2, API) \ | |
962 SPARSE_SMSM_CMP_OP_DECLS (M1, M2, API) \ | |
963 SPARSE_SMSM_BOOL_OP_DECLS (M1, M2, API) | |
5164 | 964 |
965 // matrix by matrix operations. | |
966 | |
6708 | 967 #define SPARSE_MSM_BIN_OP_DECLS(R1, R2, M1, M2, API) \ |
968 SPARSE_BIN_OP_DECL (R1, operator +, M1, M2, API); \ | |
969 SPARSE_BIN_OP_DECL (R1, operator -, M1, M2, API); \ | |
970 SPARSE_BIN_OP_DECL (R2, product, M1, M2, API); \ | |
971 SPARSE_BIN_OP_DECL (R2, quotient, M1, M2, API); | |
5164 | 972 |
973 #define SPARSE_MSM_BIN_OP_1(R, F, OP, M1, M2) \ | |
974 R \ | |
975 F (const M1& m1, const M2& m2) \ | |
976 { \ | |
977 R r; \ | |
978 \ | |
5275 | 979 octave_idx_type m1_nr = m1.rows (); \ |
980 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 981 \ |
5275 | 982 octave_idx_type m2_nr = m2.rows (); \ |
983 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 984 \ |
6221 | 985 if (m2_nr == 1 && m2_nc == 1) \ |
986 r = R (m1 OP m2.elem(0,0)); \ | |
987 else if (m1_nr != m2_nr || m1_nc != m2_nc) \ | |
5164 | 988 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ |
989 else \ | |
990 { \ | |
991 r = R (m1_nr, m1_nc); \ | |
992 \ | |
5275 | 993 for (octave_idx_type j = 0; j < m1_nc; j++) \ |
994 for (octave_idx_type i = 0; i < m1_nr; i++) \ | |
5164 | 995 r.elem (i, j) = m1.elem (i, j) OP m2.elem (i, j); \ |
996 } \ | |
997 return r; \ | |
998 } | |
999 | |
1000 #define SPARSE_MSM_BIN_OP_2(R, F, OP, M1, M2, ZERO) \ | |
1001 R \ | |
1002 F (const M1& m1, const M2& m2) \ | |
1003 { \ | |
1004 R r; \ | |
1005 \ | |
5275 | 1006 octave_idx_type m1_nr = m1.rows (); \ |
1007 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 1008 \ |
5275 | 1009 octave_idx_type m2_nr = m2.rows (); \ |
1010 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 1011 \ |
6221 | 1012 if (m2_nr == 1 && m2_nc == 1) \ |
1013 r = R (m1 OP m2.elem(0,0)); \ | |
1014 else if (m1_nr != m2_nr || m1_nc != m2_nc) \ | |
5164 | 1015 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ |
1016 else \ | |
1017 { \ | |
1018 /* Count num of non-zero elements */ \ | |
5275 | 1019 octave_idx_type nel = 0; \ |
1020 for (octave_idx_type j = 0; j < m1_nc; j++) \ | |
1021 for (octave_idx_type i = 0; i < m1_nr; i++) \ | |
5164 | 1022 if ((m1.elem(i, j) OP m2.elem(i, j)) != ZERO) \ |
1023 nel++; \ | |
1024 \ | |
1025 r = R (m1_nr, m1_nc, nel); \ | |
1026 \ | |
5275 | 1027 octave_idx_type ii = 0; \ |
5164 | 1028 r.cidx (0) = 0; \ |
5275 | 1029 for (octave_idx_type j = 0 ; j < m1_nc ; j++) \ |
5164 | 1030 { \ |
5275 | 1031 for (octave_idx_type i = 0 ; i < m1_nr ; i++) \ |
5164 | 1032 { \ |
1033 if ((m1.elem(i, j) OP m2.elem(i, j)) != ZERO) \ | |
1034 { \ | |
1035 r.data (ii) = m1.elem(i, j) OP m2.elem(i,j); \ | |
1036 r.ridx (ii++) = i; \ | |
1037 } \ | |
1038 } \ | |
1039 r.cidx(j+1) = ii; \ | |
1040 } \ | |
1041 } \ | |
1042 \ | |
1043 return r; \ | |
1044 } | |
1045 | |
5775 | 1046 // FIXME Pass a specific ZERO value |
5164 | 1047 #define SPARSE_MSM_BIN_OPS(R1, R2, M1, M2) \ |
1048 SPARSE_MSM_BIN_OP_1 (R1, operator +, +, M1, M2) \ | |
1049 SPARSE_MSM_BIN_OP_1 (R1, operator -, -, M1, M2) \ | |
1050 SPARSE_MSM_BIN_OP_2 (R2, product, *, M1, M2, 0.0) \ | |
1051 SPARSE_MSM_BIN_OP_2 (R2, quotient, /, M1, M2, 0.0) | |
1052 | |
6708 | 1053 #define SPARSE_MSM_CMP_OP_DECLS(M1, M2, API) \ |
1054 SPARSE_CMP_OP_DECL (mx_el_lt, M1, M2, API); \ | |
1055 SPARSE_CMP_OP_DECL (mx_el_le, M1, M2, API); \ | |
1056 SPARSE_CMP_OP_DECL (mx_el_ge, M1, M2, API); \ | |
1057 SPARSE_CMP_OP_DECL (mx_el_gt, M1, M2, API); \ | |
1058 SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \ | |
1059 SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API); | |
5164 | 1060 |
6708 | 1061 #define SPARSE_MSM_EQNE_OP_DECLS(M1, M2, API) \ |
1062 SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \ | |
1063 SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API); | |
5164 | 1064 |
1065 #define SPARSE_MSM_CMP_OP(F, OP, M1, C1, M2, C2) \ | |
1066 SparseBoolMatrix \ | |
1067 F (const M1& m1, const M2& m2) \ | |
1068 { \ | |
1069 SparseBoolMatrix r; \ | |
1070 \ | |
5275 | 1071 octave_idx_type m1_nr = m1.rows (); \ |
1072 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 1073 \ |
5275 | 1074 octave_idx_type m2_nr = m2.rows (); \ |
1075 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 1076 \ |
6221 | 1077 if (m2_nr == 1 && m2_nc == 1) \ |
1078 r = SparseBoolMatrix (F (m1, m2.elem(0,0))); \ | |
1079 else if (m1_nr == m2_nr && m1_nc == m2_nc) \ | |
5164 | 1080 { \ |
1081 if (m1_nr != 0 || m1_nc != 0) \ | |
1082 { \ | |
1083 /* Count num of non-zero elements */ \ | |
5275 | 1084 octave_idx_type nel = 0; \ |
1085 for (octave_idx_type j = 0; j < m1_nc; j++) \ | |
1086 for (octave_idx_type i = 0; i < m1_nr; i++) \ | |
5164 | 1087 if (C1 (m1.elem(i, j)) OP C2 (m2.elem(i, j))) \ |
1088 nel++; \ | |
1089 \ | |
1090 r = SparseBoolMatrix (m1_nr, m1_nc, nel); \ | |
1091 \ | |
5275 | 1092 octave_idx_type ii = 0; \ |
5164 | 1093 r.cidx (0) = 0; \ |
5275 | 1094 for (octave_idx_type j = 0; j < m1_nc; j++) \ |
5164 | 1095 { \ |
5275 | 1096 for (octave_idx_type i = 0; i < m1_nr; i++) \ |
5164 | 1097 { \ |
1098 bool el = C1 (m1.elem(i, j)) OP C2 (m2.elem(i, j)); \ | |
1099 if (el) \ | |
1100 { \ | |
1101 r.data(ii) = el; \ | |
1102 r.ridx(ii++) = i; \ | |
1103 } \ | |
1104 } \ | |
1105 r.cidx(j+1) = ii; \ | |
1106 } \ | |
1107 } \ | |
1108 } \ | |
1109 else \ | |
1110 { \ | |
1111 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ | |
1112 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ | |
1113 } \ | |
1114 return r; \ | |
1115 } | |
1116 | |
1117 #define SPARSE_MSM_CMP_OPS(M1, Z1, C1, M2, Z2, C2) \ | |
1118 SPARSE_MSM_CMP_OP (mx_el_lt, <, M1, C1, M2, C2) \ | |
1119 SPARSE_MSM_CMP_OP (mx_el_le, <=, M1, C1, M2, C2) \ | |
1120 SPARSE_MSM_CMP_OP (mx_el_ge, >=, M1, C1, M2, C2) \ | |
1121 SPARSE_MSM_CMP_OP (mx_el_gt, >, M1, C1, M2, C2) \ | |
1122 SPARSE_MSM_CMP_OP (mx_el_eq, ==, M1, , M2, ) \ | |
1123 SPARSE_MSM_CMP_OP (mx_el_ne, !=, M1, , M2, ) | |
1124 | |
1125 #define SPARSE_MSM_EQNE_OPS(M1, Z1, C1, M2, Z2, C2) \ | |
1126 SPARSE_MSM_CMP_OP (mx_el_eq, ==, M1, , M2, ) \ | |
1127 SPARSE_MSM_CMP_OP (mx_el_ne, !=, M1, , M2, ) | |
1128 | |
6708 | 1129 #define SPARSE_MSM_BOOL_OP_DECLS(M1, M2, API) \ |
1130 SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2, API); \ | |
1131 SPARSE_BOOL_OP_DECL (mx_el_or, M1, M2, API); | |
5164 | 1132 |
1133 #define SPARSE_MSM_BOOL_OP(F, OP, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
1134 SparseBoolMatrix \ | |
1135 F (const M1& m1, const M2& m2) \ | |
1136 { \ | |
1137 SparseBoolMatrix r; \ | |
1138 \ | |
5275 | 1139 octave_idx_type m1_nr = m1.rows (); \ |
1140 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 1141 \ |
5275 | 1142 octave_idx_type m2_nr = m2.rows (); \ |
1143 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 1144 \ |
6221 | 1145 if (m2_nr == 1 && m2_nc == 1) \ |
1146 r = SparseBoolMatrix (F (m1, m2.elem(0,0))); \ | |
1147 else if (m1_nr == m2_nr && m1_nc == m2_nc) \ | |
5164 | 1148 { \ |
1149 if (m1_nr != 0 || m1_nc != 0) \ | |
1150 { \ | |
1151 /* Count num of non-zero elements */ \ | |
5275 | 1152 octave_idx_type nel = 0; \ |
1153 for (octave_idx_type j = 0; j < m1_nc; j++) \ | |
1154 for (octave_idx_type i = 0; i < m1_nr; i++) \ | |
5164 | 1155 if ((m1.elem(i, j) != LHS_ZERO) \ |
1156 OP (m2.elem(i, j) != RHS_ZERO)) \ | |
1157 nel++; \ | |
1158 \ | |
1159 r = SparseBoolMatrix (m1_nr, m1_nc, nel); \ | |
1160 \ | |
5275 | 1161 octave_idx_type ii = 0; \ |
5164 | 1162 r.cidx (0) = 0; \ |
5275 | 1163 for (octave_idx_type j = 0; j < m1_nc; j++) \ |
5164 | 1164 { \ |
5275 | 1165 for (octave_idx_type i = 0; i < m1_nr; i++) \ |
5164 | 1166 { \ |
1167 bool el = (m1.elem(i, j) != LHS_ZERO) \ | |
1168 OP (m2.elem(i, j) != RHS_ZERO); \ | |
1169 if (el) \ | |
1170 { \ | |
1171 r.data(ii) = el; \ | |
1172 r.ridx(ii++) = i; \ | |
1173 } \ | |
1174 } \ | |
1175 r.cidx(j+1) = ii; \ | |
1176 } \ | |
1177 } \ | |
1178 } \ | |
1179 else \ | |
1180 { \ | |
1181 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ | |
1182 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ | |
1183 } \ | |
1184 return r; \ | |
1185 } | |
1186 | |
1187 #define SPARSE_MSM_BOOL_OPS2(M1, M2, LHS_ZERO, RHS_ZERO) \ | |
1188 SPARSE_MSM_BOOL_OP (mx_el_and, &&, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
1189 SPARSE_MSM_BOOL_OP (mx_el_or, ||, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
1190 | |
1191 #define SPARSE_MSM_BOOL_OPS(M1, M2, ZERO) \ | |
1192 SPARSE_MSM_BOOL_OPS2(M1, M2, ZERO, ZERO) | |
1193 | |
6708 | 1194 #define SPARSE_MSM_OP_DECLS(R1, R2, M1, M2, API) \ |
1195 SPARSE_MSM_BIN_OP_DECLS (R1, R2, M1, M2, API) \ | |
1196 SPARSE_MSM_CMP_OP_DECLS (M1, M2, API) \ | |
1197 SPARSE_MSM_BOOL_OP_DECLS (M1, M2, API) | |
5164 | 1198 |
1199 // matrix by matrix operations. | |
1200 | |
6708 | 1201 #define SPARSE_SMM_BIN_OP_DECLS(R1, R2, M1, M2, API) \ |
1202 SPARSE_BIN_OP_DECL (R1, operator +, M1, M2, API); \ | |
1203 SPARSE_BIN_OP_DECL (R1, operator -, M1, M2, API); \ | |
1204 SPARSE_BIN_OP_DECL (R2, product, M1, M2, API); \ | |
1205 SPARSE_BIN_OP_DECL (R2, quotient, M1, M2, API); | |
5164 | 1206 |
1207 #define SPARSE_SMM_BIN_OP_1(R, F, OP, M1, M2) \ | |
1208 R \ | |
1209 F (const M1& m1, const M2& m2) \ | |
1210 { \ | |
1211 R r; \ | |
1212 \ | |
5275 | 1213 octave_idx_type m1_nr = m1.rows (); \ |
1214 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 1215 \ |
5275 | 1216 octave_idx_type m2_nr = m2.rows (); \ |
1217 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 1218 \ |
6221 | 1219 if (m1_nr == 1 && m1_nc == 1) \ |
1220 r = R (m1.elem(0,0) OP m2); \ | |
1221 else if (m1_nr != m2_nr || m1_nc != m2_nc) \ | |
5164 | 1222 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ |
1223 else \ | |
1224 { \ | |
1225 r = R (m1_nr, m1_nc); \ | |
1226 \ | |
5275 | 1227 for (octave_idx_type j = 0; j < m1_nc; j++) \ |
1228 for (octave_idx_type i = 0; i < m1_nr; i++) \ | |
5164 | 1229 r.elem (i, j) = m1.elem (i, j) OP m2.elem (i, j); \ |
1230 } \ | |
1231 return r; \ | |
1232 } | |
1233 | |
1234 #define SPARSE_SMM_BIN_OP_2(R, F, OP, M1, M2, ZERO) \ | |
1235 R \ | |
1236 F (const M1& m1, const M2& m2) \ | |
1237 { \ | |
1238 R r; \ | |
1239 \ | |
5275 | 1240 octave_idx_type m1_nr = m1.rows (); \ |
1241 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 1242 \ |
5275 | 1243 octave_idx_type m2_nr = m2.rows (); \ |
1244 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 1245 \ |
6221 | 1246 if (m1_nr == 1 && m1_nc == 1) \ |
1247 r = R (m1.elem(0,0) OP m2); \ | |
1248 else if (m1_nr != m2_nr || m1_nc != m2_nc) \ | |
5164 | 1249 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ |
1250 else \ | |
1251 { \ | |
1252 /* Count num of non-zero elements */ \ | |
5275 | 1253 octave_idx_type nel = 0; \ |
1254 for (octave_idx_type j = 0; j < m1_nc; j++) \ | |
1255 for (octave_idx_type i = 0; i < m1_nr; i++) \ | |
5164 | 1256 if ((m1.elem(i, j) OP m2.elem(i, j)) != ZERO) \ |
1257 nel++; \ | |
1258 \ | |
1259 r = R (m1_nr, m1_nc, nel); \ | |
1260 \ | |
5275 | 1261 octave_idx_type ii = 0; \ |
5164 | 1262 r.cidx (0) = 0; \ |
5275 | 1263 for (octave_idx_type j = 0 ; j < m1_nc ; j++) \ |
5164 | 1264 { \ |
5275 | 1265 for (octave_idx_type i = 0 ; i < m1_nr ; i++) \ |
5164 | 1266 { \ |
1267 if ((m1.elem(i, j) OP m2.elem(i, j)) != ZERO) \ | |
1268 { \ | |
1269 r.data (ii) = m1.elem(i, j) OP m2.elem(i,j); \ | |
1270 r.ridx (ii++) = i; \ | |
1271 } \ | |
1272 } \ | |
1273 r.cidx(j+1) = ii; \ | |
1274 } \ | |
1275 } \ | |
1276 \ | |
1277 return r; \ | |
1278 } | |
1279 | |
5775 | 1280 // FIXME Pass a specific ZERO value |
5164 | 1281 #define SPARSE_SMM_BIN_OPS(R1, R2, M1, M2) \ |
1282 SPARSE_SMM_BIN_OP_1 (R1, operator +, +, M1, M2) \ | |
1283 SPARSE_SMM_BIN_OP_1 (R1, operator -, -, M1, M2) \ | |
1284 SPARSE_SMM_BIN_OP_2 (R2, product, *, M1, M2, 0.0) \ | |
1285 SPARSE_SMM_BIN_OP_2 (R2, quotient, /, M1, M2, 0.0) | |
1286 | |
6708 | 1287 #define SPARSE_SMM_CMP_OP_DECLS(M1, M2, API) \ |
1288 SPARSE_CMP_OP_DECL (mx_el_lt, M1, M2, API); \ | |
1289 SPARSE_CMP_OP_DECL (mx_el_le, M1, M2, API); \ | |
1290 SPARSE_CMP_OP_DECL (mx_el_ge, M1, M2, API); \ | |
1291 SPARSE_CMP_OP_DECL (mx_el_gt, M1, M2, API); \ | |
1292 SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \ | |
1293 SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API); | |
5164 | 1294 |
6708 | 1295 #define SPARSE_SMM_EQNE_OP_DECLS(M1, M2, API) \ |
1296 SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \ | |
1297 SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API); | |
5164 | 1298 |
1299 #define SPARSE_SMM_CMP_OP(F, OP, M1, C1, M2, C2) \ | |
1300 SparseBoolMatrix \ | |
1301 F (const M1& m1, const M2& m2) \ | |
1302 { \ | |
1303 SparseBoolMatrix r; \ | |
1304 \ | |
5275 | 1305 octave_idx_type m1_nr = m1.rows (); \ |
1306 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 1307 \ |
5275 | 1308 octave_idx_type m2_nr = m2.rows (); \ |
1309 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 1310 \ |
6221 | 1311 if (m1_nr == 1 && m1_nc == 1) \ |
1312 r = SparseBoolMatrix (F (m1.elem(0,0), m2)); \ | |
1313 else if (m1_nr == m2_nr && m1_nc == m2_nc) \ | |
5164 | 1314 { \ |
1315 if (m1_nr != 0 || m1_nc != 0) \ | |
1316 { \ | |
1317 /* Count num of non-zero elements */ \ | |
5275 | 1318 octave_idx_type nel = 0; \ |
1319 for (octave_idx_type j = 0; j < m1_nc; j++) \ | |
1320 for (octave_idx_type i = 0; i < m1_nr; i++) \ | |
5164 | 1321 if (C1 (m1.elem(i, j)) OP C2 (m2.elem(i, j))) \ |
1322 nel++; \ | |
1323 \ | |
1324 r = SparseBoolMatrix (m1_nr, m1_nc, nel); \ | |
1325 \ | |
5275 | 1326 octave_idx_type ii = 0; \ |
5164 | 1327 r.cidx (0) = 0; \ |
5275 | 1328 for (octave_idx_type j = 0; j < m1_nc; j++) \ |
5164 | 1329 { \ |
5275 | 1330 for (octave_idx_type i = 0; i < m1_nr; i++) \ |
5164 | 1331 { \ |
1332 bool el = C1 (m1.elem(i, j)) OP C2 (m2.elem(i, j)); \ | |
1333 if (el) \ | |
1334 { \ | |
1335 r.data(ii) = el; \ | |
1336 r.ridx(ii++) = i; \ | |
1337 } \ | |
1338 } \ | |
1339 r.cidx(j+1) = ii; \ | |
1340 } \ | |
1341 } \ | |
1342 } \ | |
1343 else \ | |
1344 { \ | |
1345 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ | |
1346 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ | |
1347 } \ | |
1348 return r; \ | |
1349 } | |
1350 | |
1351 #define SPARSE_SMM_CMP_OPS(M1, Z1, C1, M2, Z2, C2) \ | |
1352 SPARSE_SMM_CMP_OP (mx_el_lt, <, M1, C1, M2, C2) \ | |
1353 SPARSE_SMM_CMP_OP (mx_el_le, <=, M1, C1, M2, C2) \ | |
1354 SPARSE_SMM_CMP_OP (mx_el_ge, >=, M1, C1, M2, C2) \ | |
1355 SPARSE_SMM_CMP_OP (mx_el_gt, >, M1, C1, M2, C2) \ | |
1356 SPARSE_SMM_CMP_OP (mx_el_eq, ==, M1, , M2, ) \ | |
1357 SPARSE_SMM_CMP_OP (mx_el_ne, !=, M1, , M2, ) | |
1358 | |
1359 #define SPARSE_SMM_EQNE_OPS(M1, Z1, C1, M2, Z2, C2) \ | |
1360 SPARSE_SMM_CMP_OP (mx_el_eq, ==, M1, , M2, ) \ | |
1361 SPARSE_SMM_CMP_OP (mx_el_ne, !=, M1, , M2, ) | |
1362 | |
6708 | 1363 #define SPARSE_SMM_BOOL_OP_DECLS(M1, M2, API) \ |
1364 SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2, API); \ | |
1365 SPARSE_BOOL_OP_DECL (mx_el_or, M1, M2, API); | |
5164 | 1366 |
1367 #define SPARSE_SMM_BOOL_OP(F, OP, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
1368 SparseBoolMatrix \ | |
1369 F (const M1& m1, const M2& m2) \ | |
1370 { \ | |
1371 SparseBoolMatrix r; \ | |
1372 \ | |
5275 | 1373 octave_idx_type m1_nr = m1.rows (); \ |
1374 octave_idx_type m1_nc = m1.cols (); \ | |
5164 | 1375 \ |
5275 | 1376 octave_idx_type m2_nr = m2.rows (); \ |
1377 octave_idx_type m2_nc = m2.cols (); \ | |
5164 | 1378 \ |
6221 | 1379 if (m1_nr == 1 && m1_nc == 1) \ |
1380 r = SparseBoolMatrix (F (m1.elem(0,0), m2)); \ | |
1381 else if (m1_nr == m2_nr && m1_nc == m2_nc) \ | |
5164 | 1382 { \ |
1383 if (m1_nr != 0 || m1_nc != 0) \ | |
1384 { \ | |
1385 /* Count num of non-zero elements */ \ | |
5275 | 1386 octave_idx_type nel = 0; \ |
1387 for (octave_idx_type j = 0; j < m1_nc; j++) \ | |
1388 for (octave_idx_type i = 0; i < m1_nr; i++) \ | |
5164 | 1389 if ((m1.elem(i, j) != LHS_ZERO) \ |
1390 OP (m2.elem(i, j) != RHS_ZERO)) \ | |
1391 nel++; \ | |
1392 \ | |
1393 r = SparseBoolMatrix (m1_nr, m1_nc, nel); \ | |
1394 \ | |
5275 | 1395 octave_idx_type ii = 0; \ |
5164 | 1396 r.cidx (0) = 0; \ |
5275 | 1397 for (octave_idx_type j = 0; j < m1_nc; j++) \ |
5164 | 1398 { \ |
5275 | 1399 for (octave_idx_type i = 0; i < m1_nr; i++) \ |
5164 | 1400 { \ |
1401 bool el = (m1.elem(i, j) != LHS_ZERO) \ | |
1402 OP (m2.elem(i, j) != RHS_ZERO); \ | |
1403 if (el) \ | |
1404 { \ | |
1405 r.data(ii) = el; \ | |
1406 r.ridx(ii++) = i; \ | |
1407 } \ | |
1408 } \ | |
1409 r.cidx(j+1) = ii; \ | |
1410 } \ | |
1411 } \ | |
1412 } \ | |
1413 else \ | |
1414 { \ | |
1415 if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ | |
1416 gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ | |
1417 } \ | |
1418 return r; \ | |
1419 } | |
1420 | |
1421 #define SPARSE_SMM_BOOL_OPS2(M1, M2, LHS_ZERO, RHS_ZERO) \ | |
1422 SPARSE_SMM_BOOL_OP (mx_el_and, &&, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
1423 SPARSE_SMM_BOOL_OP (mx_el_or, ||, M1, M2, LHS_ZERO, RHS_ZERO) \ | |
1424 | |
1425 #define SPARSE_SMM_BOOL_OPS(M1, M2, ZERO) \ | |
1426 SPARSE_SMM_BOOL_OPS2(M1, M2, ZERO, ZERO) | |
1427 | |
6708 | 1428 #define SPARSE_SMM_OP_DECLS(R1, R2, M1, M2, API) \ |
1429 SPARSE_SMM_BIN_OP_DECLS (R1, R2, M1, M2, API) \ | |
1430 SPARSE_SMM_CMP_OP_DECLS (M1, M2, API) \ | |
1431 SPARSE_SMM_BOOL_OP_DECLS (M1, M2, API) | |
5164 | 1432 |
1433 // Avoid some code duplication. Maybe we should use templates. | |
1434 | |
1435 #define SPARSE_CUMSUM(RET_TYPE, ELT_TYPE, FCN) \ | |
1436 \ | |
5275 | 1437 octave_idx_type nr = rows (); \ |
1438 octave_idx_type nc = cols (); \ | |
5164 | 1439 \ |
1440 RET_TYPE retval; \ | |
1441 \ | |
1442 if (nr > 0 && nc > 0) \ | |
1443 { \ | |
1444 if ((nr == 1 && dim == -1) || dim == 1) \ | |
1445 /* Ugly!! Is there a better way? */ \ | |
1446 retval = transpose (). FCN (0) .transpose (); \ | |
1447 else \ | |
1448 { \ | |
5275 | 1449 octave_idx_type nel = 0; \ |
1450 for (octave_idx_type i = 0; i < nc; i++) \ | |
5164 | 1451 { \ |
1452 ELT_TYPE t = ELT_TYPE (); \ | |
5275 | 1453 for (octave_idx_type j = cidx (i); j < cidx (i+1); j++) \ |
5164 | 1454 { \ |
1455 t += data(j); \ | |
1456 if (t != ELT_TYPE ()) \ | |
6482 | 1457 { \ |
1458 if (j == cidx(i+1) - 1) \ | |
1459 nel += nr - ridx(j); \ | |
1460 else \ | |
1461 nel += ridx(j+1) - ridx(j); \ | |
1462 } \ | |
5164 | 1463 } \ |
1464 } \ | |
1465 retval = RET_TYPE (nr, nc, nel); \ | |
1466 retval.cidx(0) = 0; \ | |
5275 | 1467 octave_idx_type ii = 0; \ |
1468 for (octave_idx_type i = 0; i < nc; i++) \ | |
5164 | 1469 { \ |
1470 ELT_TYPE t = ELT_TYPE (); \ | |
5275 | 1471 for (octave_idx_type j = cidx (i); j < cidx (i+1); j++) \ |
5164 | 1472 { \ |
1473 t += data(j); \ | |
1474 if (t != ELT_TYPE ()) \ | |
1475 { \ | |
1476 if (j == cidx(i+1) - 1) \ | |
1477 { \ | |
5275 | 1478 for (octave_idx_type k = ridx(j); k < nr; k++) \ |
5164 | 1479 { \ |
1480 retval.data (ii) = t; \ | |
1481 retval.ridx (ii++) = k; \ | |
1482 } \ | |
1483 } \ | |
1484 else \ | |
1485 { \ | |
5275 | 1486 for (octave_idx_type k = ridx(j); k < ridx(j+1); k++) \ |
5164 | 1487 { \ |
1488 retval.data (ii) = t; \ | |
1489 retval.ridx (ii++) = k; \ | |
1490 } \ | |
1491 } \ | |
1492 } \ | |
1493 } \ | |
1494 retval.cidx(i+1) = ii; \ | |
1495 } \ | |
1496 } \ | |
1497 } \ | |
1498 else \ | |
1499 retval = RET_TYPE (nr,nc); \ | |
1500 \ | |
1501 return retval | |
1502 | |
1503 | |
1504 #define SPARSE_CUMPROD(RET_TYPE, ELT_TYPE, FCN) \ | |
1505 \ | |
5275 | 1506 octave_idx_type nr = rows (); \ |
1507 octave_idx_type nc = cols (); \ | |
5164 | 1508 \ |
1509 RET_TYPE retval; \ | |
1510 \ | |
1511 if (nr > 0 && nc > 0) \ | |
1512 { \ | |
1513 if ((nr == 1 && dim == -1) || dim == 1) \ | |
1514 /* Ugly!! Is there a better way? */ \ | |
1515 retval = transpose (). FCN (0) .transpose (); \ | |
1516 else \ | |
1517 { \ | |
5275 | 1518 octave_idx_type nel = 0; \ |
1519 for (octave_idx_type i = 0; i < nc; i++) \ | |
5164 | 1520 { \ |
5275 | 1521 octave_idx_type jj = 0; \ |
1522 for (octave_idx_type j = cidx (i); j < cidx (i+1); j++) \ | |
5164 | 1523 { \ |
1524 if (jj == ridx(j)) \ | |
1525 { \ | |
1526 nel++; \ | |
1527 jj++; \ | |
1528 } \ | |
1529 else \ | |
1530 break; \ | |
1531 } \ | |
1532 } \ | |
1533 retval = RET_TYPE (nr, nc, nel); \ | |
1534 retval.cidx(0) = 0; \ | |
5275 | 1535 octave_idx_type ii = 0; \ |
1536 for (octave_idx_type i = 0; i < nc; i++) \ | |
5164 | 1537 { \ |
1538 ELT_TYPE t = ELT_TYPE (1.); \ | |
5275 | 1539 octave_idx_type jj = 0; \ |
1540 for (octave_idx_type j = cidx (i); j < cidx (i+1); j++) \ | |
5164 | 1541 { \ |
1542 if (jj == ridx(j)) \ | |
1543 { \ | |
1544 t *= data(j); \ | |
1545 retval.data(ii) = t; \ | |
1546 retval.ridx(ii++) = jj++; \ | |
1547 } \ | |
1548 else \ | |
1549 break; \ | |
1550 } \ | |
1551 retval.cidx(i+1) = ii; \ | |
1552 } \ | |
1553 } \ | |
1554 } \ | |
1555 else \ | |
1556 retval = RET_TYPE (nr,nc); \ | |
1557 \ | |
1558 return retval | |
1559 | |
1560 #define SPARSE_BASE_REDUCTION_OP(RET_TYPE, EL_TYPE, ROW_EXPR, COL_EXPR, \ | |
1561 INIT_VAL, MT_RESULT) \ | |
1562 \ | |
5275 | 1563 octave_idx_type nr = rows (); \ |
1564 octave_idx_type nc = cols (); \ | |
5164 | 1565 \ |
1566 RET_TYPE retval; \ | |
1567 \ | |
1568 if (nr > 0 && nc > 0) \ | |
1569 { \ | |
1570 if ((nr == 1 && dim == -1) || dim == 1) \ | |
1571 { \ | |
7269 | 1572 /* Define j here to allow fancy definition for prod method */ \ |
1573 octave_idx_type j = 0; \ | |
5164 | 1574 OCTAVE_LOCAL_BUFFER (EL_TYPE, tmp, nr); \ |
1575 \ | |
5275 | 1576 for (octave_idx_type i = 0; i < nr; i++) \ |
7269 | 1577 tmp[i] = INIT_VAL; \ |
1578 for (j = 0; j < nc; j++) \ | |
1579 { \ | |
1580 for (octave_idx_type i = cidx(j); i < cidx(j + 1); i++) \ | |
1581 { \ | |
1582 ROW_EXPR; \ | |
1583 } \ | |
5164 | 1584 } \ |
5275 | 1585 octave_idx_type nel = 0; \ |
1586 for (octave_idx_type i = 0; i < nr; i++) \ | |
5164 | 1587 if (tmp[i] != EL_TYPE ()) \ |
1588 nel++ ; \ | |
5275 | 1589 retval = RET_TYPE (nr, static_cast<octave_idx_type> (1), nel); \ |
5164 | 1590 retval.cidx(0) = 0; \ |
1591 retval.cidx(1) = nel; \ | |
1592 nel = 0; \ | |
5275 | 1593 for (octave_idx_type i = 0; i < nr; i++) \ |
5164 | 1594 if (tmp[i] != EL_TYPE ()) \ |
1595 { \ | |
1596 retval.data(nel) = tmp[i]; \ | |
1597 retval.ridx(nel++) = i; \ | |
1598 } \ | |
1599 } \ | |
1600 else \ | |
1601 { \ | |
1602 OCTAVE_LOCAL_BUFFER (EL_TYPE, tmp, nc); \ | |
1603 \ | |
5275 | 1604 for (octave_idx_type j = 0; j < nc; j++) \ |
5164 | 1605 { \ |
1606 tmp[j] = INIT_VAL; \ | |
7269 | 1607 for (octave_idx_type i = cidx(j); i < cidx(j + 1); i++) \ |
1608 { \ | |
5164 | 1609 COL_EXPR; \ |
7269 | 1610 } \ |
5164 | 1611 } \ |
5275 | 1612 octave_idx_type nel = 0; \ |
1613 for (octave_idx_type i = 0; i < nc; i++) \ | |
5164 | 1614 if (tmp[i] != EL_TYPE ()) \ |
1615 nel++ ; \ | |
5275 | 1616 retval = RET_TYPE (static_cast<octave_idx_type> (1), nc, nel); \ |
5164 | 1617 retval.cidx(0) = 0; \ |
1618 nel = 0; \ | |
5275 | 1619 for (octave_idx_type i = 0; i < nc; i++) \ |
5164 | 1620 if (tmp[i] != EL_TYPE ()) \ |
1621 { \ | |
1622 retval.data(nel) = tmp[i]; \ | |
1623 retval.ridx(nel++) = 0; \ | |
1624 retval.cidx(i+1) = retval.cidx(i) + 1; \ | |
1625 } \ | |
1626 else \ | |
1627 retval.cidx(i+1) = retval.cidx(i); \ | |
1628 } \ | |
1629 } \ | |
1630 else if (nc == 0 && (nr == 0 || (nr == 1 && dim == -1))) \ | |
1631 { \ | |
7197 | 1632 if (MT_RESULT) \ |
1633 { \ | |
1634 retval = RET_TYPE (static_cast<octave_idx_type> (1), \ | |
1635 static_cast<octave_idx_type> (1), \ | |
1636 static_cast<octave_idx_type> (1)); \ | |
1637 retval.cidx(0) = 0; \ | |
1638 retval.cidx(1) = 1; \ | |
1639 retval.ridx(0) = 0; \ | |
1640 retval.data(0) = MT_RESULT; \ | |
1641 } \ | |
1642 else \ | |
1643 retval = RET_TYPE (static_cast<octave_idx_type> (1), \ | |
1644 static_cast<octave_idx_type> (1), \ | |
1645 static_cast<octave_idx_type> (0)); \ | |
5164 | 1646 } \ |
1647 else if (nr == 0 && (dim == 0 || dim == -1)) \ | |
1648 { \ | |
7197 | 1649 if (MT_RESULT) \ |
5164 | 1650 { \ |
7197 | 1651 retval = RET_TYPE (static_cast<octave_idx_type> (1), nc, nc); \ |
1652 retval.cidx (0) = 0; \ | |
1653 for (octave_idx_type i = 0; i < nc ; i++) \ | |
1654 { \ | |
1655 retval.ridx (i) = 0; \ | |
1656 retval.cidx (i+1) = i; \ | |
1657 retval.data (i) = MT_RESULT; \ | |
1658 } \ | |
1659 } \ | |
1660 else \ | |
1661 retval = RET_TYPE (static_cast<octave_idx_type> (1), nc, \ | |
1662 static_cast<octave_idx_type> (0)); \ | |
5164 | 1663 } \ |
1664 else if (nc == 0 && dim == 1) \ | |
1665 { \ | |
7197 | 1666 if (MT_RESULT) \ |
1667 { \ | |
1668 retval = RET_TYPE (nr, static_cast<octave_idx_type> (1), nr); \ | |
1669 retval.cidx(0) = 0; \ | |
1670 retval.cidx(1) = nr; \ | |
1671 for (octave_idx_type i = 0; i < nr; i++) \ | |
1672 { \ | |
1673 retval.ridx(i) = i; \ | |
1674 retval.data(i) = MT_RESULT; \ | |
1675 } \ | |
1676 } \ | |
1677 else \ | |
1678 retval = RET_TYPE (nr, static_cast<octave_idx_type> (1), \ | |
1679 static_cast<octave_idx_type> (0)); \ | |
5164 | 1680 } \ |
1681 else \ | |
1682 retval.resize (nr > 0, nc > 0); \ | |
1683 \ | |
1684 return retval | |
1685 | |
1686 #define SPARSE_REDUCTION_OP_ROW_EXPR(OP) \ | |
7269 | 1687 tmp[ridx(i)] OP data (i) |
5164 | 1688 |
1689 #define SPARSE_REDUCTION_OP_COL_EXPR(OP) \ | |
7269 | 1690 tmp[j] OP data (i) |
5164 | 1691 |
1692 #define SPARSE_REDUCTION_OP(RET_TYPE, EL_TYPE, OP, INIT_VAL, MT_RESULT) \ | |
1693 SPARSE_BASE_REDUCTION_OP (RET_TYPE, EL_TYPE, \ | |
1694 SPARSE_REDUCTION_OP_ROW_EXPR (OP), \ | |
1695 SPARSE_REDUCTION_OP_COL_EXPR (OP), \ | |
1696 INIT_VAL, MT_RESULT) | |
1697 | |
7350 | 1698 |
1699 // Don't break from this loop if the test succeeds because | |
1700 // we are looping over the rows and not the columns in the inner | |
1701 // loop. | |
5164 | 1702 #define SPARSE_ANY_ALL_OP_ROW_CODE(TEST_OP, TEST_TRUE_VAL) \ |
7269 | 1703 if (data (i) TEST_OP 0.0) \ |
7350 | 1704 tmp[ridx(i)] = TEST_TRUE_VAL; \ |
5164 | 1705 |
1706 #define SPARSE_ANY_ALL_OP_COL_CODE(TEST_OP, TEST_TRUE_VAL) \ | |
7269 | 1707 if (data (i) TEST_OP 0.0) \ |
5164 | 1708 { \ |
1709 tmp[j] = TEST_TRUE_VAL; \ | |
1710 break; \ | |
1711 } | |
1712 | |
7269 | 1713 #define SPARSE_ANY_ALL_OP(DIM, INIT_VAL, MT_RESULT, TEST_OP, TEST_TRUE_VAL) \ |
5164 | 1714 SPARSE_BASE_REDUCTION_OP (SparseBoolMatrix, char, \ |
1715 SPARSE_ANY_ALL_OP_ROW_CODE (TEST_OP, TEST_TRUE_VAL), \ | |
1716 SPARSE_ANY_ALL_OP_COL_CODE (TEST_OP, TEST_TRUE_VAL), \ | |
7269 | 1717 INIT_VAL, MT_RESULT) |
5164 | 1718 |
7269 | 1719 #define SPARSE_ALL_OP(DIM) \ |
1720 if ((rows() == 1 && dim == -1) || dim == 1) \ | |
1721 return transpose (). all (0). transpose(); \ | |
1722 else \ | |
1723 { \ | |
1724 SPARSE_ANY_ALL_OP (DIM, (cidx(j+1) - cidx(j) < nc ? false : true), \ | |
1725 true, ==, false); \ | |
1726 } | |
5164 | 1727 |
7269 | 1728 #define SPARSE_ANY_OP(DIM) SPARSE_ANY_ALL_OP (DIM, false, false, !=, true) |
5164 | 1729 |
5681 | 1730 #define SPARSE_SPARSE_MUL( RET_TYPE, RET_EL_TYPE, EL_TYPE ) \ |
5275 | 1731 octave_idx_type nr = m.rows (); \ |
1732 octave_idx_type nc = m.cols (); \ | |
5164 | 1733 \ |
5275 | 1734 octave_idx_type a_nr = a.rows (); \ |
1735 octave_idx_type a_nc = a.cols (); \ | |
5164 | 1736 \ |
6221 | 1737 if (nr == 1 && nc == 1) \ |
1738 { \ | |
1739 RET_EL_TYPE s = m.elem(0,0); \ | |
1740 octave_idx_type nz = a.nnz(); \ | |
1741 RET_TYPE r (a_nr, a_nc, nz); \ | |
1742 \ | |
1743 for (octave_idx_type i = 0; i < nz; i++) \ | |
1744 { \ | |
1745 OCTAVE_QUIT; \ | |
1746 r.data(i) = s * a.data(i); \ | |
1747 r.ridx(i) = a.ridx(i); \ | |
1748 } \ | |
1749 for (octave_idx_type i = 0; i < a_nc + 1; i++) \ | |
1750 { \ | |
1751 OCTAVE_QUIT; \ | |
1752 r.cidx(i) = a.cidx(i); \ | |
1753 } \ | |
1754 \ | |
1755 r.maybe_compress (true); \ | |
1756 return r; \ | |
1757 } \ | |
1758 else if (a_nr == 1 && a_nc == 1) \ | |
1759 { \ | |
1760 RET_EL_TYPE s = a.elem(0,0); \ | |
1761 octave_idx_type nz = m.nnz(); \ | |
1762 RET_TYPE r (nr, nc, nz); \ | |
1763 \ | |
1764 for (octave_idx_type i = 0; i < nz; i++) \ | |
1765 { \ | |
1766 OCTAVE_QUIT; \ | |
1767 r.data(i) = m.data(i) * s; \ | |
1768 r.ridx(i) = m.ridx(i); \ | |
1769 } \ | |
1770 for (octave_idx_type i = 0; i < nc + 1; i++) \ | |
1771 { \ | |
1772 OCTAVE_QUIT; \ | |
1773 r.cidx(i) = m.cidx(i); \ | |
1774 } \ | |
1775 \ | |
1776 r.maybe_compress (true); \ | |
1777 return r; \ | |
1778 } \ | |
1779 else if (nc != a_nr) \ | |
5164 | 1780 { \ |
1781 gripe_nonconformant ("operator *", nr, nc, a_nr, a_nc); \ | |
1782 return RET_TYPE (); \ | |
1783 } \ | |
1784 else \ | |
1785 { \ | |
5586 | 1786 OCTAVE_LOCAL_BUFFER (octave_idx_type, w, nr); \ |
5876 | 1787 RET_TYPE retval (nr, a_nc, static_cast<octave_idx_type> (0)); \ |
5586 | 1788 for (octave_idx_type i = 0; i < nr; i++) \ |
1789 w[i] = 0; \ | |
5795 | 1790 retval.xcidx(0) = 0; \ |
5164 | 1791 \ |
5275 | 1792 octave_idx_type nel = 0; \ |
5164 | 1793 \ |
5275 | 1794 for (octave_idx_type i = 0; i < a_nc; i++) \ |
5164 | 1795 { \ |
5275 | 1796 for (octave_idx_type j = a.cidx(i); j < a.cidx(i+1); j++) \ |
5164 | 1797 { \ |
5275 | 1798 octave_idx_type col = a.ridx(j); \ |
1799 for (octave_idx_type k = m.cidx(col) ; k < m.cidx(col+1); k++) \ | |
5586 | 1800 { \ |
1801 if (w[m.ridx(k)] < i + 1) \ | |
1802 { \ | |
1803 w[m.ridx(k)] = i + 1; \ | |
1804 nel++; \ | |
1805 } \ | |
5587 | 1806 OCTAVE_QUIT; \ |
5586 | 1807 } \ |
5164 | 1808 } \ |
5795 | 1809 retval.xcidx(i+1) = nel; \ |
5164 | 1810 } \ |
1811 \ | |
1812 if (nel == 0) \ | |
1813 return RET_TYPE (nr, a_nc); \ | |
1814 else \ | |
1815 { \ | |
5586 | 1816 for (octave_idx_type i = 0; i < nr; i++) \ |
1817 w[i] = 0; \ | |
1818 \ | |
5681 | 1819 OCTAVE_LOCAL_BUFFER (RET_EL_TYPE, Xcol, nr); \ |
5586 | 1820 \ |
5795 | 1821 retval.change_capacity (nel); \ |
5587 | 1822 /* The optimal break-point as estimated from simulations */ \ |
1823 /* Note that Mergesort is O(nz log(nz)) while searching all */ \ | |
1824 /* values is O(nr), where nz here is non-zero per row of */ \ | |
1825 /* length nr. The test itself was then derived from the */ \ | |
1826 /* simulation with random square matrices and the observation */ \ | |
1827 /* of the number of non-zero elements in the output matrix */ \ | |
1828 /* it was found that the breakpoints were */ \ | |
1829 /* nr: 500 1000 2000 5000 10000 */ \ | |
1830 /* nz: 6 25 97 585 2202 */ \ | |
1831 /* The below is a simplication of the 'polyfit'-ed parameters */ \ | |
1832 /* to these breakpoints */ \ | |
5795 | 1833 octave_idx_type n_per_col = (a_nc > 43000 ? 43000 : \ |
1834 (a_nc * a_nc) / 43000); \ | |
1835 octave_idx_type ii = 0; \ | |
1836 octave_idx_type *ri = retval.xridx(); \ | |
1837 octave_sort<octave_idx_type> sort; \ | |
1838 \ | |
1839 for (octave_idx_type i = 0; i < a_nc ; i++) \ | |
5164 | 1840 { \ |
5795 | 1841 if (retval.xcidx(i+1) - retval.xcidx(i) > n_per_col) \ |
5587 | 1842 { \ |
1843 for (octave_idx_type j = a.cidx(i); j < a.cidx(i+1); j++) \ | |
1844 { \ | |
1845 octave_idx_type col = a.ridx(j); \ | |
1846 EL_TYPE tmpval = a.data(j); \ | |
1847 for (octave_idx_type k = m.cidx(col) ; \ | |
1848 k < m.cidx(col+1); k++) \ | |
1849 { \ | |
1850 OCTAVE_QUIT; \ | |
1851 octave_idx_type row = m.ridx(k); \ | |
1852 if (w[row] < i + 1) \ | |
1853 { \ | |
1854 w[row] = i + 1; \ | |
1855 Xcol[row] = tmpval * m.data(k); \ | |
1856 } \ | |
1857 else \ | |
1858 Xcol[row] += tmpval * m.data(k); \ | |
1859 } \ | |
1860 } \ | |
1861 for (octave_idx_type k = 0; k < nr; k++) \ | |
5813 | 1862 if (w[k] == i + 1) \ |
5587 | 1863 { \ |
1864 retval.xdata(ii) = Xcol[k]; \ | |
1865 retval.xridx(ii++) = k; \ | |
1866 } \ | |
5795 | 1867 } \ |
1868 else \ | |
1869 { \ | |
1870 for (octave_idx_type j = a.cidx(i); j < a.cidx(i+1); j++) \ | |
1871 { \ | |
1872 octave_idx_type col = a.ridx(j); \ | |
1873 EL_TYPE tmpval = a.data(j); \ | |
1874 for (octave_idx_type k = m.cidx(col) ; \ | |
1875 k < m.cidx(col+1); k++) \ | |
1876 { \ | |
1877 OCTAVE_QUIT; \ | |
1878 octave_idx_type row = m.ridx(k); \ | |
1879 if (w[row] < i + 1) \ | |
1880 { \ | |
1881 w[row] = i + 1; \ | |
1882 retval.xridx(ii++) = row;\ | |
1883 Xcol[row] = tmpval * m.data(k); \ | |
1884 } \ | |
1885 else \ | |
1886 Xcol[row] += tmpval * m.data(k); \ | |
1887 } \ | |
1888 } \ | |
1889 sort.sort (ri + retval.xcidx(i), ii - retval.xcidx(i)); \ | |
1890 for (octave_idx_type k = retval.xcidx(i); k < ii; k++) \ | |
1891 retval.xdata(k) = Xcol[retval.xridx(k)]; \ | |
5587 | 1892 } \ |
5164 | 1893 } \ |
5813 | 1894 retval.maybe_compress (true);\ |
5164 | 1895 return retval; \ |
1896 } \ | |
1897 } | |
1898 | |
5681 | 1899 #define SPARSE_FULL_MUL( RET_TYPE, EL_TYPE, ZERO ) \ |
5429 | 1900 octave_idx_type nr = m.rows (); \ |
1901 octave_idx_type nc = m.cols (); \ | |
1902 \ | |
1903 octave_idx_type a_nr = a.rows (); \ | |
1904 octave_idx_type a_nc = a.cols (); \ | |
1905 \ | |
6221 | 1906 if (nr == 1 && nc == 1) \ |
1907 { \ | |
7802
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1908 RET_TYPE retval = m.elem (0,0) * a; \ |
6221 | 1909 return retval; \ |
1910 } \ | |
1911 else if (nc != a_nr) \ | |
5429 | 1912 { \ |
1913 gripe_nonconformant ("operator *", nr, nc, a_nr, a_nc); \ | |
1914 return RET_TYPE (); \ | |
1915 } \ | |
1916 else \ | |
1917 { \ | |
5681 | 1918 RET_TYPE retval (nr, a_nc, ZERO); \ |
5429 | 1919 \ |
1920 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
|
1921 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1922 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
|
1923 { \ |
5429 | 1924 OCTAVE_QUIT; \ |
7802
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1925 \ |
5429 | 1926 EL_TYPE tmpval = a.elem(j,i); \ |
7802
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1927 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
|
1928 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
|
1929 } \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1930 } \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1931 return retval; \ |
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 |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1934 #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
|
1935 octave_idx_type nr = m.rows (); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1936 octave_idx_type nc = m.cols (); \ |
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 octave_idx_type a_nr = a.rows (); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1939 octave_idx_type a_nc = a.cols (); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1940 \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1941 if (nr == 1 && nc == 1) \ |
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 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
|
1944 return retval; \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1945 } \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1946 else if (nr != a_nr) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1947 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1948 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
|
1949 return RET_TYPE (); \ |
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 else \ |
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 RET_TYPE retval (nc, a_nc); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1954 \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1955 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
|
1956 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1957 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
|
1958 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1959 OCTAVE_QUIT; \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1960 \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1961 EL_TYPE acc = ZERO; \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1962 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
|
1963 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
|
1964 retval.xelem (j,i) = acc; \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1965 } \ |
5429 | 1966 } \ |
1967 return retval; \ | |
1968 } | |
1969 | |
5681 | 1970 #define FULL_SPARSE_MUL( RET_TYPE, EL_TYPE, ZERO ) \ |
5429 | 1971 octave_idx_type nr = m.rows (); \ |
1972 octave_idx_type nc = m.cols (); \ | |
1973 \ | |
1974 octave_idx_type a_nr = a.rows (); \ | |
1975 octave_idx_type a_nc = a.cols (); \ | |
1976 \ | |
6221 | 1977 if (a_nr == 1 && a_nc == 1) \ |
1978 { \ | |
7802
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1979 RET_TYPE retval = m * a.elem (0,0); \ |
6221 | 1980 return retval; \ |
1981 } \ | |
1982 else if (nc != a_nr) \ | |
5429 | 1983 { \ |
1984 gripe_nonconformant ("operator *", nr, nc, a_nr, a_nc); \ | |
1985 return RET_TYPE (); \ | |
1986 } \ | |
1987 else \ | |
1988 { \ | |
5681 | 1989 RET_TYPE retval (nr, a_nc, ZERO); \ |
5429 | 1990 \ |
1991 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
|
1992 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1993 OCTAVE_QUIT; \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1994 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
|
1995 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1996 octave_idx_type col = a.ridx(j); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1997 EL_TYPE tmpval = a.data(j); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1998 \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
1999 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
|
2000 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
|
2001 } \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2002 } \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2003 return retval; \ |
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 |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2006 #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
|
2007 octave_idx_type nr = m.rows (); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2008 octave_idx_type nc = m.cols (); \ |
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 octave_idx_type a_nr = a.rows (); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2011 octave_idx_type a_nc = a.cols (); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2012 \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2013 if (a_nr == 1 && a_nc == 1) \ |
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 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
|
2016 return retval; \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2017 } \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2018 else if (nc != a_nc) \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2019 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2020 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
|
2021 return RET_TYPE (); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2022 } \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2023 else \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2024 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2025 RET_TYPE retval (nr, a_nr, ZERO); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2026 \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2027 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
|
2028 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2029 OCTAVE_QUIT; \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2030 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
|
2031 { \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2032 octave_idx_type col = a.ridx(j); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2033 EL_TYPE tmpval = CONJ_OP (a.data(j)); \ |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7350
diff
changeset
|
2034 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
|
2035 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
|
2036 } \ |
5429 | 2037 } \ |
2038 return retval; \ | |
2039 } | |
2040 | |
5164 | 2041 #endif |
2042 | |
2043 /* | |
2044 ;;; Local Variables: *** | |
2045 ;;; mode: C++ *** | |
2046 ;;; End: *** | |
2047 */ |