1 /**
2  * Copyright 2015 Kurt Kanzenbach
3  * Copyright 2016 Andreas Schäfer
4  *
5  * Distributed under the Boost Software License, Version 1.0. (See accompanying
6  * file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
7  */
8 
9 #ifndef FLAT_ARRAY_DETAIL_SHORT_VEC_MIC_DOUBLE_8_HPP
10 #define FLAT_ARRAY_DETAIL_SHORT_VEC_MIC_DOUBLE_8_HPP
11 
12 #if LIBFLATARRAY_WIDEST_VECTOR_ISA == LIBFLATARRAY_MIC
13 
14 #include <immintrin.h>
15 #include <libflatarray/detail/sqrt_reference.hpp>
16 #include <libflatarray/detail/short_vec_helpers.hpp>
17 #include <libflatarray/config.h>
18 
19 #ifdef LIBFLATARRAY_WITH_CPP14
20 #include <initializer_list>
21 #endif
22 
23 namespace LibFlatArray {
24 
25 template<typename CARGO, int ARITY>
26 class short_vec;
27 
28 #ifdef __ICC
29 // disabling this warning as implicit type conversion is exactly our goal here:
30 #pragma warning push
31 #pragma warning (disable: 2304)
32 #endif
33 
34 template<>
35 class short_vec<double, 8>
36 {
37 public:
38     static const int ARITY = 8;
39 
40     typedef short_vec_strategy::mic strategy;
41 
42     template<typename _CharT, typename _Traits>
43     friend std::basic_ostream<_CharT, _Traits>& operator<<(
44         std::basic_ostream<_CharT, _Traits>& __os,
45         const short_vec<double, 8>& vec);
46 
47     inline
short_vec(const double data=0)48     short_vec(const double data = 0) :
49         val1(_mm512_set1_pd(data))
50     {}
51 
52     inline
short_vec(const double * data)53     short_vec(const double *data)
54     {
55         load(data);
56     }
57 
58     inline
short_vec(const __m512d & val1)59     short_vec(const __m512d& val1) :
60         val1(val1)
61     {}
62 
63 #ifdef LIBFLATARRAY_WITH_CPP14
64     inline
short_vec(const std::initializer_list<double> & il)65     short_vec(const std::initializer_list<double>& il)
66     {
67         const double *ptr = static_cast<const double *>(&(*il.begin()));
68         load(ptr);
69     }
70 #endif
71 
72     inline
operator -=(const short_vec<double,8> & other)73     void operator-=(const short_vec<double, 8>& other)
74     {
75         val1 = _mm512_sub_pd(val1, other.val1);
76     }
77 
78     inline
operator -(const short_vec<double,8> & other) const79     short_vec<double, 8> operator-(const short_vec<double, 8>& other) const
80     {
81         return short_vec<double, 8>(
82             _mm512_sub_pd(val1, other.val1));
83     }
84 
85     inline
operator +=(const short_vec<double,8> & other)86     void operator+=(const short_vec<double, 8>& other)
87     {
88         val1 = _mm512_add_pd(val1, other.val1);
89     }
90 
91     inline
operator +(const short_vec<double,8> & other) const92     short_vec<double, 8> operator+(const short_vec<double, 8>& other) const
93     {
94         return short_vec<double, 8>(
95             _mm512_add_pd(val1, other.val1));
96     }
97 
98     inline
operator *=(const short_vec<double,8> & other)99     void operator*=(const short_vec<double, 8>& other)
100     {
101         val1 = _mm512_mul_pd(val1, other.val1);
102     }
103 
104     inline
operator *(const short_vec<double,8> & other) const105     short_vec<double, 8> operator*(const short_vec<double, 8>& other) const
106     {
107         return short_vec<double, 8>(
108             _mm512_mul_pd(val1, other.val1));
109     }
110 
111     inline
operator /=(const short_vec<double,8> & other)112     void operator/=(const short_vec<double, 8>& other)
113     {
114         val1 = _mm512_div_pd(val1, other.val1);
115     }
116 
117     inline
operator /(const short_vec<double,8> & other) const118     short_vec<double, 8> operator/(const short_vec<double, 8>& other) const
119     {
120         return short_vec<double, 8>(
121             _mm512_div_pd(val1, other.val1));
122     }
123 
124     inline
sqrt() const125     short_vec<double, 8> sqrt() const
126     {
127         return short_vec<double, 8>(
128             _mm512_sqrt_pd(val1));
129     }
130 
131     inline
load(const double * data)132     void load(const double *data)
133     {
134         val1 = _mm512_loadunpacklo_pd(val1, data + 0);
135         val1 = _mm512_loadunpackhi_pd(val1, data + 8);
136     }
137 
138     inline
load_aligned(const double * data)139     void load_aligned(const double *data)
140     {
141         SHORTVEC_ASSERT_ALIGNED(data, 64);
142         val1 = _mm512_load_pd(data);
143     }
144 
145     inline
store(double * data) const146     void store(double *data) const
147     {
148         _mm512_packstorelo_pd(data + 0, val1);
149         _mm512_packstorehi_pd(data + 8, val1);
150     }
151 
152     inline
store_aligned(double * data) const153     void store_aligned(double *data) const
154     {
155         SHORTVEC_ASSERT_ALIGNED(data, 64);
156         _mm512_store_pd(data, val1);
157     }
158 
159     inline
store_nt(double * data) const160     void store_nt(double *data) const
161     {
162         SHORTVEC_ASSERT_ALIGNED(data, 64);
163         _mm512_storenr_pd(data, val1);
164     }
165 
166     inline
gather(const double * ptr,const int * offsets)167     void gather(const double *ptr, const int *offsets)
168     {
169         __m512i indices;
170         indices = _mm512_loadunpacklo_epi32(indices, offsets);
171         val1    = _mm512_i32logather_pd(indices, ptr, 8);
172     }
173 
174     inline
scatter(double * ptr,const int * offsets) const175     void scatter(double *ptr, const int *offsets) const
176     {
177         __m512i indices;
178         indices = _mm512_loadunpacklo_epi32(indices, offsets);
179         _mm512_i32loscatter_pd(ptr, indices, val1, 8);
180     }
181 
182 private:
183     __m512d val1;
184 };
185 
186 inline
operator <<(double * data,const short_vec<double,8> & vec)187 void operator<<(double *data, const short_vec<double, 8>& vec)
188 {
189     vec.store(data);
190 }
191 
192 #ifdef __ICC
193 #pragma warning pop
194 #endif
195 
196 inline
sqrt(const short_vec<double,8> & vec)197 short_vec<double, 8> sqrt(const short_vec<double, 8>& vec)
198 {
199     return vec.sqrt();
200 }
201 
202 template<typename _CharT, typename _Traits>
203 std::basic_ostream<_CharT, _Traits>&
operator <<(std::basic_ostream<_CharT,_Traits> & __os,const short_vec<double,8> & vec)204 operator<<(std::basic_ostream<_CharT, _Traits>& __os,
205            const short_vec<double, 8>& vec)
206 {
207     const double *data1 = reinterpret_cast<const double *>(&vec.val1);
208 
209     __os << "["  << data1[0] << ", " << data1[1] << ", " << data1[2] << ", " << data1[3]
210          << ", " << data1[4] << ", " << data1[5] << ", " << data1[6] << ", " << data1[7]
211          << "]";
212     return __os;
213 }
214 
215 }
216 
217 #endif
218 
219 #endif
220