comparison liboctave/Sparse-diag-op-defs.h @ 8964:f4f4d65faaa0

Implement sparse * diagonal and diagonal * sparse operations, double-prec only. Date: Sun, 8 Mar 2009 16:28:18 -0400 These preserve sparsity, so eye(5) * sprand (5, 5, .2) is *sparse* and not dense. This may affect people who use multiplication by eye() rather than full(). The liboctave routines do *not* check if arguments are scalars in disguise. There is a type problem with checking at that level. I suspect we want diag * "sparse scalar" to stay diagonal, but we have to return a sparse matrix at the liboctave. Rather than worrying about that in liboctave, we cope with it when binding to Octave and return the correct higher-level type. The implementation is in Sparse-diag-op-defs.h rather than Sparse-op-defs.h to limit recompilation. And the implementations are templates rather than macros to produce better compiler errors and debugging information.
author Jason Riedy <jason@acm.org>
date Mon, 09 Mar 2009 17:49:13 -0400
parents
children 1bba53c0a38d
comparison
equal deleted inserted replaced
8963:d1eab3ddb02d 8964:f4f4d65faaa0
1 /* -*- C++ -*-
2
3 Copyright (C) 2009 Jason Riedy, Jaroslav Hajek
4
5 This file is part of Octave.
6
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20
21 */
22
23 #if !defined (octave_sparse_diag_op_defs_h)
24 #define octave_sparse_diag_op_defs_h 1
25
26 template <typename RT, typename DM, typename SM>
27 RT do_mul_dm_sm (const DM& d, const SM& a)
28 {
29 const octave_idx_type nr = d.rows ();
30 const octave_idx_type nc = d.cols ();
31
32 const octave_idx_type a_nr = a.rows ();
33 const octave_idx_type a_nc = a.cols ();
34
35 if (nc != a_nr)
36 {
37 gripe_nonconformant ("operator *", nr, nc, a_nr, a_nc);
38 return RT ();
39 }
40 else
41 {
42 RT r (nr, a_nc, a.nnz ());
43
44 octave_idx_type l = 0;
45
46 for (octave_idx_type j = 0; j < a_nc; j++)
47 {
48 r.xcidx (j) = l;
49 const octave_idx_type colend = a.cidx (j+1);
50 for (octave_idx_type k = a.cidx (j); k < colend; k++)
51 {
52 const octave_idx_type i = a.ridx (k);
53 if (i >= nr) break;
54 r.xdata (l) = d.dgelem (i) * a.data (k);
55 r.xridx (l) = i;
56 l++;
57 }
58 }
59
60 r.xcidx (a_nc) = l;
61
62 r.maybe_compress (true);
63 return r;
64 }
65 }
66
67 template <typename RT, typename SM, typename DM>
68 RT do_mul_sm_dm (const SM& a, const DM& d)
69 {
70 const octave_idx_type nr = d.rows ();
71 const octave_idx_type nc = d.cols ();
72
73 const octave_idx_type a_nr = a.rows ();
74 const octave_idx_type a_nc = a.cols ();
75
76 if (nr != a_nc)
77 {
78 gripe_nonconformant ("operator *", a_nr, a_nc, nr, nc);
79 return RT ();
80 }
81 else
82 {
83
84 const octave_idx_type mnc = nc < a_nc ? nc: a_nc;
85 RT r (a_nr, nc, a.cidx (mnc));
86
87 for (octave_idx_type j = 0; j < mnc; ++j)
88 {
89 const typename DM::element_type s = d.dgelem (j);
90 const octave_idx_type colend = a.cidx (j+1);
91 r.xcidx (j) = a.cidx (j);
92 for (octave_idx_type k = a.cidx (j); k < colend; ++k)
93 {
94 r.xdata (k) = s * a.data (k);
95 r.xridx (k) = a.ridx (k);
96 }
97 }
98 for (octave_idx_type j = mnc; j <= nc; ++j)
99 r.xcidx (j) = a.cidx (mnc);
100
101 r.maybe_compress (true);
102 return r;
103 }
104 }
105
106 #endif // octave_sparse_diag_op_defs_h