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