1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2004-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 // This file should not include config.h.  It is only included in other
27 // C++ source files that should have included config.h before including
28 // this file.
29 
30 #include "Array-util.h"
31 #include "mx-base.h"
32 #include "lo-ieee.h"
33 #include "mx-inlines.cc"
34 
35 // unary operations
36 
37 template <typename T>
38 boolNDArray
operator !(void) const39 intNDArray<T>::operator ! (void) const
40 {
41   boolNDArray b (this->dims ());
42 
43   for (octave_idx_type i = 0; i < this->numel (); i++)
44     b.elem (i) = ! this->elem (i);
45 
46   return b;
47 }
48 
49 template <typename T>
50 bool
any_element_not_one_or_zero(void) const51 intNDArray<T>::any_element_not_one_or_zero (void) const
52 {
53   octave_idx_type nel = this->numel ();
54 
55   for (octave_idx_type i = 0; i < nel; i++)
56     {
57       T val = this->elem (i);
58 
59       if (val != 0.0 && val != 1.0)
60         return true;
61     }
62 
63   return false;
64 }
65 
66 template <typename T>
67 intNDArray<T>
diag(octave_idx_type k) const68 intNDArray<T>::diag (octave_idx_type k) const
69 {
70   return MArray<T>::diag (k);
71 }
72 
73 template <typename T>
74 intNDArray<T>
diag(octave_idx_type m,octave_idx_type n) const75 intNDArray<T>::diag (octave_idx_type m, octave_idx_type n) const
76 {
77   return MArray<T>::diag (m, n);
78 }
79 
80 // FIXME: this is not quite the right thing.
81 
82 template <typename T>
83 boolNDArray
all(int dim) const84 intNDArray<T>::all (int dim) const
85 {
86   return do_mx_red_op<bool, T > (*this, dim, mx_inline_all);
87 }
88 
89 template <typename T>
90 boolNDArray
any(int dim) const91 intNDArray<T>::any (int dim) const
92 {
93   return do_mx_red_op<bool, T > (*this, dim, mx_inline_any);
94 }
95 
96 template <typename T>
97 void
increment_index(Array<octave_idx_type> & ra_idx,const dim_vector & dimensions,int start_dimension)98 intNDArray<T>::increment_index (Array<octave_idx_type>& ra_idx,
99                                 const dim_vector& dimensions,
100                                 int start_dimension)
101 {
102   ::increment_index (ra_idx, dimensions, start_dimension);
103 }
104 
105 template <typename T>
106 octave_idx_type
compute_index(Array<octave_idx_type> & ra_idx,const dim_vector & dimensions)107 intNDArray<T>::compute_index (Array<octave_idx_type>& ra_idx,
108                               const dim_vector& dimensions)
109 {
110   return ::compute_index (ra_idx, dimensions);
111 }
112 
113 template <typename T>
114 intNDArray<T>
concat(const intNDArray<T> & rb,const Array<octave_idx_type> & ra_idx)115 intNDArray<T>::concat (const intNDArray<T>& rb,
116                        const Array<octave_idx_type>& ra_idx)
117 {
118   if (rb.numel () > 0)
119     insert (rb, ra_idx);
120   return *this;
121 }
122 
123 template <typename T>
124 intNDArray<T>&
insert(const intNDArray<T> & a,octave_idx_type r,octave_idx_type c)125 intNDArray<T>::insert (const intNDArray<T>& a, octave_idx_type r,
126                        octave_idx_type c)
127 {
128   Array<T>::insert (a, r, c);
129   return *this;
130 }
131 
132 template <typename T>
133 intNDArray<T>&
insert(const intNDArray<T> & a,const Array<octave_idx_type> & ra_idx)134 intNDArray<T>::insert (const intNDArray<T>& a,
135                        const Array<octave_idx_type>& ra_idx)
136 {
137   Array<T>::insert (a, ra_idx);
138   return *this;
139 }
140 
141 // This contains no information on the array structure !!!
142 
143 template <typename T>
144 std::ostream&
operator <<(std::ostream & os,const intNDArray<T> & a)145 operator << (std::ostream& os, const intNDArray<T>& a)
146 {
147   octave_idx_type nel = a.numel ();
148 
149   for (octave_idx_type i = 0; i < nel; i++)
150     os << ' ' << a.elem (i) << "\n";
151 
152   return os;
153 }
154 
155 template <typename T>
156 std::istream&
operator >>(std::istream & is,intNDArray<T> & a)157 operator >> (std::istream& is, intNDArray<T>& a)
158 {
159   octave_idx_type nel = a.numel ();
160 
161   if (nel > 0)
162     {
163       T tmp;
164 
165       for (octave_idx_type i = 0; i < nel; i++)
166         {
167           is >> tmp;
168 
169           if (is)
170             a.elem (i) = tmp;
171           else
172             return is;
173         }
174     }
175 
176   return is;
177 }
178 
179 // FIXME: should abs and signum just be mapper functions?
180 
181 template <typename T>
182 intNDArray<T>
abs(void) const183 intNDArray<T>::abs (void) const
184 {
185   octave_idx_type nel = this->numel ();
186   intNDArray<T> ret (this->dims ());
187 
188   for (octave_idx_type i = 0; i < nel; i++)
189     {
190       T val = this->elem (i);
191       ret.xelem (i) = val.abs ();
192     }
193 
194   return ret;
195 }
196 
197 template <typename T>
198 intNDArray<T>
signum(void) const199 intNDArray<T>::signum (void) const
200 {
201   octave_idx_type nel = this->numel ();
202   intNDArray<T> ret (this->dims ());
203 
204   for (octave_idx_type i = 0; i < nel; i++)
205     {
206       T val = this->elem (i);
207       ret.xelem (i) = val.signum ();
208     }
209 
210   return ret;
211 }
212 
213 template <typename T>
214 intNDArray<T>
prod(int dim) const215 intNDArray<T>::prod (int dim) const
216 {
217   return do_mx_red_op<T, T> (*this, dim, mx_inline_prod);
218 }
219 
220 template <typename T>
221 intNDArray<T>
sum(int dim) const222 intNDArray<T>::sum (int dim) const
223 {
224   return do_mx_red_op<T, T> (*this, dim, mx_inline_sum);
225 }
226 
227 template <typename T>
228 NDArray
dsum(int dim) const229 intNDArray<T>::dsum (int dim) const
230 {
231   return do_mx_red_op<double, T> (*this, dim, mx_inline_dsum);
232 }
233 
234 template <typename T>
235 intNDArray<T>
cumsum(int dim) const236 intNDArray<T>::cumsum (int dim) const
237 {
238   return do_mx_cum_op<T, T> (*this, dim, mx_inline_cumsum);
239 }
240 
241 template <typename T>
242 intNDArray<T>
max(int dim) const243 intNDArray<T>::max (int dim) const
244 {
245   return do_mx_minmax_op<T> (*this, dim, mx_inline_max);
246 }
247 
248 template <typename T>
249 intNDArray<T>
max(Array<octave_idx_type> & idx_arg,int dim) const250 intNDArray<T>::max (Array<octave_idx_type>& idx_arg, int dim) const
251 {
252   return do_mx_minmax_op<T> (*this, idx_arg, dim, mx_inline_max);
253 }
254 
255 template <typename T>
256 intNDArray<T>
min(int dim) const257 intNDArray<T>::min (int dim) const
258 {
259   return do_mx_minmax_op<T> (*this, dim, mx_inline_min);
260 }
261 
262 template <typename T>
263 intNDArray<T>
min(Array<octave_idx_type> & idx_arg,int dim) const264 intNDArray<T>::min (Array<octave_idx_type>& idx_arg, int dim) const
265 {
266   return do_mx_minmax_op<T> (*this, idx_arg, dim, mx_inline_min);
267 }
268 
269 template <typename T>
270 intNDArray<T>
cummax(int dim) const271 intNDArray<T>::cummax (int dim) const
272 {
273   return do_mx_cumminmax_op<T> (*this, dim, mx_inline_cummax);
274 }
275 
276 template <typename T>
277 intNDArray<T>
cummax(Array<octave_idx_type> & idx_arg,int dim) const278 intNDArray<T>::cummax (Array<octave_idx_type>& idx_arg, int dim) const
279 {
280   return do_mx_cumminmax_op<T> (*this, idx_arg, dim, mx_inline_cummax);
281 }
282 
283 template <typename T>
284 intNDArray<T>
cummin(int dim) const285 intNDArray<T>::cummin (int dim) const
286 {
287   return do_mx_cumminmax_op<T> (*this, dim, mx_inline_cummin);
288 }
289 
290 template <typename T>
291 intNDArray<T>
cummin(Array<octave_idx_type> & idx_arg,int dim) const292 intNDArray<T>::cummin (Array<octave_idx_type>& idx_arg, int dim) const
293 {
294   return do_mx_cumminmax_op<T> (*this, idx_arg, dim, mx_inline_cummin);
295 }
296 
297 template <typename T>
298 intNDArray<T>
diff(octave_idx_type order,int dim) const299 intNDArray<T>::diff (octave_idx_type order, int dim) const
300 {
301   return do_mx_diff_op<T> (*this, dim, order, mx_inline_diff);
302 }
303