1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1998-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING.  If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if ! defined (octave_MSparse_h)
27 #define octave_MSparse_h 1
28 
29 #include "octave-config.h"
30 
31 #include "Array-util.h"
32 #include "MArray.h"
33 #include "Sparse.h"
34 #include "lo-error.h"
35 #include "quit.h"
36 
37 
38 // Two dimensional sparse array with math ops.
39 template <typename T>
40 class
41 MSparse : public Sparse<T>
42 {
43 public:
44 
MSparse(void)45   MSparse (void) : Sparse<T> () { }
46 
MSparse(octave_idx_type n,octave_idx_type m)47   MSparse (octave_idx_type n, octave_idx_type m) : Sparse<T> (n, m) { }
48 
49   MSparse (const dim_vector& dv, octave_idx_type nz = 0)
50     : Sparse<T> (dv, nz) { }
51 
MSparse(const MSparse<T> & a)52   MSparse (const MSparse<T>& a) : Sparse<T> (a) { }
53 
MSparse(const MSparse<T> & a,const dim_vector & dv)54   MSparse (const MSparse<T>& a, const dim_vector& dv) : Sparse<T> (a, dv) { }
55 
MSparse(const Sparse<T> & a)56   MSparse (const Sparse<T>& a) : Sparse<T> (a) { }
57 
58   template <typename U>
MSparse(const Sparse<U> & a)59   MSparse (const Sparse<U>& a) : Sparse<T> (a) { }
60 
61   MSparse (const Array<T>& a, const idx_vector& r, const idx_vector& c,
62            octave_idx_type nr = -1, octave_idx_type nc = -1,
63            bool sum_terms = true, octave_idx_type nzm = -1)
64     : Sparse<T> (a, r, c, nr, nc, sum_terms, nzm) { }
65 
MSparse(octave_idx_type r,octave_idx_type c,T val)66   explicit MSparse (octave_idx_type r, octave_idx_type c, T val)
67     : Sparse<T> (r, c, val) { }
68 
MSparse(const PermMatrix & a)69   explicit MSparse (const PermMatrix& a) : Sparse<T>(a) { }
70 
MSparse(octave_idx_type r,octave_idx_type c,octave_idx_type num_nz)71   MSparse (octave_idx_type r, octave_idx_type c, octave_idx_type num_nz)
72     : Sparse<T> (r, c, num_nz) { }
73 
74   ~MSparse (void) = default;
75 
76   MSparse<T>& operator = (const MSparse<T>& a)
77   {
78     Sparse<T>::operator = (a);
79     return *this;
80   }
81 
insert(const Sparse<T> & a,octave_idx_type r,octave_idx_type c)82   MSparse<T>& insert (const Sparse<T>& a, octave_idx_type r, octave_idx_type c)
83   {
84     Sparse<T>::insert (a, r, c);
85     return *this;
86   }
87 
insert(const Sparse<T> & a,const Array<octave_idx_type> & indx)88   MSparse<T>& insert (const Sparse<T>& a, const Array<octave_idx_type>& indx)
89   {
90     Sparse<T>::insert (a, indx);
91     return *this;
92   }
93 
transpose(void)94   MSparse<T> transpose (void) const { return Sparse<T>::transpose (); }
95 
squeeze(void)96   MSparse<T> squeeze (void) const { return Sparse<T>::squeeze (); }
97 
reshape(const dim_vector & new_dims)98   MSparse<T> reshape (const dim_vector& new_dims) const
99   { return Sparse<T>::reshape (new_dims); }
100 
101   MSparse<T> permute (const Array<octave_idx_type>& vec, bool inv = false) const
102   { return Sparse<T>::permute (vec, inv); }
103 
ipermute(const Array<octave_idx_type> & vec)104   MSparse<T> ipermute (const Array<octave_idx_type>& vec) const
105   { return Sparse<T>::ipermute (vec); }
106 
107   MSparse<T> diag (octave_idx_type k = 0) const
108   {
109     return Sparse<T>::diag (k);
110   }
111 
112   // FIXME: should go away.
113   template <typename U>
114   MSparse<U>
map(U (& fcn)(T))115   map (U (&fcn) (T)) const
116   { return Sparse<T>::template map<U> (fcn); }
117 
118   template <typename U>
119   MSparse<U>
map(U (& fcn)(const T &))120   map (U (&fcn) (const T&)) const
121   { return Sparse<T>::template map<U> (fcn); }
122 };
123 
124 // Include operator templates for MSparse
125 #include "MSparse.cc"
126 
127 // A macro that can be used to declare and instantiate OP= operators.
128 #define SPARSE_OP_ASSIGN_DECL(T, OP, API)       \
129   template API MSparse<T>&                      \
130   operator OP (MSparse<T>&, const MSparse<T>&)
131 
132 // A macro that can be used to declare and instantiate unary operators.
133 #define SPARSE_UNOP_DECL(T, OP, API)            \
134   template API MSparse<T>                       \
135   operator OP (const MSparse<T>&)
136 
137 // A macro that can be used to declare and instantiate binary operators.
138 #define SPARSE_BINOP_DECL(A_T, T, F, API, X_T, Y_T)     \
139   template API A_T<T>                                   \
140   F (const X_T&, const Y_T&)
141 
142 // A function that can be used to forward OP= operations from derived
143 // classes back to us.
144 #define SPARSE_OP_ASSIGN_FWD_FCN(R, F, T, C_X, X_T, C_Y, Y_T)   \
145   inline R                                                      \
146   F (X_T& x, const Y_T& y)                                      \
147   {                                                             \
148     return R (F (C_X (x), C_Y (y)));                            \
149   }
150 
151 // A function that can be used to forward unary operations from derived
152 // classes back to us.
153 #define SPARSE_UNOP_FWD_FCN(R, F, T, C_X, X_T)  \
154   inline R                                      \
155   F (const X_T& x)                              \
156   {                                             \
157     return R (F (C_X (x)));                     \
158   }
159 
160 // A function that can be used to forward binary operations from derived
161 // classes back to us.
162 #define SPARSE_BINOP_FWD_FCN(R, F, T, C_X, X_T, C_Y, Y_T)       \
163   inline R                                                      \
164   F (const X_T& x, const Y_T& y)                                \
165   {                                                             \
166     return R (F (C_X (x), C_Y (y)));                            \
167   }
168 
169 // Instantiate all the MSparse friends for MSparse element type T.
170 #define INSTANTIATE_SPARSE_FRIENDS(T, API)                              \
171   SPARSE_OP_ASSIGN_DECL (T, +=, API);                                   \
172   SPARSE_OP_ASSIGN_DECL (T, -=, API);                                   \
173   SPARSE_UNOP_DECL (T, +, API);                                         \
174   SPARSE_UNOP_DECL (T, -, API);                                         \
175   SPARSE_BINOP_DECL (MArray,  T, operator +, API, MSparse<T>, T);       \
176   SPARSE_BINOP_DECL (MArray,  T, operator -, API, MSparse<T>, T);       \
177   SPARSE_BINOP_DECL (MSparse, T, operator *, API, MSparse<T>, T);       \
178   SPARSE_BINOP_DECL (MSparse, T, operator /, API, MSparse<T>, T);       \
179   SPARSE_BINOP_DECL (MArray,  T, operator +, API, T, MSparse<T>);       \
180   SPARSE_BINOP_DECL (MArray,  T, operator -, API, T, MSparse<T>);       \
181   SPARSE_BINOP_DECL (MSparse, T, operator *, API, T, MSparse<T>);       \
182   SPARSE_BINOP_DECL (MSparse, T, operator /, API, T, MSparse<T>);       \
183   SPARSE_BINOP_DECL (MSparse, T, operator +, API, MSparse<T>, MSparse<T>); \
184   SPARSE_BINOP_DECL (MSparse, T, operator -, API, MSparse<T>, MSparse<T>); \
185   SPARSE_BINOP_DECL (MSparse, T, quotient,   API, MSparse<T>, MSparse<T>); \
186   SPARSE_BINOP_DECL (MSparse, T, product,    API, MSparse<T>, MSparse<T>);
187 
188 // Define all the MSparse forwarding functions for return type R and
189 // MSparse element type T
190 #define SPARSE_FORWARD_DEFS(B, R, F, T)                                 \
191   SPARSE_OP_ASSIGN_FWD_FCN (R, operator +=, T, dynamic_cast<B<T>&>,     \
192                             R, dynamic_cast<const B<T>&>, R)            \
193   SPARSE_OP_ASSIGN_FWD_FCN (R, operator -=, T, dynamic_cast<B<T>&>,     \
194                             R, dynamic_cast<const B<T>&>, R)            \
195   SPARSE_UNOP_FWD_FCN (R, operator +, T, dynamic_cast<const B<T>&>, R)  \
196   SPARSE_UNOP_FWD_FCN (R, operator -, T, dynamic_cast<const B<T>&>, R)  \
197   SPARSE_BINOP_FWD_FCN (F, operator +, T, dynamic_cast<const B<T>&>, R, , T) \
198   SPARSE_BINOP_FWD_FCN (F, operator -, T, dynamic_cast<const B<T>&>, R, , T) \
199   SPARSE_BINOP_FWD_FCN (R, operator *, T, dynamic_cast<const B<T>&>, R, , T) \
200   SPARSE_BINOP_FWD_FCN (R, operator /, T, dynamic_cast<const B<T>&>, R, , T) \
201   SPARSE_BINOP_FWD_FCN (F, operator +, T, , T, dynamic_cast<const B<T>&>, R) \
202   SPARSE_BINOP_FWD_FCN (F, operator -, T, , T, dynamic_cast<const B<T>&>, R) \
203   SPARSE_BINOP_FWD_FCN (R, operator *, T, , T, dynamic_cast<const B<T>&>, R) \
204   SPARSE_BINOP_FWD_FCN (R, operator /, T, , T, dynamic_cast<const B<T>&>, R) \
205   SPARSE_BINOP_FWD_FCN (R, operator +, T, dynamic_cast<const B<T>&>,    \
206                         R, dynamic_cast<const B<T>&>, R)                \
207   SPARSE_BINOP_FWD_FCN (R, operator -, T, dynamic_cast<const B<T>&>,    \
208                         R, dynamic_cast<const B<T>&>, R)                \
209   SPARSE_BINOP_FWD_FCN (R, product,    T, dynamic_cast<const B<T>&>,    \
210                         R, dynamic_cast<const B<T>&>, R)                \
211   SPARSE_BINOP_FWD_FCN (R, quotient, T, dynamic_cast<const B<T>&>,      \
212                         R, dynamic_cast<const B<T>&>, R)
213 
214 #endif
215