Mercurial > octave-nkf
comparison src/sparse-xpow.cc @ 5164:57077d0ddc8e
[project @ 2005-02-25 19:55:24 by jwe]
author | jwe |
---|---|
date | Fri, 25 Feb 2005 19:55:28 +0000 |
parents | |
children | 23b37da9fd5b |
comparison
equal
deleted
inserted
replaced
5163:9f3299378193 | 5164:57077d0ddc8e |
---|---|
1 /* | |
2 | |
3 Copyright (C) 2004 David Bateman | |
4 Copyright (C) 1998-2004 Andy Adler | |
5 | |
6 Octave is free software; you can redistribute it and/or modify it | |
7 under the terms of the GNU General Public License as published by the | |
8 Free Software Foundation; either version 2, or (at your option) any | |
9 later version. | |
10 | |
11 Octave is distributed in the hope that it will be useful, but WITHOUT | |
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with this program; see the file COPYING. If not, write to the Free | |
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
19 | |
20 */ | |
21 | |
22 #ifdef HAVE_CONFIG_H | |
23 #include <config.h> | |
24 #endif | |
25 | |
26 #include <cassert> | |
27 #include <climits> | |
28 | |
29 #include "Array-util.h" | |
30 #include "oct-cmplx.h" | |
31 #include "quit.h" | |
32 | |
33 #include "error.h" | |
34 #include "oct-obj.h" | |
35 #include "utils.h" | |
36 | |
37 #include "dSparse.h" | |
38 #include "CSparse.h" | |
39 #include "ov-re-sparse.h" | |
40 #include "ov-cx-sparse.h" | |
41 #include "sparse-xpow.h" | |
42 | |
43 static inline int | |
44 xisint (double x) | |
45 { | |
46 return (D_NINT (x) == x | |
47 && ((x >= 0 && x < INT_MAX) | |
48 || (x <= 0 && x > INT_MIN))); | |
49 } | |
50 | |
51 | |
52 // Safer pow functions. Only two make sense for sparse matrices, the | |
53 // others should all promote to full matrices. | |
54 | |
55 octave_value | |
56 xpow (const SparseMatrix& a, double b) | |
57 { | |
58 octave_value retval; | |
59 | |
60 int nr = a.rows (); | |
61 int nc = a.cols (); | |
62 | |
63 if (nr == 0 || nc == 0 || nr != nc) | |
64 error ("for A^b, A must be square"); | |
65 else | |
66 { | |
67 if (static_cast<int> (b) == b) | |
68 { | |
69 int btmp = static_cast<int> (b); | |
70 if (btmp == 0) | |
71 { | |
72 SparseMatrix tmp = SparseMatrix (nr, nr, nr); | |
73 for (int i = 0; i < nr; i++) | |
74 { | |
75 tmp.data (i) = 1.0; | |
76 tmp.ridx (i) = i; | |
77 } | |
78 for (int i = 0; i < nr + 1; i++) | |
79 tmp.cidx (i) = i; | |
80 | |
81 retval = tmp; | |
82 } | |
83 else | |
84 { | |
85 SparseMatrix atmp; | |
86 if (btmp < 0) | |
87 { | |
88 btmp = -btmp; | |
89 | |
90 int info; | |
91 double rcond = 0.0; | |
92 | |
93 atmp = a.inverse (info, rcond, 1); | |
94 | |
95 if (info == -1) | |
96 warning ("inverse: matrix singular to machine\ | |
97 precision, rcond = %g", rcond); | |
98 } | |
99 else | |
100 atmp = a; | |
101 | |
102 SparseMatrix result (atmp); | |
103 | |
104 btmp--; | |
105 | |
106 while (btmp > 0) | |
107 { | |
108 if (btmp & 1) | |
109 result = result * atmp; | |
110 | |
111 btmp >>= 1; | |
112 | |
113 if (btmp > 0) | |
114 atmp = atmp * atmp; | |
115 } | |
116 | |
117 retval = result; | |
118 } | |
119 } | |
120 else | |
121 error ("use full(a) ^ full(b)"); | |
122 } | |
123 | |
124 return retval; | |
125 } | |
126 | |
127 octave_value | |
128 xpow (const SparseComplexMatrix& a, double b) | |
129 { | |
130 octave_value retval; | |
131 | |
132 int nr = a.rows (); | |
133 int nc = a.cols (); | |
134 | |
135 if (nr == 0 || nc == 0 || nr != nc) | |
136 error ("for A^b, A must be square"); | |
137 else | |
138 { | |
139 if (static_cast<int> (b) == b) | |
140 { | |
141 int btmp = static_cast<int> (b); | |
142 if (btmp == 0) | |
143 { | |
144 SparseMatrix tmp = SparseMatrix (nr, nr, nr); | |
145 for (int i = 0; i < nr; i++) | |
146 { | |
147 tmp.data (i) = 1.0; | |
148 tmp.ridx (i) = i; | |
149 } | |
150 for (int i = 0; i < nr + 1; i++) | |
151 tmp.cidx (i) = i; | |
152 | |
153 retval = tmp; | |
154 } | |
155 else | |
156 { | |
157 SparseComplexMatrix atmp; | |
158 if (btmp < 0) | |
159 { | |
160 btmp = -btmp; | |
161 | |
162 int info; | |
163 double rcond = 0.0; | |
164 | |
165 atmp = a.inverse (info, rcond, 1); | |
166 | |
167 if (info == -1) | |
168 warning ("inverse: matrix singular to machine\ | |
169 precision, rcond = %g", rcond); | |
170 } | |
171 else | |
172 atmp = a; | |
173 | |
174 SparseComplexMatrix result (atmp); | |
175 | |
176 btmp--; | |
177 | |
178 while (btmp > 0) | |
179 { | |
180 if (btmp & 1) | |
181 result = result * atmp; | |
182 | |
183 btmp >>= 1; | |
184 | |
185 if (btmp > 0) | |
186 atmp = atmp * atmp; | |
187 } | |
188 | |
189 retval = result; | |
190 } | |
191 } | |
192 else | |
193 error ("use full(a) ^ full(b)"); | |
194 } | |
195 | |
196 return retval; | |
197 } | |
198 | |
199 // Safer pow functions that work elementwise for matrices. | |
200 // | |
201 // op2 \ op1: s m cs cm | |
202 // +-- +---+---+----+----+ | |
203 // scalar | | * | 3 | * | 9 | | |
204 // +---+---+----+----+ | |
205 // matrix | 1 | 4 | 7 | 10 | | |
206 // +---+---+----+----+ | |
207 // complex_scalar | * | 5 | * | 11 | | |
208 // +---+---+----+----+ | |
209 // complex_matrix | 2 | 6 | 8 | 12 | | |
210 // +---+---+----+----+ | |
211 // | |
212 // * -> not needed. | |
213 | |
214 // XXX FIXME XXX -- these functions need to be fixed so that things | |
215 // like | |
216 // | |
217 // a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b | |
218 // | |
219 // and | |
220 // | |
221 // a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end | |
222 // | |
223 // produce identical results. Also, it would be nice if -1^0.5 | |
224 // produced a pure imaginary result instead of a complex number with a | |
225 // small real part. But perhaps that's really a problem with the math | |
226 // library... | |
227 | |
228 // -*- 1 -*- | |
229 octave_value | |
230 elem_xpow (double a, const SparseMatrix& b) | |
231 { | |
232 octave_value retval; | |
233 | |
234 int nr = b.rows (); | |
235 int nc = b.cols (); | |
236 | |
237 double d1, d2; | |
238 | |
239 if (a < 0.0 && ! b.all_integers (d1, d2)) | |
240 { | |
241 Complex atmp (a); | |
242 ComplexMatrix result (nr, nc); | |
243 | |
244 for (int j = 0; j < nc; j++) | |
245 { | |
246 for (int i = 0; i < nr; i++) | |
247 { | |
248 OCTAVE_QUIT; | |
249 result (i, j) = pow (atmp, b(i,j)); | |
250 } | |
251 } | |
252 | |
253 retval = result; | |
254 } | |
255 else | |
256 { | |
257 Matrix result (nr, nc); | |
258 | |
259 for (int j = 0; j < nc; j++) | |
260 { | |
261 for (int i = 0; i < nr; i++) | |
262 { | |
263 OCTAVE_QUIT; | |
264 result (i, j) = pow (a, b(i,j)); | |
265 } | |
266 } | |
267 | |
268 retval = result; | |
269 } | |
270 | |
271 return retval; | |
272 } | |
273 | |
274 // -*- 2 -*- | |
275 octave_value | |
276 elem_xpow (double a, const SparseComplexMatrix& b) | |
277 { | |
278 int nr = b.rows (); | |
279 int nc = b.cols (); | |
280 | |
281 Complex atmp (a); | |
282 ComplexMatrix result (nr, nc); | |
283 | |
284 for (int j = 0; j < nc; j++) | |
285 { | |
286 for (int i = 0; i < nr; i++) | |
287 { | |
288 OCTAVE_QUIT; | |
289 result (i, j) = pow (atmp, b(i,j)); | |
290 } | |
291 } | |
292 | |
293 return result; | |
294 } | |
295 | |
296 // -*- 3 -*- | |
297 octave_value | |
298 elem_xpow (const SparseMatrix& a, double b) | |
299 { | |
300 // XXX FIXME XXX What should a .^ 0 give?? Matlab gives a | |
301 // sparse matrix with same structure as a, which is strictly | |
302 // incorrect. Keep compatiability. | |
303 | |
304 octave_value retval; | |
305 | |
306 int nz = a.nnz (); | |
307 | |
308 if (b <= 0.0) | |
309 { | |
310 int nr = a.rows (); | |
311 int nc = a.cols (); | |
312 | |
313 if (static_cast<int> (b) != b && a.any_element_is_negative ()) | |
314 { | |
315 ComplexMatrix result (nr, nc, Complex (pow (0.0, b))); | |
316 | |
317 // XXX FIXME XXX -- avoid apparent GNU libm bug by | |
318 // converting A and B to complex instead of just A. | |
319 Complex btmp (b); | |
320 | |
321 for (int j = 0; j < nc; j++) | |
322 for (int i = a.cidx(j); i < a.cidx(j+1); i++) | |
323 { | |
324 OCTAVE_QUIT; | |
325 | |
326 Complex atmp (a.data (i)); | |
327 | |
328 result (a.ridx(i), j) = pow (atmp, btmp); | |
329 } | |
330 | |
331 retval = octave_value (result); | |
332 } | |
333 else | |
334 { | |
335 Matrix result (nr, nc, (pow (0.0, b))); | |
336 | |
337 for (int j = 0; j < nc; j++) | |
338 for (int i = a.cidx(j); i < a.cidx(j+1); i++) | |
339 { | |
340 OCTAVE_QUIT; | |
341 result (a.ridx(i), j) = pow (a.data (i), b); | |
342 } | |
343 | |
344 retval = octave_value (result); | |
345 } | |
346 } | |
347 else if (static_cast<int> (b) != b && a.any_element_is_negative ()) | |
348 { | |
349 SparseComplexMatrix result (a); | |
350 | |
351 for (int i = 0; i < nz; i++) | |
352 { | |
353 OCTAVE_QUIT; | |
354 | |
355 // XXX FIXME XXX -- avoid apparent GNU libm bug by | |
356 // converting A and B to complex instead of just A. | |
357 | |
358 Complex atmp (a.data (i)); | |
359 Complex btmp (b); | |
360 | |
361 result.data (i) = pow (atmp, btmp); | |
362 } | |
363 | |
364 result.maybe_compress (true); | |
365 | |
366 retval = result; | |
367 } | |
368 else | |
369 { | |
370 SparseMatrix result (a); | |
371 | |
372 for (int i = 0; i < nz; i++) | |
373 { | |
374 OCTAVE_QUIT; | |
375 result.data (i) = pow (a.data (i), b); | |
376 } | |
377 | |
378 result.maybe_compress (true); | |
379 | |
380 retval = result; | |
381 } | |
382 | |
383 return retval; | |
384 } | |
385 | |
386 // -*- 4 -*- | |
387 octave_value | |
388 elem_xpow (const SparseMatrix& a, const SparseMatrix& b) | |
389 { | |
390 octave_value retval; | |
391 | |
392 int nr = a.rows (); | |
393 int nc = a.cols (); | |
394 | |
395 int b_nr = b.rows (); | |
396 int b_nc = b.cols (); | |
397 | |
398 if (nr != b_nr || nc != b_nc) | |
399 { | |
400 gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc); | |
401 return octave_value (); | |
402 } | |
403 | |
404 int convert_to_complex = 0; | |
405 for (int j = 0; j < nc; j++) | |
406 for (int i = 0; i < nr; i++) | |
407 { | |
408 OCTAVE_QUIT; | |
409 double atmp = a (i, j); | |
410 double btmp = b (i, j); | |
411 if (atmp < 0.0 && static_cast<int> (btmp) != btmp) | |
412 { | |
413 convert_to_complex = 1; | |
414 goto done; | |
415 } | |
416 } | |
417 | |
418 done: | |
419 | |
420 int nel = 0; | |
421 for (int j = 0; j < nc; j++) | |
422 for (int i = 0; i < nr; i++) | |
423 if (!(a.elem (i, j) == 0. && b.elem (i, j) != 0.)) | |
424 nel++; | |
425 | |
426 if (convert_to_complex) | |
427 { | |
428 SparseComplexMatrix complex_result (nr, nc, nel); | |
429 | |
430 int ii = 0; | |
431 complex_result.cidx(0) = 0; | |
432 for (int j = 0; j < nc; j++) | |
433 { | |
434 for (int i = 0; i < nr; i++) | |
435 { | |
436 OCTAVE_QUIT; | |
437 Complex atmp (a (i, j)); | |
438 Complex btmp (b (i, j)); | |
439 Complex tmp = pow (atmp, btmp); | |
440 if (tmp != 0.) | |
441 { | |
442 complex_result.data (ii) = tmp; | |
443 complex_result.ridx (ii++) = i; | |
444 } | |
445 } | |
446 complex_result.cidx (j+1) = ii; | |
447 } | |
448 complex_result.maybe_compress (); | |
449 | |
450 retval = complex_result; | |
451 } | |
452 else | |
453 { | |
454 SparseMatrix result (nr, nc, nel); | |
455 int ii = 0; | |
456 | |
457 result.cidx (0) = 0; | |
458 for (int j = 0; j < nc; j++) | |
459 { | |
460 for (int i = 0; i < nr; i++) | |
461 { | |
462 OCTAVE_QUIT; | |
463 double tmp = pow (a (i, j), b (i, j)); | |
464 if (tmp != 0.) | |
465 { | |
466 result.data (ii) = tmp; | |
467 result.ridx (ii++) = i; | |
468 } | |
469 } | |
470 result.cidx (j+1) = ii; | |
471 } | |
472 | |
473 result.maybe_compress (); | |
474 | |
475 retval = result; | |
476 } | |
477 | |
478 return retval; | |
479 } | |
480 | |
481 // -*- 5 -*- | |
482 octave_value | |
483 elem_xpow (const SparseMatrix& a, const Complex& b) | |
484 { | |
485 octave_value retval; | |
486 | |
487 if (b == 0.0) | |
488 // Can this case ever happen, due to automatic retyping with maybe_mutate? | |
489 retval = octave_value (NDArray (a.dims (), 1)); | |
490 else | |
491 { | |
492 int nz = a.nnz (); | |
493 SparseComplexMatrix result (a); | |
494 | |
495 for (int i = 0; i < nz; i++) | |
496 { | |
497 OCTAVE_QUIT; | |
498 result.data (i) = pow (Complex (a.data (i)), b); | |
499 } | |
500 | |
501 result.maybe_compress (true); | |
502 | |
503 retval = result; | |
504 } | |
505 | |
506 return retval; | |
507 } | |
508 | |
509 // -*- 6 -*- | |
510 octave_value | |
511 elem_xpow (const SparseMatrix& a, const SparseComplexMatrix& b) | |
512 { | |
513 int nr = a.rows (); | |
514 int nc = a.cols (); | |
515 | |
516 int b_nr = b.rows (); | |
517 int b_nc = b.cols (); | |
518 | |
519 if (nr != b_nr || nc != b_nc) | |
520 { | |
521 gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc); | |
522 return octave_value (); | |
523 } | |
524 | |
525 int nel = 0; | |
526 for (int j = 0; j < nc; j++) | |
527 for (int i = 0; i < nr; i++) | |
528 if (!(a.elem (i, j) == 0. && b.elem (i, j) != 0.)) | |
529 nel++; | |
530 | |
531 SparseComplexMatrix result (nr, nc, nel); | |
532 int ii = 0; | |
533 | |
534 result.cidx(0) = 0; | |
535 for (int j = 0; j < nc; j++) | |
536 { | |
537 for (int i = 0; i < nr; i++) | |
538 { | |
539 OCTAVE_QUIT; | |
540 Complex tmp = pow (Complex (a (i, j)), b (i, j)); | |
541 if (tmp != 0.) | |
542 { | |
543 result.data (ii) = tmp; | |
544 result.ridx (ii++) = i; | |
545 } | |
546 } | |
547 result.cidx (j+1) = ii; | |
548 } | |
549 | |
550 result.maybe_compress (); | |
551 | |
552 return result; | |
553 } | |
554 | |
555 // -*- 7 -*- | |
556 octave_value | |
557 elem_xpow (const Complex& a, const SparseMatrix& b) | |
558 { | |
559 int nr = b.rows (); | |
560 int nc = b.cols (); | |
561 | |
562 ComplexMatrix result (nr, nc); | |
563 | |
564 for (int j = 0; j < nc; j++) | |
565 { | |
566 for (int i = 0; i < nr; i++) | |
567 { | |
568 OCTAVE_QUIT; | |
569 double btmp = b (i, j); | |
570 if (xisint (btmp)) | |
571 result (i, j) = pow (a, static_cast<int> (btmp)); | |
572 else | |
573 result (i, j) = pow (a, btmp); | |
574 } | |
575 } | |
576 | |
577 return result; | |
578 } | |
579 | |
580 // -*- 8 -*- | |
581 octave_value | |
582 elem_xpow (const Complex& a, const SparseComplexMatrix& b) | |
583 { | |
584 int nr = b.rows (); | |
585 int nc = b.cols (); | |
586 | |
587 ComplexMatrix result (nr, nc); | |
588 for (int j = 0; j < nc; j++) | |
589 for (int i = 0; i < nr; i++) | |
590 { | |
591 OCTAVE_QUIT; | |
592 result (i, j) = pow (a, b (i, j)); | |
593 } | |
594 | |
595 return result; | |
596 } | |
597 | |
598 // -*- 9 -*- | |
599 octave_value | |
600 elem_xpow (const SparseComplexMatrix& a, double b) | |
601 { | |
602 octave_value retval; | |
603 | |
604 if (b <= 0) | |
605 { | |
606 int nr = a.rows (); | |
607 int nc = a.cols (); | |
608 | |
609 ComplexMatrix result (nr, nc, Complex (pow (0.0, b))); | |
610 | |
611 if (xisint (b)) | |
612 { | |
613 for (int j = 0; j < nc; j++) | |
614 for (int i = a.cidx(j); i < a.cidx(j+1); i++) | |
615 { | |
616 OCTAVE_QUIT; | |
617 result (a.ridx(i), j) = | |
618 pow (a.data (i), static_cast<int> (b)); | |
619 } | |
620 } | |
621 else | |
622 { | |
623 for (int j = 0; j < nc; j++) | |
624 for (int i = a.cidx(j); i < a.cidx(j+1); i++) | |
625 { | |
626 OCTAVE_QUIT; | |
627 result (a.ridx(i), j) = pow (a.data (i), b); | |
628 } | |
629 } | |
630 | |
631 retval = result; | |
632 } | |
633 else | |
634 { | |
635 int nz = a.nnz (); | |
636 | |
637 SparseComplexMatrix result (a); | |
638 | |
639 if (xisint (b)) | |
640 { | |
641 for (int i = 0; i < nz; i++) | |
642 { | |
643 OCTAVE_QUIT; | |
644 result.data (i) = pow (a.data (i), static_cast<int> (b)); | |
645 } | |
646 } | |
647 else | |
648 { | |
649 for (int i = 0; i < nz; i++) | |
650 { | |
651 OCTAVE_QUIT; | |
652 result.data (i) = pow (a.data (i), b); | |
653 } | |
654 } | |
655 | |
656 result.maybe_compress (true); | |
657 | |
658 retval = result; | |
659 } | |
660 | |
661 return retval; | |
662 } | |
663 | |
664 // -*- 10 -*- | |
665 octave_value | |
666 elem_xpow (const SparseComplexMatrix& a, const SparseMatrix& b) | |
667 { | |
668 int nr = a.rows (); | |
669 int nc = a.cols (); | |
670 | |
671 int b_nr = b.rows (); | |
672 int b_nc = b.cols (); | |
673 | |
674 if (nr != b_nr || nc != b_nc) | |
675 { | |
676 gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc); | |
677 return octave_value (); | |
678 } | |
679 | |
680 int nel = 0; | |
681 for (int j = 0; j < nc; j++) | |
682 for (int i = 0; i < nr; i++) | |
683 if (!(a.elem (i, j) == 0. && b.elem (i, j) != 0.)) | |
684 nel++; | |
685 | |
686 SparseComplexMatrix result (nr, nc, nel); | |
687 int ii = 0; | |
688 | |
689 result.cidx (0) = 0; | |
690 for (int j = 0; j < nc; j++) | |
691 { | |
692 for (int i = 0; i < nr; i++) | |
693 { | |
694 OCTAVE_QUIT; | |
695 double btmp = b (i, j); | |
696 Complex tmp; | |
697 | |
698 if (xisint (btmp)) | |
699 tmp = pow (a (i, j), static_cast<int> (btmp)); | |
700 else | |
701 tmp = pow (a (i, j), btmp); | |
702 if (tmp != 0.) | |
703 { | |
704 result.data (ii) = tmp; | |
705 result.ridx (ii++) = i; | |
706 } | |
707 } | |
708 result.cidx (j+1) = ii; | |
709 } | |
710 | |
711 result.maybe_compress (); | |
712 | |
713 return result; | |
714 } | |
715 | |
716 // -*- 11 -*- | |
717 octave_value | |
718 elem_xpow (const SparseComplexMatrix& a, const Complex& b) | |
719 { | |
720 octave_value retval; | |
721 | |
722 if (b == 0.0) | |
723 // Can this case ever happen, due to automatic retyping with maybe_mutate? | |
724 retval = octave_value (NDArray (a.dims (), 1)); | |
725 else | |
726 { | |
727 | |
728 int nz = a.nnz (); | |
729 | |
730 SparseComplexMatrix result (a); | |
731 | |
732 for (int i = 0; i < nz; i++) | |
733 { | |
734 OCTAVE_QUIT; | |
735 result.data (i) = pow (a.data (i), b); | |
736 } | |
737 | |
738 result.maybe_compress (true); | |
739 | |
740 retval = result; | |
741 } | |
742 | |
743 return retval; | |
744 } | |
745 | |
746 // -*- 12 -*- | |
747 octave_value | |
748 elem_xpow (const SparseComplexMatrix& a, const SparseComplexMatrix& b) | |
749 { | |
750 int nr = a.rows (); | |
751 int nc = a.cols (); | |
752 | |
753 int b_nr = b.rows (); | |
754 int b_nc = b.cols (); | |
755 | |
756 if (nr != b_nr || nc != b_nc) | |
757 { | |
758 gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc); | |
759 return octave_value (); | |
760 } | |
761 | |
762 int nel = 0; | |
763 for (int j = 0; j < nc; j++) | |
764 for (int i = 0; i < nr; i++) | |
765 if (!(a.elem (i, j) == 0. && b.elem (i, j) != 0.)) | |
766 nel++; | |
767 | |
768 SparseComplexMatrix result (nr, nc, nel); | |
769 int ii = 0; | |
770 | |
771 result.cidx (0) = 0; | |
772 for (int j = 0; j < nc; j++) | |
773 { | |
774 for (int i = 0; i < nr; i++) | |
775 { | |
776 OCTAVE_QUIT; | |
777 Complex tmp = pow (a (i, j), b (i, j)); | |
778 if (tmp != 0.) | |
779 { | |
780 result.data (ii) = tmp; | |
781 result.ridx (ii++) = i; | |
782 } | |
783 } | |
784 result.cidx (j+1) = ii; | |
785 } | |
786 result.maybe_compress (true); | |
787 | |
788 return result; | |
789 } | |
790 | |
791 /* | |
792 ;;; Local Variables: *** | |
793 ;;; mode: C++ *** | |
794 ;;; End: *** | |
795 */ |