FMA.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_SIMD_FMA_H_
36 #define _BLAZE_MATH_SIMD_FMA_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
47 #include <blaze/system/Inline.h>
49 
50 
51 namespace blaze {
52 
53 //=================================================================================================
54 //
55 // 32-BIT FLOATING POINT SIMD TYPES
56 //
57 //=================================================================================================
58 
59 //*************************************************************************************************
66 template< typename T1 // Type of the left-hand side multiplication operand
67  , typename T2 // Type of the right-hand side multiplication operand
68  , typename T3 > // Type of the right-hand side addition operand
69 struct SIMDf32FmaddExpr : public SIMDf32< SIMDf32FmaddExpr<T1,T2,T3> >
70 {
71  //**Type definitions****************************************************************************
73  using BaseType = SIMDf32<This>;
74  //**********************************************************************************************
75 
76  //**Constructor*********************************************************************************
83  explicit BLAZE_ALWAYS_INLINE SIMDf32FmaddExpr( const T1& a, const T2& b, const T3& c )
84  : a_( a ) // The left-hand side operand for the multiplication
85  , b_( b ) // The right-hand side operand for the multiplication
86  , c_( c ) // The right-hand side operand for the addition
87  {}
88  //**********************************************************************************************
89 
90  //**Evaluation function*************************************************************************
95  BLAZE_ALWAYS_INLINE const SIMDfloat eval() const noexcept
96 #if BLAZE_FMA_MODE && BLAZE_MIC_MODE
97  {
98  return _mm512_fmadd_ps( a_.eval().value, b_.eval().value, c_.eval().value );
99  }
100 #elif BLAZE_FMA_MODE && BLAZE_AVX_MODE
101  {
102  return _mm256_fmadd_ps( a_.eval().value, b_.eval().value, c_.eval().value );
103  }
104 #elif BLAZE_FMA_MODE && BLAZE_SSE2_MODE
105  {
106  return _mm_fmadd_ps( a_.eval().value, b_.eval().value, c_.eval().value );
107  }
108 #else
109  = delete;
110 #endif
111  //**********************************************************************************************
112 
113  //**Member variables****************************************************************************
114  const T1 a_;
115  const T2 b_;
116  const T3 c_;
117  //**********************************************************************************************
118 };
119 //*************************************************************************************************
120 
121 
122 //*************************************************************************************************
129 template< typename T1 // Type of the left-hand side multiplication operand
130  , typename T2 // Type of the right-hand side multiplication operand
131  , typename T3 > // Type of the right-hand side subtraction operand
132 struct SIMDf32FmsubExpr : public SIMDf32< SIMDf32FmsubExpr<T1,T2,T3> >
133 {
134  //**Type definitions****************************************************************************
136  using BaseType = SIMDf32<This>;
137  //**********************************************************************************************
138 
139  //**Constructor*********************************************************************************
146  explicit BLAZE_ALWAYS_INLINE SIMDf32FmsubExpr( const T1& a, const T2& b, const T3& c )
147  : a_( a ) // The left-hand side operand for the multiplication
148  , b_( b ) // The right-hand side operand for the multiplication
149  , c_( c ) // The right-hand side operand for the subtraction
150  {}
151  //**********************************************************************************************
152 
153  //**Evaluation function*************************************************************************
158  BLAZE_ALWAYS_INLINE const SIMDfloat eval() const noexcept
159 #if BLAZE_FMA_MODE && BLAZE_MIC_MODE
160  {
161  return _mm512_fmsub_ps( a_.eval().value, b_.eval().value, c_.eval().value );
162  }
163 #elif BLAZE_FMA_MODE && BLAZE_AVX_MODE
164  {
165  return _mm256_fmsub_ps( a_.eval().value, b_.eval().value, c_.eval().value );
166  }
167 #elif BLAZE_FMA_MODE && BLAZE_SSE2_MODE
168  {
169  return _mm_fmsub_ps( a_.eval().value, b_.eval().value, c_.eval().value );
170  }
171 #else
172  = delete;
173 #endif
174  //**********************************************************************************************
175 
176  //**Member variables****************************************************************************
177  const T1 a_;
178  const T2 b_;
179  const T3 c_;
180  //**********************************************************************************************
181 };
182 //*************************************************************************************************
183 
184 
185 //*************************************************************************************************
197 #if BLAZE_FMA_MODE
198 template< typename T1 // Type of the first multiplication operand
199  , typename T2 // Type of the second multiplication operand
200  , typename T3 > // Type of the second addition operand
202  operator+( const SIMDf32MultExpr<T1,T2>& a, const SIMDf32<T3>& b )
203 {
204  return SIMDf32FmaddExpr<T1,T2,T3>( a.a_, a.b_, ~b );
205 }
206 #endif
207 //*************************************************************************************************
208 
209 
210 //*************************************************************************************************
222 #if BLAZE_FMA_MODE
223 template< typename T1 // Type of the first addition operand
224  , typename T2 // Type of the first multiplication operand
225  , typename T3 > // Type of the second multiplication operand
226 BLAZE_ALWAYS_INLINE const SIMDf32FmaddExpr<T2,T3,T1>
227  operator+( const SIMDf32<T1>& a, const SIMDf32MultExpr<T2,T3>& b )
228 {
229  return SIMDf32FmaddExpr<T2,T3,T1>( b.a_, b.b_, ~a );
230 }
231 #endif
232 //*************************************************************************************************
233 
234 
235 //*************************************************************************************************
248 #if BLAZE_FMA_MODE
249 template< typename T1 // Type of the first operand of the left-hand side multiplication
250  , typename T2 // Type of the second operand of the left-hand side multiplication
251  , typename T3 // Type of the first operand of the right-hand side multiplication
252  , typename T4 > // Type of the second operand of the right-hand side multiplication
253 BLAZE_ALWAYS_INLINE const SIMDf32FmaddExpr< T1, T2, SIMDf32MultExpr<T3,T4> >
254  operator+( const SIMDf32MultExpr<T1,T2>& a, const SIMDf32MultExpr<T3,T4>& b )
255 {
256  return SIMDf32FmaddExpr< T1, T2, SIMDf32MultExpr<T3,T4> >( a.a_, a.b_, b );
257 }
258 #endif
259 
260 //*************************************************************************************************
261 
262 
263 //*************************************************************************************************
277 #if BLAZE_FMA_MODE
278 template< typename T1 // Type of the first FMA multiplication operand
279  , typename T2 // Type of the second FMA multiplication operand
280  , typename T3 // Type of the FMA addition operand
281  , typename T4 > // Type of the second addition operand
282 BLAZE_ALWAYS_INLINE const auto
283  operator+( const SIMDf32FmaddExpr<T1,T2,T3>& a, const SIMDf32<T4>& b )
284 {
285  return ( a.a_ * a.b_ ) + ( a.c_ + (~b) );
286 }
287 #endif
288 
289 //*************************************************************************************************
290 
291 
292 //*************************************************************************************************
306 #if BLAZE_FMA_MODE
307 template< typename T1 // Type of the first addition operand
308  , typename T2 // Type of the first FMA multiplication operand
309  , typename T3 // Type of the second FMA multiplication operand
310  , typename T4 > // Type of the FMA addition operand
311 BLAZE_ALWAYS_INLINE const auto
312  operator+( const SIMDf32<T1>& a, const SIMDf32FmaddExpr<T2,T3,T4>& b )
313 {
314  return ( b.a_ * b.b_ ) + ( b.c_ + (~a) );
315 }
316 #endif
317 
318 //*************************************************************************************************
319 
320 
321 //*************************************************************************************************
335 #if BLAZE_FMA_MODE
336 template< typename T1 // Type of the first FMA multiplication operand
337  , typename T2 // Type of the second FMA multiplication operand
338  , typename T3 // Type of the FMA addition operand
339  , typename T4 // Type of the first multiplication operand
340  , typename T5 > // Type of the second multiplication operand
341 BLAZE_ALWAYS_INLINE const SIMDf32FmaddExpr< T4, T5, SIMDf32FmaddExpr<T1,T2,T3> >
342  operator+( const SIMDf32FmaddExpr<T1,T2,T3>& a, const SIMDf32MultExpr<T4,T5>& b )
343 {
344  return SIMDf32FmaddExpr< T4, T5, SIMDf32FmaddExpr<T1,T2,T3> >( b.a_, b.b_, a );
345 }
346 #endif
347 
348 //*************************************************************************************************
349 
350 
351 //*************************************************************************************************
365 #if BLAZE_FMA_MODE
366 template< typename T1 // Type of the first multiplication operand
367  , typename T2 // Type of the second multiplication operand
368  , typename T3 // Type of the first FMA multiplication operand
369  , typename T4 // Type of the second FMA multiplication operand
370  , typename T5 > // Type of the FMA addition operand
371 BLAZE_ALWAYS_INLINE const SIMDf32FmaddExpr< T1, T2, SIMDf32FmaddExpr<T3,T4,T5> >
372  operator+( const SIMDf32MultExpr<T1,T2>& a, const SIMDf32FmaddExpr<T3,T4,T5>& b )
373 {
374  return SIMDf32FmaddExpr< T1, T2, SIMDf32FmaddExpr<T3,T4,T5> >( a.a_, a.b_, b );
375 }
376 #endif
377 
378 //*************************************************************************************************
379 
380 
381 //*************************************************************************************************
394 #if BLAZE_FMA_MODE
395 template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
396  , typename T2 // Type of the second multiplication operand of the left-hand side FMA
397  , typename T3 // Type of the addition operand of the left-hand side FMA
398  , typename T4 // Type of the first multiplication operand of the right-hand side FMA
399  , typename T5 // Type of the second multiplication operand of the right-hand side FMA
400  , typename T6 > // Type of the addition operand of the right-hand side FMA
401 BLAZE_ALWAYS_INLINE const auto
402  operator+( const SIMDf32FmaddExpr<T1,T2,T3>& a, const SIMDf32FmaddExpr<T4,T5,T6>& b )
403 {
404  return ( a.a_ * a.b_ ) + ( ( b.a_ * b.b_ ) + ( a.c_ + b.c_ ) );
405 }
406 #endif
407 
408 //*************************************************************************************************
409 
410 
411 //*************************************************************************************************
424 #if BLAZE_FMA_MODE
425 template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
426  , typename T2 // Type of the second multiplication operand of the left-hand side FMA
427  , typename T3 // Type of the addition operand of the left-hand side FMA
428  , typename T4 // Type of the first multiplication operand of the right-hand side FMA
429  , typename T5 // Type of the second multiplication operand of the right-hand side FMA
430  , typename T6 > // Type of the subtraction operand of the right-hand side FMA
431 BLAZE_ALWAYS_INLINE const auto
432  operator+( const SIMDf32FmaddExpr<T1,T2,T3>& a, const SIMDf32FmsubExpr<T4,T5,T6>& b )
433 {
434  return ( a.a_ * a.b_ ) + ( ( b.a_ * b.b_ ) + ( a.c_ - b.c_ ) );
435 }
436 #endif
437 
438 //*************************************************************************************************
439 
440 
441 //*************************************************************************************************
454 #if BLAZE_FMA_MODE
455 template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
456  , typename T2 // Type of the second multiplication operand of the left-hand side FMA
457  , typename T3 // Type of the subtraction operand of the left-hand side FMA
458  , typename T4 // Type of the first multiplication operand of the right-hand side FMA
459  , typename T5 // Type of the second multiplication operand of the right-hand side FMA
460  , typename T6 > // Type of the addition operand of the right-hand side FMA
461 BLAZE_ALWAYS_INLINE const auto
462  operator+( const SIMDf32FmsubExpr<T1,T2,T3>& a, const SIMDf32FmaddExpr<T4,T5,T6>& b )
463 {
464  return ( a.a_ * a.b_ ) + ( ( b.a_ * b.b_ ) + ( b.c_ - a.c_ ) );
465 }
466 #endif
467 
468 //*************************************************************************************************
469 
470 
471 //*************************************************************************************************
484 #if BLAZE_FMA_MODE
485 template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
486  , typename T2 // Type of the second multiplication operand of the left-hand side FMA
487  , typename T3 // Type of the subtraction operand of the left-hand side FMA
488  , typename T4 // Type of the first multiplication operand of the right-hand side FMA
489  , typename T5 // Type of the second multiplication operand of the right-hand side FMA
490  , typename T6 > // Type of the subtraction operand of the right-hand side FMA
491 BLAZE_ALWAYS_INLINE const auto
492  operator+( const SIMDf32FmsubExpr<T1,T2,T3>& a, const SIMDf32FmsubExpr<T4,T5,T6>& b )
493 {
494  return ( a.a_ * a.b_ ) + ( ( b.a_ * b.b_ ) - ( b.c_ + a.c_ ) );
495 }
496 #endif
497 
498 //*************************************************************************************************
499 
500 
501 //*************************************************************************************************
513 #if BLAZE_FMA_MODE
514 template< typename T1 // Type of the first multiplication operand
515  , typename T2 // Type of the second multiplication operand
516  , typename T3 > // Type of the second subtraction operand
517 BLAZE_ALWAYS_INLINE const SIMDf32FmsubExpr<T1,T2,T3>
518  operator-( const SIMDf32MultExpr<T1,T2>& a, const SIMDf32<T3>& b )
519 {
520  return SIMDf32FmsubExpr<T1,T2,T3>( a.a_, a.b_, ~b );
521 }
522 #endif
523 //*************************************************************************************************
524 
525 
526 //*************************************************************************************************
539 #if BLAZE_FMA_MODE
540 template< typename T1 // Type of the first operand of the left-hand side multiplication
541  , typename T2 // Type of the second operand of the left-hand side multiplication
542  , typename T3 // Type of the first operand of the right-hand side multiplication
543  , typename T4 > // Type of the second operand of the right-hand side multiplication
544 BLAZE_ALWAYS_INLINE const SIMDf32FmsubExpr< T1, T2, SIMDf32MultExpr<T3,T4> >
545  operator-( const SIMDf32MultExpr<T1,T2>& a, const SIMDf32MultExpr<T3,T4>& b )
546 {
547  return SIMDf32FmsubExpr< T1, T2, SIMDf32MultExpr<T3,T4> >( a.a_, a.b_, b );
548 }
549 #endif
550 
551 //*************************************************************************************************
552 
553 
554 //*************************************************************************************************
568 #if BLAZE_FMA_MODE
569 template< typename T1 // Type of the first FMA multiplication operand
570  , typename T2 // Type of the second FMA multiplication operand
571  , typename T3 // Type of the FMA subtraction operand
572  , typename T4 > // Type of the second subtraction operand
573 BLAZE_ALWAYS_INLINE const auto
574  operator-( const SIMDf32FmsubExpr<T1,T2,T3>& a, const SIMDf32<T4>& b )
575 {
576  return ( a.a_ * a.b_ ) - ( a.c_ + (~b) );
577 }
578 #endif
579 
580 //*************************************************************************************************
581 
582 
583 //*************************************************************************************************
597 #if BLAZE_FMA_MODE
598 template< typename T1 // Type of the first FMA multiplication operand
599  , typename T2 // Type of the second FMA multiplication operand
600  , typename T3 // Type of the FMA subtraction operand
601  , typename T4 // Type of the first multiplication operand
602  , typename T5 > // Type of the second multiplication operand
603 BLAZE_ALWAYS_INLINE const auto
604  operator-( const SIMDf32FmsubExpr<T1,T2,T3>& a, const SIMDf32MultExpr<T4,T5>& b )
605 {
606  return ( a.a_ * a.b_ ) - ( b.a_ * b.b_ + a.c_ );
607 }
608 #endif
609 
610 //*************************************************************************************************
611 
612 
613 //*************************************************************************************************
627 #if BLAZE_FMA_MODE
628 template< typename T1 // Type of the first multiplication operand
629  , typename T2 // Type of the second multiplication operand
630  , typename T3 // Type of the first FMA multiplication operand
631  , typename T4 // Type of the second FMA multiplication operand
632  , typename T5 > // Type of the FMA subtraction operand
633 BLAZE_ALWAYS_INLINE const SIMDf32FmsubExpr< T1, T2, SIMDf32FmsubExpr<T3,T4,T5> >
634  operator-( const SIMDf32MultExpr<T1,T2>& a, const SIMDf32FmsubExpr<T3,T4,T5>& b )
635 {
636  return SIMDf32FmsubExpr< T1, T2, SIMDf32FmsubExpr<T3,T4,T5> >( a.a_, a.b_, b );
637 }
638 #endif
639 
640 //*************************************************************************************************
641 
642 
643 //*************************************************************************************************
656 #if BLAZE_FMA_MODE
657 template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
658  , typename T2 // Type of the second multiplication operand of the left-hand side FMA
659  , typename T3 // Type of the addition operand of the left-hand side FMA
660  , typename T4 // Type of the first multiplication operand of the right-hand side FMA
661  , typename T5 // Type of the second multiplication operand of the right-hand side FMA
662  , typename T6 > // Type of the addition operand of the right-hand side FMA
663 BLAZE_ALWAYS_INLINE const auto
664  operator-( const SIMDf32FmaddExpr<T1,T2,T3>& a, const SIMDf32FmaddExpr<T4,T5,T6>& b )
665 {
666  return ( a.a_ * a.b_ ) - ( ( b.a_ * b.b_ ) + ( b.c_ - a.c_ ) );
667 }
668 #endif
669 
670 //*************************************************************************************************
671 
672 
673 //*************************************************************************************************
686 #if BLAZE_FMA_MODE
687 template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
688  , typename T2 // Type of the second multiplication operand of the left-hand side FMA
689  , typename T3 // Type of the addition operand of the left-hand side FMA
690  , typename T4 // Type of the first multiplication operand of the right-hand side FMA
691  , typename T5 // Type of the second multiplication operand of the right-hand side FMA
692  , typename T6 > // Type of the subtraction operand of the right-hand side FMA
693 BLAZE_ALWAYS_INLINE const auto
694  operator-( const SIMDf32FmaddExpr<T1,T2,T3>& a, const SIMDf32FmsubExpr<T4,T5,T6>& b )
695 {
696  return ( a.a_ * a.b_ ) - ( ( b.a_ * b.b_ ) - ( a.c_ + b.c_ ) );
697 }
698 #endif
699 
700 //*************************************************************************************************
701 
702 
703 //*************************************************************************************************
716 #if BLAZE_FMA_MODE
717 template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
718  , typename T2 // Type of the second multiplication operand of the left-hand side FMA
719  , typename T3 // Type of the subtraction operand of the left-hand side FMA
720  , typename T4 // Type of the first multiplication operand of the right-hand side FMA
721  , typename T5 // Type of the second multiplication operand of the right-hand side FMA
722  , typename T6 > // Type of the addition operand of the right-hand side FMA
723 BLAZE_ALWAYS_INLINE const auto
724  operator-( const SIMDf32FmsubExpr<T1,T2,T3>& a, const SIMDf32FmaddExpr<T4,T5,T6>& b )
725 {
726  return ( a.a_ * a.b_ ) - ( ( b.a_ * b.b_ ) + ( a.c_ + b.c_ ) );
727 }
728 #endif
729 
730 //*************************************************************************************************
731 
732 
733 //*************************************************************************************************
746 #if BLAZE_FMA_MODE
747 template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
748  , typename T2 // Type of the second multiplication operand of the left-hand side FMA
749  , typename T3 // Type of the subtraction operand of the left-hand side FMA
750  , typename T4 // Type of the first multiplication operand of the right-hand side FMA
751  , typename T5 // Type of the second multiplication operand of the right-hand side FMA
752  , typename T6 > // Type of the subtraction operand of the right-hand side FMA
753 BLAZE_ALWAYS_INLINE const auto
754  operator-( const SIMDf32FmsubExpr<T1,T2,T3>& a, const SIMDf32FmsubExpr<T4,T5,T6>& b )
755 {
756  return ( a.a_ * a.b_ ) - ( ( b.a_ * b.b_ ) + ( a.c_ - b.c_ ) );
757 }
758 #endif
759 
760 //*************************************************************************************************
761 
762 
763 
764 
765 //=================================================================================================
766 //
767 // 64-BIT FLOATING POINT SIMD TYPES
768 //
769 //=================================================================================================
770 
771 //*************************************************************************************************
778 template< typename T1 // Type of the left-hand side multiplication operand
779  , typename T2 // Type of the right-hand side multiplication operand
780  , typename T3 > // Type of the right-hand side addition operand
781 struct SIMDf64FmaddExpr : public SIMDf64< SIMDf64FmaddExpr<T1,T2,T3> >
782 {
783  //**Type definitions****************************************************************************
785  using BaseType = SIMDf64<This>;
786  //**********************************************************************************************
787 
788  //**Constructor*********************************************************************************
795  explicit BLAZE_ALWAYS_INLINE SIMDf64FmaddExpr( const T1& a, const T2& b, const T3& c )
796  : a_( a ) // The left-hand side operand for the multiplication
797  , b_( b ) // The right-hand side operand for the multiplication
798  , c_( c ) // The right-hand side operand for the addition
799  {}
800  //**********************************************************************************************
801 
802  //**Evaluation function*************************************************************************
807  BLAZE_ALWAYS_INLINE const SIMDdouble eval() const noexcept
808 #if BLAZE_FMA_MODE && BLAZE_MIC_MODE
809  {
810  return _mm512_fmadd_pd( a_.eval().value, b_.eval().value, c_.eval().value );
811  }
812 #elif BLAZE_FMA_MODE && BLAZE_AVX_MODE
813  {
814  return _mm256_fmadd_pd( a_.eval().value, b_.eval().value, c_.eval().value );
815  }
816 #elif BLAZE_FMA_MODE && BLAZE_SSE2_MODE
817  {
818  return _mm_fmadd_pd( a_.eval().value, b_.eval().value, c_.eval().value );
819  }
820 #else
821  = delete;
822 #endif
823  //**********************************************************************************************
824 
825  //**Member variables****************************************************************************
826  const T1 a_;
827  const T2 b_;
828  const T3 c_;
829  //**********************************************************************************************
830 };
831 //*************************************************************************************************
832 
833 
834 //*************************************************************************************************
841 template< typename T1 // Type of the left-hand side multiplication operand
842  , typename T2 // Type of the right-hand side multiplication operand
843  , typename T3 > // Type of the right-hand side subtraction operand
844 struct SIMDf64FmsubExpr : public SIMDf64< SIMDf64FmsubExpr<T1,T2,T3> >
845 {
846  //**Type definitions****************************************************************************
848  using BaseType = SIMDf64<This>;
849  //**********************************************************************************************
850 
851  //**Constructor*********************************************************************************
858  explicit BLAZE_ALWAYS_INLINE SIMDf64FmsubExpr( const T1& a, const T2& b, const T3& c )
859  : a_( a ) // The left-hand side operand for the multiplication
860  , b_( b ) // The right-hand side operand for the multiplication
861  , c_( c ) // The right-hand side operand for the subtraction
862  {}
863  //**********************************************************************************************
864 
865  //**Evaluation function*************************************************************************
870  BLAZE_ALWAYS_INLINE const SIMDdouble eval() const noexcept
871 #if BLAZE_FMA_MODE && BLAZE_MIC_MODE
872  {
873  return _mm512_fmsub_pd( a_.eval().value, b_.eval().value, c_.eval().value );
874  }
875 #elif BLAZE_FMA_MODE && BLAZE_AVX_MODE
876  {
877  return _mm256_fmsub_pd( a_.eval().value, b_.eval().value, c_.eval().value );
878  }
879 #elif BLAZE_FMA_MODE && BLAZE_SSE2_MODE
880  {
881  return _mm_fmsub_pd( a_.eval().value, b_.eval().value, c_.eval().value );
882  }
883 #else
884  = delete;
885 #endif
886  //**********************************************************************************************
887 
888  //**Member variables****************************************************************************
889  const T1 a_;
890  const T2 b_;
891  const T3 c_;
892  //**********************************************************************************************
893 };
894 //*************************************************************************************************
895 
896 
897 //*************************************************************************************************
909 #if BLAZE_FMA_MODE
910 template< typename T1 // Type of the first multiplication operand
911  , typename T2 // Type of the second multiplication operand
912  , typename T3 > // Type of the second addition operand
914  operator+( const SIMDf64MultExpr<T1,T2>& a, const SIMDf64<T3>& b )
915 {
916  return SIMDf64FmaddExpr<T1,T2,T3>( a.a_, a.b_, ~b );
917 }
918 #endif
919 //*************************************************************************************************
920 
921 
922 //*************************************************************************************************
934 #if BLAZE_FMA_MODE
935 template< typename T1 // Type of the first addition operand
936  , typename T2 // Type of the first multiplication operand
937  , typename T3 > // Type of the second multiplication operand
938 BLAZE_ALWAYS_INLINE const SIMDf64FmaddExpr<T2,T3,T1>
939  operator+( const SIMDf64<T1>& a, const SIMDf64MultExpr<T2,T3>& b )
940 {
941  return SIMDf64FmaddExpr<T2,T3,T1>( b.a_, b.b_, ~a );
942 }
943 #endif
944 //*************************************************************************************************
945 
946 
947 //*************************************************************************************************
960 #if BLAZE_FMA_MODE
961 template< typename T1 // Type of the first operand of the left-hand side multiplication
962  , typename T2 // Type of the second operand of the left-hand side multiplication
963  , typename T3 // Type of the first operand of the right-hand side multiplication
964  , typename T4 > // Type of the second operand of the right-hand side multiplication
965 BLAZE_ALWAYS_INLINE const SIMDf64FmaddExpr< T1, T2, SIMDf64MultExpr<T3,T4> >
966  operator+( const SIMDf64MultExpr<T1,T2>& a, const SIMDf64MultExpr<T3,T4>& b )
967 {
968  return SIMDf64FmaddExpr< T1, T2, SIMDf64MultExpr<T3,T4> >( a.a_, a.b_, b );
969 }
970 #endif
971 
972 //*************************************************************************************************
973 
974 
975 //*************************************************************************************************
989 #if BLAZE_FMA_MODE
990 template< typename T1 // Type of the first FMA multiplication operand
991  , typename T2 // Type of the second FMA multiplication operand
992  , typename T3 // Type of the FMA addition operand
993  , typename T4 > // Type of the second addition operand
994 BLAZE_ALWAYS_INLINE const auto
995  operator+( const SIMDf64FmaddExpr<T1,T2,T3>& a, const SIMDf64<T4>& b )
996 {
997  return ( a.a_ * a.b_ ) + ( a.c_ + (~b) );
998 }
999 #endif
1000 
1001 //*************************************************************************************************
1002 
1003 
1004 //*************************************************************************************************
1018 #if BLAZE_FMA_MODE
1019 template< typename T1 // Type of the first addition operand
1020  , typename T2 // Type of the first FMA multiplication operand
1021  , typename T3 // Type of the second FMA multiplication operand
1022  , typename T4 > // Type of the FMA addition operand
1023 BLAZE_ALWAYS_INLINE const auto
1024  operator+( const SIMDf64<T1>& a, const SIMDf64FmaddExpr<T2,T3,T4>& b )
1025 {
1026  return ( b.a_ * b.b_ ) + ( b.c_ + (~a) );
1027 }
1028 #endif
1029 
1030 //*************************************************************************************************
1031 
1032 
1033 //*************************************************************************************************
1047 #if BLAZE_FMA_MODE
1048 template< typename T1 // Type of the first FMA multiplication operand
1049  , typename T2 // Type of the second FMA multiplication operand
1050  , typename T3 // Type of the FMA addition operand
1051  , typename T4 // Type of the first multiplication operand
1052  , typename T5 > // Type of the second multiplication operand
1053 BLAZE_ALWAYS_INLINE const SIMDf64FmaddExpr< T4, T5, SIMDf64FmaddExpr<T1,T2,T3> >
1054  operator+( const SIMDf64FmaddExpr<T1,T2,T3>& a, const SIMDf64MultExpr<T4,T5>& b )
1055 {
1056  return SIMDf64FmaddExpr< T4, T5, SIMDf64FmaddExpr<T1,T2,T3> >( b.a_, b.b_, a );
1057 }
1058 #endif
1059 
1060 //*************************************************************************************************
1061 
1062 
1063 //*************************************************************************************************
1077 #if BLAZE_FMA_MODE
1078 template< typename T1 // Type of the first multiplication operand
1079  , typename T2 // Type of the second multiplication operand
1080  , typename T3 // Type of the first FMA multiplication operand
1081  , typename T4 // Type of the second FMA multiplication operand
1082  , typename T5 > // Type of the FMA addition operand
1083 BLAZE_ALWAYS_INLINE const SIMDf64FmaddExpr< T1, T2, SIMDf64FmaddExpr<T3,T4,T5> >
1084  operator+( const SIMDf64MultExpr<T1,T2>& a, const SIMDf64FmaddExpr<T3,T4,T5>& b )
1085 {
1086  return SIMDf64FmaddExpr< T1, T2, SIMDf64FmaddExpr<T3,T4,T5> >( a.a_, a.b_, b );
1087 }
1088 #endif
1089 
1090 //*************************************************************************************************
1091 
1092 
1093 //*************************************************************************************************
1106 #if BLAZE_FMA_MODE
1107 template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
1108  , typename T2 // Type of the second multiplication operand of the left-hand side FMA
1109  , typename T3 // Type of the addition operand of the left-hand side FMA
1110  , typename T4 // Type of the first multiplication operand of the right-hand side FMA
1111  , typename T5 // Type of the second multiplication operand of the right-hand side FMA
1112  , typename T6 > // Type of the addition operand of the right-hand side FMA
1113 BLAZE_ALWAYS_INLINE const auto
1114  operator+( const SIMDf64FmaddExpr<T1,T2,T3>& a, const SIMDf64FmaddExpr<T4,T5,T6>& b )
1115 {
1116  return ( a.a_ * a.b_ ) + ( ( b.a_ * b.b_ ) + ( a.c_ + b.c_ ) );
1117 }
1118 #endif
1119 
1120 //*************************************************************************************************
1121 
1122 
1123 //*************************************************************************************************
1136 #if BLAZE_FMA_MODE
1137 template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
1138  , typename T2 // Type of the second multiplication operand of the left-hand side FMA
1139  , typename T3 // Type of the addition operand of the left-hand side FMA
1140  , typename T4 // Type of the first multiplication operand of the right-hand side FMA
1141  , typename T5 // Type of the second multiplication operand of the right-hand side FMA
1142  , typename T6 > // Type of the subtraction operand of the right-hand side FMA
1143 BLAZE_ALWAYS_INLINE const auto
1144  operator+( const SIMDf64FmaddExpr<T1,T2,T3>& a, const SIMDf64FmsubExpr<T4,T5,T6>& b )
1145 {
1146  return ( a.a_ * a.b_ ) + ( ( b.a_ * b.b_ ) + ( a.c_ - b.c_ ) );
1147 }
1148 #endif
1149 
1150 //*************************************************************************************************
1151 
1152 
1153 //*************************************************************************************************
1166 #if BLAZE_FMA_MODE
1167 template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
1168  , typename T2 // Type of the second multiplication operand of the left-hand side FMA
1169  , typename T3 // Type of the subtraction operand of the left-hand side FMA
1170  , typename T4 // Type of the first multiplication operand of the right-hand side FMA
1171  , typename T5 // Type of the second multiplication operand of the right-hand side FMA
1172  , typename T6 > // Type of the addition operand of the right-hand side FMA
1173 BLAZE_ALWAYS_INLINE const auto
1174  operator+( const SIMDf64FmsubExpr<T1,T2,T3>& a, const SIMDf64FmaddExpr<T4,T5,T6>& b )
1175 {
1176  return ( a.a_ * a.b_ ) + ( ( b.a_ * b.b_ ) + ( b.c_ - a.c_ ) );
1177 }
1178 #endif
1179 
1180 //*************************************************************************************************
1181 
1182 
1183 //*************************************************************************************************
1196 #if BLAZE_FMA_MODE
1197 template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
1198  , typename T2 // Type of the second multiplication operand of the left-hand side FMA
1199  , typename T3 // Type of the subtraction operand of the left-hand side FMA
1200  , typename T4 // Type of the first multiplication operand of the right-hand side FMA
1201  , typename T5 // Type of the second multiplication operand of the right-hand side FMA
1202  , typename T6 > // Type of the subtraction operand of the right-hand side FMA
1203 BLAZE_ALWAYS_INLINE const auto
1204  operator+( const SIMDf64FmsubExpr<T1,T2,T3>& a, const SIMDf64FmsubExpr<T4,T5,T6>& b )
1205 {
1206  return ( a.a_ * a.b_ ) + ( ( b.a_ * b.b_ ) - ( b.c_ + a.c_ ) );
1207 }
1208 #endif
1209 
1210 //*************************************************************************************************
1211 
1212 
1213 //*************************************************************************************************
1225 #if BLAZE_FMA_MODE
1226 template< typename T1 // Type of the first multiplication operand
1227  , typename T2 // Type of the second multiplication operand
1228  , typename T3 > // Type of the second subtraction operand
1229 BLAZE_ALWAYS_INLINE const SIMDf64FmsubExpr<T1,T2,T3>
1230  operator-( const SIMDf64MultExpr<T1,T2>& a, const SIMDf64<T3>& b )
1231 {
1232  return SIMDf64FmsubExpr<T1,T2,T3>( a.a_, a.b_, ~b );
1233 }
1234 #endif
1235 //*************************************************************************************************
1236 
1237 
1238 //*************************************************************************************************
1251 #if BLAZE_FMA_MODE
1252 template< typename T1 // Type of the first operand of the left-hand side multiplication
1253  , typename T2 // Type of the second operand of the left-hand side multiplication
1254  , typename T3 // Type of the first operand of the right-hand side multiplication
1255  , typename T4 > // Type of the second operand of the right-hand side multiplication
1256 BLAZE_ALWAYS_INLINE const SIMDf64FmsubExpr< T1, T2, SIMDf64MultExpr<T3,T4> >
1257  operator-( const SIMDf64MultExpr<T1,T2>& a, const SIMDf64MultExpr<T3,T4>& b )
1258 {
1259  return SIMDf64FmsubExpr< T1, T2, SIMDf64MultExpr<T3,T4> >( a.a_, a.b_, b );
1260 }
1261 #endif
1262 
1263 //*************************************************************************************************
1264 
1265 
1266 //*************************************************************************************************
1280 #if BLAZE_FMA_MODE
1281 template< typename T1 // Type of the first FMA multiplication operand
1282  , typename T2 // Type of the second FMA multiplication operand
1283  , typename T3 // Type of the FMA subtraction operand
1284  , typename T4 > // Type of the second subtraction operand
1285 BLAZE_ALWAYS_INLINE const auto
1286  operator-( const SIMDf64FmsubExpr<T1,T2,T3>& a, const SIMDf64<T4>& b )
1287 {
1288  return ( a.a_ * a.b_ ) - ( a.c_ + (~b) );
1289 }
1290 #endif
1291 
1292 //*************************************************************************************************
1293 
1294 
1295 //*************************************************************************************************
1309 #if BLAZE_FMA_MODE
1310 template< typename T1 // Type of the first FMA multiplication operand
1311  , typename T2 // Type of the second FMA multiplication operand
1312  , typename T3 // Type of the FMA subtraction operand
1313  , typename T4 // Type of the first multiplication operand
1314  , typename T5 > // Type of the second multiplication operand
1315 BLAZE_ALWAYS_INLINE const auto
1316  operator-( const SIMDf64FmsubExpr<T1,T2,T3>& a, const SIMDf64MultExpr<T4,T5>& b )
1317 {
1318  return ( a.a_ * a.b_ ) - ( b.a_ * b.b_ + a.c_ );
1319 }
1320 #endif
1321 
1322 //*************************************************************************************************
1323 
1324 
1325 //*************************************************************************************************
1339 #if BLAZE_FMA_MODE
1340 template< typename T1 // Type of the first multiplication operand
1341  , typename T2 // Type of the second multiplication operand
1342  , typename T3 // Type of the first FMA multiplication operand
1343  , typename T4 // Type of the second FMA multiplication operand
1344  , typename T5 > // Type of the FMA subtraction operand
1345 BLAZE_ALWAYS_INLINE const SIMDf64FmsubExpr< T1, T2, SIMDf64FmsubExpr<T3,T4,T5> >
1346  operator-( const SIMDf64MultExpr<T1,T2>& a, const SIMDf64FmsubExpr<T3,T4,T5>& b )
1347 {
1348  return SIMDf64FmsubExpr< T1, T2, SIMDf64FmsubExpr<T3,T4,T5> >( a.a_, a.b_, b );
1349 }
1350 #endif
1351 
1352 //*************************************************************************************************
1353 
1354 
1355 //*************************************************************************************************
1368 #if BLAZE_FMA_MODE
1369 template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
1370  , typename T2 // Type of the second multiplication operand of the left-hand side FMA
1371  , typename T3 // Type of the addition operand of the left-hand side FMA
1372  , typename T4 // Type of the first multiplication operand of the right-hand side FMA
1373  , typename T5 // Type of the second multiplication operand of the right-hand side FMA
1374  , typename T6 > // Type of the addition operand of the right-hand side FMA
1375 BLAZE_ALWAYS_INLINE const auto
1376  operator-( const SIMDf64FmaddExpr<T1,T2,T3>& a, const SIMDf64FmaddExpr<T4,T5,T6>& b )
1377 {
1378  return ( a.a_ * a.b_ ) - ( ( b.a_ * b.b_ ) + ( b.c_ - a.c_ ) );
1379 }
1380 #endif
1381 
1382 //*************************************************************************************************
1383 
1384 
1385 //*************************************************************************************************
1398 #if BLAZE_FMA_MODE
1399 template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
1400  , typename T2 // Type of the second multiplication operand of the left-hand side FMA
1401  , typename T3 // Type of the addition operand of the left-hand side FMA
1402  , typename T4 // Type of the first multiplication operand of the right-hand side FMA
1403  , typename T5 // Type of the second multiplication operand of the right-hand side FMA
1404  , typename T6 > // Type of the subtraction operand of the right-hand side FMA
1405 BLAZE_ALWAYS_INLINE const auto
1406  operator-( const SIMDf64FmaddExpr<T1,T2,T3>& a, const SIMDf64FmsubExpr<T4,T5,T6>& b )
1407 {
1408  return ( a.a_ * a.b_ ) - ( ( b.a_ * b.b_ ) - ( a.c_ + b.c_ ) );
1409 }
1410 #endif
1411 
1412 //*************************************************************************************************
1413 
1414 
1415 //*************************************************************************************************
1428 #if BLAZE_FMA_MODE
1429 template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
1430  , typename T2 // Type of the second multiplication operand of the left-hand side FMA
1431  , typename T3 // Type of the subtraction operand of the left-hand side FMA
1432  , typename T4 // Type of the first multiplication operand of the right-hand side FMA
1433  , typename T5 // Type of the second multiplication operand of the right-hand side FMA
1434  , typename T6 > // Type of the addition operand of the right-hand side FMA
1435 BLAZE_ALWAYS_INLINE const auto
1436  operator-( const SIMDf64FmsubExpr<T1,T2,T3>& a, const SIMDf64FmaddExpr<T4,T5,T6>& b )
1437 {
1438  return ( a.a_ * a.b_ ) - ( ( b.a_ * b.b_ ) + ( a.c_ + b.c_ ) );
1439 }
1440 #endif
1441 
1442 //*************************************************************************************************
1443 
1444 
1445 //*************************************************************************************************
1458 #if BLAZE_FMA_MODE
1459 template< typename T1 // Type of the first multiplication operand of the left-hand side FMA
1460  , typename T2 // Type of the second multiplication operand of the left-hand side FMA
1461  , typename T3 // Type of the subtraction operand of the left-hand side FMA
1462  , typename T4 // Type of the first multiplication operand of the right-hand side FMA
1463  , typename T5 // Type of the second multiplication operand of the right-hand side FMA
1464  , typename T6 > // Type of the subtraction operand of the right-hand side FMA
1465 BLAZE_ALWAYS_INLINE const auto
1466  operator-( const SIMDf64FmsubExpr<T1,T2,T3>& a, const SIMDf64FmsubExpr<T4,T5,T6>& b )
1467 {
1468  return ( a.a_ * a.b_ ) - ( ( b.a_ * b.b_ ) + ( a.c_ - b.c_ ) );
1469 }
1470 #endif
1471 
1472 //*************************************************************************************************
1473 
1474 } // namespace blaze
1475 
1476 #endif
Addition operator for fusing a 32-bit floating point multiplication and addition. ...
Definition: FMA.h:781
Expression object for 64-bit floating point fused multiply-subtract operations.The SIMDf64FmsubExpr c...
Definition: FMA.h:844
BLAZE_ALWAYS_INLINE const SIMDfloat eval() const noexcept=delete
Evaluation of the expression object.
const T1 a_
The left-hand side operand for the multiplication.
Definition: FMA.h:826
Expression object for 64-bit floating point multiplication operations.The SIMDf64MultExpr class repre...
Definition: Multiplication.h:710
Expression object for 32-bit floating point fused multiply-subtract operations.The SIMDf32FmsubExpr c...
Definition: FMA.h:132
Header file for the SIMD subtraction functionality.
const T3 c_
The right-hand side operand for the addition.
Definition: FMA.h:828
const DenseIterator< Type, AF > operator+(const DenseIterator< Type, AF > &it, ptrdiff_t inc) noexcept
Addition between a DenseIterator and an integral value.
Definition: DenseIterator.h:699
Header file for the SIMD multiplication functionality.
BLAZE_ALWAYS_INLINE SIMDf64FmaddExpr(const T1 &a, const T2 &b, const T3 &c)
Constructor for the SIMDf64FmaddExpr class.
Definition: FMA.h:795
Expression object for 32-bit floating point fused multiply-add operations.The SIMDf32FmaddExpr class ...
Definition: FMA.h:69
const DenseIterator< Type, AF > operator-(const DenseIterator< Type, AF > &it, ptrdiff_t inc) noexcept
Subtraction between a DenseIterator and an integral value.
Definition: DenseIterator.h:731
SIMDf64< This > BaseType
Base type of this SIMDf64FMaddExpr instance.
Definition: FMA.h:785
SIMD type for 64-bit double precision floating point data values.
SIMDf32< This > BaseType
Base type of this SIMDf32FMaddExpr instance.
Definition: FMA.h:73
BLAZE_ALWAYS_INLINE const SIMDdouble eval() const noexcept=delete
Evaluation of the expression object.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:57
#define BLAZE_ALWAYS_INLINE
Platform dependent setup of an enforced inline keyword.
Definition: Inline.h:85
const T2 b_
The right-hand side operand for the multiplication.
Definition: Multiplication.h:754
BLAZE_ALWAYS_INLINE const SIMDdouble eval() const noexcept=delete
Evaluation of the expression object.
Header file for the basic SIMD types.
SIMDf32< This > BaseType
Base type of this SIMDf32FMsubExpr instance.
Definition: FMA.h:136
const T2 b_
The right-hand side operand for the multiplication.
Definition: FMA.h:827
const T1 a_
The left-hand side operand for the multiplication.
Definition: Multiplication.h:566
SIMDf64< This > BaseType
Base type of this SIMDf64FMsubExpr instance.
Definition: FMA.h:848
const T1 a_
The left-hand side operand for the multiplication.
Definition: FMA.h:889
BLAZE_ALWAYS_INLINE SIMDf32FmsubExpr(const T1 &a, const T2 &b, const T3 &c)
Constructor for the SIMDf32FmsubExpr class.
Definition: FMA.h:146
SIMD type for 32-bit single precision floating point data values.
const T1 a_
The left-hand side operand for the multiplication.
Definition: FMA.h:114
BLAZE_ALWAYS_INLINE SIMDf64FmsubExpr(const T1 &a, const T2 &b, const T3 &c)
Constructor for the SIMDf64FmsubExpr class.
Definition: FMA.h:858
const T1 a_
The left-hand side operand for the multiplication.
Definition: FMA.h:177
Header file for the SIMD addition functionality.
BLAZE_ALWAYS_INLINE const SIMDfloat eval() const noexcept=delete
Evaluation of the expression object.
System settings for the SSE mode.
const T2 b_
The right-hand side operand for the multiplication.
Definition: FMA.h:178
Expression object for 32-bit floating point multiplication operations.The SIMDf32MultExpr class repre...
Definition: Multiplication.h:523
const T2 b_
The right-hand side operand for the multiplication.
Definition: Multiplication.h:567
const T2 b_
The right-hand side operand for the multiplication.
Definition: FMA.h:115
System settings for the inline keywords.
BLAZE_ALWAYS_INLINE SIMDf32FmaddExpr(const T1 &a, const T2 &b, const T3 &c)
Constructor for the SIMDf32FmaddExpr class.
Definition: FMA.h:83
const T2 b_
The right-hand side operand for the multiplication.
Definition: FMA.h:890
const T1 a_
The left-hand side operand for the multiplication.
Definition: Multiplication.h:753
const T3 c_
The right-hand side operand for the subtraction.
Definition: FMA.h:179
const T3 c_
The right-hand side operand for the subtraction.
Definition: FMA.h:891
const T3 c_
The right-hand side operand for the addition.
Definition: FMA.h:116