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