GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
Sparse-diag-op-defs.h
Go to the documentation of this file.
1 /* -*- C++ -*-
2 
3 Copyright (C) 2009-2018 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
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License 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 <https://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 #include "octave-config.h"
27 
28 #include "lo-array-errwarn.h"
29 
30 // Matrix multiplication
31 
32 template <typename RT, typename DM, typename SM>
33 RT do_mul_dm_sm (const DM& d, const SM& a)
34 {
35  const octave_idx_type nr = d.rows ();
36  const octave_idx_type nc = d.cols ();
37 
38  const octave_idx_type a_nr = a.rows ();
39  const octave_idx_type a_nc = a.cols ();
40 
41  if (nc != a_nr)
42  octave::err_nonconformant ("operator *", nr, nc, a_nr, a_nc);
43 
44  RT r (nr, a_nc, a.nnz ());
45 
46  octave_idx_type l = 0;
47 
48  for (octave_idx_type j = 0; j < a_nc; j++)
49  {
50  r.xcidx (j) = l;
51  const octave_idx_type colend = a.cidx (j+1);
52  for (octave_idx_type k = a.cidx (j); k < colend; k++)
53  {
54  const octave_idx_type i = a.ridx (k);
55  if (i >= nr) break;
56  r.xdata (l) = d.dgelem (i) * a.data (k);
57  r.xridx (l) = i;
58  l++;
59  }
60  }
61 
62  r.xcidx (a_nc) = l;
63 
64  r.maybe_compress (true);
65  return r;
66 }
67 
68 template <typename RT, typename SM, typename DM>
69 RT do_mul_sm_dm (const SM& a, const DM& d)
70 {
71  const octave_idx_type nr = d.rows ();
72  const octave_idx_type nc = d.cols ();
73 
74  const octave_idx_type a_nr = a.rows ();
75  const octave_idx_type a_nc = a.cols ();
76 
77  if (nr != a_nc)
78  octave::err_nonconformant ("operator *", a_nr, a_nc, nr, nc);
79 
80  const octave_idx_type mnc = (nc < a_nc ? nc: a_nc);
81  RT r (a_nr, nc, a.cidx (mnc));
82 
83  for (octave_idx_type j = 0; j < mnc; ++j)
84  {
85  const typename DM::element_type s = d.dgelem (j);
86  const octave_idx_type colend = a.cidx (j+1);
87  r.xcidx (j) = a.cidx (j);
88  for (octave_idx_type k = a.cidx (j); k < colend; ++k)
89  {
90  r.xdata (k) = s * a.data (k);
91  r.xridx (k) = a.ridx (k);
92  }
93  }
94  for (octave_idx_type j = mnc; j <= nc; ++j)
95  r.xcidx (j) = a.cidx (mnc);
96 
97  r.maybe_compress (true);
98  return r;
99 }
100 
101 // FIXME: functors such as this should be gathered somewhere
102 template <typename T>
104  : public std::unary_function <T, T>
105 {
106  T operator () (const T x) { return x; }
107 };
108 
109 // Matrix addition
110 
111 template <typename RT, typename SM, typename DM, typename OpA, typename OpD>
112 RT inner_do_add_sm_dm (const SM& a, const DM& d, OpA opa, OpD opd)
113 {
114  using std::min;
115  const octave_idx_type nr = d.rows ();
116  const octave_idx_type nc = d.cols ();
117  const octave_idx_type n = min (nr, nc);
118 
119  const octave_idx_type a_nr = a.rows ();
120  const octave_idx_type a_nc = a.cols ();
121 
122  const octave_idx_type nz = a.nnz ();
123  RT r (a_nr, a_nc, nz + n);
124  octave_idx_type k = 0;
125 
126  for (octave_idx_type j = 0; j < nc; ++j)
127  {
128  octave_quit ();
129  const octave_idx_type colend = a.cidx (j+1);
130  r.xcidx (j) = k;
131  octave_idx_type k_src = a.cidx (j), k_split;
132 
133  for (k_split = k_src; k_split < colend; k_split++)
134  if (a.ridx (k_split) >= j)
135  break;
136 
137  for (; k_src < k_split; k_src++, k++)
138  {
139  r.xridx (k) = a.ridx (k_src);
140  r.xdata (k) = opa (a.data (k_src));
141  }
142 
143  if (k_src < colend && a.ridx (k_src) == j)
144  {
145  r.xridx (k) = j;
146  r.xdata (k) = opa (a.data (k_src)) + opd (d.dgelem (j));
147  k++; k_src++;
148  }
149  else
150  {
151  r.xridx (k) = j;
152  r.xdata (k) = opd (d.dgelem (j));
153  k++;
154  }
155 
156  for (; k_src < colend; k_src++, k++)
157  {
158  r.xridx (k) = a.ridx (k_src);
159  r.xdata (k) = opa (a.data (k_src));
160  }
161 
162  }
163  r.xcidx (nc) = k;
164 
165  r.maybe_compress (true);
166  return r;
167 }
168 
169 template <typename RT, typename DM, typename SM>
170 RT do_commutative_add_dm_sm (const DM& d, const SM& a)
171 {
172  // Extra function to ensure this is only emitted once.
173  return inner_do_add_sm_dm<RT> (a, d,
176 }
177 
178 template <typename RT, typename DM, typename SM>
179 RT do_add_dm_sm (const DM& d, const SM& a)
180 {
181  if (a.rows () != d.rows () || a.cols () != d.cols ())
182  octave::err_nonconformant ("operator +",
183  d.rows (), d.cols (), a.rows (), a.cols ());
184  else
185  return do_commutative_add_dm_sm<RT> (d, a);
186 }
187 
188 template <typename RT, typename DM, typename SM>
189 RT do_sub_dm_sm (const DM& d, const SM& a)
190 {
191  if (a.rows () != d.rows () || a.cols () != d.cols ())
192  octave::err_nonconformant ("operator -",
193  d.rows (), d.cols (), a.rows (), a.cols ());
194 
195  return inner_do_add_sm_dm<RT> (a, d,
196  std::negate<typename SM::element_type> (),
198 }
199 
200 template <typename RT, typename SM, typename DM>
201 RT do_add_sm_dm (const SM& a, const DM& d)
202 {
203  if (a.rows () != d.rows () || a.cols () != d.cols ())
204  octave::err_nonconformant ("operator +",
205  a.rows (), a.cols (), d.rows (), d.cols ());
206 
207  return do_commutative_add_dm_sm<RT> (d, a);
208 }
209 
210 template <typename RT, typename SM, typename DM>
211 RT do_sub_sm_dm (const SM& a, const DM& d)
212 {
213  if (a.rows () != d.rows () || a.cols () != d.cols ())
214  octave::err_nonconformant ("operator -",
215  a.rows (), a.cols (), d.rows (), d.cols ());
216 
217  return inner_do_add_sm_dm<RT> (a, d,
219  std::negate<typename DM::element_type> ());
220 }
221 
222 #endif
RT do_commutative_add_dm_sm(const DM &d, const SM &a)
RT do_mul_sm_dm(const SM &a, const DM &d)
RT do_add_dm_sm(const DM &d, const SM &a)
for large enough k
Definition: lu.cc:617
RT do_sub_dm_sm(const DM &d, const SM &a)
s
Definition: file-io.cc:2729
octave_idx_type a_nc
Definition: sylvester.cc:74
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
calling an anonymous function involves an overhead quite comparable to the overhead of an m file function Passing a handle to a built in function is because the interpreter is not involved in the internal loop For a
Definition: cellfun.cc:400
octave_idx_type a_nr
Definition: sylvester.cc:73
RT do_add_sm_dm(const SM &a, const DM &d)
void err_nonconformant(const char *op, octave_idx_type op1_len, octave_idx_type op2_len)
RT inner_do_add_sm_dm(const SM &a, const DM &d, OpA opa, OpD opd)
RT do_sub_sm_dm(const SM &a, const DM &d)
for i
Definition: data.cc:5264
T operator()(const T x)
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE * x
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:204
RT do_mul_dm_sm(const DM &d, const SM &a)