GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
MSparse.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2004-2017 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 the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 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 <http://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)
41  octave::err_nonconformant (op_name , a_nr, a_nc, b_nr, 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)
305  octave::err_nonconformant (op_name, a_nr, a_nc, b_nr, 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 }
octave_idx_type cols(void) const
Definition: Sparse.h:272
T * data(void)
Definition: Sparse.h:521
octave_idx_type rows(void) const
Definition: Sparse.h:271
T & elem(octave_idx_type n)
Definition: Sparse.h:374
MSparse< T > operator*(const MSparse< T > &a, const T &s)
Definition: MSparse.cc:166
void fill(const T &val)
Definition: Array.cc:81
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:5068
MSparse< T > & operator-=(MSparse< T > &a, const MSparse< T > &b)
Definition: MSparse.cc:107
MSparse< T > product(const MSparse< T > &a, const MSparse< T > &b)
Definition: MSparse.cc:381
octave_idx_type b_nr
Definition: sylvester.cc:74
octave_idx_type * cidx(void)
Definition: Sparse.h:543
T & elem(octave_idx_type n)
Definition: Array.h:482
Template for N-dimensional array classes with like-type math operators.
Definition: MArray.h:32
s
Definition: file-io.cc:2682
octave_idx_type a_nc
Definition: sylvester.cc:72
octave_idx_type nnz(void) const
Actual number of nonzero terms.
Definition: Sparse.h:253
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:398
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
octave_idx_type a_nr
Definition: sylvester.cc:71
Sparse< T > maybe_compress(bool remove_zeros=false)
Definition: Sparse.h:481
void err_nonconformant(const char *op, octave_idx_type op1_len, octave_idx_type op2_len)
octave_value retval
Definition: data.cc:6294
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
octave_idx_type * ridx(void)
Definition: Sparse.h:530
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
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
octave_idx_type b_nc
Definition: sylvester.cc:75
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:398
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