1 //=================================================================================================
2 /*!
3 //  \file blaze/math/typetraits/HasSIMDAdd.h
4 //  \brief Header file for the HasSIMDAdd type trait
5 //
6 //  Copyright (C) 2012-2020 Klaus Iglberger - All Rights Reserved
7 //
8 //  This file is part of the Blaze library. You can redistribute it and/or modify it under
9 //  the terms of the New (Revised) BSD License. Redistribution and use in source and binary
10 //  forms, with or without modification, are permitted provided that the following conditions
11 //  are met:
12 //
13 //  1. Redistributions of source code must retain the above copyright notice, this list of
14 //     conditions and the following disclaimer.
15 //  2. Redistributions in binary form must reproduce the above copyright notice, this list
16 //     of conditions and the following disclaimer in the documentation and/or other materials
17 //     provided with the distribution.
18 //  3. Neither the names of the Blaze development group nor the names of its contributors
19 //     may be used to endorse or promote products derived from this software without specific
20 //     prior written permission.
21 //
22 //  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
23 //  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 //  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25 //  SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 //  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27 //  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 //  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 //  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 //  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 //  DAMAGE.
32 */
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_TYPETRAITS_HASSIMDADD_H_
36 #define _BLAZE_MATH_TYPETRAITS_HASSIMDADD_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <blaze/system/Vectorization.h>
44 #include <blaze/util/Complex.h>
45 #include <blaze/util/EnableIf.h>
46 #include <blaze/util/IntegralConstant.h>
47 #include <blaze/util/typetraits/IsIntegral.h>
48 #include <blaze/util/typetraits/IsNumeric.h>
49 #include <blaze/util/typetraits/RemoveCVRef.h>
50 
51 
52 namespace blaze {
53 
54 //=================================================================================================
55 //
56 //  CLASS DEFINITION
57 //
58 //=================================================================================================
59 
60 //*************************************************************************************************
61 /*! \cond BLAZE_INTERNAL */
62 /*!\brief Auxiliary helper struct for the HasSIMDAdd type trait.
63 // \ingroup math_type_traits
64 */
65 template< typename T1        // Type of the left-hand side operand
66         , typename T2        // Type of the right-hand side operand
67         , typename = void >  // Restricting condition
68 struct HasSIMDAddHelper
69    : public FalseType
70 {};
71 /*! \endcond */
72 //*************************************************************************************************
73 
74 
75 //*************************************************************************************************
76 /*! \cond BLAZE_INTERNAL */
77 template< typename T1, typename T2 >
78 struct HasSIMDAddHelper< T1, T2, EnableIf_t< IsNumeric_v<T1> && IsIntegral_v<T1> &&
79                                              IsNumeric_v<T2> && IsIntegral_v<T2> &&
80                                              sizeof(T1) == sizeof(T2) > >
81    : public BoolConstant< ( bool( BLAZE_SSE2_MODE ) ) ||
82                           ( bool( BLAZE_AVX2_MODE ) ) ||
83                           ( bool( BLAZE_MIC_MODE      ) && sizeof(T1) >= 4UL ) ||
84                           ( bool( BLAZE_AVX512BW_MODE ) && sizeof(T1) <= 2UL ) ||
85                           ( bool( BLAZE_AVX512F_MODE  ) && sizeof(T1) >= 4UL ) >
86 {};
87 
88 template< typename T >
89 struct HasSIMDAddHelper< complex<T>, complex<T>, EnableIf_t< IsNumeric_v<T> && IsIntegral_v<T> > >
90    : public BoolConstant< ( bool( BLAZE_SSE2_MODE ) ) ||
91                           ( bool( BLAZE_AVX2_MODE ) ) ||
92                           ( bool( BLAZE_MIC_MODE      ) && sizeof(T) >= 4UL ) ||
93                           ( bool( BLAZE_AVX512BW_MODE ) && sizeof(T) <= 2UL ) ||
94                           ( bool( BLAZE_AVX512F_MODE  ) && sizeof(T) >= 4UL ) >
95 {};
96 /*! \endcond */
97 //*************************************************************************************************
98 
99 
100 //*************************************************************************************************
101 /*! \cond BLAZE_INTERNAL */
102 template<>
103 struct HasSIMDAddHelper< float, float >
104    : public BoolConstant< bool( BLAZE_SSE_MODE     ) ||
105                           bool( BLAZE_AVX_MODE     ) ||
106                           bool( BLAZE_MIC_MODE     ) ||
107                           bool( BLAZE_AVX512F_MODE ) >
108 {};
109 
110 template<>
111 struct HasSIMDAddHelper< complex<float>, complex<float> >
112    : public BoolConstant< bool( BLAZE_SSE_MODE     ) ||
113                           bool( BLAZE_AVX_MODE     ) ||
114                           bool( BLAZE_MIC_MODE     ) ||
115                           bool( BLAZE_AVX512F_MODE ) >
116 {};
117 /*! \endcond */
118 //*************************************************************************************************
119 
120 
121 //*************************************************************************************************
122 /*! \cond BLAZE_INTERNAL */
123 template<>
124 struct HasSIMDAddHelper< double, double >
125    : public BoolConstant< bool( BLAZE_SSE2_MODE    ) ||
126                           bool( BLAZE_AVX_MODE     ) ||
127                           bool( BLAZE_MIC_MODE     ) ||
128                           bool( BLAZE_AVX512F_MODE ) >
129 {};
130 
131 template<>
132 struct HasSIMDAddHelper< complex<double>, complex<double> >
133    : public BoolConstant< bool( BLAZE_SSE2_MODE    ) ||
134                           bool( BLAZE_AVX_MODE     ) ||
135                           bool( BLAZE_MIC_MODE     ) ||
136                           bool( BLAZE_AVX512F_MODE ) >
137 {};
138 /*! \endcond */
139 //*************************************************************************************************
140 
141 
142 //*************************************************************************************************
143 /*!\brief Availability of a SIMD addition for the given data types.
144 // \ingroup math_type_traits
145 //
146 // Depending on the available instruction set (SSE, SSE2, SSE3, SSE4, AVX, AVX2, MIC, ...), and
147 // the used compiler, this type trait provides the information whether a SIMD addition operation
148 // exists for the two given data types \a T1 and \a T2 (ignoring the cv-qualifiers). In case the
149 // SIMD addition is available, the \a value member constant is set to \a true, the nested type
150 // definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value
151 // is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. The
152 // following example assumes that AVX is available:
153 
154    \code
155    blaze::HasSIMDAdd< int, int >::value     // Evaluates to 1
156    blaze::HasSIMDAdd< float, float >::Type  // Results in TrueType
157    blaze::HasSIMDAdd< double, double >      // Is derived from TrueType
158    blaze::HasSIMDAdd< bool, bool >::value   // Evaluates to 0
159    blaze::HasSIMDAdd< float, int >::Type    // Results in FalseType
160    blaze::HasSIMDAdd< float, double >       // Is derived from FalseType
161    \endcode
162 */
163 template< typename T1        // Type of the left-hand side operand
164         , typename T2        // Type of the right-hand side operand
165         , typename = void >  // Restricting condition
166 struct HasSIMDAdd
167    : public BoolConstant< HasSIMDAddHelper< RemoveCVRef_t<T1>, RemoveCVRef_t<T2> >::value >
168 {};
169 //*************************************************************************************************
170 
171 
172 //*************************************************************************************************
173 /*!\brief Auxiliary variable template for the HasSIMDAdd type trait.
174 // \ingroup math_type_traits
175 //
176 // The HasSIMDAdd_v variable template provides a convenient shortcut to access the nested
177 // \a value of the HasSIMDAdd class template. For instance, given the types \a T1 and \a T2
178 // the following two statements are identical:
179 
180    \code
181    constexpr bool value1 = blaze::HasSIMDAdd<T1,T2>::value;
182    constexpr bool value2 = blaze::HasSIMDAdd_v<T1,T2>;
183    \endcode
184 */
185 template< typename T1    // Type of the left-hand side operand
186         , typename T2 >  // Type of the right-hand side operand
187 constexpr bool HasSIMDAdd_v = HasSIMDAdd<T1,T2>::value;
188 //*************************************************************************************************
189 
190 } // namespace blaze
191 
192 #endif
193