1 // SPDX-License-Identifier: Apache-2.0
2 //
3 // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
4 // Copyright 2008-2016 National ICT Australia (NICTA)
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 // ------------------------------------------------------------------------
17 
18 
19 //! \addtogroup Mat
20 //! @{
21 
22 
23 
24 //! Dense matrix class
25 
26 template<typename eT>
27 class Mat : public Base< eT, Mat<eT> >
28   {
29   public:
30 
31   typedef eT                                elem_type;  //!< the type of elements stored in the matrix
32   typedef typename get_pod_type<eT>::result  pod_type;  //!< if eT is std::complex<T>, pod_type is T; otherwise pod_type is eT
33 
34   const uword  n_rows;    //!< number of rows               (read-only)
35   const uword  n_cols;    //!< number of columns            (read-only)
36   const uword  n_elem;    //!< number of elements           (read-only)
37   const uword  n_alloc;   //!< number of allocated elements (read-only); NOTE: n_alloc can be 0, even if n_elem > 0
38   const uhword vec_state; //!< 0: matrix layout; 1: column vector layout; 2: row vector layout
39   const uhword mem_state;
40 
41   // mem_state = 0: normal matrix which manages its own memory
42   // mem_state = 1: use auxiliary memory until a size change
43   // mem_state = 2: use auxiliary memory and don't allow the number of elements to be changed
44   // mem_state = 3: fixed size (eg. via template based size specification)
45 
46   arma_aligned const eT* const mem;  //!< pointer to the memory used for storing elements (memory is read-only)
47 
48 
49   protected:
50 
51   arma_align_mem eT mem_local[ arma_config::mat_prealloc ];  // local storage, for small vectors and matrices
52 
53 
54   public:
55 
56   static constexpr bool is_col  = false;
57   static constexpr bool is_row  = false;
58   static constexpr bool is_xvec = false;
59 
60   inline ~Mat();
61   inline  Mat();
62 
63   inline explicit Mat(const uword in_rows, const uword in_cols);
64   inline explicit Mat(const SizeMat& s);
65 
66   template<bool do_zeros> inline explicit Mat(const uword in_rows, const uword in_cols, const arma_initmode_indicator<do_zeros>&);
67   template<bool do_zeros> inline explicit Mat(const SizeMat& s,                         const arma_initmode_indicator<do_zeros>&);
68 
69   template<typename fill_type> inline Mat(const uword in_rows, const uword in_cols, const fill::fill_class<fill_type>& f);
70   template<typename fill_type> inline Mat(const SizeMat& s,                         const fill::fill_class<fill_type>& f);
71 
72   inline Mat(const uword in_rows, const uword in_cols, const fill::scalar_holder<eT> f);
73   inline Mat(const SizeMat& s,                         const fill::scalar_holder<eT> f);
74 
75   inline arma_cold            Mat(const char*        text);
76   inline arma_cold Mat& operator=(const char*        text);
77 
78   inline arma_cold            Mat(const std::string& text);
79   inline arma_cold Mat& operator=(const std::string& text);
80 
81   inline            Mat(const std::vector<eT>& x);
82   inline Mat& operator=(const std::vector<eT>& x);
83 
84   inline            Mat(const std::initializer_list<eT>& list);
85   inline Mat& operator=(const std::initializer_list<eT>& list);
86 
87   inline            Mat(const std::initializer_list< std::initializer_list<eT> >& list);
88   inline Mat& operator=(const std::initializer_list< std::initializer_list<eT> >& list);
89 
90   inline            Mat(Mat&& m);
91   inline Mat& operator=(Mat&& m);
92 
93   inline Mat(      eT* aux_mem, const uword aux_n_rows, const uword aux_n_cols, const bool copy_aux_mem = true, const bool strict = false);
94   inline Mat(const eT* aux_mem, const uword aux_n_rows, const uword aux_n_cols);
95 
96   inline Mat& operator= (const eT val);
97   inline Mat& operator+=(const eT val);
98   inline Mat& operator-=(const eT val);
99   inline Mat& operator*=(const eT val);
100   inline Mat& operator/=(const eT val);
101 
102   inline             Mat(const Mat& m);
103   inline Mat& operator= (const Mat& m);
104   inline Mat& operator+=(const Mat& m);
105   inline Mat& operator-=(const Mat& m);
106   inline Mat& operator*=(const Mat& m);
107   inline Mat& operator%=(const Mat& m);
108   inline Mat& operator/=(const Mat& m);
109 
110   template<typename T1> inline             Mat(const BaseCube<eT,T1>& X);
111   template<typename T1> inline Mat& operator= (const BaseCube<eT,T1>& X);
112   template<typename T1> inline Mat& operator+=(const BaseCube<eT,T1>& X);
113   template<typename T1> inline Mat& operator-=(const BaseCube<eT,T1>& X);
114   template<typename T1> inline Mat& operator*=(const BaseCube<eT,T1>& X);
115   template<typename T1> inline Mat& operator%=(const BaseCube<eT,T1>& X);
116   template<typename T1> inline Mat& operator/=(const BaseCube<eT,T1>& X);
117 
118   template<typename T1, typename T2>
119   inline explicit Mat(const Base<pod_type,T1>& A, const Base<pod_type,T2>& B);
120 
121   inline explicit          Mat(const subview<eT>& X, const bool use_colmem);  // only to be used by the quasi_unwrap class
122 
123   inline             Mat(const subview<eT>& X);
124   inline Mat& operator= (const subview<eT>& X);
125   inline Mat& operator+=(const subview<eT>& X);
126   inline Mat& operator-=(const subview<eT>& X);
127   inline Mat& operator*=(const subview<eT>& X);
128   inline Mat& operator%=(const subview<eT>& X);
129   inline Mat& operator/=(const subview<eT>& X);
130 
131   inline Mat(const subview_row_strans<eT>& X);  // subview_row_strans can only be generated by the Proxy class
132   inline Mat(const subview_row_htrans<eT>& X);  // subview_row_htrans can only be generated by the Proxy class
133   inline Mat(const        xvec_htrans<eT>& X);  //        xvec_htrans can only be generated by the Proxy class
134 
135   template<bool do_conj>
136   inline Mat(const xtrans_mat<eT,do_conj>& X);  //        xtrans_mat can only be generated by the Proxy class
137 
138   inline             Mat(const subview_cube<eT>& X);
139   inline Mat& operator= (const subview_cube<eT>& X);
140   inline Mat& operator+=(const subview_cube<eT>& X);
141   inline Mat& operator-=(const subview_cube<eT>& X);
142   inline Mat& operator*=(const subview_cube<eT>& X);
143   inline Mat& operator%=(const subview_cube<eT>& X);
144   inline Mat& operator/=(const subview_cube<eT>& X);
145 
146   inline             Mat(const diagview<eT>& X);
147   inline Mat& operator= (const diagview<eT>& X);
148   inline Mat& operator+=(const diagview<eT>& X);
149   inline Mat& operator-=(const diagview<eT>& X);
150   inline Mat& operator*=(const diagview<eT>& X);
151   inline Mat& operator%=(const diagview<eT>& X);
152   inline Mat& operator/=(const diagview<eT>& X);
153 
154   template<typename T1> inline             Mat(const subview_elem1<eT,T1>& X);
155   template<typename T1> inline Mat& operator= (const subview_elem1<eT,T1>& X);
156   template<typename T1> inline Mat& operator+=(const subview_elem1<eT,T1>& X);
157   template<typename T1> inline Mat& operator-=(const subview_elem1<eT,T1>& X);
158   template<typename T1> inline Mat& operator*=(const subview_elem1<eT,T1>& X);
159   template<typename T1> inline Mat& operator%=(const subview_elem1<eT,T1>& X);
160   template<typename T1> inline Mat& operator/=(const subview_elem1<eT,T1>& X);
161 
162   template<typename T1, typename T2> inline             Mat(const subview_elem2<eT,T1,T2>& X);
163   template<typename T1, typename T2> inline Mat& operator= (const subview_elem2<eT,T1,T2>& X);
164   template<typename T1, typename T2> inline Mat& operator+=(const subview_elem2<eT,T1,T2>& X);
165   template<typename T1, typename T2> inline Mat& operator-=(const subview_elem2<eT,T1,T2>& X);
166   template<typename T1, typename T2> inline Mat& operator*=(const subview_elem2<eT,T1,T2>& X);
167   template<typename T1, typename T2> inline Mat& operator%=(const subview_elem2<eT,T1,T2>& X);
168   template<typename T1, typename T2> inline Mat& operator/=(const subview_elem2<eT,T1,T2>& X);
169 
170   // Operators on sparse matrices (and subviews)
171   template<typename T1> inline explicit    Mat(const SpBase<eT, T1>& m);
172   template<typename T1> inline Mat& operator= (const SpBase<eT, T1>& m);
173   template<typename T1> inline Mat& operator+=(const SpBase<eT, T1>& m);
174   template<typename T1> inline Mat& operator-=(const SpBase<eT, T1>& m);
175   template<typename T1> inline Mat& operator*=(const SpBase<eT, T1>& m);
176   template<typename T1> inline Mat& operator%=(const SpBase<eT, T1>& m);
177   template<typename T1> inline Mat& operator/=(const SpBase<eT, T1>& m);
178 
179   inline explicit    Mat(const SpSubview<eT>& X);
180   inline Mat& operator= (const SpSubview<eT>& X);
181 
182   inline explicit    Mat(const spdiagview<eT>& X);
183   inline Mat& operator= (const spdiagview<eT>& X);
184   inline Mat& operator+=(const spdiagview<eT>& X);
185   inline Mat& operator-=(const spdiagview<eT>& X);
186   inline Mat& operator*=(const spdiagview<eT>& X);
187   inline Mat& operator%=(const spdiagview<eT>& X);
188   inline Mat& operator/=(const spdiagview<eT>& X);
189 
190 
191   arma_cold inline mat_injector<Mat> operator<<(const eT val);
192   arma_cold inline mat_injector<Mat> operator<<(const injector_end_of_row<>& x);
193 
194 
195   arma_inline       subview_row<eT> row(const uword row_num);
196   arma_inline const subview_row<eT> row(const uword row_num) const;
197 
198   inline            subview_row<eT> operator()(const uword row_num, const span& col_span);
199   inline      const subview_row<eT> operator()(const uword row_num, const span& col_span) const;
200 
201 
202   arma_inline       subview_col<eT> col(const uword col_num);
203   arma_inline const subview_col<eT> col(const uword col_num) const;
204 
205   inline            subview_col<eT> operator()(const span& row_span, const uword col_num);
206   inline      const subview_col<eT> operator()(const span& row_span, const uword col_num) const;
207 
208   inline            Col<eT>  unsafe_col(const uword col_num);
209   inline      const Col<eT>  unsafe_col(const uword col_num) const;
210 
211 
212   arma_inline       subview<eT>      rows(const uword in_row1, const uword in_row2);
213   arma_inline const subview<eT>      rows(const uword in_row1, const uword in_row2) const;
214 
215   arma_inline       subview_cols<eT> cols(const uword in_col1, const uword in_col2);
216   arma_inline const subview_cols<eT> cols(const uword in_col1, const uword in_col2) const;
217 
218   inline            subview<eT>      rows(const span& row_span);
219   inline      const subview<eT>      rows(const span& row_span) const;
220 
221   arma_inline       subview_cols<eT> cols(const span& col_span);
222   arma_inline const subview_cols<eT> cols(const span& col_span) const;
223 
224 
225   arma_inline       subview<eT> submat(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2);
226   arma_inline const subview<eT> submat(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2) const;
227 
228   arma_inline       subview<eT> submat(const uword in_row1, const uword in_col1, const SizeMat& s);
229   arma_inline const subview<eT> submat(const uword in_row1, const uword in_col1, const SizeMat& s) const;
230 
231   inline            subview<eT> submat    (const span& row_span, const span& col_span);
232   inline      const subview<eT> submat    (const span& row_span, const span& col_span) const;
233 
234   inline            subview<eT> operator()(const span& row_span, const span& col_span);
235   inline      const subview<eT> operator()(const span& row_span, const span& col_span) const;
236 
237   inline            subview<eT> operator()(const uword in_row1, const uword in_col1, const SizeMat& s);
238   inline      const subview<eT> operator()(const uword in_row1, const uword in_col1, const SizeMat& s) const;
239 
240   inline       subview<eT> head_rows(const uword N);
241   inline const subview<eT> head_rows(const uword N) const;
242 
243   inline       subview<eT> tail_rows(const uword N);
244   inline const subview<eT> tail_rows(const uword N) const;
245 
246   inline       subview_cols<eT> head_cols(const uword N);
247   inline const subview_cols<eT> head_cols(const uword N) const;
248 
249   inline       subview_cols<eT> tail_cols(const uword N);
250   inline const subview_cols<eT> tail_cols(const uword N) const;
251 
252   template<typename T1> arma_inline       subview_elem1<eT,T1> elem(const Base<uword,T1>& a);
253   template<typename T1> arma_inline const subview_elem1<eT,T1> elem(const Base<uword,T1>& a) const;
254 
255   template<typename T1> arma_inline       subview_elem1<eT,T1> operator()(const Base<uword,T1>& a);
256   template<typename T1> arma_inline const subview_elem1<eT,T1> operator()(const Base<uword,T1>& a) const;
257 
258 
259   template<typename T1, typename T2> arma_inline       subview_elem2<eT,T1,T2> elem(const Base<uword,T1>& ri, const Base<uword,T2>& ci);
260   template<typename T1, typename T2> arma_inline const subview_elem2<eT,T1,T2> elem(const Base<uword,T1>& ri, const Base<uword,T2>& ci) const;
261 
262   template<typename T1, typename T2> arma_inline       subview_elem2<eT,T1,T2> submat(const Base<uword,T1>& ri, const Base<uword,T2>& ci);
263   template<typename T1, typename T2> arma_inline const subview_elem2<eT,T1,T2> submat(const Base<uword,T1>& ri, const Base<uword,T2>& ci) const;
264 
265   template<typename T1, typename T2> arma_inline       subview_elem2<eT,T1,T2> operator()(const Base<uword,T1>& ri, const Base<uword,T2>& ci);
266   template<typename T1, typename T2> arma_inline const subview_elem2<eT,T1,T2> operator()(const Base<uword,T1>& ri, const Base<uword,T2>& ci) const;
267 
268 
269   template<typename T1> arma_inline       subview_elem2<eT,T1,T1> rows(const Base<uword,T1>& ri);
270   template<typename T1> arma_inline const subview_elem2<eT,T1,T1> rows(const Base<uword,T1>& ri) const;
271 
272   template<typename T2> arma_inline       subview_elem2<eT,T2,T2> cols(const Base<uword,T2>& ci);
273   template<typename T2> arma_inline const subview_elem2<eT,T2,T2> cols(const Base<uword,T2>& ci) const;
274 
275 
276   arma_inline       subview_each1< Mat<eT>, 0 > each_col();
277   arma_inline       subview_each1< Mat<eT>, 1 > each_row();
278 
279   arma_inline const subview_each1< Mat<eT>, 0 > each_col() const;
280   arma_inline const subview_each1< Mat<eT>, 1 > each_row() const;
281 
282   template<typename T1> inline       subview_each2< Mat<eT>, 0, T1 > each_col(const Base<uword, T1>& indices);
283   template<typename T1> inline       subview_each2< Mat<eT>, 1, T1 > each_row(const Base<uword, T1>& indices);
284 
285   template<typename T1> inline const subview_each2< Mat<eT>, 0, T1 > each_col(const Base<uword, T1>& indices) const;
286   template<typename T1> inline const subview_each2< Mat<eT>, 1, T1 > each_row(const Base<uword, T1>& indices) const;
287 
288   inline const Mat& each_col(const std::function< void(      Col<eT>&) >& F);
289   inline const Mat& each_col(const std::function< void(const Col<eT>&) >& F) const;
290 
291   inline const Mat& each_row(const std::function< void(      Row<eT>&) >& F);
292   inline const Mat& each_row(const std::function< void(const Row<eT>&) >& F) const;
293 
294 
295   arma_inline       diagview<eT> diag(const sword in_id = 0);
296   arma_inline const diagview<eT> diag(const sword in_id = 0) const;
297 
298 
299   inline void swap_rows(const uword in_row1, const uword in_row2);
300   inline void swap_cols(const uword in_col1, const uword in_col2);
301 
302   inline void shed_row(const uword row_num);
303   inline void shed_col(const uword col_num);
304 
305   inline void shed_rows(const uword in_row1, const uword in_row2);
306   inline void shed_cols(const uword in_col1, const uword in_col2);
307 
308   template<typename T1> inline void shed_rows(const Base<uword, T1>& indices);
309   template<typename T1> inline void shed_cols(const Base<uword, T1>& indices);
310 
311   inline void insert_rows(const uword row_num, const uword N, const bool set_to_zero = true);
312   inline void insert_cols(const uword col_num, const uword N, const bool set_to_zero = true);
313 
314   template<typename T1> inline void insert_rows(const uword row_num, const Base<eT,T1>& X);
315   template<typename T1> inline void insert_cols(const uword col_num, const Base<eT,T1>& X);
316 
317 
318   template<typename T1, typename gen_type> inline             Mat(const Gen<T1, gen_type>& X);
319   template<typename T1, typename gen_type> inline Mat& operator= (const Gen<T1, gen_type>& X);
320   template<typename T1, typename gen_type> inline Mat& operator+=(const Gen<T1, gen_type>& X);
321   template<typename T1, typename gen_type> inline Mat& operator-=(const Gen<T1, gen_type>& X);
322   template<typename T1, typename gen_type> inline Mat& operator*=(const Gen<T1, gen_type>& X);
323   template<typename T1, typename gen_type> inline Mat& operator%=(const Gen<T1, gen_type>& X);
324   template<typename T1, typename gen_type> inline Mat& operator/=(const Gen<T1, gen_type>& X);
325 
326   template<typename T1, typename op_type> inline             Mat(const Op<T1, op_type>& X);
327   template<typename T1, typename op_type> inline Mat& operator= (const Op<T1, op_type>& X);
328   template<typename T1, typename op_type> inline Mat& operator+=(const Op<T1, op_type>& X);
329   template<typename T1, typename op_type> inline Mat& operator-=(const Op<T1, op_type>& X);
330   template<typename T1, typename op_type> inline Mat& operator*=(const Op<T1, op_type>& X);
331   template<typename T1, typename op_type> inline Mat& operator%=(const Op<T1, op_type>& X);
332   template<typename T1, typename op_type> inline Mat& operator/=(const Op<T1, op_type>& X);
333 
334   template<typename T1, typename eop_type> inline             Mat(const eOp<T1, eop_type>& X);
335   template<typename T1, typename eop_type> inline Mat& operator= (const eOp<T1, eop_type>& X);
336   template<typename T1, typename eop_type> inline Mat& operator+=(const eOp<T1, eop_type>& X);
337   template<typename T1, typename eop_type> inline Mat& operator-=(const eOp<T1, eop_type>& X);
338   template<typename T1, typename eop_type> inline Mat& operator*=(const eOp<T1, eop_type>& X);
339   template<typename T1, typename eop_type> inline Mat& operator%=(const eOp<T1, eop_type>& X);
340   template<typename T1, typename eop_type> inline Mat& operator/=(const eOp<T1, eop_type>& X);
341 
342   template<typename T1, typename op_type> inline             Mat(const mtOp<eT, T1, op_type>& X);
343   template<typename T1, typename op_type> inline Mat& operator= (const mtOp<eT, T1, op_type>& X);
344   template<typename T1, typename op_type> inline Mat& operator+=(const mtOp<eT, T1, op_type>& X);
345   template<typename T1, typename op_type> inline Mat& operator-=(const mtOp<eT, T1, op_type>& X);
346   template<typename T1, typename op_type> inline Mat& operator*=(const mtOp<eT, T1, op_type>& X);
347   template<typename T1, typename op_type> inline Mat& operator%=(const mtOp<eT, T1, op_type>& X);
348   template<typename T1, typename op_type> inline Mat& operator/=(const mtOp<eT, T1, op_type>& X);
349 
350   template<typename T1, typename op_type> inline             Mat(const CubeToMatOp<T1, op_type>& X);
351   template<typename T1, typename op_type> inline Mat& operator= (const CubeToMatOp<T1, op_type>& X);
352   template<typename T1, typename op_type> inline Mat& operator+=(const CubeToMatOp<T1, op_type>& X);
353   template<typename T1, typename op_type> inline Mat& operator-=(const CubeToMatOp<T1, op_type>& X);
354   template<typename T1, typename op_type> inline Mat& operator*=(const CubeToMatOp<T1, op_type>& X);
355   template<typename T1, typename op_type> inline Mat& operator%=(const CubeToMatOp<T1, op_type>& X);
356   template<typename T1, typename op_type> inline Mat& operator/=(const CubeToMatOp<T1, op_type>& X);
357 
358   template<typename T1, typename op_type> inline             Mat(const SpToDOp<T1, op_type>& X);
359   template<typename T1, typename op_type> inline Mat& operator= (const SpToDOp<T1, op_type>& X);
360   template<typename T1, typename op_type> inline Mat& operator+=(const SpToDOp<T1, op_type>& X);
361   template<typename T1, typename op_type> inline Mat& operator-=(const SpToDOp<T1, op_type>& X);
362   template<typename T1, typename op_type> inline Mat& operator*=(const SpToDOp<T1, op_type>& X);
363   template<typename T1, typename op_type> inline Mat& operator%=(const SpToDOp<T1, op_type>& X);
364   template<typename T1, typename op_type> inline Mat& operator/=(const SpToDOp<T1, op_type>& X);
365 
366   template<typename T1, typename T2, typename glue_type> inline             Mat(const Glue<T1, T2, glue_type>& X);
367   template<typename T1, typename T2, typename glue_type> inline Mat& operator= (const Glue<T1, T2, glue_type>& X);
368   template<typename T1, typename T2, typename glue_type> inline Mat& operator+=(const Glue<T1, T2, glue_type>& X);
369   template<typename T1, typename T2, typename glue_type> inline Mat& operator-=(const Glue<T1, T2, glue_type>& X);
370   template<typename T1, typename T2, typename glue_type> inline Mat& operator*=(const Glue<T1, T2, glue_type>& X);
371   template<typename T1, typename T2, typename glue_type> inline Mat& operator%=(const Glue<T1, T2, glue_type>& X);
372   template<typename T1, typename T2, typename glue_type> inline Mat& operator/=(const Glue<T1, T2, glue_type>& X);
373 
374   template<typename T1, typename T2>                     inline Mat& operator+=(const Glue<T1, T2, glue_times>& X);
375   template<typename T1, typename T2>                     inline Mat& operator-=(const Glue<T1, T2, glue_times>& X);
376 
377   template<typename T1, typename T2, typename eglue_type> inline             Mat(const eGlue<T1, T2, eglue_type>& X);
378   template<typename T1, typename T2, typename eglue_type> inline Mat& operator= (const eGlue<T1, T2, eglue_type>& X);
379   template<typename T1, typename T2, typename eglue_type> inline Mat& operator+=(const eGlue<T1, T2, eglue_type>& X);
380   template<typename T1, typename T2, typename eglue_type> inline Mat& operator-=(const eGlue<T1, T2, eglue_type>& X);
381   template<typename T1, typename T2, typename eglue_type> inline Mat& operator*=(const eGlue<T1, T2, eglue_type>& X);
382   template<typename T1, typename T2, typename eglue_type> inline Mat& operator%=(const eGlue<T1, T2, eglue_type>& X);
383   template<typename T1, typename T2, typename eglue_type> inline Mat& operator/=(const eGlue<T1, T2, eglue_type>& X);
384 
385   template<typename T1, typename T2, typename glue_type> inline             Mat(const mtGlue<eT, T1, T2, glue_type>& X);
386   template<typename T1, typename T2, typename glue_type> inline Mat& operator= (const mtGlue<eT, T1, T2, glue_type>& X);
387   template<typename T1, typename T2, typename glue_type> inline Mat& operator+=(const mtGlue<eT, T1, T2, glue_type>& X);
388   template<typename T1, typename T2, typename glue_type> inline Mat& operator-=(const mtGlue<eT, T1, T2, glue_type>& X);
389   template<typename T1, typename T2, typename glue_type> inline Mat& operator*=(const mtGlue<eT, T1, T2, glue_type>& X);
390   template<typename T1, typename T2, typename glue_type> inline Mat& operator%=(const mtGlue<eT, T1, T2, glue_type>& X);
391   template<typename T1, typename T2, typename glue_type> inline Mat& operator/=(const mtGlue<eT, T1, T2, glue_type>& X);
392 
393 
394   arma_inline arma_warn_unused const eT& at_alt     (const uword ii) const;
395 
396   arma_inline arma_warn_unused       eT& operator[] (const uword ii);
397   arma_inline arma_warn_unused const eT& operator[] (const uword ii) const;
398   arma_inline arma_warn_unused       eT& at         (const uword ii);
399   arma_inline arma_warn_unused const eT& at         (const uword ii) const;
400   arma_inline arma_warn_unused       eT& operator() (const uword ii);
401   arma_inline arma_warn_unused const eT& operator() (const uword ii) const;
402 
403   arma_inline arma_warn_unused       eT& at         (const uword in_row, const uword in_col);
404   arma_inline arma_warn_unused const eT& at         (const uword in_row, const uword in_col) const;
405   arma_inline arma_warn_unused       eT& operator() (const uword in_row, const uword in_col);
406   arma_inline arma_warn_unused const eT& operator() (const uword in_row, const uword in_col) const;
407 
408   arma_inline const Mat& operator++();
409   arma_inline void       operator++(int);
410 
411   arma_inline const Mat& operator--();
412   arma_inline void       operator--(int);
413 
414   arma_inline arma_warn_unused bool is_empty()  const;
415   arma_inline arma_warn_unused bool is_vec()    const;
416   arma_inline arma_warn_unused bool is_rowvec() const;
417   arma_inline arma_warn_unused bool is_colvec() const;
418   arma_inline arma_warn_unused bool is_square() const;
419        inline arma_warn_unused bool is_finite() const;
420 
421   inline arma_warn_unused bool has_inf() const;
422   inline arma_warn_unused bool has_nan() const;
423 
424   inline arma_warn_unused bool is_sorted(const char* direction = "ascend")       const;
425   inline arma_warn_unused bool is_sorted(const char* direction, const uword dim) const;
426 
427   template<typename comparator>
428   inline arma_warn_unused bool is_sorted_helper(const comparator& comp, const uword dim) const;
429 
430   arma_inline arma_warn_unused bool in_range(const uword ii) const;
431   arma_inline arma_warn_unused bool in_range(const span& x ) const;
432 
433   arma_inline arma_warn_unused bool in_range(const uword   in_row, const uword   in_col) const;
434   arma_inline arma_warn_unused bool in_range(const span& row_span, const uword   in_col) const;
435   arma_inline arma_warn_unused bool in_range(const uword   in_row, const span& col_span) const;
436   arma_inline arma_warn_unused bool in_range(const span& row_span, const span& col_span) const;
437 
438   arma_inline arma_warn_unused bool in_range(const uword in_row, const uword in_col, const SizeMat& s) const;
439 
440   arma_inline arma_warn_unused       eT* colptr(const uword in_col);
441   arma_inline arma_warn_unused const eT* colptr(const uword in_col) const;
442 
443   arma_inline arma_warn_unused       eT* memptr();
444   arma_inline arma_warn_unused const eT* memptr() const;
445 
446 
447   template<typename eT2, typename expr>
448   inline void copy_size(const Base<eT2,expr>& X);
449 
450   inline void set_size(const uword in_elem);
451   inline void set_size(const uword in_rows, const uword in_cols);
452   inline void set_size(const SizeMat& s);
453 
454   inline void   resize(const uword in_elem);
455   inline void   resize(const uword in_rows, const uword in_cols);
456   inline void   resize(const SizeMat& s);
457 
458   inline void  reshape(const uword in_rows, const uword in_cols);
459   inline void  reshape(const SizeMat& s);
460 
461   arma_deprecated inline void reshape(const uword in_rows, const uword in_cols, const uword dim);  //!< NOTE: don't use this form: it will be removed
462 
463 
464   template<typename functor> inline const Mat&  for_each(functor F);
465   template<typename functor> inline const Mat&  for_each(functor F) const;
466 
467   template<typename functor> inline const Mat& transform(functor F);
468   template<typename functor> inline const Mat&     imbue(functor F);
469 
470 
471   inline const Mat& replace(const eT old_val, const eT new_val);
472 
473   inline const Mat& clean(const pod_type threshold);
474 
475   inline const Mat& clamp(const eT min_val, const eT max_val);
476 
477   inline const Mat& fill(const eT val);
478 
479   template<typename fill_type>
480   inline const Mat& fill(const fill::fill_class<fill_type>& f);
481 
482   inline const Mat& zeros();
483   inline const Mat& zeros(const uword in_elem);
484   inline const Mat& zeros(const uword in_rows, const uword in_cols);
485   inline const Mat& zeros(const SizeMat& s);
486 
487   inline const Mat& ones();
488   inline const Mat& ones(const uword in_elem);
489   inline const Mat& ones(const uword in_rows, const uword in_cols);
490   inline const Mat& ones(const SizeMat& s);
491 
492   inline const Mat& randu();
493   inline const Mat& randu(const uword in_elem);
494   inline const Mat& randu(const uword in_rows, const uword in_cols);
495   inline const Mat& randu(const SizeMat& s);
496 
497   inline const Mat& randn();
498   inline const Mat& randn(const uword in_elem);
499   inline const Mat& randn(const uword in_rows, const uword in_cols);
500   inline const Mat& randn(const SizeMat& s);
501 
502   inline const Mat& eye();
503   inline const Mat& eye(const uword in_rows, const uword in_cols);
504   inline const Mat& eye(const SizeMat& s);
505 
506   inline arma_cold void      reset();
507   inline arma_cold void soft_reset();
508 
509 
510   template<typename T1> inline void set_real(const Base<pod_type,T1>& X);
511   template<typename T1> inline void set_imag(const Base<pod_type,T1>& X);
512 
513 
514   inline arma_warn_unused eT min() const;
515   inline arma_warn_unused eT max() const;
516 
517   inline eT min(uword& index_of_min_val) const;
518   inline eT max(uword& index_of_max_val) const;
519 
520   inline eT min(uword& row_of_min_val, uword& col_of_min_val) const;
521   inline eT max(uword& row_of_max_val, uword& col_of_max_val) const;
522 
523 
524   inline arma_cold bool save(const std::string   name, const file_type type = arma_binary) const;
525   inline arma_cold bool save(const hdf5_name&    spec, const file_type type = hdf5_binary) const;
526   inline arma_cold bool save(const  csv_name&    spec, const file_type type =   csv_ascii) const;
527   inline arma_cold bool save(      std::ostream& os,   const file_type type = arma_binary) const;
528 
529   inline arma_cold bool load(const std::string   name, const file_type type = auto_detect);
530   inline arma_cold bool load(const hdf5_name&    spec, const file_type type = hdf5_binary);
531   inline arma_cold bool load(const  csv_name&    spec, const file_type type =   csv_ascii);
532   inline arma_cold bool load(      std::istream& is,   const file_type type = auto_detect);
533 
534   inline arma_cold bool quiet_save(const std::string   name, const file_type type = arma_binary) const;
535   inline arma_cold bool quiet_save(const hdf5_name&    spec, const file_type type = hdf5_binary) const;
536   inline arma_cold bool quiet_save(const  csv_name&    spec, const file_type type =   csv_ascii) const;
537   inline arma_cold bool quiet_save(      std::ostream& os,   const file_type type = arma_binary) const;
538 
539   inline arma_cold bool quiet_load(const std::string   name, const file_type type = auto_detect);
540   inline arma_cold bool quiet_load(const hdf5_name&    spec, const file_type type = hdf5_binary);
541   inline arma_cold bool quiet_load(const  csv_name&    spec, const file_type type =   csv_ascii);
542   inline arma_cold bool quiet_load(      std::istream& is,   const file_type type = auto_detect);
543 
544 
545   // for container-like functionality
546 
547   typedef eT    value_type;
548   typedef uword size_type;
549 
550   typedef       eT*       iterator;
551   typedef const eT* const_iterator;
552 
553   typedef       eT*       col_iterator;
554   typedef const eT* const_col_iterator;
555 
556   class const_row_iterator;
557 
558   class row_iterator
559     {
560     public:
561 
562     inline row_iterator();
563     inline row_iterator(const row_iterator& X);
564     inline row_iterator(Mat<eT>& in_M, const uword in_row, const uword in_col);
565 
566     inline arma_warn_unused eT& operator* ();
567 
568     inline                  row_iterator& operator++();
569     inline arma_warn_unused row_iterator  operator++(int);
570 
571     inline                  row_iterator& operator--();
572     inline arma_warn_unused row_iterator  operator--(int);
573 
574     inline arma_warn_unused bool operator!=(const       row_iterator& X) const;
575     inline arma_warn_unused bool operator==(const       row_iterator& X) const;
576     inline arma_warn_unused bool operator!=(const const_row_iterator& X) const;
577     inline arma_warn_unused bool operator==(const const_row_iterator& X) const;
578 
579     typedef std::bidirectional_iterator_tag iterator_category;
580     typedef eT                              value_type;
581     typedef std::ptrdiff_t                  difference_type;  // TODO: not certain on this one
582     typedef eT*                             pointer;
583     typedef eT&                             reference;
584 
585     arma_aligned Mat<eT>* M;
586     arma_aligned uword    current_row;
587     arma_aligned uword    current_col;
588     };
589 
590 
591   class const_row_iterator
592     {
593     public:
594 
595     inline const_row_iterator();
596     inline const_row_iterator(const       row_iterator& X);
597     inline const_row_iterator(const const_row_iterator& X);
598     inline const_row_iterator(const Mat<eT>& in_M, const uword in_row, const uword in_col);
599 
600     inline arma_warn_unused const eT& operator*() const;
601 
602     inline                  const_row_iterator& operator++();
603     inline arma_warn_unused const_row_iterator  operator++(int);
604 
605     inline                  const_row_iterator& operator--();
606     inline arma_warn_unused const_row_iterator  operator--(int);
607 
608     inline arma_warn_unused bool operator!=(const       row_iterator& X) const;
609     inline arma_warn_unused bool operator==(const       row_iterator& X) const;
610     inline arma_warn_unused bool operator!=(const const_row_iterator& X) const;
611     inline arma_warn_unused bool operator==(const const_row_iterator& X) const;
612 
613     typedef std::bidirectional_iterator_tag iterator_category;
614     typedef eT                              value_type;
615     typedef std::ptrdiff_t                  difference_type;  // TODO: not certain on this one
616     typedef const eT*                       pointer;
617     typedef const eT&                       reference;
618 
619     arma_aligned const Mat<eT>* M;
620     arma_aligned       uword    current_row;
621     arma_aligned       uword    current_col;
622     };
623 
624 
625   class const_row_col_iterator;
626 
627   class row_col_iterator
628     {
629     public:
630 
631     inline row_col_iterator();
632     inline row_col_iterator(const row_col_iterator& in_it);
633     inline row_col_iterator(Mat<eT>& in_M, const uword row = 0, const uword col = 0);
634 
635     inline arma_warn_unused eT& operator*();
636 
637     inline                  row_col_iterator& operator++();
638     inline arma_warn_unused row_col_iterator  operator++(int);
639 
640     inline                  row_col_iterator& operator--();
641     inline arma_warn_unused row_col_iterator  operator--(int);
642 
643     inline arma_warn_unused uword row() const;
644     inline arma_warn_unused uword col() const;
645 
646     inline arma_warn_unused bool operator==(const       row_col_iterator& rhs) const;
647     inline arma_warn_unused bool operator!=(const       row_col_iterator& rhs) const;
648     inline arma_warn_unused bool operator==(const const_row_col_iterator& rhs) const;
649     inline arma_warn_unused bool operator!=(const const_row_col_iterator& rhs) const;
650 
651     typedef std::bidirectional_iterator_tag iterator_category;
652     typedef eT                              value_type;
653     typedef std::ptrdiff_t                  difference_type;  // TODO: not certain on this one
654     typedef eT*                             pointer;
655     typedef eT&                             reference;
656 
657     arma_aligned Mat<eT>* M;
658     arma_aligned eT*      current_ptr;
659     arma_aligned uword    current_col;
660     arma_aligned uword    current_row;
661     };
662 
663 
664   class const_row_col_iterator
665     {
666     public:
667 
668     inline const_row_col_iterator();
669     inline const_row_col_iterator(const       row_col_iterator& in_it);
670     inline const_row_col_iterator(const const_row_col_iterator& in_it);
671     inline const_row_col_iterator(const Mat<eT>& in_M, const uword row = 0, const uword col = 0);
672 
673     inline arma_warn_unused const eT& operator*() const;
674 
675     inline                  const_row_col_iterator& operator++();
676     inline arma_warn_unused const_row_col_iterator  operator++(int);
677 
678     inline                  const_row_col_iterator& operator--();
679     inline arma_warn_unused const_row_col_iterator  operator--(int);
680 
681     inline arma_warn_unused uword row() const;
682     inline arma_warn_unused uword col() const;
683 
684     inline arma_warn_unused bool operator==(const const_row_col_iterator& rhs) const;
685     inline arma_warn_unused bool operator!=(const const_row_col_iterator& rhs) const;
686     inline arma_warn_unused bool operator==(const       row_col_iterator& rhs) const;
687     inline arma_warn_unused bool operator!=(const       row_col_iterator& rhs) const;
688 
689     // So that we satisfy the STL iterator types.
690     typedef std::bidirectional_iterator_tag iterator_category;
691     typedef eT                              value_type;
692     typedef std::ptrdiff_t                  difference_type;  // TODO: not certain on this one
693     typedef const eT*                       pointer;
694     typedef const eT&                       reference;
695 
696     arma_aligned const Mat<eT>* M;
697     arma_aligned const eT*      current_ptr;
698     arma_aligned       uword    current_col;
699     arma_aligned       uword    current_row;
700     };
701 
702 
703   inline       iterator  begin();
704   inline const_iterator  begin() const;
705   inline const_iterator cbegin() const;
706 
707   inline       iterator  end();
708   inline const_iterator  end() const;
709   inline const_iterator cend() const;
710 
711   inline       col_iterator begin_col(const uword col_num);
712   inline const_col_iterator begin_col(const uword col_num) const;
713 
714   inline       col_iterator end_col  (const uword col_num);
715   inline const_col_iterator end_col  (const uword col_num) const;
716 
717   inline       row_iterator begin_row(const uword row_num);
718   inline const_row_iterator begin_row(const uword row_num) const;
719 
720   inline       row_iterator end_row  (const uword row_num);
721   inline const_row_iterator end_row  (const uword row_num) const;
722 
723   inline       row_col_iterator begin_row_col();
724   inline const_row_col_iterator begin_row_col() const;
725 
726   inline       row_col_iterator end_row_col();
727   inline const_row_col_iterator end_row_col() const;
728 
729 
730   inline void  clear();
731   inline bool  empty() const;
732   inline uword size()  const;
733 
734   inline arma_warn_unused       eT& front();
735   inline arma_warn_unused const eT& front() const;
736 
737   inline arma_warn_unused       eT& back();
738   inline arma_warn_unused const eT& back() const;
739 
740   inline void swap(Mat& B);
741 
742   inline void steal_mem(Mat& X);  //!< don't use this unless you're writing code internal to Armadillo
743 
744   inline void steal_mem_col(Mat& X, const uword max_n_rows);
745 
746 
747   template<uword fixed_n_rows, uword fixed_n_cols> class fixed;
748 
749 
750   protected:
751 
752   inline void init_cold();
753   inline void init_warm(uword in_rows, uword in_cols);
754 
755   inline arma_cold void init(const std::string& text);
756 
757   inline void init(const std::initializer_list<eT>& list);
758   inline void init(const std::initializer_list< std::initializer_list<eT> >& list);
759 
760   template<typename T1, typename T2>
761   inline void init(const Base<pod_type,T1>& A, const Base<pod_type,T2>& B);
762 
763   inline Mat(const char junk, const eT* aux_mem, const uword aux_n_rows, const uword aux_n_cols);
764 
765   inline Mat(const arma_vec_indicator&, const uhword in_vec_state);
766   inline Mat(const arma_vec_indicator&, const uword in_n_rows, const uword in_n_cols, const uhword in_vec_state);
767 
768   inline Mat(const arma_fixed_indicator&, const uword in_n_rows, const uword in_n_cols, const uhword in_vec_state, const eT* in_mem);
769 
770 
771   friend class Cube<eT>;
772   friend class subview_cube<eT>;
773   friend class glue_join;
774   friend class op_strans;
775   friend class op_htrans;
776   friend class op_resize;
777   friend class op_mean;
778   friend class op_max;
779   friend class op_min;
780 
781 
782   public:
783 
784   #ifdef ARMA_EXTRA_MAT_PROTO
785     #include ARMA_INCFILE_WRAP(ARMA_EXTRA_MAT_PROTO)
786   #endif
787   };
788 
789 
790 
791 template<typename eT>
792 template<uword fixed_n_rows, uword fixed_n_cols>
793 class Mat<eT>::fixed : public Mat<eT>
794   {
795   private:
796 
797   static constexpr uword fixed_n_elem = fixed_n_rows * fixed_n_cols;
798   static constexpr bool  use_extra    = (fixed_n_elem > arma_config::mat_prealloc);
799 
800   arma_align_mem eT mem_local_extra[ (use_extra) ? fixed_n_elem : 1 ];
801 
802 
803   public:
804 
805   typedef fixed<fixed_n_rows, fixed_n_cols> Mat_fixed_type;
806 
807   typedef eT                                elem_type;
808   typedef typename get_pod_type<eT>::result pod_type;
809 
810   static constexpr bool is_col  = (fixed_n_cols == 1);
811   static constexpr bool is_row  = (fixed_n_rows == 1);
812   static constexpr bool is_xvec = false;
813 
814   static const uword n_rows;  // value provided below the class definition
815   static const uword n_cols;  // value provided below the class definition
816   static const uword n_elem;  // value provided below the class definition
817 
818   arma_inline fixed();
819   arma_inline fixed(const fixed<fixed_n_rows, fixed_n_cols>& X);
820 
821                                      inline fixed(const fill::scalar_holder<eT> f);
822   template<typename fill_type>       inline fixed(const fill::fill_class<fill_type>& f);
823   template<typename T1>              inline fixed(const Base<eT,T1>& A);
824   template<typename T1, typename T2> inline fixed(const Base<pod_type,T1>& A, const Base<pod_type,T2>& B);
825 
826   inline fixed(const eT* aux_mem);
827 
828   inline fixed(const char*        text);
829   inline fixed(const std::string& text);
830 
831   using Mat<eT>::operator=;
832   using Mat<eT>::operator();
833 
834   inline          fixed(const std::initializer_list<eT>& list);
835   inline Mat& operator=(const std::initializer_list<eT>& list);
836 
837   inline          fixed(const std::initializer_list< std::initializer_list<eT> >& list);
838   inline Mat& operator=(const std::initializer_list< std::initializer_list<eT> >& list);
839 
840   arma_inline Mat& operator=(const fixed<fixed_n_rows, fixed_n_cols>& X);
841 
842   #if defined(ARMA_GOOD_COMPILER)
843     template<typename T1,              typename   eop_type> inline Mat& operator=(const   eOp<T1,       eop_type>& X);
844     template<typename T1, typename T2, typename eglue_type> inline Mat& operator=(const eGlue<T1, T2, eglue_type>& X);
845   #endif
846 
847   arma_inline arma_warn_unused const Op< Mat_fixed_type, op_htrans >  t() const;
848   arma_inline arma_warn_unused const Op< Mat_fixed_type, op_htrans > ht() const;
849   arma_inline arma_warn_unused const Op< Mat_fixed_type, op_strans > st() const;
850 
851   arma_inline arma_warn_unused const eT& at_alt     (const uword i) const;
852 
853   arma_inline arma_warn_unused       eT& operator[] (const uword i);
854   arma_inline arma_warn_unused const eT& operator[] (const uword i) const;
855   arma_inline arma_warn_unused       eT& at         (const uword i);
856   arma_inline arma_warn_unused const eT& at         (const uword i) const;
857   arma_inline arma_warn_unused       eT& operator() (const uword i);
858   arma_inline arma_warn_unused const eT& operator() (const uword i) const;
859 
860   arma_inline arma_warn_unused       eT& at         (const uword in_row, const uword in_col);
861   arma_inline arma_warn_unused const eT& at         (const uword in_row, const uword in_col) const;
862   arma_inline arma_warn_unused       eT& operator() (const uword in_row, const uword in_col);
863   arma_inline arma_warn_unused const eT& operator() (const uword in_row, const uword in_col) const;
864 
865   arma_inline arma_warn_unused       eT* colptr(const uword in_col);
866   arma_inline arma_warn_unused const eT* colptr(const uword in_col) const;
867 
868   arma_inline arma_warn_unused       eT* memptr();
869   arma_inline arma_warn_unused const eT* memptr() const;
870 
871   arma_inline arma_warn_unused bool is_vec() const;
872 
873   inline const Mat<eT>& fill(const eT val);
874   inline const Mat<eT>& zeros();
875   inline const Mat<eT>& ones();
876   };
877 
878 
879 
880 // these definitions are outside of the class due to bizarre C++ rules;
881 // C++17 has inline variables to address this shortcoming
882 
883 template<typename eT>
884 template<uword fixed_n_rows, uword fixed_n_cols>
885 const uword Mat<eT>::fixed<fixed_n_rows, fixed_n_cols>::n_rows = fixed_n_rows;
886 
887 template<typename eT>
888 template<uword fixed_n_rows, uword fixed_n_cols>
889 const uword Mat<eT>::fixed<fixed_n_rows, fixed_n_cols>::n_cols = fixed_n_cols;
890 
891 template<typename eT>
892 template<uword fixed_n_rows, uword fixed_n_cols>
893 const uword Mat<eT>::fixed<fixed_n_rows, fixed_n_cols>::n_elem = fixed_n_rows * fixed_n_cols;
894 
895 
896 
897 class Mat_aux
898   {
899   public:
900 
901   template<typename eT> inline static void prefix_pp(Mat<eT>& x);
902   template<typename T>  inline static void prefix_pp(Mat< std::complex<T> >& x);
903 
904   template<typename eT> inline static void postfix_pp(Mat<eT>& x);
905   template<typename T>  inline static void postfix_pp(Mat< std::complex<T> >& x);
906 
907   template<typename eT> inline static void prefix_mm(Mat<eT>& x);
908   template<typename T>  inline static void prefix_mm(Mat< std::complex<T> >& x);
909 
910   template<typename eT> inline static void postfix_mm(Mat<eT>& x);
911   template<typename T>  inline static void postfix_mm(Mat< std::complex<T> >& x);
912 
913   template<typename eT, typename T1> inline static void set_real(Mat<eT>&                out, const Base<eT,T1>& X);
914   template<typename T,  typename T1> inline static void set_real(Mat< std::complex<T> >& out, const Base< T,T1>& X);
915 
916   template<typename eT, typename T1> inline static void set_imag(Mat<eT>&                out, const Base<eT,T1>& X);
917   template<typename T,  typename T1> inline static void set_imag(Mat< std::complex<T> >& out, const Base< T,T1>& X);
918   };
919 
920 
921 
922 //! @}
923