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