Created SIMD module
[alexxy/gromacs.git] / src / gromacs / simd / math_x86_avx_256_double.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 #ifndef GMX_SIMD_MATH_AVX_256_DOUBLE_H
36 #define GMX_SIMD_MATH_AVX_256_DOUBLE_H
37
38 #include <math.h>
39
40 #include "general_x86_avx_256.h"
41
42 #ifndef M_PI
43 #  define M_PI 3.14159265358979323846264338327950288
44 #endif
45
46
47 /************************
48  *                      *
49  * Simple math routines *
50  *                      *
51  ************************/
52
53 /* 1.0/sqrt(x), 256 bit wide */
54 static gmx_inline __m256d
55 gmx_mm256_invsqrt_pd(__m256d x)
56 {
57     const __m256d half  = _mm256_set1_pd(0.5);
58     const __m256d three = _mm256_set1_pd(3.0);
59
60     /* Lookup instruction only exists in single precision, convert back and forth... */
61     __m256d lu = _mm256_cvtps_pd(_mm_rsqrt_ps( _mm256_cvtpd_ps(x)));
62
63     lu = _mm256_mul_pd(half, _mm256_mul_pd(_mm256_sub_pd(three, _mm256_mul_pd(_mm256_mul_pd(lu, lu), x)), lu));
64     return _mm256_mul_pd(half, _mm256_mul_pd(_mm256_sub_pd(three, _mm256_mul_pd(_mm256_mul_pd(lu, lu), x)), lu));
65 }
66
67 /* 1.0/sqrt(x), done for a pair of arguments to improve throughput */
68 static void
69 gmx_mm256_invsqrt_pair_pd(__m256d x1, __m256d x2, __m256d *invsqrt1, __m256d *invsqrt2)
70 {
71     const __m256d half   = _mm256_set1_pd(0.5);
72     const __m256d three  = _mm256_set1_pd(3.0);
73     const __m256  halff  = _mm256_set1_ps(0.5f);
74     const __m256  threef = _mm256_set1_ps(3.0f);
75
76     __m256        xf, luf;
77     __m256d       lu1, lu2;
78
79     /* Do first N-R step in float for 2x throughput */
80     xf  = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm256_cvtpd_ps(x1)), _mm256_cvtpd_ps(x2), 0x1);
81     luf = _mm256_rsqrt_ps(xf);
82
83     luf = _mm256_mul_ps(halff, _mm256_mul_ps(_mm256_sub_ps(threef, _mm256_mul_ps(_mm256_mul_ps(luf, luf), xf)), luf));
84
85     lu2 = _mm256_cvtps_pd(_mm256_extractf128_ps(luf, 0x1));
86     lu1 = _mm256_cvtps_pd(_mm256_castps256_ps128(luf));
87
88     *invsqrt1 = _mm256_mul_pd(half, _mm256_mul_pd(_mm256_sub_pd(three, _mm256_mul_pd(_mm256_mul_pd(lu1, lu1), x1)), lu1));
89     *invsqrt2 = _mm256_mul_pd(half, _mm256_mul_pd(_mm256_sub_pd(three, _mm256_mul_pd(_mm256_mul_pd(lu2, lu2), x2)), lu2));
90 }
91
92 /* 1.0/sqrt(x), 128 bit wide */
93 static gmx_inline __m128d
94 gmx_mm_invsqrt_pd(__m128d x)
95 {
96     const __m128d half  = _mm_set1_pd(0.5);
97     const __m128d three = _mm_set1_pd(3.0);
98
99     /* Lookup instruction only exists in single precision, convert back and forth... */
100     __m128d lu = _mm_cvtps_pd(_mm_rsqrt_ps( _mm_cvtpd_ps(x)));
101
102     lu = _mm_mul_pd(half, _mm_mul_pd(_mm_sub_pd(three, _mm_mul_pd(_mm_mul_pd(lu, lu), x)), lu));
103     return _mm_mul_pd(half, _mm_mul_pd(_mm_sub_pd(three, _mm_mul_pd(_mm_mul_pd(lu, lu), x)), lu));
104 }
105
106 /* 1.0/sqrt(x), done for two pairs to improve throughput */
107 static void
108 gmx_mm_invsqrt_pair_pd(__m128d x1, __m128d x2, __m128d *invsqrt1, __m128d *invsqrt2)
109 {
110     const __m128d half   = _mm_set1_pd(0.5);
111     const __m128d three  = _mm_set1_pd(3.0);
112     const __m128  halff  = _mm_set1_ps(0.5f);
113     const __m128  threef = _mm_set1_ps(3.0f);
114
115     __m128        xf, luf;
116     __m128d       lu1, lu2;
117
118     /* Do first N-R step in float for 2x throughput */
119     xf  = _mm_shuffle_ps(_mm_cvtpd_ps(x1), _mm_cvtpd_ps(x2), _MM_SHUFFLE(1, 0, 1, 0));
120     luf = _mm_rsqrt_ps(xf);
121     luf = _mm_mul_ps(halff, _mm_mul_ps(_mm_sub_ps(threef, _mm_mul_ps(_mm_mul_ps(luf, luf), xf)), luf));
122
123     lu2 = _mm_cvtps_pd(_mm_shuffle_ps(luf, luf, _MM_SHUFFLE(3, 2, 3, 2)));
124     lu1 = _mm_cvtps_pd(luf);
125
126     *invsqrt1 = _mm_mul_pd(half, _mm_mul_pd(_mm_sub_pd(three, _mm_mul_pd(_mm_mul_pd(lu1, lu1), x1)), lu1));
127     *invsqrt2 = _mm_mul_pd(half, _mm_mul_pd(_mm_sub_pd(three, _mm_mul_pd(_mm_mul_pd(lu2, lu2), x2)), lu2));
128 }
129
130 /* sqrt(x) (256 bit)- Do NOT use this (but rather invsqrt) if you actually need 1.0/sqrt(x) */
131 static gmx_inline __m256d
132 gmx_mm256_sqrt_pd(__m256d x)
133 {
134     __m256d mask;
135     __m256d res;
136
137     mask = _mm256_cmp_pd(x, _mm256_setzero_pd(), _CMP_EQ_OQ);
138     res  = _mm256_andnot_pd(mask, gmx_mm256_invsqrt_pd(x));
139
140     res  = _mm256_mul_pd(x, res);
141
142     return res;
143 }
144
145 /* sqrt(x) (128 bit) - Do NOT use this (but rather invsqrt) if you actually need 1.0/sqrt(x) */
146 static gmx_inline __m128d
147 gmx_mm_sqrt_pd(__m128d x)
148 {
149     __m128d mask;
150     __m128d res;
151
152     mask = _mm_cmpeq_pd(x, _mm_setzero_pd());
153     res  = _mm_andnot_pd(mask, gmx_mm_invsqrt_pd(x));
154
155     res  = _mm_mul_pd(x, res);
156
157     return res;
158 }
159
160
161 /* 1.0/x, 256 bit wide */
162 static gmx_inline __m256d
163 gmx_mm256_inv_pd(__m256d x)
164 {
165     const __m256d two  = _mm256_set1_pd(2.0);
166
167     /* Lookup instruction only exists in single precision, convert back and forth... */
168     __m256d lu = _mm256_cvtps_pd(_mm_rcp_ps( _mm256_cvtpd_ps(x)));
169
170     /* Perform two N-R steps for double precision */
171     lu         = _mm256_mul_pd(lu, _mm256_sub_pd(two, _mm256_mul_pd(x, lu)));
172     return _mm256_mul_pd(lu, _mm256_sub_pd(two, _mm256_mul_pd(x, lu)));
173 }
174
175 /* 1.0/x, 128 bit */
176 static gmx_inline __m128d
177 gmx_mm_inv_pd(__m128d x)
178 {
179     const __m128d two  = _mm_set1_pd(2.0);
180
181     /* Lookup instruction only exists in single precision, convert back and forth... */
182     __m128d lu = _mm_cvtps_pd(_mm_rcp_ps( _mm_cvtpd_ps(x)));
183
184     /* Perform two N-R steps for double precision */
185     lu         = _mm_mul_pd(lu, _mm_sub_pd(two, _mm_mul_pd(x, lu)));
186     return _mm_mul_pd(lu, _mm_sub_pd(two, _mm_mul_pd(x, lu)));
187 }
188
189
190 static gmx_inline __m256d
191 gmx_mm256_abs_pd(__m256d x)
192 {
193     const __m256d signmask  = _mm256_castsi256_pd( _mm256_set_epi32(0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF,
194                                                                     0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF) );
195
196     return _mm256_and_pd(x, signmask);
197 }
198
199 static gmx_inline __m128d
200 gmx_mm_abs_pd(__m128d x)
201 {
202     const __m128d signmask  = gmx_mm_castsi128_pd( _mm_set_epi32(0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF) );
203
204     return _mm_and_pd(x, signmask);
205 }
206
207
208 /*
209  * 2^x function, 256 bit
210  *
211  * The 2^w term is calculated from a (6,0)-th order (no denominator) Minimax polynomia on the interval
212  * [-0.5,0.5].
213  *
214  * The approximation on [-0.5,0.5] is a rational Padé approximation, 1+2*P(x^2)/(Q(x^2)-P(x^2)),
215  * according to the same algorithm as used in the Cephes/netlib math routines.
216  */
217 static __m256d
218 gmx_mm256_exp2_pd(__m256d x)
219 {
220     /* Lower bound: We do not allow numbers that would lead to an IEEE fp representation exponent smaller than -126. */
221     const __m256d arglimit = _mm256_set1_pd(1022.0);
222     const __m128i expbase  = _mm_set1_epi32(1023);
223
224     const __m256d P2       = _mm256_set1_pd(2.30933477057345225087e-2);
225     const __m256d P1       = _mm256_set1_pd(2.02020656693165307700e1);
226     const __m256d P0       = _mm256_set1_pd(1.51390680115615096133e3);
227     /* Q2 == 1.0 */
228     const __m256d Q1       = _mm256_set1_pd(2.33184211722314911771e2);
229     const __m256d Q0       = _mm256_set1_pd(4.36821166879210612817e3);
230     const __m256d one      = _mm256_set1_pd(1.0);
231     const __m256d two      = _mm256_set1_pd(2.0);
232
233     __m256d       valuemask;
234     __m256i       iexppart;
235     __m128i       iexppart128a, iexppart128b;
236     __m256d       fexppart;
237     __m256d       intpart;
238     __m256d       z, z2;
239     __m256d       PolyP, PolyQ;
240
241     iexppart128a  = _mm256_cvtpd_epi32(x);
242     intpart       = _mm256_round_pd(x, _MM_FROUND_TO_NEAREST_INT);
243
244     /* Add exponent bias */
245     iexppart128a   = _mm_add_epi32(iexppart128a, expbase);
246
247     /* We now want to shift the exponent 52 positions left, but to achieve this we need
248      * to separate the 128-bit register data into two registers (4x64-bit > 128bit)
249      * shift them, and then merge into a single __m256d.
250      * Elements 0/1 should end up in iexppart128a, and 2/3 in iexppart128b.
251      * It doesnt matter what we put in the 2nd/4th position, since that data will be
252      * shifted out and replaced with zeros.
253      */
254     iexppart128b   = _mm_shuffle_epi32(iexppart128a, _MM_SHUFFLE(3, 3, 2, 2));
255     iexppart128a   = _mm_shuffle_epi32(iexppart128a, _MM_SHUFFLE(1, 1, 0, 0));
256
257     iexppart128b   = _mm_slli_epi64(iexppart128b, 52);
258     iexppart128a   = _mm_slli_epi64(iexppart128a, 52);
259
260     iexppart  = _mm256_castsi128_si256(iexppart128a);
261     iexppart  = _mm256_insertf128_si256(iexppart, iexppart128b, 0x1);
262
263     valuemask = _mm256_cmp_pd(arglimit, gmx_mm256_abs_pd(x), _CMP_GE_OQ);
264     fexppart  = _mm256_and_pd(valuemask, _mm256_castsi256_pd(iexppart));
265
266     z         = _mm256_sub_pd(x, intpart);
267
268     z2        = _mm256_mul_pd(z, z);
269
270     PolyP     = _mm256_mul_pd(P2, z2);
271     PolyP     = _mm256_add_pd(PolyP, P1);
272     PolyQ     = _mm256_add_pd(z2, Q1);
273     PolyP     = _mm256_mul_pd(PolyP, z2);
274     PolyQ     = _mm256_mul_pd(PolyQ, z2);
275     PolyP     = _mm256_add_pd(PolyP, P0);
276     PolyQ     = _mm256_add_pd(PolyQ, Q0);
277     PolyP     = _mm256_mul_pd(PolyP, z);
278
279     z         = _mm256_mul_pd(PolyP, gmx_mm256_inv_pd(_mm256_sub_pd(PolyQ, PolyP)));
280     z         = _mm256_add_pd(one, _mm256_mul_pd(two, z));
281
282     z         = _mm256_mul_pd(z, fexppart);
283
284     return z;
285 }
286
287 /* 2^x, 128 bit */
288 static __m128d
289 gmx_mm_exp2_pd(__m128d x)
290 {
291     /* Lower bound: We do not allow numbers that would lead to an IEEE fp representation exponent smaller than -126. */
292     const __m128d arglimit = _mm_set1_pd(1022.0);
293     const __m128i expbase  = _mm_set1_epi32(1023);
294
295     const __m128d P2       = _mm_set1_pd(2.30933477057345225087e-2);
296     const __m128d P1       = _mm_set1_pd(2.02020656693165307700e1);
297     const __m128d P0       = _mm_set1_pd(1.51390680115615096133e3);
298     /* Q2 == 1.0 */
299     const __m128d Q1       = _mm_set1_pd(2.33184211722314911771e2);
300     const __m128d Q0       = _mm_set1_pd(4.36821166879210612817e3);
301     const __m128d one      = _mm_set1_pd(1.0);
302     const __m128d two      = _mm_set1_pd(2.0);
303
304     __m128d       valuemask;
305     __m128i       iexppart;
306     __m128d       fexppart;
307     __m128d       intpart;
308     __m128d       z, z2;
309     __m128d       PolyP, PolyQ;
310
311     iexppart  = _mm_cvtpd_epi32(x);
312     intpart   = _mm_round_pd(x, _MM_FROUND_TO_NEAREST_INT);
313
314     /* The two lowest elements of iexppart now contains 32-bit numbers with a correctly biased exponent.
315      * To be able to shift it into the exponent for a double precision number we first need to
316      * shuffle so that the lower half contains the first element, and the upper half the second.
317      * This should really be done as a zero-extension, but since the next instructions will shift
318      * the registers left by 52 bits it doesn't matter what we put there - it will be shifted out.
319      * (thus we just use element 2 from iexppart).
320      */
321     iexppart  = _mm_shuffle_epi32(iexppart, _MM_SHUFFLE(2, 1, 2, 0));
322
323     /* Do the shift operation on the 64-bit registers */
324     iexppart  = _mm_add_epi32(iexppart, expbase);
325     iexppart  = _mm_slli_epi64(iexppart, 52);
326
327     valuemask = _mm_cmpge_pd(arglimit, gmx_mm_abs_pd(x));
328     fexppart  = _mm_and_pd(valuemask, gmx_mm_castsi128_pd(iexppart));
329
330     z         = _mm_sub_pd(x, intpart);
331     z2        = _mm_mul_pd(z, z);
332
333     PolyP     = _mm_mul_pd(P2, z2);
334     PolyP     = _mm_add_pd(PolyP, P1);
335     PolyQ     = _mm_add_pd(z2, Q1);
336     PolyP     = _mm_mul_pd(PolyP, z2);
337     PolyQ     = _mm_mul_pd(PolyQ, z2);
338     PolyP     = _mm_add_pd(PolyP, P0);
339     PolyQ     = _mm_add_pd(PolyQ, Q0);
340     PolyP     = _mm_mul_pd(PolyP, z);
341
342     z         = _mm_mul_pd(PolyP, gmx_mm_inv_pd(_mm_sub_pd(PolyQ, PolyP)));
343     z         = _mm_add_pd(one, _mm_mul_pd(two, z));
344
345     z         = _mm_mul_pd(z, fexppart);
346
347     return z;
348 }
349
350
351 /* Exponential function, 256 bit. This could be calculated from 2^x as Exp(x)=2^(y),
352  * where y=log2(e)*x, but there will then be a small rounding error since we lose
353  * some precision due to the multiplication. This will then be magnified a lot by
354  * the exponential.
355  *
356  * Instead, we calculate the fractional part directly as a Padé approximation of
357  * Exp(z) on [-0.5,0.5]. We use extended precision arithmetics to calculate the fraction
358  * remaining after 2^y, which avoids the precision-loss.
359  */
360 static __m256d
361 gmx_mm256_exp_pd(__m256d exparg)
362 {
363     const __m256d argscale = _mm256_set1_pd(1.4426950408889634073599);
364     /* Lower bound: We do not allow numbers that would lead to an IEEE fp representation exponent smaller than -126. */
365     const __m256d arglimit = _mm256_set1_pd(1022.0);
366     const __m128i expbase  = _mm_set1_epi32(1023);
367
368     const __m256d invargscale0  = _mm256_set1_pd(6.93145751953125e-1);
369     const __m256d invargscale1  = _mm256_set1_pd(1.42860682030941723212e-6);
370
371     const __m256d P2       = _mm256_set1_pd(1.26177193074810590878e-4);
372     const __m256d P1       = _mm256_set1_pd(3.02994407707441961300e-2);
373     /* P0 == 1.0 */
374     const __m256d Q3       = _mm256_set1_pd(3.00198505138664455042E-6);
375     const __m256d Q2       = _mm256_set1_pd(2.52448340349684104192E-3);
376     const __m256d Q1       = _mm256_set1_pd(2.27265548208155028766E-1);
377     /* Q0 == 2.0 */
378     const __m256d one      = _mm256_set1_pd(1.0);
379     const __m256d two      = _mm256_set1_pd(2.0);
380
381     __m256d       valuemask;
382     __m256i       iexppart;
383     __m128i       iexppart128a, iexppart128b;
384     __m256d       fexppart;
385     __m256d       intpart;
386     __m256d       x, z, z2;
387     __m256d       PolyP, PolyQ;
388
389     x             = _mm256_mul_pd(exparg, argscale);
390
391     iexppart128a  = _mm256_cvtpd_epi32(x);
392     intpart       = _mm256_round_pd(x, _MM_FROUND_TO_NEAREST_INT);
393
394     /* Add exponent bias */
395     iexppart128a   = _mm_add_epi32(iexppart128a, expbase);
396
397     /* We now want to shift the exponent 52 positions left, but to achieve this we need
398      * to separate the 128-bit register data into two registers (4x64-bit > 128bit)
399      * shift them, and then merge into a single __m256d.
400      * Elements 0/1 should end up in iexppart128a, and 2/3 in iexppart128b.
401      * It doesnt matter what we put in the 2nd/4th position, since that data will be
402      * shifted out and replaced with zeros.
403      */
404     iexppart128b   = _mm_shuffle_epi32(iexppart128a, _MM_SHUFFLE(3, 3, 2, 2));
405     iexppart128a   = _mm_shuffle_epi32(iexppart128a, _MM_SHUFFLE(1, 1, 0, 0));
406
407     iexppart128b   = _mm_slli_epi64(iexppart128b, 52);
408     iexppart128a   = _mm_slli_epi64(iexppart128a, 52);
409
410     iexppart  = _mm256_castsi128_si256(iexppart128a);
411     iexppart  = _mm256_insertf128_si256(iexppart, iexppart128b, 0x1);
412
413     valuemask = _mm256_cmp_pd(arglimit, gmx_mm256_abs_pd(x), _CMP_GE_OQ);
414     fexppart  = _mm256_and_pd(valuemask, _mm256_castsi256_pd(iexppart));
415
416     z         = _mm256_sub_pd(exparg, _mm256_mul_pd(invargscale0, intpart));
417     z         = _mm256_sub_pd(z, _mm256_mul_pd(invargscale1, intpart));
418
419     z2        = _mm256_mul_pd(z, z);
420
421     PolyQ     = _mm256_mul_pd(Q3, z2);
422     PolyQ     = _mm256_add_pd(PolyQ, Q2);
423     PolyP     = _mm256_mul_pd(P2, z2);
424     PolyQ     = _mm256_mul_pd(PolyQ, z2);
425     PolyP     = _mm256_add_pd(PolyP, P1);
426     PolyQ     = _mm256_add_pd(PolyQ, Q1);
427     PolyP     = _mm256_mul_pd(PolyP, z2);
428     PolyQ     = _mm256_mul_pd(PolyQ, z2);
429     PolyP     = _mm256_add_pd(PolyP, one);
430     PolyQ     = _mm256_add_pd(PolyQ, two);
431
432     PolyP     = _mm256_mul_pd(PolyP, z);
433
434     z         = _mm256_mul_pd(PolyP, gmx_mm256_inv_pd(_mm256_sub_pd(PolyQ, PolyP)));
435     z         = _mm256_add_pd(one, _mm256_mul_pd(two, z));
436
437     z         = _mm256_mul_pd(z, fexppart);
438
439     return z;
440 }
441
442 /* exp(), 128 bit */
443 static __m128d
444 gmx_mm_exp_pd(__m128d exparg)
445 {
446     const __m128d argscale = _mm_set1_pd(1.4426950408889634073599);
447     /* Lower bound: We do not allow numbers that would lead to an IEEE fp representation exponent smaller than -126. */
448     const __m128d arglimit = _mm_set1_pd(1022.0);
449     const __m128i expbase  = _mm_set1_epi32(1023);
450
451     const __m128d invargscale0  = _mm_set1_pd(6.93145751953125e-1);
452     const __m128d invargscale1  = _mm_set1_pd(1.42860682030941723212e-6);
453
454     const __m128d P2       = _mm_set1_pd(1.26177193074810590878e-4);
455     const __m128d P1       = _mm_set1_pd(3.02994407707441961300e-2);
456     /* P0 == 1.0 */
457     const __m128d Q3       = _mm_set1_pd(3.00198505138664455042E-6);
458     const __m128d Q2       = _mm_set1_pd(2.52448340349684104192E-3);
459     const __m128d Q1       = _mm_set1_pd(2.27265548208155028766E-1);
460     /* Q0 == 2.0 */
461     const __m128d one      = _mm_set1_pd(1.0);
462     const __m128d two      = _mm_set1_pd(2.0);
463
464     __m128d       valuemask;
465     __m128i       iexppart;
466     __m128d       fexppart;
467     __m128d       intpart;
468     __m128d       x, z, z2;
469     __m128d       PolyP, PolyQ;
470
471     x             = _mm_mul_pd(exparg, argscale);
472
473     iexppart  = _mm_cvtpd_epi32(x);
474     intpart   = _mm_round_pd(x, _MM_FROUND_TO_NEAREST_INT);
475
476     /* The two lowest elements of iexppart now contains 32-bit numbers with a correctly biased exponent.
477      * To be able to shift it into the exponent for a double precision number we first need to
478      * shuffle so that the lower half contains the first element, and the upper half the second.
479      * This should really be done as a zero-extension, but since the next instructions will shift
480      * the registers left by 52 bits it doesn't matter what we put there - it will be shifted out.
481      * (thus we just use element 2 from iexppart).
482      */
483     iexppart  = _mm_shuffle_epi32(iexppart, _MM_SHUFFLE(2, 1, 2, 0));
484
485     /* Do the shift operation on the 64-bit registers */
486     iexppart  = _mm_add_epi32(iexppart, expbase);
487     iexppart  = _mm_slli_epi64(iexppart, 52);
488
489     valuemask = _mm_cmpge_pd(arglimit, gmx_mm_abs_pd(x));
490     fexppart  = _mm_and_pd(valuemask, gmx_mm_castsi128_pd(iexppart));
491
492     z         = _mm_sub_pd(exparg, _mm_mul_pd(invargscale0, intpart));
493     z         = _mm_sub_pd(z, _mm_mul_pd(invargscale1, intpart));
494
495     z2        = _mm_mul_pd(z, z);
496
497     PolyQ     = _mm_mul_pd(Q3, z2);
498     PolyQ     = _mm_add_pd(PolyQ, Q2);
499     PolyP     = _mm_mul_pd(P2, z2);
500     PolyQ     = _mm_mul_pd(PolyQ, z2);
501     PolyP     = _mm_add_pd(PolyP, P1);
502     PolyQ     = _mm_add_pd(PolyQ, Q1);
503     PolyP     = _mm_mul_pd(PolyP, z2);
504     PolyQ     = _mm_mul_pd(PolyQ, z2);
505     PolyP     = _mm_add_pd(PolyP, one);
506     PolyQ     = _mm_add_pd(PolyQ, two);
507
508     PolyP     = _mm_mul_pd(PolyP, z);
509
510     z         = _mm_mul_pd(PolyP, gmx_mm_inv_pd(_mm_sub_pd(PolyQ, PolyP)));
511     z         = _mm_add_pd(one, _mm_mul_pd(two, z));
512
513     z         = _mm_mul_pd(z, fexppart);
514
515     return z;
516 }
517
518
519 static __m256d
520 gmx_mm256_log_pd(__m256d x)
521 {
522     /* Same algorithm as cephes library */
523     const __m256d expmask    = _mm256_castsi256_pd( _mm256_set_epi32(0x7FF00000, 0x00000000, 0x7FF00000, 0x00000000,
524                                                                      0x7FF00000, 0x00000000, 0x7FF00000, 0x00000000) );
525
526     const __m128i expbase_m1 = _mm_set1_epi32(1023-1); /* We want non-IEEE format */
527
528     const __m256d half       = _mm256_set1_pd(0.5);
529     const __m256d one        = _mm256_set1_pd(1.0);
530     const __m256d two        = _mm256_set1_pd(2.0);
531     const __m256d invsq2     = _mm256_set1_pd(1.0/sqrt(2.0));
532
533     const __m256d corr1      = _mm256_set1_pd(-2.121944400546905827679e-4);
534     const __m256d corr2      = _mm256_set1_pd(0.693359375);
535
536     const __m256d P5         = _mm256_set1_pd(1.01875663804580931796e-4);
537     const __m256d P4         = _mm256_set1_pd(4.97494994976747001425e-1);
538     const __m256d P3         = _mm256_set1_pd(4.70579119878881725854e0);
539     const __m256d P2         = _mm256_set1_pd(1.44989225341610930846e1);
540     const __m256d P1         = _mm256_set1_pd(1.79368678507819816313e1);
541     const __m256d P0         = _mm256_set1_pd(7.70838733755885391666e0);
542
543     const __m256d Q4         = _mm256_set1_pd(1.12873587189167450590e1);
544     const __m256d Q3         = _mm256_set1_pd(4.52279145837532221105e1);
545     const __m256d Q2         = _mm256_set1_pd(8.29875266912776603211e1);
546     const __m256d Q1         = _mm256_set1_pd(7.11544750618563894466e1);
547     const __m256d Q0         = _mm256_set1_pd(2.31251620126765340583e1);
548
549     const __m256d R2         = _mm256_set1_pd(-7.89580278884799154124e-1);
550     const __m256d R1         = _mm256_set1_pd(1.63866645699558079767e1);
551     const __m256d R0         = _mm256_set1_pd(-6.41409952958715622951e1);
552
553     const __m256d S2         = _mm256_set1_pd(-3.56722798256324312549E1);
554     const __m256d S1         = _mm256_set1_pd(3.12093766372244180303E2);
555     const __m256d S0         = _mm256_set1_pd(-7.69691943550460008604E2);
556
557     __m256d       fexp;
558     __m256i       iexp;
559     __m128i       iexp128a, iexp128b;
560
561     __m256d       mask1, mask2;
562     __m256d       corr, t1, t2, q;
563     __m256d       zA, yA, xA, zB, yB, xB, z;
564     __m256d       polyR, polyS;
565     __m256d       polyP1, polyP2, polyQ1, polyQ2;
566
567     /* Separate x into exponent and mantissa, with a mantissa in the range [0.5..1[ (not IEEE754 standard!) */
568     fexp     = _mm256_and_pd(x, expmask);
569
570     iexp     = _mm256_castpd_si256(fexp);
571     iexp128b = _mm256_extractf128_si256(iexp, 0x1);
572     iexp128a = _mm256_castsi256_si128(iexp);
573
574     iexp128a  = _mm_srli_epi64(iexp128a, 52);
575     iexp128b  = _mm_srli_epi64(iexp128b, 52);
576     /* Merge into a single register */
577     iexp128a  = _mm_shuffle_epi32(iexp128a, _MM_SHUFFLE(1, 1, 2, 0));
578     iexp128b  = _mm_shuffle_epi32(iexp128b, _MM_SHUFFLE(2, 0, 1, 1));
579     iexp128a  = _mm_or_si128(iexp128a, iexp128b);
580     iexp128a  = _mm_sub_epi32(iexp128a, expbase_m1);
581
582     fexp      = _mm256_cvtepi32_pd(iexp128a);
583
584     x         = _mm256_andnot_pd(expmask, x); /* Get mantissa */
585     x         = _mm256_or_pd(x, one);
586     x         = _mm256_mul_pd(x, half);
587
588     mask1     = _mm256_cmp_pd(gmx_mm256_abs_pd(fexp), two, _CMP_GT_OQ);
589     mask2     = _mm256_cmp_pd(x, invsq2, _CMP_LT_OQ);
590
591     fexp      = _mm256_sub_pd(fexp, _mm256_and_pd(mask2, one));
592
593     /* If mask1 is set ('A') */
594     zA     = _mm256_sub_pd(x, half);
595     t1     = _mm256_blendv_pd( zA, x, mask2 );
596     zA     = _mm256_sub_pd(t1, half);
597     t2     = _mm256_blendv_pd( x, zA, mask2 );
598     yA     = _mm256_mul_pd(half, _mm256_add_pd(t2, one));
599
600     xA     = _mm256_mul_pd(zA, gmx_mm256_inv_pd(yA));
601     zA     = _mm256_mul_pd(xA, xA);
602
603     /* EVALUATE POLY */
604     polyR  = _mm256_mul_pd(R2, zA);
605     polyR  = _mm256_add_pd(polyR, R1);
606     polyR  = _mm256_mul_pd(polyR, zA);
607     polyR  = _mm256_add_pd(polyR, R0);
608
609     polyS  = _mm256_add_pd(zA, S2);
610     polyS  = _mm256_mul_pd(polyS, zA);
611     polyS  = _mm256_add_pd(polyS, S1);
612     polyS  = _mm256_mul_pd(polyS, zA);
613     polyS  = _mm256_add_pd(polyS, S0);
614
615     q      = _mm256_mul_pd(polyR, gmx_mm256_inv_pd(polyS));
616     zA     = _mm256_mul_pd(_mm256_mul_pd(xA, zA), q);
617
618     zA     = _mm256_add_pd(zA, _mm256_mul_pd(corr1, fexp));
619     zA     = _mm256_add_pd(zA, xA);
620     zA     = _mm256_add_pd(zA, _mm256_mul_pd(corr2, fexp));
621
622     /* If mask1 is not set ('B') */
623     corr   = _mm256_and_pd(mask2, x);
624     xB     = _mm256_add_pd(x, corr);
625     xB     = _mm256_sub_pd(xB, one);
626     zB     = _mm256_mul_pd(xB, xB);
627
628     polyP1 = _mm256_mul_pd(P5, zB);
629     polyP2 = _mm256_mul_pd(P4, zB);
630     polyP1 = _mm256_add_pd(polyP1, P3);
631     polyP2 = _mm256_add_pd(polyP2, P2);
632     polyP1 = _mm256_mul_pd(polyP1, zB);
633     polyP2 = _mm256_mul_pd(polyP2, zB);
634     polyP1 = _mm256_add_pd(polyP1, P1);
635     polyP2 = _mm256_add_pd(polyP2, P0);
636     polyP1 = _mm256_mul_pd(polyP1, xB);
637     polyP1 = _mm256_add_pd(polyP1, polyP2);
638
639     polyQ2 = _mm256_mul_pd(Q4, zB);
640     polyQ1 = _mm256_add_pd(zB, Q3);
641     polyQ2 = _mm256_add_pd(polyQ2, Q2);
642     polyQ1 = _mm256_mul_pd(polyQ1, zB);
643     polyQ2 = _mm256_mul_pd(polyQ2, zB);
644     polyQ1 = _mm256_add_pd(polyQ1, Q1);
645     polyQ2 = _mm256_add_pd(polyQ2, Q0);
646     polyQ1 = _mm256_mul_pd(polyQ1, xB);
647     polyQ1 = _mm256_add_pd(polyQ1, polyQ2);
648
649     fexp   = _mm256_and_pd(fexp, _mm256_cmp_pd(fexp, _mm256_setzero_pd(), _CMP_NEQ_OQ));
650
651     q      = _mm256_mul_pd(polyP1, gmx_mm256_inv_pd(polyQ1));
652     yB     = _mm256_mul_pd(_mm256_mul_pd(xB, zB), q);
653
654     yB     = _mm256_add_pd(yB, _mm256_mul_pd(corr1, fexp));
655     yB     = _mm256_sub_pd(yB, _mm256_mul_pd(half, zB));
656     zB     = _mm256_add_pd(xB, yB);
657     zB     = _mm256_add_pd(zB, _mm256_mul_pd(corr2, fexp));
658
659     z      = _mm256_blendv_pd( zB, zA, mask1 );
660
661     return z;
662 }
663
664 static __m128d
665 gmx_mm_log_pd(__m128d x)
666 {
667     /* Same algorithm as cephes library */
668     const __m128d expmask    = gmx_mm_castsi128_pd( _mm_set_epi32(0x7FF00000, 0x00000000, 0x7FF00000, 0x00000000) );
669
670     const __m128i expbase_m1 = _mm_set1_epi32(1023-1); /* We want non-IEEE format */
671
672     const __m128d half       = _mm_set1_pd(0.5);
673     const __m128d one        = _mm_set1_pd(1.0);
674     const __m128d two        = _mm_set1_pd(2.0);
675     const __m128d invsq2     = _mm_set1_pd(1.0/sqrt(2.0));
676
677     const __m128d corr1      = _mm_set1_pd(-2.121944400546905827679e-4);
678     const __m128d corr2      = _mm_set1_pd(0.693359375);
679
680     const __m128d P5         = _mm_set1_pd(1.01875663804580931796e-4);
681     const __m128d P4         = _mm_set1_pd(4.97494994976747001425e-1);
682     const __m128d P3         = _mm_set1_pd(4.70579119878881725854e0);
683     const __m128d P2         = _mm_set1_pd(1.44989225341610930846e1);
684     const __m128d P1         = _mm_set1_pd(1.79368678507819816313e1);
685     const __m128d P0         = _mm_set1_pd(7.70838733755885391666e0);
686
687     const __m128d Q4         = _mm_set1_pd(1.12873587189167450590e1);
688     const __m128d Q3         = _mm_set1_pd(4.52279145837532221105e1);
689     const __m128d Q2         = _mm_set1_pd(8.29875266912776603211e1);
690     const __m128d Q1         = _mm_set1_pd(7.11544750618563894466e1);
691     const __m128d Q0         = _mm_set1_pd(2.31251620126765340583e1);
692
693     const __m128d R2         = _mm_set1_pd(-7.89580278884799154124e-1);
694     const __m128d R1         = _mm_set1_pd(1.63866645699558079767e1);
695     const __m128d R0         = _mm_set1_pd(-6.41409952958715622951e1);
696
697     const __m128d S2         = _mm_set1_pd(-3.56722798256324312549E1);
698     const __m128d S1         = _mm_set1_pd(3.12093766372244180303E2);
699     const __m128d S0         = _mm_set1_pd(-7.69691943550460008604E2);
700
701     __m128d       fexp;
702     __m128i       iexp;
703
704     __m128d       mask1, mask2;
705     __m128d       corr, t1, t2, q;
706     __m128d       zA, yA, xA, zB, yB, xB, z;
707     __m128d       polyR, polyS;
708     __m128d       polyP1, polyP2, polyQ1, polyQ2;
709
710     /* Separate x into exponent and mantissa, with a mantissa in the range [0.5..1[ (not IEEE754 standard!) */
711     fexp   = _mm_and_pd(x, expmask);
712     iexp   = gmx_mm_castpd_si128(fexp);
713     iexp   = _mm_srli_epi64(iexp, 52);
714     iexp   = _mm_sub_epi32(iexp, expbase_m1);
715     iexp   = _mm_shuffle_epi32(iexp, _MM_SHUFFLE(1, 1, 2, 0) );
716     fexp   = _mm_cvtepi32_pd(iexp);
717
718     x      = _mm_andnot_pd(expmask, x);
719     x      = _mm_or_pd(x, one);
720     x      = _mm_mul_pd(x, half);
721
722     mask1     = _mm_cmpgt_pd(gmx_mm_abs_pd(fexp), two);
723     mask2     = _mm_cmplt_pd(x, invsq2);
724
725     fexp   = _mm_sub_pd(fexp, _mm_and_pd(mask2, one));
726
727     /* If mask1 is set ('A') */
728     zA     = _mm_sub_pd(x, half);
729     t1     = _mm_blendv_pd( zA, x, mask2 );
730     zA     = _mm_sub_pd(t1, half);
731     t2     = _mm_blendv_pd( x, zA, mask2 );
732     yA     = _mm_mul_pd(half, _mm_add_pd(t2, one));
733
734     xA     = _mm_mul_pd(zA, gmx_mm_inv_pd(yA));
735     zA     = _mm_mul_pd(xA, xA);
736
737     /* EVALUATE POLY */
738     polyR  = _mm_mul_pd(R2, zA);
739     polyR  = _mm_add_pd(polyR, R1);
740     polyR  = _mm_mul_pd(polyR, zA);
741     polyR  = _mm_add_pd(polyR, R0);
742
743     polyS  = _mm_add_pd(zA, S2);
744     polyS  = _mm_mul_pd(polyS, zA);
745     polyS  = _mm_add_pd(polyS, S1);
746     polyS  = _mm_mul_pd(polyS, zA);
747     polyS  = _mm_add_pd(polyS, S0);
748
749     q      = _mm_mul_pd(polyR, gmx_mm_inv_pd(polyS));
750     zA     = _mm_mul_pd(_mm_mul_pd(xA, zA), q);
751
752     zA     = _mm_add_pd(zA, _mm_mul_pd(corr1, fexp));
753     zA     = _mm_add_pd(zA, xA);
754     zA     = _mm_add_pd(zA, _mm_mul_pd(corr2, fexp));
755
756     /* If mask1 is not set ('B') */
757     corr   = _mm_and_pd(mask2, x);
758     xB     = _mm_add_pd(x, corr);
759     xB     = _mm_sub_pd(xB, one);
760     zB     = _mm_mul_pd(xB, xB);
761
762     polyP1 = _mm_mul_pd(P5, zB);
763     polyP2 = _mm_mul_pd(P4, zB);
764     polyP1 = _mm_add_pd(polyP1, P3);
765     polyP2 = _mm_add_pd(polyP2, P2);
766     polyP1 = _mm_mul_pd(polyP1, zB);
767     polyP2 = _mm_mul_pd(polyP2, zB);
768     polyP1 = _mm_add_pd(polyP1, P1);
769     polyP2 = _mm_add_pd(polyP2, P0);
770     polyP1 = _mm_mul_pd(polyP1, xB);
771     polyP1 = _mm_add_pd(polyP1, polyP2);
772
773     polyQ2 = _mm_mul_pd(Q4, zB);
774     polyQ1 = _mm_add_pd(zB, Q3);
775     polyQ2 = _mm_add_pd(polyQ2, Q2);
776     polyQ1 = _mm_mul_pd(polyQ1, zB);
777     polyQ2 = _mm_mul_pd(polyQ2, zB);
778     polyQ1 = _mm_add_pd(polyQ1, Q1);
779     polyQ2 = _mm_add_pd(polyQ2, Q0);
780     polyQ1 = _mm_mul_pd(polyQ1, xB);
781     polyQ1 = _mm_add_pd(polyQ1, polyQ2);
782
783     fexp   = _mm_and_pd(fexp, _mm_cmpneq_pd(fexp, _mm_setzero_pd()));
784
785     q      = _mm_mul_pd(polyP1, gmx_mm_inv_pd(polyQ1));
786     yB     = _mm_mul_pd(_mm_mul_pd(xB, zB), q);
787
788     yB     = _mm_add_pd(yB, _mm_mul_pd(corr1, fexp));
789     yB     = _mm_sub_pd(yB, _mm_mul_pd(half, zB));
790     zB     = _mm_add_pd(xB, yB);
791     zB     = _mm_add_pd(zB, _mm_mul_pd(corr2, fexp));
792
793     z      = _mm_blendv_pd( zB, zA, mask1 );
794
795     return z;
796 }
797
798
799 static __m256d
800 gmx_mm256_erf_pd(__m256d x)
801 {
802     /* Coefficients for minimax approximation of erf(x)=x*(CAoffset + P(x^2)/Q(x^2)) in range [-0.75,0.75] */
803     const __m256d CAP4      = _mm256_set1_pd(-0.431780540597889301512e-4);
804     const __m256d CAP3      = _mm256_set1_pd(-0.00578562306260059236059);
805     const __m256d CAP2      = _mm256_set1_pd(-0.028593586920219752446);
806     const __m256d CAP1      = _mm256_set1_pd(-0.315924962948621698209);
807     const __m256d CAP0      = _mm256_set1_pd(0.14952975608477029151);
808
809     const __m256d CAQ5      = _mm256_set1_pd(-0.374089300177174709737e-5);
810     const __m256d CAQ4      = _mm256_set1_pd(0.00015126584532155383535);
811     const __m256d CAQ3      = _mm256_set1_pd(0.00536692680669480725423);
812     const __m256d CAQ2      = _mm256_set1_pd(0.0668686825594046122636);
813     const __m256d CAQ1      = _mm256_set1_pd(0.402604990869284362773);
814     /* CAQ0 == 1.0 */
815     const __m256d CAoffset  = _mm256_set1_pd(0.9788494110107421875);
816
817     /* Coefficients for minimax approximation of erfc(x)=exp(-x^2)*x*(P(x-1)/Q(x-1)) in range [1.0,4.5] */
818     const __m256d CBP6      = _mm256_set1_pd(2.49650423685462752497647637088e-10);
819     const __m256d CBP5      = _mm256_set1_pd(0.00119770193298159629350136085658);
820     const __m256d CBP4      = _mm256_set1_pd(0.0164944422378370965881008942733);
821     const __m256d CBP3      = _mm256_set1_pd(0.0984581468691775932063932439252);
822     const __m256d CBP2      = _mm256_set1_pd(0.317364595806937763843589437418);
823     const __m256d CBP1      = _mm256_set1_pd(0.554167062641455850932670067075);
824     const __m256d CBP0      = _mm256_set1_pd(0.427583576155807163756925301060);
825     const __m256d CBQ7      = _mm256_set1_pd(0.00212288829699830145976198384930);
826     const __m256d CBQ6      = _mm256_set1_pd(0.0334810979522685300554606393425);
827     const __m256d CBQ5      = _mm256_set1_pd(0.2361713785181450957579508850717);
828     const __m256d CBQ4      = _mm256_set1_pd(0.955364736493055670530981883072);
829     const __m256d CBQ3      = _mm256_set1_pd(2.36815675631420037315349279199);
830     const __m256d CBQ2      = _mm256_set1_pd(3.55261649184083035537184223542);
831     const __m256d CBQ1      = _mm256_set1_pd(2.93501136050160872574376997993);
832     /* CBQ0 == 1.0 */
833
834     /* Coefficients for minimax approximation of erfc(x)=exp(-x^2)/x*(P(1/x)/Q(1/x)) in range [4.5,inf] */
835     const __m256d CCP6      = _mm256_set1_pd(-2.8175401114513378771);
836     const __m256d CCP5      = _mm256_set1_pd(-3.22729451764143718517);
837     const __m256d CCP4      = _mm256_set1_pd(-2.5518551727311523996);
838     const __m256d CCP3      = _mm256_set1_pd(-0.687717681153649930619);
839     const __m256d CCP2      = _mm256_set1_pd(-0.212652252872804219852);
840     const __m256d CCP1      = _mm256_set1_pd(0.0175389834052493308818);
841     const __m256d CCP0      = _mm256_set1_pd(0.00628057170626964891937);
842
843     const __m256d CCQ6      = _mm256_set1_pd(5.48409182238641741584);
844     const __m256d CCQ5      = _mm256_set1_pd(13.5064170191802889145);
845     const __m256d CCQ4      = _mm256_set1_pd(22.9367376522880577224);
846     const __m256d CCQ3      = _mm256_set1_pd(15.930646027911794143);
847     const __m256d CCQ2      = _mm256_set1_pd(11.0567237927800161565);
848     const __m256d CCQ1      = _mm256_set1_pd(2.79257750980575282228);
849     /* CCQ0 == 1.0 */
850     const __m256d CCoffset  = _mm256_set1_pd(0.5579090118408203125);
851
852     const __m256d one       = _mm256_set1_pd(1.0);
853     const __m256d two       = _mm256_set1_pd(2.0);
854
855     const __m256d signbit   = _mm256_castsi256_pd( _mm256_set_epi32(0x80000000, 0x00000000, 0x80000000, 0x00000000,
856                                                                     0x80000000, 0x00000000, 0x80000000, 0x00000000) );
857
858     __m256d xabs, x2, x4, t, t2, w, w2;
859     __m256d PolyAP0, PolyAP1, PolyAQ0, PolyAQ1;
860     __m256d PolyBP0, PolyBP1, PolyBQ0, PolyBQ1;
861     __m256d PolyCP0, PolyCP1, PolyCQ0, PolyCQ1;
862     __m256d res_erf, res_erfcB, res_erfcC, res_erfc, res;
863     __m256d mask, expmx2;
864
865     /* Calculate erf() */
866     xabs     = gmx_mm256_abs_pd(x);
867     x2       = _mm256_mul_pd(x, x);
868     x4       = _mm256_mul_pd(x2, x2);
869
870     PolyAP0  = _mm256_mul_pd(CAP4, x4);
871     PolyAP1  = _mm256_mul_pd(CAP3, x4);
872     PolyAP0  = _mm256_add_pd(PolyAP0, CAP2);
873     PolyAP1  = _mm256_add_pd(PolyAP1, CAP1);
874     PolyAP0  = _mm256_mul_pd(PolyAP0, x4);
875     PolyAP1  = _mm256_mul_pd(PolyAP1, x2);
876     PolyAP0  = _mm256_add_pd(PolyAP0, CAP0);
877     PolyAP0  = _mm256_add_pd(PolyAP0, PolyAP1);
878
879     PolyAQ1  = _mm256_mul_pd(CAQ5, x4);
880     PolyAQ0  = _mm256_mul_pd(CAQ4, x4);
881     PolyAQ1  = _mm256_add_pd(PolyAQ1, CAQ3);
882     PolyAQ0  = _mm256_add_pd(PolyAQ0, CAQ2);
883     PolyAQ1  = _mm256_mul_pd(PolyAQ1, x4);
884     PolyAQ0  = _mm256_mul_pd(PolyAQ0, x4);
885     PolyAQ1  = _mm256_add_pd(PolyAQ1, CAQ1);
886     PolyAQ0  = _mm256_add_pd(PolyAQ0, one);
887     PolyAQ1  = _mm256_mul_pd(PolyAQ1, x2);
888     PolyAQ0  = _mm256_add_pd(PolyAQ0, PolyAQ1);
889
890     res_erf  = _mm256_mul_pd(PolyAP0, gmx_mm256_inv_pd(PolyAQ0));
891     res_erf  = _mm256_add_pd(CAoffset, res_erf);
892     res_erf  = _mm256_mul_pd(x, res_erf);
893
894     /* Calculate erfc() in range [1,4.5] */
895     t       = _mm256_sub_pd(xabs, one);
896     t2      = _mm256_mul_pd(t, t);
897
898     PolyBP0  = _mm256_mul_pd(CBP6, t2);
899     PolyBP1  = _mm256_mul_pd(CBP5, t2);
900     PolyBP0  = _mm256_add_pd(PolyBP0, CBP4);
901     PolyBP1  = _mm256_add_pd(PolyBP1, CBP3);
902     PolyBP0  = _mm256_mul_pd(PolyBP0, t2);
903     PolyBP1  = _mm256_mul_pd(PolyBP1, t2);
904     PolyBP0  = _mm256_add_pd(PolyBP0, CBP2);
905     PolyBP1  = _mm256_add_pd(PolyBP1, CBP1);
906     PolyBP0  = _mm256_mul_pd(PolyBP0, t2);
907     PolyBP1  = _mm256_mul_pd(PolyBP1, t);
908     PolyBP0  = _mm256_add_pd(PolyBP0, CBP0);
909     PolyBP0  = _mm256_add_pd(PolyBP0, PolyBP1);
910
911     PolyBQ1 = _mm256_mul_pd(CBQ7, t2);
912     PolyBQ0 = _mm256_mul_pd(CBQ6, t2);
913     PolyBQ1 = _mm256_add_pd(PolyBQ1, CBQ5);
914     PolyBQ0 = _mm256_add_pd(PolyBQ0, CBQ4);
915     PolyBQ1 = _mm256_mul_pd(PolyBQ1, t2);
916     PolyBQ0 = _mm256_mul_pd(PolyBQ0, t2);
917     PolyBQ1 = _mm256_add_pd(PolyBQ1, CBQ3);
918     PolyBQ0 = _mm256_add_pd(PolyBQ0, CBQ2);
919     PolyBQ1 = _mm256_mul_pd(PolyBQ1, t2);
920     PolyBQ0 = _mm256_mul_pd(PolyBQ0, t2);
921     PolyBQ1 = _mm256_add_pd(PolyBQ1, CBQ1);
922     PolyBQ0 = _mm256_add_pd(PolyBQ0, one);
923     PolyBQ1 = _mm256_mul_pd(PolyBQ1, t);
924     PolyBQ0 = _mm256_add_pd(PolyBQ0, PolyBQ1);
925
926     res_erfcB = _mm256_mul_pd(PolyBP0, gmx_mm256_inv_pd(PolyBQ0));
927
928     res_erfcB = _mm256_mul_pd(res_erfcB, xabs);
929
930     /* Calculate erfc() in range [4.5,inf] */
931     w       = gmx_mm256_inv_pd(xabs);
932     w2      = _mm256_mul_pd(w, w);
933
934     PolyCP0  = _mm256_mul_pd(CCP6, w2);
935     PolyCP1  = _mm256_mul_pd(CCP5, w2);
936     PolyCP0  = _mm256_add_pd(PolyCP0, CCP4);
937     PolyCP1  = _mm256_add_pd(PolyCP1, CCP3);
938     PolyCP0  = _mm256_mul_pd(PolyCP0, w2);
939     PolyCP1  = _mm256_mul_pd(PolyCP1, w2);
940     PolyCP0  = _mm256_add_pd(PolyCP0, CCP2);
941     PolyCP1  = _mm256_add_pd(PolyCP1, CCP1);
942     PolyCP0  = _mm256_mul_pd(PolyCP0, w2);
943     PolyCP1  = _mm256_mul_pd(PolyCP1, w);
944     PolyCP0  = _mm256_add_pd(PolyCP0, CCP0);
945     PolyCP0  = _mm256_add_pd(PolyCP0, PolyCP1);
946
947     PolyCQ0  = _mm256_mul_pd(CCQ6, w2);
948     PolyCQ1  = _mm256_mul_pd(CCQ5, w2);
949     PolyCQ0  = _mm256_add_pd(PolyCQ0, CCQ4);
950     PolyCQ1  = _mm256_add_pd(PolyCQ1, CCQ3);
951     PolyCQ0  = _mm256_mul_pd(PolyCQ0, w2);
952     PolyCQ1  = _mm256_mul_pd(PolyCQ1, w2);
953     PolyCQ0  = _mm256_add_pd(PolyCQ0, CCQ2);
954     PolyCQ1  = _mm256_add_pd(PolyCQ1, CCQ1);
955     PolyCQ0  = _mm256_mul_pd(PolyCQ0, w2);
956     PolyCQ1  = _mm256_mul_pd(PolyCQ1, w);
957     PolyCQ0  = _mm256_add_pd(PolyCQ0, one);
958     PolyCQ0  = _mm256_add_pd(PolyCQ0, PolyCQ1);
959
960     expmx2   = gmx_mm256_exp_pd( _mm256_or_pd(signbit, x2) );
961
962     res_erfcC = _mm256_mul_pd(PolyCP0, gmx_mm256_inv_pd(PolyCQ0));
963     res_erfcC = _mm256_add_pd(res_erfcC, CCoffset);
964     res_erfcC = _mm256_mul_pd(res_erfcC, w);
965
966     mask     = _mm256_cmp_pd(xabs, _mm256_set1_pd(4.5), _CMP_GT_OQ);
967     res_erfc = _mm256_blendv_pd(res_erfcB, res_erfcC, mask);
968
969     res_erfc = _mm256_mul_pd(res_erfc, expmx2);
970
971     /* erfc(x<0) = 2-erfc(|x|) */
972     mask     = _mm256_cmp_pd(x, _mm256_setzero_pd(), _CMP_LT_OQ);
973     res_erfc = _mm256_blendv_pd(res_erfc, _mm256_sub_pd(two, res_erfc), mask);
974
975     /* Select erf() or erfc() */
976     mask = _mm256_cmp_pd(xabs, one, _CMP_LT_OQ);
977     res  = _mm256_blendv_pd(_mm256_sub_pd(one, res_erfc), res_erf, mask);
978
979     return res;
980 }
981
982 static __m128d
983 gmx_mm_erf_pd(__m128d x)
984 {
985     /* Coefficients for minimax approximation of erf(x)=x*(CAoffset + P(x^2)/Q(x^2)) in range [-0.75,0.75] */
986     const __m128d CAP4      = _mm_set1_pd(-0.431780540597889301512e-4);
987     const __m128d CAP3      = _mm_set1_pd(-0.00578562306260059236059);
988     const __m128d CAP2      = _mm_set1_pd(-0.028593586920219752446);
989     const __m128d CAP1      = _mm_set1_pd(-0.315924962948621698209);
990     const __m128d CAP0      = _mm_set1_pd(0.14952975608477029151);
991
992     const __m128d CAQ5      = _mm_set1_pd(-0.374089300177174709737e-5);
993     const __m128d CAQ4      = _mm_set1_pd(0.00015126584532155383535);
994     const __m128d CAQ3      = _mm_set1_pd(0.00536692680669480725423);
995     const __m128d CAQ2      = _mm_set1_pd(0.0668686825594046122636);
996     const __m128d CAQ1      = _mm_set1_pd(0.402604990869284362773);
997     /* CAQ0 == 1.0 */
998     const __m128d CAoffset  = _mm_set1_pd(0.9788494110107421875);
999
1000     /* Coefficients for minimax approximation of erfc(x)=exp(-x^2)*x*(P(x-1)/Q(x-1)) in range [1.0,4.5] */
1001     const __m128d CBP6      = _mm_set1_pd(2.49650423685462752497647637088e-10);
1002     const __m128d CBP5      = _mm_set1_pd(0.00119770193298159629350136085658);
1003     const __m128d CBP4      = _mm_set1_pd(0.0164944422378370965881008942733);
1004     const __m128d CBP3      = _mm_set1_pd(0.0984581468691775932063932439252);
1005     const __m128d CBP2      = _mm_set1_pd(0.317364595806937763843589437418);
1006     const __m128d CBP1      = _mm_set1_pd(0.554167062641455850932670067075);
1007     const __m128d CBP0      = _mm_set1_pd(0.427583576155807163756925301060);
1008     const __m128d CBQ7      = _mm_set1_pd(0.00212288829699830145976198384930);
1009     const __m128d CBQ6      = _mm_set1_pd(0.0334810979522685300554606393425);
1010     const __m128d CBQ5      = _mm_set1_pd(0.2361713785181450957579508850717);
1011     const __m128d CBQ4      = _mm_set1_pd(0.955364736493055670530981883072);
1012     const __m128d CBQ3      = _mm_set1_pd(2.36815675631420037315349279199);
1013     const __m128d CBQ2      = _mm_set1_pd(3.55261649184083035537184223542);
1014     const __m128d CBQ1      = _mm_set1_pd(2.93501136050160872574376997993);
1015     /* CBQ0 == 1.0 */
1016
1017     /* Coefficients for minimax approximation of erfc(x)=exp(-x^2)/x*(P(1/x)/Q(1/x)) in range [4.5,inf] */
1018     const __m128d CCP6      = _mm_set1_pd(-2.8175401114513378771);
1019     const __m128d CCP5      = _mm_set1_pd(-3.22729451764143718517);
1020     const __m128d CCP4      = _mm_set1_pd(-2.5518551727311523996);
1021     const __m128d CCP3      = _mm_set1_pd(-0.687717681153649930619);
1022     const __m128d CCP2      = _mm_set1_pd(-0.212652252872804219852);
1023     const __m128d CCP1      = _mm_set1_pd(0.0175389834052493308818);
1024     const __m128d CCP0      = _mm_set1_pd(0.00628057170626964891937);
1025
1026     const __m128d CCQ6      = _mm_set1_pd(5.48409182238641741584);
1027     const __m128d CCQ5      = _mm_set1_pd(13.5064170191802889145);
1028     const __m128d CCQ4      = _mm_set1_pd(22.9367376522880577224);
1029     const __m128d CCQ3      = _mm_set1_pd(15.930646027911794143);
1030     const __m128d CCQ2      = _mm_set1_pd(11.0567237927800161565);
1031     const __m128d CCQ1      = _mm_set1_pd(2.79257750980575282228);
1032     /* CCQ0 == 1.0 */
1033     const __m128d CCoffset  = _mm_set1_pd(0.5579090118408203125);
1034
1035     const __m128d one       = _mm_set1_pd(1.0);
1036     const __m128d two       = _mm_set1_pd(2.0);
1037
1038     const __m128d signbit   = gmx_mm_castsi128_pd( _mm_set_epi32(0x80000000, 0x00000000, 0x80000000, 0x00000000) );
1039
1040     __m128d       xabs, x2, x4, t, t2, w, w2;
1041     __m128d       PolyAP0, PolyAP1, PolyAQ0, PolyAQ1;
1042     __m128d       PolyBP0, PolyBP1, PolyBQ0, PolyBQ1;
1043     __m128d       PolyCP0, PolyCP1, PolyCQ0, PolyCQ1;
1044     __m128d       res_erf, res_erfcB, res_erfcC, res_erfc, res;
1045     __m128d       mask, expmx2;
1046
1047     /* Calculate erf() */
1048     xabs     = gmx_mm_abs_pd(x);
1049     x2       = _mm_mul_pd(x, x);
1050     x4       = _mm_mul_pd(x2, x2);
1051
1052     PolyAP0  = _mm_mul_pd(CAP4, x4);
1053     PolyAP1  = _mm_mul_pd(CAP3, x4);
1054     PolyAP0  = _mm_add_pd(PolyAP0, CAP2);
1055     PolyAP1  = _mm_add_pd(PolyAP1, CAP1);
1056     PolyAP0  = _mm_mul_pd(PolyAP0, x4);
1057     PolyAP1  = _mm_mul_pd(PolyAP1, x2);
1058     PolyAP0  = _mm_add_pd(PolyAP0, CAP0);
1059     PolyAP0  = _mm_add_pd(PolyAP0, PolyAP1);
1060
1061     PolyAQ1  = _mm_mul_pd(CAQ5, x4);
1062     PolyAQ0  = _mm_mul_pd(CAQ4, x4);
1063     PolyAQ1  = _mm_add_pd(PolyAQ1, CAQ3);
1064     PolyAQ0  = _mm_add_pd(PolyAQ0, CAQ2);
1065     PolyAQ1  = _mm_mul_pd(PolyAQ1, x4);
1066     PolyAQ0  = _mm_mul_pd(PolyAQ0, x4);
1067     PolyAQ1  = _mm_add_pd(PolyAQ1, CAQ1);
1068     PolyAQ0  = _mm_add_pd(PolyAQ0, one);
1069     PolyAQ1  = _mm_mul_pd(PolyAQ1, x2);
1070     PolyAQ0  = _mm_add_pd(PolyAQ0, PolyAQ1);
1071
1072     res_erf  = _mm_mul_pd(PolyAP0, gmx_mm_inv_pd(PolyAQ0));
1073     res_erf  = _mm_add_pd(CAoffset, res_erf);
1074     res_erf  = _mm_mul_pd(x, res_erf);
1075
1076     /* Calculate erfc() in range [1,4.5] */
1077     t       = _mm_sub_pd(xabs, one);
1078     t2      = _mm_mul_pd(t, t);
1079
1080     PolyBP0  = _mm_mul_pd(CBP6, t2);
1081     PolyBP1  = _mm_mul_pd(CBP5, t2);
1082     PolyBP0  = _mm_add_pd(PolyBP0, CBP4);
1083     PolyBP1  = _mm_add_pd(PolyBP1, CBP3);
1084     PolyBP0  = _mm_mul_pd(PolyBP0, t2);
1085     PolyBP1  = _mm_mul_pd(PolyBP1, t2);
1086     PolyBP0  = _mm_add_pd(PolyBP0, CBP2);
1087     PolyBP1  = _mm_add_pd(PolyBP1, CBP1);
1088     PolyBP0  = _mm_mul_pd(PolyBP0, t2);
1089     PolyBP1  = _mm_mul_pd(PolyBP1, t);
1090     PolyBP0  = _mm_add_pd(PolyBP0, CBP0);
1091     PolyBP0  = _mm_add_pd(PolyBP0, PolyBP1);
1092
1093     PolyBQ1 = _mm_mul_pd(CBQ7, t2);
1094     PolyBQ0 = _mm_mul_pd(CBQ6, t2);
1095     PolyBQ1 = _mm_add_pd(PolyBQ1, CBQ5);
1096     PolyBQ0 = _mm_add_pd(PolyBQ0, CBQ4);
1097     PolyBQ1 = _mm_mul_pd(PolyBQ1, t2);
1098     PolyBQ0 = _mm_mul_pd(PolyBQ0, t2);
1099     PolyBQ1 = _mm_add_pd(PolyBQ1, CBQ3);
1100     PolyBQ0 = _mm_add_pd(PolyBQ0, CBQ2);
1101     PolyBQ1 = _mm_mul_pd(PolyBQ1, t2);
1102     PolyBQ0 = _mm_mul_pd(PolyBQ0, t2);
1103     PolyBQ1 = _mm_add_pd(PolyBQ1, CBQ1);
1104     PolyBQ0 = _mm_add_pd(PolyBQ0, one);
1105     PolyBQ1 = _mm_mul_pd(PolyBQ1, t);
1106     PolyBQ0 = _mm_add_pd(PolyBQ0, PolyBQ1);
1107
1108     res_erfcB = _mm_mul_pd(PolyBP0, gmx_mm_inv_pd(PolyBQ0));
1109
1110     res_erfcB = _mm_mul_pd(res_erfcB, xabs);
1111
1112     /* Calculate erfc() in range [4.5,inf] */
1113     w       = gmx_mm_inv_pd(xabs);
1114     w2      = _mm_mul_pd(w, w);
1115
1116     PolyCP0  = _mm_mul_pd(CCP6, w2);
1117     PolyCP1  = _mm_mul_pd(CCP5, w2);
1118     PolyCP0  = _mm_add_pd(PolyCP0, CCP4);
1119     PolyCP1  = _mm_add_pd(PolyCP1, CCP3);
1120     PolyCP0  = _mm_mul_pd(PolyCP0, w2);
1121     PolyCP1  = _mm_mul_pd(PolyCP1, w2);
1122     PolyCP0  = _mm_add_pd(PolyCP0, CCP2);
1123     PolyCP1  = _mm_add_pd(PolyCP1, CCP1);
1124     PolyCP0  = _mm_mul_pd(PolyCP0, w2);
1125     PolyCP1  = _mm_mul_pd(PolyCP1, w);
1126     PolyCP0  = _mm_add_pd(PolyCP0, CCP0);
1127     PolyCP0  = _mm_add_pd(PolyCP0, PolyCP1);
1128
1129     PolyCQ0  = _mm_mul_pd(CCQ6, w2);
1130     PolyCQ1  = _mm_mul_pd(CCQ5, w2);
1131     PolyCQ0  = _mm_add_pd(PolyCQ0, CCQ4);
1132     PolyCQ1  = _mm_add_pd(PolyCQ1, CCQ3);
1133     PolyCQ0  = _mm_mul_pd(PolyCQ0, w2);
1134     PolyCQ1  = _mm_mul_pd(PolyCQ1, w2);
1135     PolyCQ0  = _mm_add_pd(PolyCQ0, CCQ2);
1136     PolyCQ1  = _mm_add_pd(PolyCQ1, CCQ1);
1137     PolyCQ0  = _mm_mul_pd(PolyCQ0, w2);
1138     PolyCQ1  = _mm_mul_pd(PolyCQ1, w);
1139     PolyCQ0  = _mm_add_pd(PolyCQ0, one);
1140     PolyCQ0  = _mm_add_pd(PolyCQ0, PolyCQ1);
1141
1142     expmx2   = gmx_mm_exp_pd( _mm_or_pd(signbit, x2) );
1143
1144     res_erfcC = _mm_mul_pd(PolyCP0, gmx_mm_inv_pd(PolyCQ0));
1145     res_erfcC = _mm_add_pd(res_erfcC, CCoffset);
1146     res_erfcC = _mm_mul_pd(res_erfcC, w);
1147
1148     mask     = _mm_cmpgt_pd(xabs, _mm_set1_pd(4.5));
1149     res_erfc = _mm_blendv_pd(res_erfcB, res_erfcC, mask);
1150
1151     res_erfc = _mm_mul_pd(res_erfc, expmx2);
1152
1153     /* erfc(x<0) = 2-erfc(|x|) */
1154     mask     = _mm_cmplt_pd(x, _mm_setzero_pd());
1155     res_erfc = _mm_blendv_pd(res_erfc, _mm_sub_pd(two, res_erfc), mask);
1156
1157     /* Select erf() or erfc() */
1158     mask = _mm_cmplt_pd(xabs, one);
1159     res  = _mm_blendv_pd(_mm_sub_pd(one, res_erfc), res_erf, mask);
1160
1161     return res;
1162 }
1163
1164
1165 static __m256d
1166 gmx_mm256_erfc_pd(__m256d x)
1167 {
1168     /* Coefficients for minimax approximation of erf(x)=x*(CAoffset + P(x^2)/Q(x^2)) in range [-0.75,0.75] */
1169     const __m256d CAP4      = _mm256_set1_pd(-0.431780540597889301512e-4);
1170     const __m256d CAP3      = _mm256_set1_pd(-0.00578562306260059236059);
1171     const __m256d CAP2      = _mm256_set1_pd(-0.028593586920219752446);
1172     const __m256d CAP1      = _mm256_set1_pd(-0.315924962948621698209);
1173     const __m256d CAP0      = _mm256_set1_pd(0.14952975608477029151);
1174
1175     const __m256d CAQ5      = _mm256_set1_pd(-0.374089300177174709737e-5);
1176     const __m256d CAQ4      = _mm256_set1_pd(0.00015126584532155383535);
1177     const __m256d CAQ3      = _mm256_set1_pd(0.00536692680669480725423);
1178     const __m256d CAQ2      = _mm256_set1_pd(0.0668686825594046122636);
1179     const __m256d CAQ1      = _mm256_set1_pd(0.402604990869284362773);
1180     /* CAQ0 == 1.0 */
1181     const __m256d CAoffset  = _mm256_set1_pd(0.9788494110107421875);
1182
1183     /* Coefficients for minimax approximation of erfc(x)=exp(-x^2)*x*(P(x-1)/Q(x-1)) in range [1.0,4.5] */
1184     const __m256d CBP6      = _mm256_set1_pd(2.49650423685462752497647637088e-10);
1185     const __m256d CBP5      = _mm256_set1_pd(0.00119770193298159629350136085658);
1186     const __m256d CBP4      = _mm256_set1_pd(0.0164944422378370965881008942733);
1187     const __m256d CBP3      = _mm256_set1_pd(0.0984581468691775932063932439252);
1188     const __m256d CBP2      = _mm256_set1_pd(0.317364595806937763843589437418);
1189     const __m256d CBP1      = _mm256_set1_pd(0.554167062641455850932670067075);
1190     const __m256d CBP0      = _mm256_set1_pd(0.427583576155807163756925301060);
1191     const __m256d CBQ7      = _mm256_set1_pd(0.00212288829699830145976198384930);
1192     const __m256d CBQ6      = _mm256_set1_pd(0.0334810979522685300554606393425);
1193     const __m256d CBQ5      = _mm256_set1_pd(0.2361713785181450957579508850717);
1194     const __m256d CBQ4      = _mm256_set1_pd(0.955364736493055670530981883072);
1195     const __m256d CBQ3      = _mm256_set1_pd(2.36815675631420037315349279199);
1196     const __m256d CBQ2      = _mm256_set1_pd(3.55261649184083035537184223542);
1197     const __m256d CBQ1      = _mm256_set1_pd(2.93501136050160872574376997993);
1198     /* CBQ0 == 1.0 */
1199
1200     /* Coefficients for minimax approximation of erfc(x)=exp(-x^2)/x*(P(1/x)/Q(1/x)) in range [4.5,inf] */
1201     const __m256d CCP6      = _mm256_set1_pd(-2.8175401114513378771);
1202     const __m256d CCP5      = _mm256_set1_pd(-3.22729451764143718517);
1203     const __m256d CCP4      = _mm256_set1_pd(-2.5518551727311523996);
1204     const __m256d CCP3      = _mm256_set1_pd(-0.687717681153649930619);
1205     const __m256d CCP2      = _mm256_set1_pd(-0.212652252872804219852);
1206     const __m256d CCP1      = _mm256_set1_pd(0.0175389834052493308818);
1207     const __m256d CCP0      = _mm256_set1_pd(0.00628057170626964891937);
1208
1209     const __m256d CCQ6      = _mm256_set1_pd(5.48409182238641741584);
1210     const __m256d CCQ5      = _mm256_set1_pd(13.5064170191802889145);
1211     const __m256d CCQ4      = _mm256_set1_pd(22.9367376522880577224);
1212     const __m256d CCQ3      = _mm256_set1_pd(15.930646027911794143);
1213     const __m256d CCQ2      = _mm256_set1_pd(11.0567237927800161565);
1214     const __m256d CCQ1      = _mm256_set1_pd(2.79257750980575282228);
1215     /* CCQ0 == 1.0 */
1216     const __m256d CCoffset  = _mm256_set1_pd(0.5579090118408203125);
1217
1218     const __m256d one       = _mm256_set1_pd(1.0);
1219     const __m256d two       = _mm256_set1_pd(2.0);
1220
1221     const __m256d signbit   = _mm256_castsi256_pd( _mm256_set_epi32(0x80000000, 0x00000000, 0x80000000, 0x00000000,
1222                                                                     0x80000000, 0x00000000, 0x80000000, 0x00000000) );
1223
1224     __m256d xabs, x2, x4, t, t2, w, w2;
1225     __m256d PolyAP0, PolyAP1, PolyAQ0, PolyAQ1;
1226     __m256d PolyBP0, PolyBP1, PolyBQ0, PolyBQ1;
1227     __m256d PolyCP0, PolyCP1, PolyCQ0, PolyCQ1;
1228     __m256d res_erf, res_erfcB, res_erfcC, res_erfc, res;
1229     __m256d mask, expmx2;
1230
1231     /* Calculate erf() */
1232     xabs     = gmx_mm256_abs_pd(x);
1233     x2       = _mm256_mul_pd(x, x);
1234     x4       = _mm256_mul_pd(x2, x2);
1235
1236     PolyAP0  = _mm256_mul_pd(CAP4, x4);
1237     PolyAP1  = _mm256_mul_pd(CAP3, x4);
1238     PolyAP0  = _mm256_add_pd(PolyAP0, CAP2);
1239     PolyAP1  = _mm256_add_pd(PolyAP1, CAP1);
1240     PolyAP0  = _mm256_mul_pd(PolyAP0, x4);
1241     PolyAP1  = _mm256_mul_pd(PolyAP1, x2);
1242     PolyAP0  = _mm256_add_pd(PolyAP0, CAP0);
1243     PolyAP0  = _mm256_add_pd(PolyAP0, PolyAP1);
1244
1245     PolyAQ1  = _mm256_mul_pd(CAQ5, x4);
1246     PolyAQ0  = _mm256_mul_pd(CAQ4, x4);
1247     PolyAQ1  = _mm256_add_pd(PolyAQ1, CAQ3);
1248     PolyAQ0  = _mm256_add_pd(PolyAQ0, CAQ2);
1249     PolyAQ1  = _mm256_mul_pd(PolyAQ1, x4);
1250     PolyAQ0  = _mm256_mul_pd(PolyAQ0, x4);
1251     PolyAQ1  = _mm256_add_pd(PolyAQ1, CAQ1);
1252     PolyAQ0  = _mm256_add_pd(PolyAQ0, one);
1253     PolyAQ1  = _mm256_mul_pd(PolyAQ1, x2);
1254     PolyAQ0  = _mm256_add_pd(PolyAQ0, PolyAQ1);
1255
1256     res_erf  = _mm256_mul_pd(PolyAP0, gmx_mm256_inv_pd(PolyAQ0));
1257     res_erf  = _mm256_add_pd(CAoffset, res_erf);
1258     res_erf  = _mm256_mul_pd(x, res_erf);
1259
1260     /* Calculate erfc() in range [1,4.5] */
1261     t       = _mm256_sub_pd(xabs, one);
1262     t2      = _mm256_mul_pd(t, t);
1263
1264     PolyBP0  = _mm256_mul_pd(CBP6, t2);
1265     PolyBP1  = _mm256_mul_pd(CBP5, t2);
1266     PolyBP0  = _mm256_add_pd(PolyBP0, CBP4);
1267     PolyBP1  = _mm256_add_pd(PolyBP1, CBP3);
1268     PolyBP0  = _mm256_mul_pd(PolyBP0, t2);
1269     PolyBP1  = _mm256_mul_pd(PolyBP1, t2);
1270     PolyBP0  = _mm256_add_pd(PolyBP0, CBP2);
1271     PolyBP1  = _mm256_add_pd(PolyBP1, CBP1);
1272     PolyBP0  = _mm256_mul_pd(PolyBP0, t2);
1273     PolyBP1  = _mm256_mul_pd(PolyBP1, t);
1274     PolyBP0  = _mm256_add_pd(PolyBP0, CBP0);
1275     PolyBP0  = _mm256_add_pd(PolyBP0, PolyBP1);
1276
1277     PolyBQ1 = _mm256_mul_pd(CBQ7, t2);
1278     PolyBQ0 = _mm256_mul_pd(CBQ6, t2);
1279     PolyBQ1 = _mm256_add_pd(PolyBQ1, CBQ5);
1280     PolyBQ0 = _mm256_add_pd(PolyBQ0, CBQ4);
1281     PolyBQ1 = _mm256_mul_pd(PolyBQ1, t2);
1282     PolyBQ0 = _mm256_mul_pd(PolyBQ0, t2);
1283     PolyBQ1 = _mm256_add_pd(PolyBQ1, CBQ3);
1284     PolyBQ0 = _mm256_add_pd(PolyBQ0, CBQ2);
1285     PolyBQ1 = _mm256_mul_pd(PolyBQ1, t2);
1286     PolyBQ0 = _mm256_mul_pd(PolyBQ0, t2);
1287     PolyBQ1 = _mm256_add_pd(PolyBQ1, CBQ1);
1288     PolyBQ0 = _mm256_add_pd(PolyBQ0, one);
1289     PolyBQ1 = _mm256_mul_pd(PolyBQ1, t);
1290     PolyBQ0 = _mm256_add_pd(PolyBQ0, PolyBQ1);
1291
1292     res_erfcB = _mm256_mul_pd(PolyBP0, gmx_mm256_inv_pd(PolyBQ0));
1293
1294     res_erfcB = _mm256_mul_pd(res_erfcB, xabs);
1295
1296     /* Calculate erfc() in range [4.5,inf] */
1297     w       = gmx_mm256_inv_pd(xabs);
1298     w2      = _mm256_mul_pd(w, w);
1299
1300     PolyCP0  = _mm256_mul_pd(CCP6, w2);
1301     PolyCP1  = _mm256_mul_pd(CCP5, w2);
1302     PolyCP0  = _mm256_add_pd(PolyCP0, CCP4);
1303     PolyCP1  = _mm256_add_pd(PolyCP1, CCP3);
1304     PolyCP0  = _mm256_mul_pd(PolyCP0, w2);
1305     PolyCP1  = _mm256_mul_pd(PolyCP1, w2);
1306     PolyCP0  = _mm256_add_pd(PolyCP0, CCP2);
1307     PolyCP1  = _mm256_add_pd(PolyCP1, CCP1);
1308     PolyCP0  = _mm256_mul_pd(PolyCP0, w2);
1309     PolyCP1  = _mm256_mul_pd(PolyCP1, w);
1310     PolyCP0  = _mm256_add_pd(PolyCP0, CCP0);
1311     PolyCP0  = _mm256_add_pd(PolyCP0, PolyCP1);
1312
1313     PolyCQ0  = _mm256_mul_pd(CCQ6, w2);
1314     PolyCQ1  = _mm256_mul_pd(CCQ5, w2);
1315     PolyCQ0  = _mm256_add_pd(PolyCQ0, CCQ4);
1316     PolyCQ1  = _mm256_add_pd(PolyCQ1, CCQ3);
1317     PolyCQ0  = _mm256_mul_pd(PolyCQ0, w2);
1318     PolyCQ1  = _mm256_mul_pd(PolyCQ1, w2);
1319     PolyCQ0  = _mm256_add_pd(PolyCQ0, CCQ2);
1320     PolyCQ1  = _mm256_add_pd(PolyCQ1, CCQ1);
1321     PolyCQ0  = _mm256_mul_pd(PolyCQ0, w2);
1322     PolyCQ1  = _mm256_mul_pd(PolyCQ1, w);
1323     PolyCQ0  = _mm256_add_pd(PolyCQ0, one);
1324     PolyCQ0  = _mm256_add_pd(PolyCQ0, PolyCQ1);
1325
1326     expmx2   = gmx_mm256_exp_pd( _mm256_or_pd(signbit, x2) );
1327
1328     res_erfcC = _mm256_mul_pd(PolyCP0, gmx_mm256_inv_pd(PolyCQ0));
1329     res_erfcC = _mm256_add_pd(res_erfcC, CCoffset);
1330     res_erfcC = _mm256_mul_pd(res_erfcC, w);
1331
1332     mask     = _mm256_cmp_pd(xabs, _mm256_set1_pd(4.5), _CMP_GT_OQ);
1333     res_erfc = _mm256_blendv_pd(res_erfcB, res_erfcC, mask);
1334
1335     res_erfc = _mm256_mul_pd(res_erfc, expmx2);
1336
1337     /* erfc(x<0) = 2-erfc(|x|) */
1338     mask     = _mm256_cmp_pd(x, _mm256_setzero_pd(), _CMP_LT_OQ);
1339     res_erfc = _mm256_blendv_pd(res_erfc, _mm256_sub_pd(two, res_erfc), mask);
1340
1341     /* Select erf() or erfc() */
1342     mask = _mm256_cmp_pd(xabs, one, _CMP_LT_OQ);
1343     res  = _mm256_blendv_pd(res_erfc, _mm256_sub_pd(one, res_erf), mask);
1344
1345     return res;
1346 }
1347
1348
1349 static __m128d
1350 gmx_mm_erfc_pd(__m128d x)
1351 {
1352     /* Coefficients for minimax approximation of erf(x)=x*(CAoffset + P(x^2)/Q(x^2)) in range [-0.75,0.75] */
1353     const __m128d CAP4      = _mm_set1_pd(-0.431780540597889301512e-4);
1354     const __m128d CAP3      = _mm_set1_pd(-0.00578562306260059236059);
1355     const __m128d CAP2      = _mm_set1_pd(-0.028593586920219752446);
1356     const __m128d CAP1      = _mm_set1_pd(-0.315924962948621698209);
1357     const __m128d CAP0      = _mm_set1_pd(0.14952975608477029151);
1358
1359     const __m128d CAQ5      = _mm_set1_pd(-0.374089300177174709737e-5);
1360     const __m128d CAQ4      = _mm_set1_pd(0.00015126584532155383535);
1361     const __m128d CAQ3      = _mm_set1_pd(0.00536692680669480725423);
1362     const __m128d CAQ2      = _mm_set1_pd(0.0668686825594046122636);
1363     const __m128d CAQ1      = _mm_set1_pd(0.402604990869284362773);
1364     /* CAQ0 == 1.0 */
1365     const __m128d CAoffset  = _mm_set1_pd(0.9788494110107421875);
1366
1367     /* Coefficients for minimax approximation of erfc(x)=exp(-x^2)*x*(P(x-1)/Q(x-1)) in range [1.0,4.5] */
1368     const __m128d CBP6      = _mm_set1_pd(2.49650423685462752497647637088e-10);
1369     const __m128d CBP5      = _mm_set1_pd(0.00119770193298159629350136085658);
1370     const __m128d CBP4      = _mm_set1_pd(0.0164944422378370965881008942733);
1371     const __m128d CBP3      = _mm_set1_pd(0.0984581468691775932063932439252);
1372     const __m128d CBP2      = _mm_set1_pd(0.317364595806937763843589437418);
1373     const __m128d CBP1      = _mm_set1_pd(0.554167062641455850932670067075);
1374     const __m128d CBP0      = _mm_set1_pd(0.427583576155807163756925301060);
1375     const __m128d CBQ7      = _mm_set1_pd(0.00212288829699830145976198384930);
1376     const __m128d CBQ6      = _mm_set1_pd(0.0334810979522685300554606393425);
1377     const __m128d CBQ5      = _mm_set1_pd(0.2361713785181450957579508850717);
1378     const __m128d CBQ4      = _mm_set1_pd(0.955364736493055670530981883072);
1379     const __m128d CBQ3      = _mm_set1_pd(2.36815675631420037315349279199);
1380     const __m128d CBQ2      = _mm_set1_pd(3.55261649184083035537184223542);
1381     const __m128d CBQ1      = _mm_set1_pd(2.93501136050160872574376997993);
1382     /* CBQ0 == 1.0 */
1383
1384     /* Coefficients for minimax approximation of erfc(x)=exp(-x^2)/x*(P(1/x)/Q(1/x)) in range [4.5,inf] */
1385     const __m128d CCP6      = _mm_set1_pd(-2.8175401114513378771);
1386     const __m128d CCP5      = _mm_set1_pd(-3.22729451764143718517);
1387     const __m128d CCP4      = _mm_set1_pd(-2.5518551727311523996);
1388     const __m128d CCP3      = _mm_set1_pd(-0.687717681153649930619);
1389     const __m128d CCP2      = _mm_set1_pd(-0.212652252872804219852);
1390     const __m128d CCP1      = _mm_set1_pd(0.0175389834052493308818);
1391     const __m128d CCP0      = _mm_set1_pd(0.00628057170626964891937);
1392
1393     const __m128d CCQ6      = _mm_set1_pd(5.48409182238641741584);
1394     const __m128d CCQ5      = _mm_set1_pd(13.5064170191802889145);
1395     const __m128d CCQ4      = _mm_set1_pd(22.9367376522880577224);
1396     const __m128d CCQ3      = _mm_set1_pd(15.930646027911794143);
1397     const __m128d CCQ2      = _mm_set1_pd(11.0567237927800161565);
1398     const __m128d CCQ1      = _mm_set1_pd(2.79257750980575282228);
1399     /* CCQ0 == 1.0 */
1400     const __m128d CCoffset  = _mm_set1_pd(0.5579090118408203125);
1401
1402     const __m128d one       = _mm_set1_pd(1.0);
1403     const __m128d two       = _mm_set1_pd(2.0);
1404
1405     const __m128d signbit   = gmx_mm_castsi128_pd( _mm_set_epi32(0x80000000, 0x00000000, 0x80000000, 0x00000000) );
1406
1407     __m128d       xabs, x2, x4, t, t2, w, w2;
1408     __m128d       PolyAP0, PolyAP1, PolyAQ0, PolyAQ1;
1409     __m128d       PolyBP0, PolyBP1, PolyBQ0, PolyBQ1;
1410     __m128d       PolyCP0, PolyCP1, PolyCQ0, PolyCQ1;
1411     __m128d       res_erf, res_erfcB, res_erfcC, res_erfc, res;
1412     __m128d       mask, expmx2;
1413
1414     /* Calculate erf() */
1415     xabs     = gmx_mm_abs_pd(x);
1416     x2       = _mm_mul_pd(x, x);
1417     x4       = _mm_mul_pd(x2, x2);
1418
1419     PolyAP0  = _mm_mul_pd(CAP4, x4);
1420     PolyAP1  = _mm_mul_pd(CAP3, x4);
1421     PolyAP0  = _mm_add_pd(PolyAP0, CAP2);
1422     PolyAP1  = _mm_add_pd(PolyAP1, CAP1);
1423     PolyAP0  = _mm_mul_pd(PolyAP0, x4);
1424     PolyAP1  = _mm_mul_pd(PolyAP1, x2);
1425     PolyAP0  = _mm_add_pd(PolyAP0, CAP0);
1426     PolyAP0  = _mm_add_pd(PolyAP0, PolyAP1);
1427
1428     PolyAQ1  = _mm_mul_pd(CAQ5, x4);
1429     PolyAQ0  = _mm_mul_pd(CAQ4, x4);
1430     PolyAQ1  = _mm_add_pd(PolyAQ1, CAQ3);
1431     PolyAQ0  = _mm_add_pd(PolyAQ0, CAQ2);
1432     PolyAQ1  = _mm_mul_pd(PolyAQ1, x4);
1433     PolyAQ0  = _mm_mul_pd(PolyAQ0, x4);
1434     PolyAQ1  = _mm_add_pd(PolyAQ1, CAQ1);
1435     PolyAQ0  = _mm_add_pd(PolyAQ0, one);
1436     PolyAQ1  = _mm_mul_pd(PolyAQ1, x2);
1437     PolyAQ0  = _mm_add_pd(PolyAQ0, PolyAQ1);
1438
1439     res_erf  = _mm_mul_pd(PolyAP0, gmx_mm_inv_pd(PolyAQ0));
1440     res_erf  = _mm_add_pd(CAoffset, res_erf);
1441     res_erf  = _mm_mul_pd(x, res_erf);
1442
1443     /* Calculate erfc() in range [1,4.5] */
1444     t       = _mm_sub_pd(xabs, one);
1445     t2      = _mm_mul_pd(t, t);
1446
1447     PolyBP0  = _mm_mul_pd(CBP6, t2);
1448     PolyBP1  = _mm_mul_pd(CBP5, t2);
1449     PolyBP0  = _mm_add_pd(PolyBP0, CBP4);
1450     PolyBP1  = _mm_add_pd(PolyBP1, CBP3);
1451     PolyBP0  = _mm_mul_pd(PolyBP0, t2);
1452     PolyBP1  = _mm_mul_pd(PolyBP1, t2);
1453     PolyBP0  = _mm_add_pd(PolyBP0, CBP2);
1454     PolyBP1  = _mm_add_pd(PolyBP1, CBP1);
1455     PolyBP0  = _mm_mul_pd(PolyBP0, t2);
1456     PolyBP1  = _mm_mul_pd(PolyBP1, t);
1457     PolyBP0  = _mm_add_pd(PolyBP0, CBP0);
1458     PolyBP0  = _mm_add_pd(PolyBP0, PolyBP1);
1459
1460     PolyBQ1 = _mm_mul_pd(CBQ7, t2);
1461     PolyBQ0 = _mm_mul_pd(CBQ6, t2);
1462     PolyBQ1 = _mm_add_pd(PolyBQ1, CBQ5);
1463     PolyBQ0 = _mm_add_pd(PolyBQ0, CBQ4);
1464     PolyBQ1 = _mm_mul_pd(PolyBQ1, t2);
1465     PolyBQ0 = _mm_mul_pd(PolyBQ0, t2);
1466     PolyBQ1 = _mm_add_pd(PolyBQ1, CBQ3);
1467     PolyBQ0 = _mm_add_pd(PolyBQ0, CBQ2);
1468     PolyBQ1 = _mm_mul_pd(PolyBQ1, t2);
1469     PolyBQ0 = _mm_mul_pd(PolyBQ0, t2);
1470     PolyBQ1 = _mm_add_pd(PolyBQ1, CBQ1);
1471     PolyBQ0 = _mm_add_pd(PolyBQ0, one);
1472     PolyBQ1 = _mm_mul_pd(PolyBQ1, t);
1473     PolyBQ0 = _mm_add_pd(PolyBQ0, PolyBQ1);
1474
1475     res_erfcB = _mm_mul_pd(PolyBP0, gmx_mm_inv_pd(PolyBQ0));
1476
1477     res_erfcB = _mm_mul_pd(res_erfcB, xabs);
1478
1479     /* Calculate erfc() in range [4.5,inf] */
1480     w       = gmx_mm_inv_pd(xabs);
1481     w2      = _mm_mul_pd(w, w);
1482
1483     PolyCP0  = _mm_mul_pd(CCP6, w2);
1484     PolyCP1  = _mm_mul_pd(CCP5, w2);
1485     PolyCP0  = _mm_add_pd(PolyCP0, CCP4);
1486     PolyCP1  = _mm_add_pd(PolyCP1, CCP3);
1487     PolyCP0  = _mm_mul_pd(PolyCP0, w2);
1488     PolyCP1  = _mm_mul_pd(PolyCP1, w2);
1489     PolyCP0  = _mm_add_pd(PolyCP0, CCP2);
1490     PolyCP1  = _mm_add_pd(PolyCP1, CCP1);
1491     PolyCP0  = _mm_mul_pd(PolyCP0, w2);
1492     PolyCP1  = _mm_mul_pd(PolyCP1, w);
1493     PolyCP0  = _mm_add_pd(PolyCP0, CCP0);
1494     PolyCP0  = _mm_add_pd(PolyCP0, PolyCP1);
1495
1496     PolyCQ0  = _mm_mul_pd(CCQ6, w2);
1497     PolyCQ1  = _mm_mul_pd(CCQ5, w2);
1498     PolyCQ0  = _mm_add_pd(PolyCQ0, CCQ4);
1499     PolyCQ1  = _mm_add_pd(PolyCQ1, CCQ3);
1500     PolyCQ0  = _mm_mul_pd(PolyCQ0, w2);
1501     PolyCQ1  = _mm_mul_pd(PolyCQ1, w2);
1502     PolyCQ0  = _mm_add_pd(PolyCQ0, CCQ2);
1503     PolyCQ1  = _mm_add_pd(PolyCQ1, CCQ1);
1504     PolyCQ0  = _mm_mul_pd(PolyCQ0, w2);
1505     PolyCQ1  = _mm_mul_pd(PolyCQ1, w);
1506     PolyCQ0  = _mm_add_pd(PolyCQ0, one);
1507     PolyCQ0  = _mm_add_pd(PolyCQ0, PolyCQ1);
1508
1509     expmx2   = gmx_mm_exp_pd( _mm_or_pd(signbit, x2) );
1510
1511     res_erfcC = _mm_mul_pd(PolyCP0, gmx_mm_inv_pd(PolyCQ0));
1512     res_erfcC = _mm_add_pd(res_erfcC, CCoffset);
1513     res_erfcC = _mm_mul_pd(res_erfcC, w);
1514
1515     mask     = _mm_cmpgt_pd(xabs, _mm_set1_pd(4.5));
1516     res_erfc = _mm_blendv_pd(res_erfcB, res_erfcC, mask);
1517
1518     res_erfc = _mm_mul_pd(res_erfc, expmx2);
1519
1520     /* erfc(x<0) = 2-erfc(|x|) */
1521     mask     = _mm_cmplt_pd(x, _mm_setzero_pd());
1522     res_erfc = _mm_blendv_pd(res_erfc, _mm_sub_pd(two, res_erfc), mask);
1523
1524     /* Select erf() or erfc() */
1525     mask = _mm_cmplt_pd(xabs, one);
1526     res  = _mm_blendv_pd(res_erfc, _mm_sub_pd(one, res_erf), mask);
1527
1528     return res;
1529 }
1530
1531
1532 /* Calculate the force correction due to PME analytically.
1533  *
1534  * This routine is meant to enable analytical evaluation of the
1535  * direct-space PME electrostatic force to avoid tables.
1536  *
1537  * The direct-space potential should be Erfc(beta*r)/r, but there
1538  * are some problems evaluating that:
1539  *
1540  * First, the error function is difficult (read: expensive) to
1541  * approxmiate accurately for intermediate to large arguments, and
1542  * this happens already in ranges of beta*r that occur in simulations.
1543  * Second, we now try to avoid calculating potentials in Gromacs but
1544  * use forces directly.
1545  *
1546  * We can simply things slight by noting that the PME part is really
1547  * a correction to the normal Coulomb force since Erfc(z)=1-Erf(z), i.e.
1548  *
1549  * V= 1/r - Erf(beta*r)/r
1550  *
1551  * The first term we already have from the inverse square root, so
1552  * that we can leave out of this routine.
1553  *
1554  * For pme tolerances of 1e-3 to 1e-8 and cutoffs of 0.5nm to 1.8nm,
1555  * the argument beta*r will be in the range 0.15 to ~4. Use your
1556  * favorite plotting program to realize how well-behaved Erf(z)/z is
1557  * in this range!
1558  *
1559  * We approximate f(z)=erf(z)/z with a rational minimax polynomial.
1560  * However, it turns out it is more efficient to approximate f(z)/z and
1561  * then only use even powers. This is another minor optimization, since
1562  * we actually WANT f(z)/z, because it is going to be multiplied by
1563  * the vector between the two atoms to get the vectorial force. The
1564  * fastest flops are the ones we can avoid calculating!
1565  *
1566  * So, here's how it should be used:
1567  *
1568  * 1. Calculate r^2.
1569  * 2. Multiply by beta^2, so you get z^2=beta^2*r^2.
1570  * 3. Evaluate this routine with z^2 as the argument.
1571  * 4. The return value is the expression:
1572  *
1573  *
1574  *       2*exp(-z^2)     erf(z)
1575  *       ------------ - --------
1576  *       sqrt(Pi)*z^2      z^3
1577  *
1578  * 5. Multiply the entire expression by beta^3. This will get you
1579  *
1580  *       beta^3*2*exp(-z^2)     beta^3*erf(z)
1581  *       ------------------  - ---------------
1582  *          sqrt(Pi)*z^2            z^3
1583  *
1584  *    or, switching back to r (z=r*beta):
1585  *
1586  *       2*beta*exp(-r^2*beta^2)   erf(r*beta)
1587  *       ----------------------- - -----------
1588  *            sqrt(Pi)*r^2            r^3
1589  *
1590  *
1591  *    With a bit of math exercise you should be able to confirm that
1592  *    this is exactly D[Erf[beta*r]/r,r] divided by r another time.
1593  *
1594  * 6. Add the result to 1/r^3, multiply by the product of the charges,
1595  *    and you have your force (divided by r). A final multiplication
1596  *    with the vector connecting the two particles and you have your
1597  *    vectorial force to add to the particles.
1598  *
1599  */
1600 static __m256d
1601 gmx_mm256_pmecorrF_pd(__m256d z2)
1602 {
1603     const __m256d  FN10     = _mm256_set1_pd(-8.0072854618360083154e-14);
1604     const __m256d  FN9      = _mm256_set1_pd(1.1859116242260148027e-11);
1605     const __m256d  FN8      = _mm256_set1_pd(-8.1490406329798423616e-10);
1606     const __m256d  FN7      = _mm256_set1_pd(3.4404793543907847655e-8);
1607     const __m256d  FN6      = _mm256_set1_pd(-9.9471420832602741006e-7);
1608     const __m256d  FN5      = _mm256_set1_pd(0.000020740315999115847456);
1609     const __m256d  FN4      = _mm256_set1_pd(-0.00031991745139313364005);
1610     const __m256d  FN3      = _mm256_set1_pd(0.0035074449373659008203);
1611     const __m256d  FN2      = _mm256_set1_pd(-0.031750380176100813405);
1612     const __m256d  FN1      = _mm256_set1_pd(0.13884101728898463426);
1613     const __m256d  FN0      = _mm256_set1_pd(-0.75225277815249618847);
1614
1615     const __m256d  FD5      = _mm256_set1_pd(0.000016009278224355026701);
1616     const __m256d  FD4      = _mm256_set1_pd(0.00051055686934806966046);
1617     const __m256d  FD3      = _mm256_set1_pd(0.0081803507497974289008);
1618     const __m256d  FD2      = _mm256_set1_pd(0.077181146026670287235);
1619     const __m256d  FD1      = _mm256_set1_pd(0.41543303143712535988);
1620     const __m256d  FD0      = _mm256_set1_pd(1.0);
1621
1622     __m256d        z4;
1623     __m256d        polyFN0, polyFN1, polyFD0, polyFD1;
1624
1625     z4             = _mm256_mul_pd(z2, z2);
1626
1627     polyFD1        = _mm256_mul_pd(FD5, z4);
1628     polyFD0        = _mm256_mul_pd(FD4, z4);
1629     polyFD1        = _mm256_add_pd(polyFD1, FD3);
1630     polyFD0        = _mm256_add_pd(polyFD0, FD2);
1631     polyFD1        = _mm256_mul_pd(polyFD1, z4);
1632     polyFD0        = _mm256_mul_pd(polyFD0, z4);
1633     polyFD1        = _mm256_add_pd(polyFD1, FD1);
1634     polyFD0        = _mm256_add_pd(polyFD0, FD0);
1635     polyFD1        = _mm256_mul_pd(polyFD1, z2);
1636     polyFD0        = _mm256_add_pd(polyFD0, polyFD1);
1637
1638     polyFD0        = gmx_mm256_inv_pd(polyFD0);
1639
1640     polyFN0        = _mm256_mul_pd(FN10, z4);
1641     polyFN1        = _mm256_mul_pd(FN9, z4);
1642     polyFN0        = _mm256_add_pd(polyFN0, FN8);
1643     polyFN1        = _mm256_add_pd(polyFN1, FN7);
1644     polyFN0        = _mm256_mul_pd(polyFN0, z4);
1645     polyFN1        = _mm256_mul_pd(polyFN1, z4);
1646     polyFN0        = _mm256_add_pd(polyFN0, FN6);
1647     polyFN1        = _mm256_add_pd(polyFN1, FN5);
1648     polyFN0        = _mm256_mul_pd(polyFN0, z4);
1649     polyFN1        = _mm256_mul_pd(polyFN1, z4);
1650     polyFN0        = _mm256_add_pd(polyFN0, FN4);
1651     polyFN1        = _mm256_add_pd(polyFN1, FN3);
1652     polyFN0        = _mm256_mul_pd(polyFN0, z4);
1653     polyFN1        = _mm256_mul_pd(polyFN1, z4);
1654     polyFN0        = _mm256_add_pd(polyFN0, FN2);
1655     polyFN1        = _mm256_add_pd(polyFN1, FN1);
1656     polyFN0        = _mm256_mul_pd(polyFN0, z4);
1657     polyFN1        = _mm256_mul_pd(polyFN1, z2);
1658     polyFN0        = _mm256_add_pd(polyFN0, FN0);
1659     polyFN0        = _mm256_add_pd(polyFN0, polyFN1);
1660
1661     return _mm256_mul_pd(polyFN0, polyFD0);
1662 }
1663
1664
1665 static __m128d
1666 gmx_mm_pmecorrF_pd(__m128d z2)
1667 {
1668     const __m128d  FN10     = _mm_set1_pd(-8.0072854618360083154e-14);
1669     const __m128d  FN9      = _mm_set1_pd(1.1859116242260148027e-11);
1670     const __m128d  FN8      = _mm_set1_pd(-8.1490406329798423616e-10);
1671     const __m128d  FN7      = _mm_set1_pd(3.4404793543907847655e-8);
1672     const __m128d  FN6      = _mm_set1_pd(-9.9471420832602741006e-7);
1673     const __m128d  FN5      = _mm_set1_pd(0.000020740315999115847456);
1674     const __m128d  FN4      = _mm_set1_pd(-0.00031991745139313364005);
1675     const __m128d  FN3      = _mm_set1_pd(0.0035074449373659008203);
1676     const __m128d  FN2      = _mm_set1_pd(-0.031750380176100813405);
1677     const __m128d  FN1      = _mm_set1_pd(0.13884101728898463426);
1678     const __m128d  FN0      = _mm_set1_pd(-0.75225277815249618847);
1679
1680     const __m128d  FD5      = _mm_set1_pd(0.000016009278224355026701);
1681     const __m128d  FD4      = _mm_set1_pd(0.00051055686934806966046);
1682     const __m128d  FD3      = _mm_set1_pd(0.0081803507497974289008);
1683     const __m128d  FD2      = _mm_set1_pd(0.077181146026670287235);
1684     const __m128d  FD1      = _mm_set1_pd(0.41543303143712535988);
1685     const __m128d  FD0      = _mm_set1_pd(1.0);
1686
1687     __m128d        z4;
1688     __m128d        polyFN0, polyFN1, polyFD0, polyFD1;
1689
1690     z4             = _mm_mul_pd(z2, z2);
1691
1692     polyFD1        = _mm_mul_pd(FD5, z4);
1693     polyFD0        = _mm_mul_pd(FD4, z4);
1694     polyFD1        = _mm_add_pd(polyFD1, FD3);
1695     polyFD0        = _mm_add_pd(polyFD0, FD2);
1696     polyFD1        = _mm_mul_pd(polyFD1, z4);
1697     polyFD0        = _mm_mul_pd(polyFD0, z4);
1698     polyFD1        = _mm_add_pd(polyFD1, FD1);
1699     polyFD0        = _mm_add_pd(polyFD0, FD0);
1700     polyFD1        = _mm_mul_pd(polyFD1, z2);
1701     polyFD0        = _mm_add_pd(polyFD0, polyFD1);
1702
1703     polyFD0        = gmx_mm_inv_pd(polyFD0);
1704
1705     polyFN0        = _mm_mul_pd(FN10, z4);
1706     polyFN1        = _mm_mul_pd(FN9, z4);
1707     polyFN0        = _mm_add_pd(polyFN0, FN8);
1708     polyFN1        = _mm_add_pd(polyFN1, FN7);
1709     polyFN0        = _mm_mul_pd(polyFN0, z4);
1710     polyFN1        = _mm_mul_pd(polyFN1, z4);
1711     polyFN0        = _mm_add_pd(polyFN0, FN6);
1712     polyFN1        = _mm_add_pd(polyFN1, FN5);
1713     polyFN0        = _mm_mul_pd(polyFN0, z4);
1714     polyFN1        = _mm_mul_pd(polyFN1, z4);
1715     polyFN0        = _mm_add_pd(polyFN0, FN4);
1716     polyFN1        = _mm_add_pd(polyFN1, FN3);
1717     polyFN0        = _mm_mul_pd(polyFN0, z4);
1718     polyFN1        = _mm_mul_pd(polyFN1, z4);
1719     polyFN0        = _mm_add_pd(polyFN0, FN2);
1720     polyFN1        = _mm_add_pd(polyFN1, FN1);
1721     polyFN0        = _mm_mul_pd(polyFN0, z4);
1722     polyFN1        = _mm_mul_pd(polyFN1, z2);
1723     polyFN0        = _mm_add_pd(polyFN0, FN0);
1724     polyFN0        = _mm_add_pd(polyFN0, polyFN1);
1725
1726     return _mm_mul_pd(polyFN0, polyFD0);
1727 }
1728
1729
1730
1731
1732 /* Calculate the potential correction due to PME analytically.
1733  *
1734  * See gmx_mm256_pmecorrF_ps() for details about the approximation.
1735  *
1736  * This routine calculates Erf(z)/z, although you should provide z^2
1737  * as the input argument.
1738  *
1739  * Here's how it should be used:
1740  *
1741  * 1. Calculate r^2.
1742  * 2. Multiply by beta^2, so you get z^2=beta^2*r^2.
1743  * 3. Evaluate this routine with z^2 as the argument.
1744  * 4. The return value is the expression:
1745  *
1746  *
1747  *        erf(z)
1748  *       --------
1749  *          z
1750  *
1751  * 5. Multiply the entire expression by beta and switching back to r (z=r*beta):
1752  *
1753  *       erf(r*beta)
1754  *       -----------
1755  *           r
1756  *
1757  * 6. Subtract the result from 1/r, multiply by the product of the charges,
1758  *    and you have your potential.
1759  *
1760  */
1761 static __m256d
1762 gmx_mm256_pmecorrV_pd(__m256d z2)
1763 {
1764     const __m256d  VN9      = _mm256_set1_pd(-9.3723776169321855475e-13);
1765     const __m256d  VN8      = _mm256_set1_pd(1.2280156762674215741e-10);
1766     const __m256d  VN7      = _mm256_set1_pd(-7.3562157912251309487e-9);
1767     const __m256d  VN6      = _mm256_set1_pd(2.6215886208032517509e-7);
1768     const __m256d  VN5      = _mm256_set1_pd(-4.9532491651265819499e-6);
1769     const __m256d  VN4      = _mm256_set1_pd(0.00025907400778966060389);
1770     const __m256d  VN3      = _mm256_set1_pd(0.0010585044856156469792);
1771     const __m256d  VN2      = _mm256_set1_pd(0.045247661136833092885);
1772     const __m256d  VN1      = _mm256_set1_pd(0.11643931522926034421);
1773     const __m256d  VN0      = _mm256_set1_pd(1.1283791671726767970);
1774
1775     const __m256d  VD5      = _mm256_set1_pd(0.000021784709867336150342);
1776     const __m256d  VD4      = _mm256_set1_pd(0.00064293662010911388448);
1777     const __m256d  VD3      = _mm256_set1_pd(0.0096311444822588683504);
1778     const __m256d  VD2      = _mm256_set1_pd(0.085608012351550627051);
1779     const __m256d  VD1      = _mm256_set1_pd(0.43652499166614811084);
1780     const __m256d  VD0      = _mm256_set1_pd(1.0);
1781
1782     __m256d        z4;
1783     __m256d        polyVN0, polyVN1, polyVD0, polyVD1;
1784
1785     z4             = _mm256_mul_pd(z2, z2);
1786
1787     polyVD1        = _mm256_mul_pd(VD5, z4);
1788     polyVD0        = _mm256_mul_pd(VD4, z4);
1789     polyVD1        = _mm256_add_pd(polyVD1, VD3);
1790     polyVD0        = _mm256_add_pd(polyVD0, VD2);
1791     polyVD1        = _mm256_mul_pd(polyVD1, z4);
1792     polyVD0        = _mm256_mul_pd(polyVD0, z4);
1793     polyVD1        = _mm256_add_pd(polyVD1, VD1);
1794     polyVD0        = _mm256_add_pd(polyVD0, VD0);
1795     polyVD1        = _mm256_mul_pd(polyVD1, z2);
1796     polyVD0        = _mm256_add_pd(polyVD0, polyVD1);
1797
1798     polyVD0        = gmx_mm256_inv_pd(polyVD0);
1799
1800     polyVN1        = _mm256_mul_pd(VN9, z4);
1801     polyVN0        = _mm256_mul_pd(VN8, z4);
1802     polyVN1        = _mm256_add_pd(polyVN1, VN7);
1803     polyVN0        = _mm256_add_pd(polyVN0, VN6);
1804     polyVN1        = _mm256_mul_pd(polyVN1, z4);
1805     polyVN0        = _mm256_mul_pd(polyVN0, z4);
1806     polyVN1        = _mm256_add_pd(polyVN1, VN5);
1807     polyVN0        = _mm256_add_pd(polyVN0, VN4);
1808     polyVN1        = _mm256_mul_pd(polyVN1, z4);
1809     polyVN0        = _mm256_mul_pd(polyVN0, z4);
1810     polyVN1        = _mm256_add_pd(polyVN1, VN3);
1811     polyVN0        = _mm256_add_pd(polyVN0, VN2);
1812     polyVN1        = _mm256_mul_pd(polyVN1, z4);
1813     polyVN0        = _mm256_mul_pd(polyVN0, z4);
1814     polyVN1        = _mm256_add_pd(polyVN1, VN1);
1815     polyVN0        = _mm256_add_pd(polyVN0, VN0);
1816     polyVN1        = _mm256_mul_pd(polyVN1, z2);
1817     polyVN0        = _mm256_add_pd(polyVN0, polyVN1);
1818
1819     return _mm256_mul_pd(polyVN0, polyVD0);
1820 }
1821
1822
1823 static __m128d
1824 gmx_mm_pmecorrV_pd(__m128d z2)
1825 {
1826     const __m128d  VN9      = _mm_set1_pd(-9.3723776169321855475e-13);
1827     const __m128d  VN8      = _mm_set1_pd(1.2280156762674215741e-10);
1828     const __m128d  VN7      = _mm_set1_pd(-7.3562157912251309487e-9);
1829     const __m128d  VN6      = _mm_set1_pd(2.6215886208032517509e-7);
1830     const __m128d  VN5      = _mm_set1_pd(-4.9532491651265819499e-6);
1831     const __m128d  VN4      = _mm_set1_pd(0.00025907400778966060389);
1832     const __m128d  VN3      = _mm_set1_pd(0.0010585044856156469792);
1833     const __m128d  VN2      = _mm_set1_pd(0.045247661136833092885);
1834     const __m128d  VN1      = _mm_set1_pd(0.11643931522926034421);
1835     const __m128d  VN0      = _mm_set1_pd(1.1283791671726767970);
1836
1837     const __m128d  VD5      = _mm_set1_pd(0.000021784709867336150342);
1838     const __m128d  VD4      = _mm_set1_pd(0.00064293662010911388448);
1839     const __m128d  VD3      = _mm_set1_pd(0.0096311444822588683504);
1840     const __m128d  VD2      = _mm_set1_pd(0.085608012351550627051);
1841     const __m128d  VD1      = _mm_set1_pd(0.43652499166614811084);
1842     const __m128d  VD0      = _mm_set1_pd(1.0);
1843
1844     __m128d        z4;
1845     __m128d        polyVN0, polyVN1, polyVD0, polyVD1;
1846
1847     z4             = _mm_mul_pd(z2, z2);
1848
1849     polyVD1        = _mm_mul_pd(VD5, z4);
1850     polyVD0        = _mm_mul_pd(VD4, z4);
1851     polyVD1        = _mm_add_pd(polyVD1, VD3);
1852     polyVD0        = _mm_add_pd(polyVD0, VD2);
1853     polyVD1        = _mm_mul_pd(polyVD1, z4);
1854     polyVD0        = _mm_mul_pd(polyVD0, z4);
1855     polyVD1        = _mm_add_pd(polyVD1, VD1);
1856     polyVD0        = _mm_add_pd(polyVD0, VD0);
1857     polyVD1        = _mm_mul_pd(polyVD1, z2);
1858     polyVD0        = _mm_add_pd(polyVD0, polyVD1);
1859
1860     polyVD0        = gmx_mm_inv_pd(polyVD0);
1861
1862     polyVN1        = _mm_mul_pd(VN9, z4);
1863     polyVN0        = _mm_mul_pd(VN8, z4);
1864     polyVN1        = _mm_add_pd(polyVN1, VN7);
1865     polyVN0        = _mm_add_pd(polyVN0, VN6);
1866     polyVN1        = _mm_mul_pd(polyVN1, z4);
1867     polyVN0        = _mm_mul_pd(polyVN0, z4);
1868     polyVN1        = _mm_add_pd(polyVN1, VN5);
1869     polyVN0        = _mm_add_pd(polyVN0, VN4);
1870     polyVN1        = _mm_mul_pd(polyVN1, z4);
1871     polyVN0        = _mm_mul_pd(polyVN0, z4);
1872     polyVN1        = _mm_add_pd(polyVN1, VN3);
1873     polyVN0        = _mm_add_pd(polyVN0, VN2);
1874     polyVN1        = _mm_mul_pd(polyVN1, z4);
1875     polyVN0        = _mm_mul_pd(polyVN0, z4);
1876     polyVN1        = _mm_add_pd(polyVN1, VN1);
1877     polyVN0        = _mm_add_pd(polyVN0, VN0);
1878     polyVN1        = _mm_mul_pd(polyVN1, z2);
1879     polyVN0        = _mm_add_pd(polyVN0, polyVN1);
1880
1881     return _mm_mul_pd(polyVN0, polyVD0);
1882 }
1883
1884
1885
1886 static int
1887 gmx_mm256_sincos_pd(__m256d  x,
1888                     __m256d *sinval,
1889                     __m256d *cosval)
1890 {
1891 #ifdef _MSC_VER
1892     __declspec(align(16))
1893     const double sintable[34] =
1894     {
1895         1.00000000000000000e+00, 0.00000000000000000e+00,
1896         9.95184726672196929e-01, 9.80171403295606036e-02,
1897         9.80785280403230431e-01, 1.95090322016128248e-01,
1898         9.56940335732208824e-01, 2.90284677254462331e-01,
1899         9.23879532511286738e-01, 3.82683432365089782e-01,
1900         8.81921264348355050e-01, 4.71396736825997642e-01,
1901         8.31469612302545236e-01, 5.55570233019602178e-01,
1902         7.73010453362736993e-01, 6.34393284163645488e-01,
1903         7.07106781186547573e-01, 7.07106781186547462e-01,
1904         6.34393284163645599e-01, 7.73010453362736882e-01,
1905         5.55570233019602289e-01, 8.31469612302545125e-01,
1906         4.71396736825997809e-01, 8.81921264348354939e-01,
1907         3.82683432365089837e-01, 9.23879532511286738e-01,
1908         2.90284677254462276e-01, 9.56940335732208935e-01,
1909         1.95090322016128304e-01, 9.80785280403230431e-01,
1910         9.80171403295607702e-02, 9.95184726672196818e-01,
1911         0.0, 1.00000000000000000e+00
1912     };
1913 #else
1914     const __m128d sintable[17] =
1915     {
1916         _mm_set_pd( 0.0, 1.0 ),
1917         _mm_set_pd( sin(  1.0 * (M_PI/2.0) / 16.0), cos(  1.0 * (M_PI/2.0) / 16.0) ),
1918         _mm_set_pd( sin(  2.0 * (M_PI/2.0) / 16.0), cos(  2.0 * (M_PI/2.0) / 16.0) ),
1919         _mm_set_pd( sin(  3.0 * (M_PI/2.0) / 16.0), cos(  3.0 * (M_PI/2.0) / 16.0) ),
1920         _mm_set_pd( sin(  4.0 * (M_PI/2.0) / 16.0), cos(  4.0 * (M_PI/2.0) / 16.0) ),
1921         _mm_set_pd( sin(  5.0 * (M_PI/2.0) / 16.0), cos(  5.0 * (M_PI/2.0) / 16.0) ),
1922         _mm_set_pd( sin(  6.0 * (M_PI/2.0) / 16.0), cos(  6.0 * (M_PI/2.0) / 16.0) ),
1923         _mm_set_pd( sin(  7.0 * (M_PI/2.0) / 16.0), cos(  7.0 * (M_PI/2.0) / 16.0) ),
1924         _mm_set_pd( sin(  8.0 * (M_PI/2.0) / 16.0), cos(  8.0 * (M_PI/2.0) / 16.0) ),
1925         _mm_set_pd( sin(  9.0 * (M_PI/2.0) / 16.0), cos(  9.0 * (M_PI/2.0) / 16.0) ),
1926         _mm_set_pd( sin( 10.0 * (M_PI/2.0) / 16.0), cos( 10.0 * (M_PI/2.0) / 16.0) ),
1927         _mm_set_pd( sin( 11.0 * (M_PI/2.0) / 16.0), cos( 11.0 * (M_PI/2.0) / 16.0) ),
1928         _mm_set_pd( sin( 12.0 * (M_PI/2.0) / 16.0), cos( 12.0 * (M_PI/2.0) / 16.0) ),
1929         _mm_set_pd( sin( 13.0 * (M_PI/2.0) / 16.0), cos( 13.0 * (M_PI/2.0) / 16.0) ),
1930         _mm_set_pd( sin( 14.0 * (M_PI/2.0) / 16.0), cos( 14.0 * (M_PI/2.0) / 16.0) ),
1931         _mm_set_pd( sin( 15.0 * (M_PI/2.0) / 16.0), cos( 15.0 * (M_PI/2.0) / 16.0) ),
1932         _mm_set_pd(  1.0, 0.0 )
1933     };
1934 #endif
1935
1936     const __m256d signmask    = _mm256_castsi256_pd( _mm256_set_epi32(0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF,
1937                                                                       0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF) );
1938
1939     const __m256d tabscale      = _mm256_set1_pd(32.0/M_PI);
1940     const __m256d invtabscale0  = _mm256_set1_pd(9.81747508049011230469e-02);
1941     const __m256d invtabscale1  = _mm256_set1_pd(1.96197799156550576057e-08);
1942     const __m128i ione          = _mm_set1_epi32(1);
1943     const __m128i i32           = _mm_set1_epi32(32);
1944     const __m128i i16           = _mm_set1_epi32(16);
1945     const __m128i tabmask       = _mm_set1_epi32(0x3F);
1946     const __m256d sinP7         = _mm256_set1_pd(-1.0/5040.0);
1947     const __m256d sinP5         = _mm256_set1_pd(1.0/120.0);
1948     const __m256d sinP3         = _mm256_set1_pd(-1.0/6.0);
1949     const __m256d sinP1         = _mm256_set1_pd(1.0);
1950
1951     const __m256d cosP6         = _mm256_set1_pd(-1.0/720.0);
1952     const __m256d cosP4         = _mm256_set1_pd(1.0/24.0);
1953     const __m256d cosP2         = _mm256_set1_pd(-1.0/2.0);
1954     const __m256d cosP0         = _mm256_set1_pd(1.0);
1955
1956     __m256d       scalex;
1957     __m128i       tabidx, corridx;
1958     __m256d       xabs, z, z2, polySin, polyCos;
1959     __m256d       xpoint;
1960     __m256d       t1, t2;
1961
1962     __m256d       sinpoint, cospoint;
1963     __m256d       xsign, ssign, csign;
1964     __m128i       imask, sswapsign, cswapsign;
1965
1966     xsign    = _mm256_andnot_pd(signmask, x);
1967     xabs     = _mm256_and_pd(x, signmask);
1968
1969     scalex   = _mm256_mul_pd(tabscale, xabs);
1970     tabidx   = _mm256_cvtpd_epi32(scalex);
1971
1972     xpoint   = _mm256_round_pd(scalex, _MM_FROUND_TO_NEAREST_INT);
1973
1974     /* Extended precision arithmetics */
1975     z        = _mm256_sub_pd(xabs, _mm256_mul_pd(invtabscale0, xpoint));
1976     z        = _mm256_sub_pd(z, _mm256_mul_pd(invtabscale1, xpoint));
1977
1978     /* Range reduction to 0..2*Pi */
1979     tabidx   = _mm_and_si128(tabidx, tabmask);
1980
1981     /* tabidx is now in range [0,..,64] */
1982     imask     = _mm_cmpgt_epi32(tabidx, i32);
1983     sswapsign = imask;
1984     cswapsign = imask;
1985     corridx   = _mm_and_si128(imask, i32);
1986     tabidx    = _mm_sub_epi32(tabidx, corridx);
1987
1988     /* tabidx is now in range [0..32] */
1989     imask     = _mm_cmpgt_epi32(tabidx, i16);
1990     cswapsign = _mm_xor_si128(cswapsign, imask);
1991     corridx   = _mm_sub_epi32(i32, tabidx);
1992     tabidx    = _mm_blendv_epi8(tabidx, corridx, imask);
1993     /* tabidx is now in range [0..16] */
1994     ssign     = _mm256_cvtepi32_pd( _mm_or_si128( sswapsign, ione ) );
1995     csign     = _mm256_cvtepi32_pd( _mm_or_si128( cswapsign, ione ) );
1996
1997     /* First lookup into table */
1998 #ifdef _MSC_VER
1999     t1       = _mm256_insertf128_pd(_mm256_castpd128_pd256(_mm_load_pd(sintable + 2*_mm_extract_epi32(tabidx, 0))),
2000                                     _mm_load_pd(sintable + 2*_mm_extract_epi32(tabidx, 2)), 0x1);
2001     t2       = _mm256_insertf128_pd(_mm256_castpd128_pd256(_mm_load_pd(sintable + 2*_mm_extract_epi32(tabidx, 1))),
2002                                     _mm_load_pd(sintable + 2*_mm_extract_epi32(tabidx, 3)), 0x1);
2003 #else
2004     t1       = _mm256_insertf128_pd(_mm256_castpd128_pd256(sintable[_mm_extract_epi32(tabidx, 0)]),
2005                                     sintable[_mm_extract_epi32(tabidx, 2)], 0x1);
2006     t2       = _mm256_insertf128_pd(_mm256_castpd128_pd256(sintable[_mm_extract_epi32(tabidx, 1)]),
2007                                     sintable[_mm_extract_epi32(tabidx, 3)], 0x1);
2008 #endif
2009
2010     sinpoint  = _mm256_unpackhi_pd(t1, t2);
2011     cospoint  = _mm256_unpacklo_pd(t1, t2);
2012
2013     sinpoint = _mm256_mul_pd(sinpoint, ssign);
2014     cospoint = _mm256_mul_pd(cospoint, csign);
2015
2016     z2       = _mm256_mul_pd(z, z);
2017
2018     polySin  = _mm256_mul_pd(sinP7, z2);
2019     polySin  = _mm256_add_pd(polySin, sinP5);
2020     polySin  = _mm256_mul_pd(polySin, z2);
2021     polySin  = _mm256_add_pd(polySin, sinP3);
2022     polySin  = _mm256_mul_pd(polySin, z2);
2023     polySin  = _mm256_add_pd(polySin, sinP1);
2024     polySin  = _mm256_mul_pd(polySin, z);
2025
2026     polyCos  = _mm256_mul_pd(cosP6, z2);
2027     polyCos  = _mm256_add_pd(polyCos, cosP4);
2028     polyCos  = _mm256_mul_pd(polyCos, z2);
2029     polyCos  = _mm256_add_pd(polyCos, cosP2);
2030     polyCos  = _mm256_mul_pd(polyCos, z2);
2031     polyCos  = _mm256_add_pd(polyCos, cosP0);
2032
2033     *sinval  = _mm256_xor_pd(_mm256_add_pd( _mm256_mul_pd(sinpoint, polyCos), _mm256_mul_pd(cospoint, polySin) ), xsign);
2034     *cosval  = _mm256_sub_pd( _mm256_mul_pd(cospoint, polyCos), _mm256_mul_pd(sinpoint, polySin) );
2035
2036     return 0;
2037 }
2038
2039 static int
2040 gmx_mm_sincos_pd(__m128d  x,
2041                  __m128d *sinval,
2042                  __m128d *cosval)
2043 {
2044 #ifdef _MSC_VER
2045     __declspec(align(16))
2046     const double sintable[34] =
2047     {
2048         1.00000000000000000e+00, 0.00000000000000000e+00,
2049         9.95184726672196929e-01, 9.80171403295606036e-02,
2050         9.80785280403230431e-01, 1.95090322016128248e-01,
2051         9.56940335732208824e-01, 2.90284677254462331e-01,
2052         9.23879532511286738e-01, 3.82683432365089782e-01,
2053         8.81921264348355050e-01, 4.71396736825997642e-01,
2054         8.31469612302545236e-01, 5.55570233019602178e-01,
2055         7.73010453362736993e-01, 6.34393284163645488e-01,
2056         7.07106781186547573e-01, 7.07106781186547462e-01,
2057         6.34393284163645599e-01, 7.73010453362736882e-01,
2058         5.55570233019602289e-01, 8.31469612302545125e-01,
2059         4.71396736825997809e-01, 8.81921264348354939e-01,
2060         3.82683432365089837e-01, 9.23879532511286738e-01,
2061         2.90284677254462276e-01, 9.56940335732208935e-01,
2062         1.95090322016128304e-01, 9.80785280403230431e-01,
2063         9.80171403295607702e-02, 9.95184726672196818e-01,
2064         0.0, 1.00000000000000000e+00
2065     };
2066 #else
2067     const __m128d sintable[17] =
2068     {
2069         _mm_set_pd( 0.0, 1.0 ),
2070         _mm_set_pd( sin(  1.0 * (M_PI/2.0) / 16.0), cos(  1.0 * (M_PI/2.0) / 16.0) ),
2071         _mm_set_pd( sin(  2.0 * (M_PI/2.0) / 16.0), cos(  2.0 * (M_PI/2.0) / 16.0) ),
2072         _mm_set_pd( sin(  3.0 * (M_PI/2.0) / 16.0), cos(  3.0 * (M_PI/2.0) / 16.0) ),
2073         _mm_set_pd( sin(  4.0 * (M_PI/2.0) / 16.0), cos(  4.0 * (M_PI/2.0) / 16.0) ),
2074         _mm_set_pd( sin(  5.0 * (M_PI/2.0) / 16.0), cos(  5.0 * (M_PI/2.0) / 16.0) ),
2075         _mm_set_pd( sin(  6.0 * (M_PI/2.0) / 16.0), cos(  6.0 * (M_PI/2.0) / 16.0) ),
2076         _mm_set_pd( sin(  7.0 * (M_PI/2.0) / 16.0), cos(  7.0 * (M_PI/2.0) / 16.0) ),
2077         _mm_set_pd( sin(  8.0 * (M_PI/2.0) / 16.0), cos(  8.0 * (M_PI/2.0) / 16.0) ),
2078         _mm_set_pd( sin(  9.0 * (M_PI/2.0) / 16.0), cos(  9.0 * (M_PI/2.0) / 16.0) ),
2079         _mm_set_pd( sin( 10.0 * (M_PI/2.0) / 16.0), cos( 10.0 * (M_PI/2.0) / 16.0) ),
2080         _mm_set_pd( sin( 11.0 * (M_PI/2.0) / 16.0), cos( 11.0 * (M_PI/2.0) / 16.0) ),
2081         _mm_set_pd( sin( 12.0 * (M_PI/2.0) / 16.0), cos( 12.0 * (M_PI/2.0) / 16.0) ),
2082         _mm_set_pd( sin( 13.0 * (M_PI/2.0) / 16.0), cos( 13.0 * (M_PI/2.0) / 16.0) ),
2083         _mm_set_pd( sin( 14.0 * (M_PI/2.0) / 16.0), cos( 14.0 * (M_PI/2.0) / 16.0) ),
2084         _mm_set_pd( sin( 15.0 * (M_PI/2.0) / 16.0), cos( 15.0 * (M_PI/2.0) / 16.0) ),
2085         _mm_set_pd(  1.0, 0.0 )
2086     };
2087 #endif
2088
2089     const __m128d signmask       = gmx_mm_castsi128_pd( _mm_set_epi32(0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF) );
2090
2091     const __m128d tabscale      = _mm_set1_pd(32.0/M_PI);
2092     const __m128d invtabscale0  = _mm_set1_pd(9.81747508049011230469e-02);
2093     const __m128d invtabscale1  = _mm_set1_pd(1.96197799156550576057e-08);
2094     const __m128i ione          = _mm_set1_epi32(1);
2095     const __m128i i32           = _mm_set1_epi32(32);
2096     const __m128i i16           = _mm_set1_epi32(16);
2097     const __m128i tabmask       = _mm_set1_epi32(0x3F);
2098     const __m128d sinP7         = _mm_set1_pd(-1.0/5040.0);
2099     const __m128d sinP5         = _mm_set1_pd(1.0/120.0);
2100     const __m128d sinP3         = _mm_set1_pd(-1.0/6.0);
2101     const __m128d sinP1         = _mm_set1_pd(1.0);
2102
2103     const __m128d cosP6         = _mm_set1_pd(-1.0/720.0);
2104     const __m128d cosP4         = _mm_set1_pd(1.0/24.0);
2105     const __m128d cosP2         = _mm_set1_pd(-1.0/2.0);
2106     const __m128d cosP0         = _mm_set1_pd(1.0);
2107
2108     __m128d       scalex;
2109     __m128i       tabidx, corridx;
2110     __m128d       xabs, z, z2, polySin, polyCos;
2111     __m128d       xpoint;
2112     __m128d       ypoint0, ypoint1;
2113
2114     __m128d       sinpoint, cospoint;
2115     __m128d       xsign, ssign, csign;
2116     __m128i       imask, sswapsign, cswapsign;
2117
2118     xsign    = _mm_andnot_pd(signmask, x);
2119     xabs     = _mm_and_pd(x, signmask);
2120
2121     scalex   = _mm_mul_pd(tabscale, xabs);
2122     tabidx   = _mm_cvtpd_epi32(scalex);
2123
2124     xpoint   = _mm_round_pd(scalex, _MM_FROUND_TO_NEAREST_INT);
2125
2126     /* Extended precision arithmetics */
2127     z        = _mm_sub_pd(xabs, _mm_mul_pd(invtabscale0, xpoint));
2128     z        = _mm_sub_pd(z, _mm_mul_pd(invtabscale1, xpoint));
2129
2130     /* Range reduction to 0..2*Pi */
2131     tabidx   = _mm_and_si128(tabidx, tabmask);
2132
2133     /* tabidx is now in range [0,..,64] */
2134     imask     = _mm_cmpgt_epi32(tabidx, i32);
2135     sswapsign = imask;
2136     cswapsign = imask;
2137     corridx   = _mm_and_si128(imask, i32);
2138     tabidx    = _mm_sub_epi32(tabidx, corridx);
2139
2140     /* tabidx is now in range [0..32] */
2141     imask     = _mm_cmpgt_epi32(tabidx, i16);
2142     cswapsign = _mm_xor_si128(cswapsign, imask);
2143     corridx   = _mm_sub_epi32(i32, tabidx);
2144     tabidx    = _mm_blendv_epi8(tabidx, corridx, imask);
2145     /* tabidx is now in range [0..16] */
2146     ssign     = _mm_cvtepi32_pd( _mm_or_si128( sswapsign, ione ) );
2147     csign     = _mm_cvtepi32_pd( _mm_or_si128( cswapsign, ione ) );
2148
2149 #ifdef _MSC_VER
2150     ypoint0  = _mm_load_pd(sintable + 2*_mm_extract_epi32(tabidx, 0));
2151     ypoint1  = _mm_load_pd(sintable + 2*_mm_extract_epi32(tabidx, 1));
2152 #else
2153     ypoint0  = sintable[_mm_extract_epi32(tabidx, 0)];
2154     ypoint1  = sintable[_mm_extract_epi32(tabidx, 1)];
2155 #endif
2156     sinpoint = _mm_unpackhi_pd(ypoint0, ypoint1);
2157     cospoint = _mm_unpacklo_pd(ypoint0, ypoint1);
2158
2159     sinpoint = _mm_mul_pd(sinpoint, ssign);
2160     cospoint = _mm_mul_pd(cospoint, csign);
2161
2162     z2       = _mm_mul_pd(z, z);
2163
2164     polySin  = _mm_mul_pd(sinP7, z2);
2165     polySin  = _mm_add_pd(polySin, sinP5);
2166     polySin  = _mm_mul_pd(polySin, z2);
2167     polySin  = _mm_add_pd(polySin, sinP3);
2168     polySin  = _mm_mul_pd(polySin, z2);
2169     polySin  = _mm_add_pd(polySin, sinP1);
2170     polySin  = _mm_mul_pd(polySin, z);
2171
2172     polyCos  = _mm_mul_pd(cosP6, z2);
2173     polyCos  = _mm_add_pd(polyCos, cosP4);
2174     polyCos  = _mm_mul_pd(polyCos, z2);
2175     polyCos  = _mm_add_pd(polyCos, cosP2);
2176     polyCos  = _mm_mul_pd(polyCos, z2);
2177     polyCos  = _mm_add_pd(polyCos, cosP0);
2178
2179     *sinval  = _mm_xor_pd(_mm_add_pd( _mm_mul_pd(sinpoint, polyCos), _mm_mul_pd(cospoint, polySin) ), xsign);
2180     *cosval  = _mm_sub_pd( _mm_mul_pd(cospoint, polyCos), _mm_mul_pd(sinpoint, polySin) );
2181
2182     return 0;
2183 }
2184
2185
2186 /*
2187  * IMPORTANT: Do NOT call both sin & cos if you need both results, since each of them
2188  * will then call the sincos() routine and waste a factor 2 in performance!
2189  */
2190 static __m256d
2191 gmx_mm256_sin_pd(__m256d x)
2192 {
2193     __m256d s, c;
2194     gmx_mm256_sincos_pd(x, &s, &c);
2195     return s;
2196 }
2197
2198 static __m128d
2199 gmx_mm_sin_pd(__m128d x)
2200 {
2201     __m128d s, c;
2202     gmx_mm_sincos_pd(x, &s, &c);
2203     return s;
2204 }
2205
2206 /*
2207  * IMPORTANT: Do NOT call both sin & cos if you need both results, since each of them
2208  * will then call the sincos() routine and waste a factor 2 in performance!
2209  */
2210 static __m256d
2211 gmx_mm256_cos_pd(__m256d x)
2212 {
2213     __m256d s, c;
2214     gmx_mm256_sincos_pd(x, &s, &c);
2215     return c;
2216 }
2217
2218 static __m128d
2219 gmx_mm_cos_pd(__m128d x)
2220 {
2221     __m128d s, c;
2222     gmx_mm_sincos_pd(x, &s, &c);
2223     return c;
2224 }
2225
2226
2227 static __m256d
2228 gmx_mm256_tan_pd(__m256d x)
2229 {
2230     __m256d sinval, cosval;
2231     __m256d tanval;
2232
2233     gmx_mm256_sincos_pd(x, &sinval, &cosval);
2234
2235     tanval = _mm256_mul_pd(sinval, gmx_mm256_inv_pd(cosval));
2236
2237     return tanval;
2238 }
2239
2240 static __m128d
2241 gmx_mm_tan_pd(__m128d x)
2242 {
2243     __m128d sinval, cosval;
2244     __m128d tanval;
2245
2246     gmx_mm_sincos_pd(x, &sinval, &cosval);
2247
2248     tanval = _mm_mul_pd(sinval, gmx_mm_inv_pd(cosval));
2249
2250     return tanval;
2251 }
2252
2253
2254 static __m256d
2255 gmx_mm256_asin_pd(__m256d x)
2256 {
2257     /* Same algorithm as cephes library */
2258     const __m256d signmask  = _mm256_castsi256_pd( _mm256_set_epi32(0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF,
2259                                                                     0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF) );
2260     const __m256d limit1    = _mm256_set1_pd(0.625);
2261     const __m256d limit2    = _mm256_set1_pd(1e-8);
2262     const __m256d one       = _mm256_set1_pd(1.0);
2263     const __m256d quarterpi = _mm256_set1_pd(M_PI/4.0);
2264     const __m256d morebits  = _mm256_set1_pd(6.123233995736765886130e-17);
2265
2266     const __m256d P5        = _mm256_set1_pd(4.253011369004428248960e-3);
2267     const __m256d P4        = _mm256_set1_pd(-6.019598008014123785661e-1);
2268     const __m256d P3        = _mm256_set1_pd(5.444622390564711410273e0);
2269     const __m256d P2        = _mm256_set1_pd(-1.626247967210700244449e1);
2270     const __m256d P1        = _mm256_set1_pd(1.956261983317594739197e1);
2271     const __m256d P0        = _mm256_set1_pd(-8.198089802484824371615e0);
2272
2273     const __m256d Q4        = _mm256_set1_pd(-1.474091372988853791896e1);
2274     const __m256d Q3        = _mm256_set1_pd(7.049610280856842141659e1);
2275     const __m256d Q2        = _mm256_set1_pd(-1.471791292232726029859e2);
2276     const __m256d Q1        = _mm256_set1_pd(1.395105614657485689735e2);
2277     const __m256d Q0        = _mm256_set1_pd(-4.918853881490881290097e1);
2278
2279     const __m256d R4        = _mm256_set1_pd(2.967721961301243206100e-3);
2280     const __m256d R3        = _mm256_set1_pd(-5.634242780008963776856e-1);
2281     const __m256d R2        = _mm256_set1_pd(6.968710824104713396794e0);
2282     const __m256d R1        = _mm256_set1_pd(-2.556901049652824852289e1);
2283     const __m256d R0        = _mm256_set1_pd(2.853665548261061424989e1);
2284
2285     const __m256d S3        = _mm256_set1_pd(-2.194779531642920639778e1);
2286     const __m256d S2        = _mm256_set1_pd(1.470656354026814941758e2);
2287     const __m256d S1        = _mm256_set1_pd(-3.838770957603691357202e2);
2288     const __m256d S0        = _mm256_set1_pd(3.424398657913078477438e2);
2289
2290     __m256d       sign;
2291     __m256d       mask;
2292     __m256d       xabs;
2293     __m256d       zz, ww, z, q, w, zz2, ww2;
2294     __m256d       PA, PB;
2295     __m256d       QA, QB;
2296     __m256d       RA, RB;
2297     __m256d       SA, SB;
2298     __m256d       nom, denom;
2299
2300     sign  = _mm256_andnot_pd(signmask, x);
2301     xabs  = _mm256_and_pd(x, signmask);
2302
2303     mask  = _mm256_cmp_pd(xabs, limit1, _CMP_GT_OQ);
2304
2305     zz    = _mm256_sub_pd(one, xabs);
2306     ww    = _mm256_mul_pd(xabs, xabs);
2307     zz2   = _mm256_mul_pd(zz, zz);
2308     ww2   = _mm256_mul_pd(ww, ww);
2309
2310     /* R */
2311     RA    = _mm256_mul_pd(R4, zz2);
2312     RB    = _mm256_mul_pd(R3, zz2);
2313     RA    = _mm256_add_pd(RA, R2);
2314     RB    = _mm256_add_pd(RB, R1);
2315     RA    = _mm256_mul_pd(RA, zz2);
2316     RB    = _mm256_mul_pd(RB, zz);
2317     RA    = _mm256_add_pd(RA, R0);
2318     RA    = _mm256_add_pd(RA, RB);
2319
2320     /* S, SA = zz2 */
2321     SB    = _mm256_mul_pd(S3, zz2);
2322     SA    = _mm256_add_pd(zz2, S2);
2323     SB    = _mm256_add_pd(SB, S1);
2324     SA    = _mm256_mul_pd(SA, zz2);
2325     SB    = _mm256_mul_pd(SB, zz);
2326     SA    = _mm256_add_pd(SA, S0);
2327     SA    = _mm256_add_pd(SA, SB);
2328
2329     /* P */
2330     PA    = _mm256_mul_pd(P5, ww2);
2331     PB    = _mm256_mul_pd(P4, ww2);
2332     PA    = _mm256_add_pd(PA, P3);
2333     PB    = _mm256_add_pd(PB, P2);
2334     PA    = _mm256_mul_pd(PA, ww2);
2335     PB    = _mm256_mul_pd(PB, ww2);
2336     PA    = _mm256_add_pd(PA, P1);
2337     PB    = _mm256_add_pd(PB, P0);
2338     PA    = _mm256_mul_pd(PA, ww);
2339     PA    = _mm256_add_pd(PA, PB);
2340
2341     /* Q, QA = ww2 */
2342     QB    = _mm256_mul_pd(Q4, ww2);
2343     QA    = _mm256_add_pd(ww2, Q3);
2344     QB    = _mm256_add_pd(QB, Q2);
2345     QA    = _mm256_mul_pd(QA, ww2);
2346     QB    = _mm256_mul_pd(QB, ww2);
2347     QA    = _mm256_add_pd(QA, Q1);
2348     QB    = _mm256_add_pd(QB, Q0);
2349     QA    = _mm256_mul_pd(QA, ww);
2350     QA    = _mm256_add_pd(QA, QB);
2351
2352     RA    = _mm256_mul_pd(RA, zz);
2353     PA    = _mm256_mul_pd(PA, ww);
2354
2355     nom   = _mm256_blendv_pd( PA, RA, mask );
2356     denom = _mm256_blendv_pd( QA, SA, mask );
2357
2358     q     = _mm256_mul_pd( nom, gmx_mm256_inv_pd(denom) );
2359
2360     zz    = _mm256_add_pd(zz, zz);
2361     zz    = gmx_mm256_sqrt_pd(zz);
2362     z     = _mm256_sub_pd(quarterpi, zz);
2363     zz    = _mm256_mul_pd(zz, q);
2364     zz    = _mm256_sub_pd(zz, morebits);
2365     z     = _mm256_sub_pd(z, zz);
2366     z     = _mm256_add_pd(z, quarterpi);
2367
2368     w     = _mm256_mul_pd(xabs, q);
2369     w     = _mm256_add_pd(w, xabs);
2370
2371     z     = _mm256_blendv_pd( w, z, mask );
2372
2373     mask  = _mm256_cmp_pd(xabs, limit2, _CMP_GT_OQ);
2374     z     = _mm256_blendv_pd( xabs, z, mask );
2375
2376     z = _mm256_xor_pd(z, sign);
2377
2378     return z;
2379 }
2380
2381 static __m128d
2382 gmx_mm_asin_pd(__m128d x)
2383 {
2384     /* Same algorithm as cephes library */
2385     const __m128d signmask  = gmx_mm_castsi128_pd( _mm_set_epi32(0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF) );
2386     const __m128d limit1    = _mm_set1_pd(0.625);
2387     const __m128d limit2    = _mm_set1_pd(1e-8);
2388     const __m128d one       = _mm_set1_pd(1.0);
2389     const __m128d quarterpi = _mm_set1_pd(M_PI/4.0);
2390     const __m128d morebits  = _mm_set1_pd(6.123233995736765886130e-17);
2391
2392     const __m128d P5        = _mm_set1_pd(4.253011369004428248960e-3);
2393     const __m128d P4        = _mm_set1_pd(-6.019598008014123785661e-1);
2394     const __m128d P3        = _mm_set1_pd(5.444622390564711410273e0);
2395     const __m128d P2        = _mm_set1_pd(-1.626247967210700244449e1);
2396     const __m128d P1        = _mm_set1_pd(1.956261983317594739197e1);
2397     const __m128d P0        = _mm_set1_pd(-8.198089802484824371615e0);
2398
2399     const __m128d Q4        = _mm_set1_pd(-1.474091372988853791896e1);
2400     const __m128d Q3        = _mm_set1_pd(7.049610280856842141659e1);
2401     const __m128d Q2        = _mm_set1_pd(-1.471791292232726029859e2);
2402     const __m128d Q1        = _mm_set1_pd(1.395105614657485689735e2);
2403     const __m128d Q0        = _mm_set1_pd(-4.918853881490881290097e1);
2404
2405     const __m128d R4        = _mm_set1_pd(2.967721961301243206100e-3);
2406     const __m128d R3        = _mm_set1_pd(-5.634242780008963776856e-1);
2407     const __m128d R2        = _mm_set1_pd(6.968710824104713396794e0);
2408     const __m128d R1        = _mm_set1_pd(-2.556901049652824852289e1);
2409     const __m128d R0        = _mm_set1_pd(2.853665548261061424989e1);
2410
2411     const __m128d S3        = _mm_set1_pd(-2.194779531642920639778e1);
2412     const __m128d S2        = _mm_set1_pd(1.470656354026814941758e2);
2413     const __m128d S1        = _mm_set1_pd(-3.838770957603691357202e2);
2414     const __m128d S0        = _mm_set1_pd(3.424398657913078477438e2);
2415
2416     __m128d       sign;
2417     __m128d       mask;
2418     __m128d       xabs;
2419     __m128d       zz, ww, z, q, w, zz2, ww2;
2420     __m128d       PA, PB;
2421     __m128d       QA, QB;
2422     __m128d       RA, RB;
2423     __m128d       SA, SB;
2424     __m128d       nom, denom;
2425
2426     sign  = _mm_andnot_pd(signmask, x);
2427     xabs  = _mm_and_pd(x, signmask);
2428
2429     mask  = _mm_cmpgt_pd(xabs, limit1);
2430
2431     zz    = _mm_sub_pd(one, xabs);
2432     ww    = _mm_mul_pd(xabs, xabs);
2433     zz2   = _mm_mul_pd(zz, zz);
2434     ww2   = _mm_mul_pd(ww, ww);
2435
2436     /* R */
2437     RA    = _mm_mul_pd(R4, zz2);
2438     RB    = _mm_mul_pd(R3, zz2);
2439     RA    = _mm_add_pd(RA, R2);
2440     RB    = _mm_add_pd(RB, R1);
2441     RA    = _mm_mul_pd(RA, zz2);
2442     RB    = _mm_mul_pd(RB, zz);
2443     RA    = _mm_add_pd(RA, R0);
2444     RA    = _mm_add_pd(RA, RB);
2445
2446     /* S, SA = zz2 */
2447     SB    = _mm_mul_pd(S3, zz2);
2448     SA    = _mm_add_pd(zz2, S2);
2449     SB    = _mm_add_pd(SB, S1);
2450     SA    = _mm_mul_pd(SA, zz2);
2451     SB    = _mm_mul_pd(SB, zz);
2452     SA    = _mm_add_pd(SA, S0);
2453     SA    = _mm_add_pd(SA, SB);
2454
2455     /* P */
2456     PA    = _mm_mul_pd(P5, ww2);
2457     PB    = _mm_mul_pd(P4, ww2);
2458     PA    = _mm_add_pd(PA, P3);
2459     PB    = _mm_add_pd(PB, P2);
2460     PA    = _mm_mul_pd(PA, ww2);
2461     PB    = _mm_mul_pd(PB, ww2);
2462     PA    = _mm_add_pd(PA, P1);
2463     PB    = _mm_add_pd(PB, P0);
2464     PA    = _mm_mul_pd(PA, ww);
2465     PA    = _mm_add_pd(PA, PB);
2466
2467     /* Q, QA = ww2 */
2468     QB    = _mm_mul_pd(Q4, ww2);
2469     QA    = _mm_add_pd(ww2, Q3);
2470     QB    = _mm_add_pd(QB, Q2);
2471     QA    = _mm_mul_pd(QA, ww2);
2472     QB    = _mm_mul_pd(QB, ww2);
2473     QA    = _mm_add_pd(QA, Q1);
2474     QB    = _mm_add_pd(QB, Q0);
2475     QA    = _mm_mul_pd(QA, ww);
2476     QA    = _mm_add_pd(QA, QB);
2477
2478     RA    = _mm_mul_pd(RA, zz);
2479     PA    = _mm_mul_pd(PA, ww);
2480
2481     nom   = _mm_blendv_pd( PA, RA, mask );
2482     denom = _mm_blendv_pd( QA, SA, mask );
2483
2484     q     = _mm_mul_pd( nom, gmx_mm_inv_pd(denom) );
2485
2486     zz    = _mm_add_pd(zz, zz);
2487     zz    = gmx_mm_sqrt_pd(zz);
2488     z     = _mm_sub_pd(quarterpi, zz);
2489     zz    = _mm_mul_pd(zz, q);
2490     zz    = _mm_sub_pd(zz, morebits);
2491     z     = _mm_sub_pd(z, zz);
2492     z     = _mm_add_pd(z, quarterpi);
2493
2494     w     = _mm_mul_pd(xabs, q);
2495     w     = _mm_add_pd(w, xabs);
2496
2497     z     = _mm_blendv_pd( w, z, mask );
2498
2499     mask  = _mm_cmpgt_pd(xabs, limit2);
2500     z     = _mm_blendv_pd( xabs, z, mask );
2501
2502     z = _mm_xor_pd(z, sign);
2503
2504     return z;
2505 }
2506
2507
2508 static __m256d
2509 gmx_mm256_acos_pd(__m256d x)
2510 {
2511     const __m256d one        = _mm256_set1_pd(1.0);
2512     const __m256d half       = _mm256_set1_pd(0.5);
2513     const __m256d quarterpi0 = _mm256_set1_pd(7.85398163397448309616e-1);
2514     const __m256d quarterpi1 = _mm256_set1_pd(6.123233995736765886130e-17);
2515
2516
2517     __m256d mask1;
2518
2519     __m256d z, z1, z2;
2520
2521     mask1 = _mm256_cmp_pd(x, half, _CMP_GT_OQ);
2522     z1    = _mm256_mul_pd(half, _mm256_sub_pd(one, x));
2523     z1    = gmx_mm256_sqrt_pd(z1);
2524     z     = _mm256_blendv_pd( x, z1, mask1 );
2525
2526     z     = gmx_mm256_asin_pd(z);
2527
2528     z1    = _mm256_add_pd(z, z);
2529
2530     z2    = _mm256_sub_pd(quarterpi0, z);
2531     z2    = _mm256_add_pd(z2, quarterpi1);
2532     z2    = _mm256_add_pd(z2, quarterpi0);
2533
2534     z     = _mm256_blendv_pd(z2, z1, mask1);
2535
2536     return z;
2537 }
2538
2539 static __m128d
2540 gmx_mm_acos_pd(__m128d x)
2541 {
2542     const __m128d one        = _mm_set1_pd(1.0);
2543     const __m128d half       = _mm_set1_pd(0.5);
2544     const __m128d quarterpi0 = _mm_set1_pd(7.85398163397448309616e-1);
2545     const __m128d quarterpi1 = _mm_set1_pd(6.123233995736765886130e-17);
2546
2547
2548     __m128d mask1;
2549
2550     __m128d z, z1, z2;
2551
2552     mask1 = _mm_cmpgt_pd(x, half);
2553     z1    = _mm_mul_pd(half, _mm_sub_pd(one, x));
2554     z1    = gmx_mm_sqrt_pd(z1);
2555     z     = _mm_blendv_pd( x, z1, mask1 );
2556
2557     z     = gmx_mm_asin_pd(z);
2558
2559     z1    = _mm_add_pd(z, z);
2560
2561     z2    = _mm_sub_pd(quarterpi0, z);
2562     z2    = _mm_add_pd(z2, quarterpi1);
2563     z2    = _mm_add_pd(z2, quarterpi0);
2564
2565     z     = _mm_blendv_pd(z2, z1, mask1);
2566
2567     return z;
2568 }
2569
2570
2571 static __m256d
2572 gmx_mm256_atan_pd(__m256d x)
2573 {
2574     /* Same algorithm as cephes library */
2575     const __m256d signmask  = _mm256_castsi256_pd( _mm256_set_epi32(0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF,
2576                                                                     0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF) );
2577     const __m256d limit1    = _mm256_set1_pd(0.66);
2578     const __m256d limit2    = _mm256_set1_pd(2.41421356237309504880);
2579     const __m256d quarterpi = _mm256_set1_pd(M_PI/4.0);
2580     const __m256d halfpi    = _mm256_set1_pd(M_PI/2.0);
2581     const __m256d mone      = _mm256_set1_pd(-1.0);
2582     const __m256d morebits1 = _mm256_set1_pd(0.5*6.123233995736765886130E-17);
2583     const __m256d morebits2 = _mm256_set1_pd(6.123233995736765886130E-17);
2584
2585     const __m256d P4        = _mm256_set1_pd(-8.750608600031904122785E-1);
2586     const __m256d P3        = _mm256_set1_pd(-1.615753718733365076637E1);
2587     const __m256d P2        = _mm256_set1_pd(-7.500855792314704667340E1);
2588     const __m256d P1        = _mm256_set1_pd(-1.228866684490136173410E2);
2589     const __m256d P0        = _mm256_set1_pd(-6.485021904942025371773E1);
2590
2591     const __m256d Q4        = _mm256_set1_pd(2.485846490142306297962E1);
2592     const __m256d Q3        = _mm256_set1_pd(1.650270098316988542046E2);
2593     const __m256d Q2        = _mm256_set1_pd(4.328810604912902668951E2);
2594     const __m256d Q1        = _mm256_set1_pd(4.853903996359136964868E2);
2595     const __m256d Q0        = _mm256_set1_pd(1.945506571482613964425E2);
2596
2597     __m256d       sign;
2598     __m256d       mask1, mask2;
2599     __m256d       y, t1, t2;
2600     __m256d       z, z2;
2601     __m256d       P_A, P_B, Q_A, Q_B;
2602
2603     sign   = _mm256_andnot_pd(signmask, x);
2604     x      = _mm256_and_pd(x, signmask);
2605
2606     mask1  = _mm256_cmp_pd(x, limit1, _CMP_GT_OQ);
2607     mask2  = _mm256_cmp_pd(x, limit2, _CMP_GT_OQ);
2608
2609     t1     = _mm256_mul_pd(_mm256_add_pd(x, mone), gmx_mm256_inv_pd(_mm256_sub_pd(x, mone)));
2610     t2     = _mm256_mul_pd(mone, gmx_mm256_inv_pd(x));
2611
2612     y      = _mm256_and_pd(mask1, quarterpi);
2613     y      = _mm256_or_pd( _mm256_and_pd(mask2, halfpi), _mm256_andnot_pd(mask2, y) );
2614
2615     x      = _mm256_or_pd( _mm256_and_pd(mask1, t1), _mm256_andnot_pd(mask1, x) );
2616     x      = _mm256_or_pd( _mm256_and_pd(mask2, t2), _mm256_andnot_pd(mask2, x) );
2617
2618     z      = _mm256_mul_pd(x, x);
2619     z2     = _mm256_mul_pd(z, z);
2620
2621     P_A    = _mm256_mul_pd(P4, z2);
2622     P_B    = _mm256_mul_pd(P3, z2);
2623     P_A    = _mm256_add_pd(P_A, P2);
2624     P_B    = _mm256_add_pd(P_B, P1);
2625     P_A    = _mm256_mul_pd(P_A, z2);
2626     P_B    = _mm256_mul_pd(P_B, z);
2627     P_A    = _mm256_add_pd(P_A, P0);
2628     P_A    = _mm256_add_pd(P_A, P_B);
2629
2630     /* Q_A = z2 */
2631     Q_B    = _mm256_mul_pd(Q4, z2);
2632     Q_A    = _mm256_add_pd(z2, Q3);
2633     Q_B    = _mm256_add_pd(Q_B, Q2);
2634     Q_A    = _mm256_mul_pd(Q_A, z2);
2635     Q_B    = _mm256_mul_pd(Q_B, z2);
2636     Q_A    = _mm256_add_pd(Q_A, Q1);
2637     Q_B    = _mm256_add_pd(Q_B, Q0);
2638     Q_A    = _mm256_mul_pd(Q_A, z);
2639     Q_A    = _mm256_add_pd(Q_A, Q_B);
2640
2641     z      = _mm256_mul_pd(z, P_A);
2642     z      = _mm256_mul_pd(z, gmx_mm256_inv_pd(Q_A));
2643     z      = _mm256_mul_pd(z, x);
2644     z      = _mm256_add_pd(z, x);
2645
2646     t1     = _mm256_and_pd(mask1, morebits1);
2647     t1     = _mm256_or_pd( _mm256_and_pd(mask2, morebits2), _mm256_andnot_pd(mask2, t1) );
2648
2649     z      = _mm256_add_pd(z, t1);
2650     y      = _mm256_add_pd(y, z);
2651
2652     y      = _mm256_xor_pd(y, sign);
2653
2654     return y;
2655 }
2656
2657 static __m128d
2658 gmx_mm_atan_pd(__m128d x)
2659 {
2660     /* Same algorithm as cephes library */
2661     const __m128d signmask  = gmx_mm_castsi128_pd( _mm_set_epi32(0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF) );
2662     const __m128d limit1    = _mm_set1_pd(0.66);
2663     const __m128d limit2    = _mm_set1_pd(2.41421356237309504880);
2664     const __m128d quarterpi = _mm_set1_pd(M_PI/4.0);
2665     const __m128d halfpi    = _mm_set1_pd(M_PI/2.0);
2666     const __m128d mone      = _mm_set1_pd(-1.0);
2667     const __m128d morebits1 = _mm_set1_pd(0.5*6.123233995736765886130E-17);
2668     const __m128d morebits2 = _mm_set1_pd(6.123233995736765886130E-17);
2669
2670     const __m128d P4        = _mm_set1_pd(-8.750608600031904122785E-1);
2671     const __m128d P3        = _mm_set1_pd(-1.615753718733365076637E1);
2672     const __m128d P2        = _mm_set1_pd(-7.500855792314704667340E1);
2673     const __m128d P1        = _mm_set1_pd(-1.228866684490136173410E2);
2674     const __m128d P0        = _mm_set1_pd(-6.485021904942025371773E1);
2675
2676     const __m128d Q4        = _mm_set1_pd(2.485846490142306297962E1);
2677     const __m128d Q3        = _mm_set1_pd(1.650270098316988542046E2);
2678     const __m128d Q2        = _mm_set1_pd(4.328810604912902668951E2);
2679     const __m128d Q1        = _mm_set1_pd(4.853903996359136964868E2);
2680     const __m128d Q0        = _mm_set1_pd(1.945506571482613964425E2);
2681
2682     __m128d       sign;
2683     __m128d       mask1, mask2;
2684     __m128d       y, t1, t2;
2685     __m128d       z, z2;
2686     __m128d       P_A, P_B, Q_A, Q_B;
2687
2688     sign   = _mm_andnot_pd(signmask, x);
2689     x      = _mm_and_pd(x, signmask);
2690
2691     mask1  = _mm_cmpgt_pd(x, limit1);
2692     mask2  = _mm_cmpgt_pd(x, limit2);
2693
2694     t1     = _mm_mul_pd(_mm_add_pd(x, mone), gmx_mm_inv_pd(_mm_sub_pd(x, mone)));
2695     t2     = _mm_mul_pd(mone, gmx_mm_inv_pd(x));
2696
2697     y      = _mm_and_pd(mask1, quarterpi);
2698     y      = _mm_or_pd( _mm_and_pd(mask2, halfpi), _mm_andnot_pd(mask2, y) );
2699
2700     x      = _mm_or_pd( _mm_and_pd(mask1, t1), _mm_andnot_pd(mask1, x) );
2701     x      = _mm_or_pd( _mm_and_pd(mask2, t2), _mm_andnot_pd(mask2, x) );
2702
2703     z      = _mm_mul_pd(x, x);
2704     z2     = _mm_mul_pd(z, z);
2705
2706     P_A    = _mm_mul_pd(P4, z2);
2707     P_B    = _mm_mul_pd(P3, z2);
2708     P_A    = _mm_add_pd(P_A, P2);
2709     P_B    = _mm_add_pd(P_B, P1);
2710     P_A    = _mm_mul_pd(P_A, z2);
2711     P_B    = _mm_mul_pd(P_B, z);
2712     P_A    = _mm_add_pd(P_A, P0);
2713     P_A    = _mm_add_pd(P_A, P_B);
2714
2715     /* Q_A = z2 */
2716     Q_B    = _mm_mul_pd(Q4, z2);
2717     Q_A    = _mm_add_pd(z2, Q3);
2718     Q_B    = _mm_add_pd(Q_B, Q2);
2719     Q_A    = _mm_mul_pd(Q_A, z2);
2720     Q_B    = _mm_mul_pd(Q_B, z2);
2721     Q_A    = _mm_add_pd(Q_A, Q1);
2722     Q_B    = _mm_add_pd(Q_B, Q0);
2723     Q_A    = _mm_mul_pd(Q_A, z);
2724     Q_A    = _mm_add_pd(Q_A, Q_B);
2725
2726     z      = _mm_mul_pd(z, P_A);
2727     z      = _mm_mul_pd(z, gmx_mm_inv_pd(Q_A));
2728     z      = _mm_mul_pd(z, x);
2729     z      = _mm_add_pd(z, x);
2730
2731     t1     = _mm_and_pd(mask1, morebits1);
2732     t1     = _mm_or_pd( _mm_and_pd(mask2, morebits2), _mm_andnot_pd(mask2, t1) );
2733
2734     z      = _mm_add_pd(z, t1);
2735     y      = _mm_add_pd(y, z);
2736
2737     y      = _mm_xor_pd(y, sign);
2738
2739     return y;
2740 }
2741
2742
2743
2744 static __m256d
2745 gmx_mm256_atan2_pd(__m256d y, __m256d x)
2746 {
2747     const __m256d pi          = _mm256_set1_pd(M_PI);
2748     const __m256d minuspi     = _mm256_set1_pd(-M_PI);
2749     const __m256d halfpi      = _mm256_set1_pd(M_PI/2.0);
2750     const __m256d minushalfpi = _mm256_set1_pd(-M_PI/2.0);
2751
2752     __m256d       z, z1, z3, z4;
2753     __m256d       w;
2754     __m256d       maskx_lt, maskx_eq;
2755     __m256d       masky_lt, masky_eq;
2756     __m256d       mask1, mask2, mask3, mask4, maskall;
2757
2758     maskx_lt  = _mm256_cmp_pd(x, _mm256_setzero_pd(), _CMP_LT_OQ);
2759     masky_lt  = _mm256_cmp_pd(y, _mm256_setzero_pd(), _CMP_LT_OQ);
2760     maskx_eq  = _mm256_cmp_pd(x, _mm256_setzero_pd(), _CMP_EQ_OQ);
2761     masky_eq  = _mm256_cmp_pd(y, _mm256_setzero_pd(), _CMP_EQ_OQ);
2762
2763     z         = _mm256_mul_pd(y, gmx_mm256_inv_pd(x));
2764     z         = gmx_mm256_atan_pd(z);
2765
2766     mask1     = _mm256_and_pd(maskx_eq, masky_lt);
2767     mask2     = _mm256_andnot_pd(maskx_lt, masky_eq);
2768     mask3     = _mm256_andnot_pd( _mm256_or_pd(masky_lt, masky_eq), maskx_eq);
2769     mask4     = _mm256_and_pd(masky_eq, maskx_lt);
2770
2771     maskall   = _mm256_or_pd( _mm256_or_pd(mask1, mask2), _mm256_or_pd(mask3, mask4) );
2772
2773     z         = _mm256_andnot_pd(maskall, z);
2774     z1        = _mm256_and_pd(mask1, minushalfpi);
2775     z3        = _mm256_and_pd(mask3, halfpi);
2776     z4        = _mm256_and_pd(mask4, pi);
2777
2778     z         = _mm256_or_pd( _mm256_or_pd(z, z1), _mm256_or_pd(z3, z4) );
2779
2780     w         = _mm256_blendv_pd(pi, minuspi, masky_lt);
2781     w         = _mm256_and_pd(w, maskx_lt);
2782
2783     w         = _mm256_andnot_pd(maskall, w);
2784
2785     z         = _mm256_add_pd(z, w);
2786
2787     return z;
2788 }
2789
2790 static __m128d
2791 gmx_mm_atan2_pd(__m128d y, __m128d x)
2792 {
2793     const __m128d pi          = _mm_set1_pd(M_PI);
2794     const __m128d minuspi     = _mm_set1_pd(-M_PI);
2795     const __m128d halfpi      = _mm_set1_pd(M_PI/2.0);
2796     const __m128d minushalfpi = _mm_set1_pd(-M_PI/2.0);
2797
2798     __m128d       z, z1, z3, z4;
2799     __m128d       w;
2800     __m128d       maskx_lt, maskx_eq;
2801     __m128d       masky_lt, masky_eq;
2802     __m128d       mask1, mask2, mask3, mask4, maskall;
2803
2804     maskx_lt  = _mm_cmplt_pd(x, _mm_setzero_pd());
2805     masky_lt  = _mm_cmplt_pd(y, _mm_setzero_pd());
2806     maskx_eq  = _mm_cmpeq_pd(x, _mm_setzero_pd());
2807     masky_eq  = _mm_cmpeq_pd(y, _mm_setzero_pd());
2808
2809     z         = _mm_mul_pd(y, gmx_mm_inv_pd(x));
2810     z         = gmx_mm_atan_pd(z);
2811
2812     mask1     = _mm_and_pd(maskx_eq, masky_lt);
2813     mask2     = _mm_andnot_pd(maskx_lt, masky_eq);
2814     mask3     = _mm_andnot_pd( _mm_or_pd(masky_lt, masky_eq), maskx_eq);
2815     mask4     = _mm_and_pd(masky_eq, maskx_lt);
2816
2817     maskall   = _mm_or_pd( _mm_or_pd(mask1, mask2), _mm_or_pd(mask3, mask4) );
2818
2819     z         = _mm_andnot_pd(maskall, z);
2820     z1        = _mm_and_pd(mask1, minushalfpi);
2821     z3        = _mm_and_pd(mask3, halfpi);
2822     z4        = _mm_and_pd(mask4, pi);
2823
2824     z         = _mm_or_pd( _mm_or_pd(z, z1), _mm_or_pd(z3, z4) );
2825
2826     w         = _mm_blendv_pd(pi, minuspi, masky_lt);
2827     w         = _mm_and_pd(w, maskx_lt);
2828
2829     w         = _mm_andnot_pd(maskall, w);
2830
2831     z         = _mm_add_pd(z, w);
2832
2833     return z;
2834 }
2835
2836 #endif