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 operator_minus
20 //! @{
21 
22 
23 
24 //! unary -
25 template<typename T1>
26 arma_inline
27 typename
28 enable_if2< is_arma_type<T1>::value, const eOp<T1, eop_neg> >::result
operator -(const T1 & X)29 operator-
30 (const T1& X)
31   {
32   arma_extra_debug_sigprint();
33 
34   return eOp<T1,eop_neg>(X);
35   }
36 
37 
38 
39 //! Base - scalar
40 template<typename T1>
41 arma_inline
42 typename
43 enable_if2< is_arma_type<T1>::value, const eOp<T1, eop_scalar_minus_post> >::result
operator -(const T1 & X,const typename T1::elem_type k)44 operator-
45   (
46   const T1&                    X,
47   const typename T1::elem_type k
48   )
49   {
50   arma_extra_debug_sigprint();
51 
52   return eOp<T1, eop_scalar_minus_post>(X, k);
53   }
54 
55 
56 
57 //! scalar - Base
58 template<typename T1>
59 arma_inline
60 typename
61 enable_if2< is_arma_type<T1>::value, const eOp<T1, eop_scalar_minus_pre> >::result
operator -(const typename T1::elem_type k,const T1 & X)62 operator-
63   (
64   const typename T1::elem_type k,
65   const T1&                    X
66   )
67   {
68   arma_extra_debug_sigprint();
69 
70   return eOp<T1, eop_scalar_minus_pre>(X, k);
71   }
72 
73 
74 
75 //! complex scalar - non-complex Base
76 template<typename T1>
77 arma_inline
78 typename
79 enable_if2
80   <
81   (is_arma_type<T1>::value && is_cx<typename T1::elem_type>::no),
82   const mtOp<typename std::complex<typename T1::pod_type>, T1, op_cx_scalar_minus_pre>
83   >::result
operator -(const std::complex<typename T1::pod_type> & k,const T1 & X)84 operator-
85   (
86   const std::complex<typename T1::pod_type>& k,
87   const T1&                                  X
88   )
89   {
90   arma_extra_debug_sigprint();
91 
92   return mtOp<typename std::complex<typename T1::pod_type>, T1, op_cx_scalar_minus_pre>('j', X, k);
93   }
94 
95 
96 
97 //! non-complex Base - complex scalar
98 template<typename T1>
99 arma_inline
100 typename
101 enable_if2
102   <
103   (is_arma_type<T1>::value && is_cx<typename T1::elem_type>::no),
104   const mtOp<typename std::complex<typename T1::pod_type>, T1, op_cx_scalar_minus_post>
105   >::result
operator -(const T1 & X,const std::complex<typename T1::pod_type> & k)106 operator-
107   (
108   const T1&                                  X,
109   const std::complex<typename T1::pod_type>& k
110   )
111   {
112   arma_extra_debug_sigprint();
113 
114   return mtOp<typename std::complex<typename T1::pod_type>, T1, op_cx_scalar_minus_post>('j', X, k);
115   }
116 
117 
118 
119 //! subtraction of Base objects with same element type
120 template<typename T1, typename T2>
121 arma_inline
122 typename
123 enable_if2
124   <
125   is_arma_type<T1>::value && is_arma_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value,
126   const eGlue<T1, T2, eglue_minus>
127   >::result
operator -(const T1 & X,const T2 & Y)128 operator-
129   (
130   const T1& X,
131   const T2& Y
132   )
133   {
134   arma_extra_debug_sigprint();
135 
136   return eGlue<T1, T2, eglue_minus>(X, Y);
137   }
138 
139 
140 
141 //! subtraction of Base objects with different element types
142 template<typename T1, typename T2>
143 inline
144 typename
145 enable_if2
146   <
147   (is_arma_type<T1>::value && is_arma_type<T2>::value && (is_same_type<typename T1::elem_type, typename T2::elem_type>::no)),
148   const mtGlue<typename promote_type<typename T1::elem_type, typename T2::elem_type>::result, T1, T2, glue_mixed_minus>
149   >::result
operator -(const T1 & X,const T2 & Y)150 operator-
151   (
152   const T1& X,
153   const T2& Y
154   )
155   {
156   arma_extra_debug_sigprint();
157 
158   typedef typename T1::elem_type eT1;
159   typedef typename T2::elem_type eT2;
160 
161   typedef typename promote_type<eT1,eT2>::result out_eT;
162 
163   promote_type<eT1,eT2>::check();
164 
165   return mtGlue<out_eT, T1, T2, glue_mixed_minus>( X, Y );
166   }
167 
168 
169 
170 //! unary "-" for sparse objects
171 template<typename T1>
172 inline
173 typename
174 enable_if2
175   <
176   is_arma_sparse_type<T1>::value && is_signed<typename T1::elem_type>::value,
177   SpOp<T1,spop_scalar_times>
178   >::result
operator -(const T1 & X)179 operator-
180 (const T1& X)
181   {
182   arma_extra_debug_sigprint();
183 
184   typedef typename T1::elem_type eT;
185 
186   return SpOp<T1,spop_scalar_times>(X, eT(-1));
187   }
188 
189 
190 
191 //! subtraction of two sparse objects
192 template<typename T1, typename T2>
193 inline
194 typename
195 enable_if2
196   <
197   (is_arma_sparse_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
198   const SpGlue<T1,T2,spglue_minus>
199   >::result
operator -(const T1 & X,const T2 & Y)200 operator-
201   (
202   const T1& X,
203   const T2& Y
204   )
205   {
206   arma_extra_debug_sigprint();
207 
208   return SpGlue<T1,T2,spglue_minus>(X,Y);
209   }
210 
211 
212 
213 //! subtraction of one sparse and one dense object
214 template<typename T1, typename T2>
215 inline
216 typename
217 enable_if2
218   <
219   (is_arma_sparse_type<T1>::value && is_arma_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
220   Mat<typename T1::elem_type>
221   >::result
operator -(const T1 & x,const T2 & y)222 operator-
223   (
224   const T1& x,
225   const T2& y
226   )
227   {
228   arma_extra_debug_sigprint();
229 
230   const SpProxy<T1> pa(x);
231 
232   Mat<typename T1::elem_type> result(-y);
233 
234   arma_debug_assert_same_size( pa.get_n_rows(), pa.get_n_cols(), result.n_rows, result.n_cols, "subtraction" );
235 
236   typename SpProxy<T1>::const_iterator_type it     = pa.begin();
237   typename SpProxy<T1>::const_iterator_type it_end = pa.end();
238 
239   while(it != it_end)
240     {
241     result.at(it.row(), it.col()) += (*it);
242     ++it;
243     }
244 
245   return result;
246   }
247 
248 
249 
250 //! subtraction of one dense and one sparse object
251 template<typename T1, typename T2>
252 inline
253 typename
254 enable_if2
255   <
256   (is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
257   Mat<typename T1::elem_type>
258   >::result
operator -(const T1 & x,const T2 & y)259 operator-
260   (
261   const T1& x,
262   const T2& y
263   )
264   {
265   arma_extra_debug_sigprint();
266 
267   Mat<typename T1::elem_type> result(x);
268 
269   const SpProxy<T2> pb(y);
270 
271   arma_debug_assert_same_size( result.n_rows, result.n_cols, pb.get_n_rows(), pb.get_n_cols(), "subtraction" );
272 
273   typename SpProxy<T2>::const_iterator_type it     = pb.begin();
274   typename SpProxy<T2>::const_iterator_type it_end = pb.end();
275 
276   while(it != it_end)
277     {
278     result.at(it.row(), it.col()) -= (*it);
279     ++it;
280     }
281 
282   return result;
283   }
284 
285 
286 
287 //! subtraction of two sparse objects with different element types
288 template<typename T1, typename T2>
289 inline
290 typename
291 enable_if2
292   <
293   (is_arma_sparse_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::no),
294   const mtSpGlue< typename promote_type<typename T1::elem_type, typename T2::elem_type>::result, T1, T2, spglue_minus_mixed >
295   >::result
operator -(const T1 & X,const T2 & Y)296 operator-
297   (
298   const T1& X,
299   const T2& Y
300   )
301   {
302   arma_extra_debug_sigprint();
303 
304   typedef typename T1::elem_type eT1;
305   typedef typename T2::elem_type eT2;
306 
307   typedef typename promote_type<eT1,eT2>::result out_eT;
308 
309   promote_type<eT1,eT2>::check();
310 
311   return mtSpGlue<out_eT, T1, T2, spglue_minus_mixed>( X, Y );
312   }
313 
314 
315 
316 //! subtraction of sparse and non-sparse objects with different element types
317 template<typename T1, typename T2>
318 inline
319 typename
320 enable_if2
321   <
322   (is_arma_sparse_type<T1>::value && is_arma_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::no),
323   Mat< typename promote_type<typename T1::elem_type, typename T2::elem_type>::result >
324   >::result
operator -(const T1 & x,const T2 & y)325 operator-
326   (
327   const T1& x,
328   const T2& y
329   )
330   {
331   arma_extra_debug_sigprint();
332 
333   Mat< typename promote_type<typename T1::elem_type, typename T2::elem_type>::result > out;
334 
335   spglue_minus_mixed::sparse_minus_dense(out, x, y);
336 
337   return out;
338   }
339 
340 
341 
342 //! subtraction of sparse and non-sparse objects with different element types
343 template<typename T1, typename T2>
344 inline
345 typename
346 enable_if2
347   <
348   (is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::no),
349   Mat< typename promote_type<typename T1::elem_type, typename T2::elem_type>::result >
350   >::result
operator -(const T1 & x,const T2 & y)351 operator-
352   (
353   const T1& x,
354   const T2& y
355   )
356   {
357   arma_extra_debug_sigprint();
358 
359   Mat< typename promote_type<typename T1::elem_type, typename T2::elem_type>::result > out;
360 
361   spglue_minus_mixed::dense_minus_sparse(out, x, y);
362 
363   return out;
364   }
365 
366 
367 
368 //! sparse - scalar
369 template<typename T1>
370 arma_inline
371 typename
372 enable_if2< is_arma_sparse_type<T1>::value, const SpToDOp<T1, op_sp_minus_post> >::result
operator -(const T1 & X,const typename T1::elem_type k)373 operator-
374   (
375   const T1&                    X,
376   const typename T1::elem_type k
377   )
378   {
379   arma_extra_debug_sigprint();
380 
381   return SpToDOp<T1, op_sp_minus_post>(X, k);
382   }
383 
384 
385 
386 //! scalar - sparse
387 template<typename T1>
388 arma_inline
389 typename
390 enable_if2< is_arma_sparse_type<T1>::value, const SpToDOp<T1, op_sp_minus_pre> >::result
operator -(const typename T1::elem_type k,const T1 & X)391 operator-
392   (
393   const typename T1::elem_type k,
394   const T1&                    X
395   )
396   {
397   arma_extra_debug_sigprint();
398 
399   return SpToDOp<T1, op_sp_minus_pre>(X, k);
400   }
401 
402 
403 
404 // TODO: this is an uncommon use case; remove?
405 //! multiple applications of add/subtract scalars can be condensed
406 template<typename T1, typename op_type>
407 inline
408 typename
409 enable_if2
410   <
411   (is_arma_sparse_type<T1>::value &&
412       (is_same_type<op_type, op_sp_plus>::value ||
413        is_same_type<op_type, op_sp_minus_post>::value)),
414   const SpToDOp<T1, op_sp_minus_post>
415   >::result
operator -(const SpToDOp<T1,op_type> & x,const typename T1::elem_type k)416 operator-
417   (
418   const SpToDOp<T1, op_type>&  x,
419   const typename T1::elem_type k
420   )
421   {
422   arma_extra_debug_sigprint();
423 
424   const typename T1::elem_type aux = (is_same_type<op_type, op_sp_plus>::value) ? -x.aux : x.aux;
425 
426   return SpToDOp<T1, op_sp_minus_post>(x.m, aux + k);
427   }
428 
429 
430 
431 // TODO: this is an uncommon use case; remove?
432 //! multiple applications of add/subtract scalars can be condensed
433 template<typename T1, typename op_type>
434 inline
435 typename
436 enable_if2
437   <
438   (is_arma_sparse_type<T1>::value &&
439       (is_same_type<op_type, op_sp_plus>::value ||
440        is_same_type<op_type, op_sp_minus_post>::value)),
441   const SpToDOp<T1, op_sp_minus_pre>
442   >::result
operator -(const typename T1::elem_type k,const SpToDOp<T1,op_type> & x)443 operator-
444   (
445   const typename T1::elem_type k,
446   const SpToDOp<T1, op_type>&  x
447   )
448   {
449   arma_extra_debug_sigprint();
450 
451   const typename T1::elem_type aux = (is_same_type<op_type, op_sp_plus>::value) ? -x.aux : x.aux;
452 
453   return SpToDOp<T1, op_sp_minus_pre>(x.m, k + aux);
454   }
455 
456 
457 
458 // TODO: this is an uncommon use case; remove?
459 //! multiple applications of add/subtract scalars can be condensed
460 template<typename T1, typename op_type>
461 inline
462 typename
463 enable_if2
464   <
465   (is_arma_sparse_type<T1>::value &&
466        is_same_type<op_type, op_sp_minus_pre>::value),
467   const SpToDOp<T1, op_sp_minus_pre>
468   >::result
operator -(const SpToDOp<T1,op_type> & x,const typename T1::elem_type k)469 operator-
470   (
471   const SpToDOp<T1, op_type>&  x,
472   const typename T1::elem_type k
473   )
474   {
475   arma_extra_debug_sigprint();
476 
477   return SpToDOp<T1, op_sp_minus_pre>(x.m, x.aux - k);
478   }
479 
480 
481 
482 // TODO: this is an uncommon use case; remove?
483 //! multiple applications of add/subtract scalars can be condensed
484 template<typename T1, typename op_type>
485 inline
486 typename
487 enable_if2
488   <
489   (is_arma_sparse_type<T1>::value &&
490        is_same_type<op_type, op_sp_minus_pre>::value),
491   const SpToDOp<T1, op_sp_plus>
492   >::result
operator -(const typename T1::elem_type k,const SpToDOp<T1,op_type> & x)493 operator-
494   (
495   const typename T1::elem_type k,
496   const SpToDOp<T1, op_type>&  x
497   )
498   {
499   arma_extra_debug_sigprint();
500 
501   return SpToDOp<T1, op_sp_plus>(x.m, k - x.aux);
502   }
503 
504 
505 
506 template<typename parent, unsigned int mode, typename T2>
507 arma_inline
508 Mat<typename parent::elem_type>
operator -(const subview_each1<parent,mode> & X,const Base<typename parent::elem_type,T2> & Y)509 operator-
510   (
511   const subview_each1<parent,mode>&          X,
512   const Base<typename parent::elem_type,T2>& Y
513   )
514   {
515   arma_extra_debug_sigprint();
516 
517   return subview_each1_aux::operator_minus(X, Y.get_ref());
518   }
519 
520 
521 
522 template<typename T1, typename parent, unsigned int mode>
523 arma_inline
524 Mat<typename parent::elem_type>
operator -(const Base<typename parent::elem_type,T1> & X,const subview_each1<parent,mode> & Y)525 operator-
526   (
527   const Base<typename parent::elem_type,T1>& X,
528   const subview_each1<parent,mode>&          Y
529   )
530   {
531   arma_extra_debug_sigprint();
532 
533   return subview_each1_aux::operator_minus(X.get_ref(), Y);
534   }
535 
536 
537 
538 template<typename parent, unsigned int mode, typename TB, typename T2>
539 arma_inline
540 Mat<typename parent::elem_type>
operator -(const subview_each2<parent,mode,TB> & X,const Base<typename parent::elem_type,T2> & Y)541 operator-
542   (
543   const subview_each2<parent,mode,TB>&       X,
544   const Base<typename parent::elem_type,T2>& Y
545   )
546   {
547   arma_extra_debug_sigprint();
548 
549   return subview_each2_aux::operator_minus(X, Y.get_ref());
550   }
551 
552 
553 
554 template<typename T1, typename parent, unsigned int mode, typename TB>
555 arma_inline
556 Mat<typename parent::elem_type>
operator -(const Base<typename parent::elem_type,T1> & X,const subview_each2<parent,mode,TB> & Y)557 operator-
558   (
559   const Base<typename parent::elem_type,T1>& X,
560   const subview_each2<parent,mode,TB>&       Y
561   )
562   {
563   arma_extra_debug_sigprint();
564 
565   return subview_each2_aux::operator_minus(X.get_ref(), Y);
566   }
567 
568 
569 
570 //! @}
571