GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
MSparse.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2004-2018 David Bateman
4 Copyright (C) 1998-2004 Andy Adler
5 
6 This file is part of Octave.
7 
8 Octave is free software: you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <https://www.gnu.org/licenses/>.
21 
22 */
23 
24 // sparse array with math ops.
25 
26 // Element by element MSparse by MSparse ops.
27 
28 template <typename T, typename OP>
30 plus_or_minus (MSparse<T>& a, const MSparse<T>& b, OP op, const char *op_name)
31 {
32  MSparse<T> r;
33 
34  octave_idx_type a_nr = a.rows ();
35  octave_idx_type a_nc = a.cols ();
36 
37  octave_idx_type b_nr = b.rows ();
38  octave_idx_type b_nc = b.cols ();
39 
40  if (a_nr != b_nr || a_nc != b_nc)
42 
43  r = MSparse<T> (a_nr, a_nc, (a.nnz () + b.nnz ()));
44 
45  octave_idx_type jx = 0;
46  for (octave_idx_type i = 0 ; i < a_nc ; i++)
47  {
48  octave_idx_type ja = a.cidx (i);
49  octave_idx_type ja_max = a.cidx (i+1);
50  bool ja_lt_max = ja < ja_max;
51 
52  octave_idx_type jb = b.cidx (i);
53  octave_idx_type jb_max = b.cidx (i+1);
54  bool jb_lt_max = jb < jb_max;
55 
56  while (ja_lt_max || jb_lt_max)
57  {
58  octave_quit ();
59  if ((! jb_lt_max) || (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))
60  {
61  r.ridx (jx) = a.ridx (ja);
62  r.data (jx) = op (a.data (ja), 0.);
63  jx++;
64  ja++;
65  ja_lt_max= ja < ja_max;
66  }
67  else if ((! ja_lt_max)
68  || (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))
69  {
70  r.ridx (jx) = b.ridx (jb);
71  r.data (jx) = op (0., b.data (jb));
72  jx++;
73  jb++;
74  jb_lt_max= jb < jb_max;
75  }
76  else
77  {
78  if (op (a.data (ja), b.data (jb)) != 0.)
79  {
80  r.data (jx) = op (a.data (ja), b.data (jb));
81  r.ridx (jx) = a.ridx (ja);
82  jx++;
83  }
84  ja++;
85  ja_lt_max= ja < ja_max;
86  jb++;
87  jb_lt_max= jb < jb_max;
88  }
89  }
90  r.cidx (i+1) = jx;
91  }
92 
93  a = r.maybe_compress ();
94 
95  return a;
96 }
97 
98 template <typename T>
101 {
102  return plus_or_minus (a, b, std::plus<T> (), "operator +=");
103 }
104 
105 template <typename T>
106 MSparse<T>&
108 {
109  return plus_or_minus (a, b, std::minus<T> (), "operator -=");
110 }
111 
112 // Element by element MSparse by scalar ops.
113 
114 template <typename T, typename OP>
115 MArray<T>
116 plus_or_minus (const MSparse<T>& a, const T& s, OP op)
117 {
118  octave_idx_type nr = a.rows ();
119  octave_idx_type nc = a.cols ();
120 
121  MArray<T> r (dim_vector (nr, nc), op (0.0, s));
122 
123  for (octave_idx_type j = 0; j < nc; j++)
124  for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
125  r.elem (a.ridx (i), j) = op (a.data (i), s);
126  return r;
127 }
128 
129 template <typename T>
130 MArray<T>
131 operator + (const MSparse<T>& a, const T& s)
132 {
133  return plus_or_minus (a, s, std::plus<T> ());
134 }
135 
136 template <typename T>
137 MArray<T>
138 operator - (const MSparse<T>& a, const T& s)
139 {
140  return plus_or_minus (a, s, std::minus<T> ());
141 }
142 
143 template <typename T, typename OP>
145 times_or_divide (const MSparse<T>& a, const T& s, OP op)
146 {
147  octave_idx_type nr = a.rows ();
148  octave_idx_type nc = a.cols ();
149  octave_idx_type nz = a.nnz ();
150 
151  MSparse<T> r (nr, nc, nz);
152 
153  for (octave_idx_type i = 0; i < nz; i++)
154  {
155  r.data (i) = op (a.data (i), s);
156  r.ridx (i) = a.ridx (i);
157  }
158  for (octave_idx_type i = 0; i < nc + 1; i++)
159  r.cidx (i) = a.cidx (i);
160  r.maybe_compress (true);
161  return r;
162 }
163 
164 template <typename T>
166 operator * (const MSparse<T>& a, const T& s)
167 {
168  return times_or_divide (a, s, std::multiplies<T> ());
169 }
170 
171 template <typename T>
173 operator / (const MSparse<T>& a, const T& s)
174 {
175  return times_or_divide (a, s, std::divides<T> ());
176 }
177 
178 // Element by element scalar by MSparse ops.
179 
180 template <typename T, typename OP>
181 MArray<T>
182 plus_or_minus (const T& s, const MSparse<T>& a, OP op)
183 {
184  octave_idx_type nr = a.rows ();
185  octave_idx_type nc = a.cols ();
186 
187  MArray<T> r (dim_vector (nr, nc), op (s, 0.0));
188 
189  for (octave_idx_type j = 0; j < nc; j++)
190  for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
191  r.elem (a.ridx (i), j) = op (s, a.data (i));
192  return r;
193 }
194 
195 template <typename T>
196 MArray<T>
197 operator + (const T& s, const MSparse<T>& a)
198 {
199  return plus_or_minus (s, a, std::plus<T> ());
200 }
201 
202 template <typename T>
203 MArray<T>
204 operator - (const T& s, const MSparse<T>& a)
205 {
206  return plus_or_minus (s, a, std::minus<T> ());
207 }
208 
209 template <typename T, typename OP>
211 times_or_divides (const T& s, const MSparse<T>& a, OP op)
212 {
213  octave_idx_type nr = a.rows ();
214  octave_idx_type nc = a.cols ();
215  octave_idx_type nz = a.nnz ();
216 
217  MSparse<T> r (nr, nc, nz);
218 
219  for (octave_idx_type i = 0; i < nz; i++)
220  {
221  r.data (i) = op (s, a.data (i));
222  r.ridx (i) = a.ridx (i);
223  }
224  for (octave_idx_type i = 0; i < nc + 1; i++)
225  r.cidx (i) = a.cidx (i);
226  r.maybe_compress (true);
227  return r;
228 }
229 
230 template <typename T>
232 operator * (const T& s, const MSparse<T>& a)
233 {
234  return times_or_divides (s, a, std::multiplies<T> ());
235 }
236 
237 template <typename T>
239 operator / (const T& s, const MSparse<T>& a)
240 {
241  return times_or_divides (s, a, std::divides<T> ());
242 }
243 
244 // Element by element MSparse by MSparse ops.
245 
246 template <typename T, typename OP>
248 plus_or_minus (const MSparse<T>& a, const MSparse<T>& b, OP op,
249  const char *op_name, bool negate)
250 {
251  MSparse<T> r;
252 
253  octave_idx_type a_nr = a.rows ();
254  octave_idx_type a_nc = a.cols ();
255 
256  octave_idx_type b_nr = b.rows ();
257  octave_idx_type b_nc = b.cols ();
258 
259  if (a_nr == 1 && a_nc == 1)
260  {
261  if (a.elem (0,0) == 0.)
262  if (negate)
263  r = -MSparse<T> (b);
264  else
265  r = MSparse<T> (b);
266  else
267  {
268  r = MSparse<T> (b_nr, b_nc, op (a.data (0), 0.));
269 
270  for (octave_idx_type j = 0 ; j < b_nc ; j++)
271  {
272  octave_quit ();
273  octave_idx_type idxj = j * b_nr;
274  for (octave_idx_type i = b.cidx (j) ; i < b.cidx (j+1) ; i++)
275  {
276  octave_quit ();
277  r.data (idxj + b.ridx (i)) = op (a.data (0), b.data (i));
278  }
279  }
280  r.maybe_compress ();
281  }
282  }
283  else if (b_nr == 1 && b_nc == 1)
284  {
285  if (b.elem (0,0) == 0.)
286  r = MSparse<T> (a);
287  else
288  {
289  r = MSparse<T> (a_nr, a_nc, op (0.0, b.data (0)));
290 
291  for (octave_idx_type j = 0 ; j < a_nc ; j++)
292  {
293  octave_quit ();
294  octave_idx_type idxj = j * a_nr;
295  for (octave_idx_type i = a.cidx (j) ; i < a.cidx (j+1) ; i++)
296  {
297  octave_quit ();
298  r.data (idxj + a.ridx (i)) = op (a.data (i), b.data (0));
299  }
300  }
301  r.maybe_compress ();
302  }
303  }
304  else if (a_nr != b_nr || a_nc != b_nc)
306  else
307  {
308  r = MSparse<T> (a_nr, a_nc, (a.nnz () + b.nnz ()));
309 
310  octave_idx_type jx = 0;
311  r.cidx (0) = 0;
312  for (octave_idx_type i = 0 ; i < a_nc ; i++)
313  {
314  octave_idx_type ja = a.cidx (i);
315  octave_idx_type ja_max = a.cidx (i+1);
316  bool ja_lt_max = ja < ja_max;
317 
318  octave_idx_type jb = b.cidx (i);
319  octave_idx_type jb_max = b.cidx (i+1);
320  bool jb_lt_max = jb < jb_max;
321 
322  while (ja_lt_max || jb_lt_max)
323  {
324  octave_quit ();
325  if ((! jb_lt_max) || (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))
326  {
327  r.ridx (jx) = a.ridx (ja);
328  r.data (jx) = op (a.data (ja), 0.);
329  jx++;
330  ja++;
331  ja_lt_max= ja < ja_max;
332  }
333  else if ((! ja_lt_max)
334  || (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))
335  {
336  r.ridx (jx) = b.ridx (jb);
337  r.data (jx) = op (0., b.data (jb));
338  jx++;
339  jb++;
340  jb_lt_max= jb < jb_max;
341  }
342  else
343  {
344  if (op (a.data (ja), b.data (jb)) != 0.)
345  {
346  r.data (jx) = op (a.data (ja), b.data (jb));
347  r.ridx (jx) = a.ridx (ja);
348  jx++;
349  }
350  ja++;
351  ja_lt_max= ja < ja_max;
352  jb++;
353  jb_lt_max= jb < jb_max;
354  }
355  }
356  r.cidx (i+1) = jx;
357  }
358 
359  r.maybe_compress ();
360  }
361 
362  return r;
363 }
364 
365 template <typename T>
368 {
369  return plus_or_minus (a, b, std::plus<T> (), "operator +", false);
370 }
371 
372 template <typename T>
375 {
376  return plus_or_minus (a, b, std::minus<T> (), "operator -", true);
377 }
378 
379 template <typename T>
381 product (const MSparse<T>& a, const MSparse<T>& b)
382 {
383  MSparse<T> r;
384 
385  octave_idx_type a_nr = a.rows ();
386  octave_idx_type a_nc = a.cols ();
387 
388  octave_idx_type b_nr = b.rows ();
389  octave_idx_type b_nc = b.cols ();
390 
391  if (a_nr == 1 && a_nc == 1)
392  {
393  if (a.elem (0,0) == 0.)
394  r = MSparse<T> (b_nr, b_nc);
395  else
396  {
397  r = MSparse<T> (b);
398  octave_idx_type b_nnz = b.nnz ();
399 
400  for (octave_idx_type i = 0 ; i < b_nnz ; i++)
401  {
402  octave_quit ();
403  r.data (i) = a.data (0) * r.data (i);
404  }
405  r.maybe_compress ();
406  }
407  }
408  else if (b_nr == 1 && b_nc == 1)
409  {
410  if (b.elem (0,0) == 0.)
411  r = MSparse<T> (a_nr, a_nc);
412  else
413  {
414  r = MSparse<T> (a);
415  octave_idx_type a_nnz = a.nnz ();
416 
417  for (octave_idx_type i = 0 ; i < a_nnz ; i++)
418  {
419  octave_quit ();
420  r.data (i) = r.data (i) * b.data (0);
421  }
422  r.maybe_compress ();
423  }
424  }
425  else if (a_nr != b_nr || a_nc != b_nc)
426  octave::err_nonconformant ("product", a_nr, a_nc, b_nr, b_nc);
427  else
428  {
429  r = MSparse<T> (a_nr, a_nc, (a.nnz () > b.nnz () ? a.nnz () : b.nnz ()));
430 
431  octave_idx_type jx = 0;
432  r.cidx (0) = 0;
433  for (octave_idx_type i = 0 ; i < a_nc ; i++)
434  {
435  octave_idx_type ja = a.cidx (i);
436  octave_idx_type ja_max = a.cidx (i+1);
437  bool ja_lt_max = ja < ja_max;
438 
439  octave_idx_type jb = b.cidx (i);
440  octave_idx_type jb_max = b.cidx (i+1);
441  bool jb_lt_max = jb < jb_max;
442 
443  while (ja_lt_max || jb_lt_max)
444  {
445  octave_quit ();
446  if ((! jb_lt_max) || (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))
447  {
448  ja++; ja_lt_max= ja < ja_max;
449  }
450  else if ((! ja_lt_max)
451  || (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))
452  {
453  jb++; jb_lt_max= jb < jb_max;
454  }
455  else
456  {
457  if ((a.data (ja) * b.data (jb)) != 0.)
458  {
459  r.data (jx) = a.data (ja) * b.data (jb);
460  r.ridx (jx) = a.ridx (ja);
461  jx++;
462  }
463  ja++; ja_lt_max= ja < ja_max;
464  jb++; jb_lt_max= jb < jb_max;
465  }
466  }
467  r.cidx (i+1) = jx;
468  }
469 
470  r.maybe_compress ();
471  }
472 
473  return r;
474 }
475 
476 template <typename T>
478 quotient (const MSparse<T>& a, const MSparse<T>& b)
479 {
480  MSparse<T> r;
481  T Zero = T ();
482 
483  octave_idx_type a_nr = a.rows ();
484  octave_idx_type a_nc = a.cols ();
485 
486  octave_idx_type b_nr = b.rows ();
487  octave_idx_type b_nc = b.cols ();
488 
489  if (a_nr == 1 && a_nc == 1)
490  {
491  T val = a.elem (0,0);
492  T fill = val / T ();
493  if (fill == T ())
494  {
495  octave_idx_type b_nnz = b.nnz ();
496  r = MSparse<T> (b);
497  for (octave_idx_type i = 0 ; i < b_nnz ; i++)
498  r.data (i) = val / r.data (i);
499  r.maybe_compress ();
500  }
501  else
502  {
503  r = MSparse<T> (b_nr, b_nc, fill);
504  for (octave_idx_type j = 0 ; j < b_nc ; j++)
505  {
506  octave_quit ();
507  octave_idx_type idxj = j * b_nr;
508  for (octave_idx_type i = b.cidx (j) ; i < b.cidx (j+1) ; i++)
509  {
510  octave_quit ();
511  r.data (idxj + b.ridx (i)) = val / b.data (i);
512  }
513  }
514  r.maybe_compress ();
515  }
516  }
517  else if (b_nr == 1 && b_nc == 1)
518  {
519  T val = b.elem (0,0);
520  T fill = T () / val;
521  if (fill == T ())
522  {
523  octave_idx_type a_nnz = a.nnz ();
524  r = MSparse<T> (a);
525  for (octave_idx_type i = 0 ; i < a_nnz ; i++)
526  r.data (i) = r.data (i) / val;
527  r.maybe_compress ();
528  }
529  else
530  {
531  r = MSparse<T> (a_nr, a_nc, fill);
532  for (octave_idx_type j = 0 ; j < a_nc ; j++)
533  {
534  octave_quit ();
535  octave_idx_type idxj = j * a_nr;
536  for (octave_idx_type i = a.cidx (j) ; i < a.cidx (j+1) ; i++)
537  {
538  octave_quit ();
539  r.data (idxj + a.ridx (i)) = a.data (i) / val;
540  }
541  }
542  r.maybe_compress ();
543  }
544  }
545  else if (a_nr != b_nr || a_nc != b_nc)
546  octave::err_nonconformant ("quotient", a_nr, a_nc, b_nr, b_nc);
547  else
548  {
549  r = MSparse<T> (a_nr, a_nc, (Zero / Zero));
550 
551  for (octave_idx_type i = 0 ; i < a_nc ; i++)
552  {
553  octave_idx_type ja = a.cidx (i);
554  octave_idx_type ja_max = a.cidx (i+1);
555  bool ja_lt_max = ja < ja_max;
556 
557  octave_idx_type jb = b.cidx (i);
558  octave_idx_type jb_max = b.cidx (i+1);
559  bool jb_lt_max = jb < jb_max;
560 
561  while (ja_lt_max || jb_lt_max)
562  {
563  octave_quit ();
564  if ((! jb_lt_max) || (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))
565  {
566  r.elem (a.ridx (ja),i) = a.data (ja) / Zero;
567  ja++; ja_lt_max= ja < ja_max;
568  }
569  else if ((! ja_lt_max)
570  || (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))
571  {
572  r.elem (b.ridx (jb),i) = Zero / b.data (jb);
573  jb++; jb_lt_max= jb < jb_max;
574  }
575  else
576  {
577  r.elem (a.ridx (ja),i) = a.data (ja) / b.data (jb);
578  ja++; ja_lt_max= ja < ja_max;
579  jb++; jb_lt_max= jb < jb_max;
580  }
581  }
582  }
583 
584  r.maybe_compress (true);
585  }
586 
587  return r;
588 }
589 
590 // Unary MSparse ops.
591 
592 template <typename T>
595 {
596  return a;
597 }
598 
599 template <typename T>
602 {
603  MSparse<T> retval (a);
604  octave_idx_type nz = a.nnz ();
605  for (octave_idx_type i = 0; i < nz; i++)
606  retval.data (i) = - retval.data (i);
607  return retval;
608 }
T * data(void)
Definition: Sparse.h:486
Template for N-dimensional array classes with like-type math operators.
Definition: MArray.h:32
MSparse< T > operator*(const MSparse< T > &a, const T &s)
Definition: MSparse.cc:166
void fill(const T &val)
Definition: Array.cc:72
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:4986
MSparse< T > & operator-=(MSparse< T > &a, const MSparse< T > &b)
Definition: MSparse.cc:107
octave_idx_type * cidx(void)
Definition: Sparse.h:508
MSparse< T > product(const MSparse< T > &a, const MSparse< T > &b)
Definition: MSparse.cc:381
octave_idx_type b_nr
Definition: sylvester.cc:76
T & elem(octave_idx_type n)
Definition: Array.h:488
s
Definition: file-io.cc:2729
octave_idx_type a_nc
Definition: sylvester.cc:74
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
MSparse< T > times_or_divide(const MSparse< T > &a, const T &s, OP op)
Definition: MSparse.cc:145
MSparse< T > quotient(const MSparse< T > &a, const MSparse< T > &b)
Definition: MSparse.cc:478
T & elem(octave_idx_type n)
Definition: Sparse.h:363
octave_idx_type a_nr
Definition: sylvester.cc:73
void err_nonconformant(const char *op, octave_idx_type op1_len, octave_idx_type op2_len)
octave_value retval
Definition: data.cc:6246
octave_idx_type * ridx(void)
Definition: Sparse.h:495
MSparse< T > times_or_divides(const T &s, const MSparse< T > &a, OP op)
Definition: MSparse.cc:211
MSparse< T > operator/(const MSparse< T > &a, const T &s)
Definition: MSparse.cc:173
MSparse< T > & operator+=(MSparse< T > &a, const MSparse< T > &b)
Definition: MSparse.cc:100
MArray< T > operator-(const MSparse< T > &a, const T &s)
Definition: MSparse.cc:138
octave_idx_type b_nc
Definition: sylvester.cc:77
MSparse< T > & plus_or_minus(MSparse< T > &a, const MSparse< T > &b, OP op, const char *op_name)
Definition: MSparse.cc:30
b
Definition: cellfun.cc:400
Sparse< T > maybe_compress(bool remove_zeros=false)
Definition: Sparse.h:438
for i
Definition: data.cc:5264
MArray< T > operator+(const MSparse< T > &a, const T &s)
Definition: MSparse.cc:131
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87