1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
4 * This file is part of GROMACS.
7 * Written by the Gromacs development team under coordination of
8 * David van der Spoel, Berk Hess, and Erik Lindahl.
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * To help us fund GROMACS development, we humbly ask that you cite
16 * the research papers on the package. Check out http://www.gromacs.org
19 * Gnomes, ROck Monsters And Chili Sauce
21 #ifndef _gmx_math_x86_avx_128_fma_double_h_
22 #define _gmx_math_x86_avx_128_fma_double_h_
24 #include <immintrin.h> /* AVX */
25 #ifdef HAVE_X86INTRIN_H
26 #include <x86intrin.h> /* FMA */
29 #include <intrin.h> /* FMA MSVC */
34 #include "gmx_x86_avx_128_fma.h"
38 # define M_PI 3.14159265358979323846264338327950288
42 /************************
44 * Simple math routines *
46 ************************/
49 static gmx_inline __m128d
50 gmx_mm_invsqrt_pd(__m128d x)
52 const __m128d half = _mm_set1_pd(0.5);
53 const __m128d three = _mm_set1_pd(3.0);
55 /* Lookup instruction only exists in single precision, convert back and forth... */
56 __m128d lu = _mm_cvtps_pd(_mm_rsqrt_ps( _mm_cvtpd_ps(x)));
58 lu = _mm_mul_pd(_mm_mul_pd(half, lu), _mm_nmacc_pd(_mm_mul_pd(lu, lu), x, three));
59 return _mm_mul_pd(_mm_mul_pd(half, lu), _mm_nmacc_pd(_mm_mul_pd(lu, lu), x, three));
62 /* 1.0/sqrt(x), done for a pair of arguments to improve throughput */
64 gmx_mm_invsqrt_pair_pd(__m128d x1, __m128d x2, __m128d *invsqrt1, __m128d *invsqrt2)
66 const __m128d half = _mm_set1_pd(0.5);
67 const __m128d three = _mm_set1_pd(3.0);
68 const __m128 halff = _mm_set1_ps(0.5f);
69 const __m128 threef = _mm_set1_ps(3.0f);
74 /* Do first N-R step in float for 2x throughput */
75 xf = _mm_shuffle_ps(_mm_cvtpd_ps(x1), _mm_cvtpd_ps(x2), _MM_SHUFFLE(1, 0, 1, 0));
76 luf = _mm_rsqrt_ps(xf);
78 luf = _mm_mul_ps(_mm_mul_ps(halff, luf), _mm_nmacc_ps(_mm_mul_ps(luf, luf), xf, threef));
81 lu2 = _mm_cvtps_pd(_mm_shuffle_ps(luf, luf, _MM_SHUFFLE(3, 2, 3, 2)));
82 lu1 = _mm_cvtps_pd(luf);
84 *invsqrt1 = _mm_mul_pd(_mm_mul_pd(half, lu1), _mm_nmacc_pd(_mm_mul_pd(lu1, lu1), x1, three));
85 *invsqrt2 = _mm_mul_pd(_mm_mul_pd(half, lu2), _mm_nmacc_pd(_mm_mul_pd(lu2, lu2), x2, three));
88 /* sqrt(x) - Do NOT use this (but rather invsqrt) if you actually need 1.0/sqrt(x) */
89 static gmx_inline __m128d
90 gmx_mm_sqrt_pd(__m128d x)
95 mask = _mm_cmpeq_pd(x, _mm_setzero_pd());
96 res = _mm_andnot_pd(mask, gmx_mm_invsqrt_pd(x));
98 res = _mm_mul_pd(x, res);
104 static gmx_inline __m128d
105 gmx_mm_inv_pd(__m128d x)
107 const __m128d two = _mm_set1_pd(2.0);
109 /* Lookup instruction only exists in single precision, convert back and forth... */
110 __m128d lu = _mm_cvtps_pd(_mm_rcp_ps( _mm_cvtpd_ps(x)));
112 /* Perform two N-R steps for double precision */
113 lu = _mm_mul_pd(lu, _mm_nmacc_pd(lu, x, two));
114 return _mm_mul_pd(lu, _mm_nmacc_pd(lu, x, two));
117 static gmx_inline __m128d
118 gmx_mm_abs_pd(__m128d x)
120 const __m128d signmask = gmx_mm_castsi128_pd( _mm_set_epi32(0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF) );
122 return _mm_and_pd(x, signmask);
129 * The 2^w term is calculated from a (6,0)-th order (no denominator) Minimax polynomia on the interval
132 * The approximation on [-0.5,0.5] is a rational Padé approximation, 1+2*P(x^2)/(Q(x^2)-P(x^2)),
133 * according to the same algorithm as used in the Cephes/netlib math routines.
136 gmx_mm_exp2_pd(__m128d x)
138 /* Lower bound: We do not allow numbers that would lead to an IEEE fp representation exponent smaller than -126. */
139 const __m128d arglimit = _mm_set1_pd(1022.0);
140 const __m128i expbase = _mm_set1_epi32(1023);
142 const __m128d P2 = _mm_set1_pd(2.30933477057345225087e-2);
143 const __m128d P1 = _mm_set1_pd(2.02020656693165307700e1);
144 const __m128d P0 = _mm_set1_pd(1.51390680115615096133e3);
146 const __m128d Q1 = _mm_set1_pd(2.33184211722314911771e2);
147 const __m128d Q0 = _mm_set1_pd(4.36821166879210612817e3);
148 const __m128d one = _mm_set1_pd(1.0);
149 const __m128d two = _mm_set1_pd(2.0);
156 __m128d PolyP, PolyQ;
158 iexppart = _mm_cvtpd_epi32(x);
159 intpart = _mm_round_pd(x, _MM_FROUND_TO_NEAREST_INT);
161 /* The two lowest elements of iexppart now contains 32-bit numbers with a correctly biased exponent.
162 * To be able to shift it into the exponent for a double precision number we first need to
163 * shuffle so that the lower half contains the first element, and the upper half the second.
164 * This should really be done as a zero-extension, but since the next instructions will shift
165 * the registers left by 52 bits it doesn't matter what we put there - it will be shifted out.
166 * (thus we just use element 2 from iexppart).
168 iexppart = _mm_shuffle_epi32(iexppart, _MM_SHUFFLE(2, 1, 2, 0));
170 /* Do the shift operation on the 64-bit registers */
171 iexppart = _mm_add_epi32(iexppart, expbase);
172 iexppart = _mm_slli_epi64(iexppart, 52);
174 valuemask = _mm_cmpge_pd(arglimit, gmx_mm_abs_pd(x));
175 fexppart = _mm_and_pd(valuemask, gmx_mm_castsi128_pd(iexppart));
177 z = _mm_sub_pd(x, intpart);
178 z2 = _mm_mul_pd(z, z);
180 PolyP = _mm_macc_pd(P2, z2, P1);
181 PolyQ = _mm_add_pd(z2, Q1);
182 PolyP = _mm_macc_pd(PolyP, z2, P0);
183 PolyQ = _mm_macc_pd(PolyQ, z2, Q0);
184 PolyP = _mm_mul_pd(PolyP, z);
186 z = _mm_mul_pd(PolyP, gmx_mm_inv_pd(_mm_sub_pd(PolyQ, PolyP)));
187 z = _mm_macc_pd(two, z, one);
189 z = _mm_mul_pd(z, fexppart);
194 /* Exponential function. This could be calculated from 2^x as Exp(x)=2^(y), where y=log2(e)*x,
195 * but there will then be a small rounding error since we lose some precision due to the
196 * multiplication. This will then be magnified a lot by the exponential.
198 * Instead, we calculate the fractional part directly as a Padé approximation of
199 * Exp(z) on [-0.5,0.5]. We use extended precision arithmetics to calculate the fraction
200 * remaining after 2^y, which avoids the precision-loss.
203 gmx_mm_exp_pd(__m128d exparg)
205 const __m128d argscale = _mm_set1_pd(1.4426950408889634073599);
206 /* Lower bound: We do not allow numbers that would lead to an IEEE fp representation exponent smaller than -126. */
207 const __m128d arglimit = _mm_set1_pd(1022.0);
208 const __m128i expbase = _mm_set1_epi32(1023);
210 const __m128d invargscale0 = _mm_set1_pd(6.93145751953125e-1);
211 const __m128d invargscale1 = _mm_set1_pd(1.42860682030941723212e-6);
213 const __m128d P2 = _mm_set1_pd(1.26177193074810590878e-4);
214 const __m128d P1 = _mm_set1_pd(3.02994407707441961300e-2);
216 const __m128d Q3 = _mm_set1_pd(3.00198505138664455042E-6);
217 const __m128d Q2 = _mm_set1_pd(2.52448340349684104192E-3);
218 const __m128d Q1 = _mm_set1_pd(2.27265548208155028766E-1);
220 const __m128d one = _mm_set1_pd(1.0);
221 const __m128d two = _mm_set1_pd(2.0);
228 __m128d PolyP, PolyQ;
230 x = _mm_mul_pd(exparg, argscale);
232 iexppart = _mm_cvtpd_epi32(x);
233 intpart = _mm_round_pd(x, _MM_FROUND_TO_NEAREST_INT);
235 /* The two lowest elements of iexppart now contains 32-bit numbers with a correctly biased exponent.
236 * To be able to shift it into the exponent for a double precision number we first need to
237 * shuffle so that the lower half contains the first element, and the upper half the second.
238 * This should really be done as a zero-extension, but since the next instructions will shift
239 * the registers left by 52 bits it doesn't matter what we put there - it will be shifted out.
240 * (thus we just use element 2 from iexppart).
242 iexppart = _mm_shuffle_epi32(iexppart, _MM_SHUFFLE(2, 1, 2, 0));
244 /* Do the shift operation on the 64-bit registers */
245 iexppart = _mm_add_epi32(iexppart, expbase);
246 iexppart = _mm_slli_epi64(iexppart, 52);
248 valuemask = _mm_cmpge_pd(arglimit, gmx_mm_abs_pd(x));
249 fexppart = _mm_and_pd(valuemask, gmx_mm_castsi128_pd(iexppart));
251 z = _mm_sub_pd(exparg, _mm_mul_pd(invargscale0, intpart));
252 z = _mm_sub_pd(z, _mm_mul_pd(invargscale1, intpart));
254 z2 = _mm_mul_pd(z, z);
256 PolyQ = _mm_macc_pd(Q3, z2, Q2);
257 PolyP = _mm_macc_pd(P2, z2, P1);
258 PolyQ = _mm_macc_pd(PolyQ, z2, Q1);
260 PolyP = _mm_macc_pd(PolyP, z2, one);
261 PolyQ = _mm_macc_pd(PolyQ, z2, two);
263 PolyP = _mm_mul_pd(PolyP, z);
265 z = _mm_mul_pd(PolyP, gmx_mm_inv_pd(_mm_sub_pd(PolyQ, PolyP)));
266 z = _mm_macc_pd(two, z, one);
268 z = _mm_mul_pd(z, fexppart);
276 gmx_mm_log_pd(__m128d x)
278 /* Same algorithm as cephes library */
279 const __m128d expmask = gmx_mm_castsi128_pd( _mm_set_epi32(0x7FF00000, 0x00000000, 0x7FF00000, 0x00000000) );
281 const __m128i expbase_m1 = _mm_set1_epi32(1023-1); /* We want non-IEEE format */
283 const __m128d half = _mm_set1_pd(0.5);
284 const __m128d one = _mm_set1_pd(1.0);
285 const __m128d two = _mm_set1_pd(2.0);
286 const __m128d invsq2 = _mm_set1_pd(1.0/sqrt(2.0));
288 const __m128d corr1 = _mm_set1_pd(-2.121944400546905827679e-4);
289 const __m128d corr2 = _mm_set1_pd(0.693359375);
291 const __m128d P5 = _mm_set1_pd(1.01875663804580931796e-4);
292 const __m128d P4 = _mm_set1_pd(4.97494994976747001425e-1);
293 const __m128d P3 = _mm_set1_pd(4.70579119878881725854e0);
294 const __m128d P2 = _mm_set1_pd(1.44989225341610930846e1);
295 const __m128d P1 = _mm_set1_pd(1.79368678507819816313e1);
296 const __m128d P0 = _mm_set1_pd(7.70838733755885391666e0);
298 const __m128d Q4 = _mm_set1_pd(1.12873587189167450590e1);
299 const __m128d Q3 = _mm_set1_pd(4.52279145837532221105e1);
300 const __m128d Q2 = _mm_set1_pd(8.29875266912776603211e1);
301 const __m128d Q1 = _mm_set1_pd(7.11544750618563894466e1);
302 const __m128d Q0 = _mm_set1_pd(2.31251620126765340583e1);
304 const __m128d R2 = _mm_set1_pd(-7.89580278884799154124e-1);
305 const __m128d R1 = _mm_set1_pd(1.63866645699558079767e1);
306 const __m128d R0 = _mm_set1_pd(-6.41409952958715622951e1);
308 const __m128d S2 = _mm_set1_pd(-3.56722798256324312549E1);
309 const __m128d S1 = _mm_set1_pd(3.12093766372244180303E2);
310 const __m128d S0 = _mm_set1_pd(-7.69691943550460008604E2);
315 __m128d mask1, mask2;
316 __m128d corr, t1, t2, q;
317 __m128d zA, yA, xA, zB, yB, xB, z;
318 __m128d polyR, polyS;
319 __m128d polyP1, polyP2, polyQ1, polyQ2;
321 /* Separate x into exponent and mantissa, with a mantissa in the range [0.5..1[ (not IEEE754 standard!) */
322 fexp = _mm_and_pd(x, expmask);
323 iexp = gmx_mm_castpd_si128(fexp);
324 iexp = _mm_srli_epi64(iexp, 52);
325 iexp = _mm_sub_epi32(iexp, expbase_m1);
326 iexp = _mm_shuffle_epi32(iexp, _MM_SHUFFLE(1, 1, 2, 0) );
327 fexp = _mm_cvtepi32_pd(iexp);
329 x = _mm_andnot_pd(expmask, x);
330 x = _mm_or_pd(x, one);
331 x = _mm_mul_pd(x, half);
333 mask1 = _mm_cmpgt_pd(gmx_mm_abs_pd(fexp), two);
334 mask2 = _mm_cmplt_pd(x, invsq2);
336 fexp = _mm_sub_pd(fexp, _mm_and_pd(mask2, one));
338 /* If mask1 is set ('A') */
339 zA = _mm_sub_pd(x, half);
340 t1 = _mm_blendv_pd( zA, x, mask2 );
341 zA = _mm_sub_pd(t1, half);
342 t2 = _mm_blendv_pd( x, zA, mask2 );
343 yA = _mm_mul_pd(half, _mm_add_pd(t2, one));
345 xA = _mm_mul_pd(zA, gmx_mm_inv_pd(yA));
346 zA = _mm_mul_pd(xA, xA);
349 polyR = _mm_macc_pd(R2, zA, R1);
350 polyR = _mm_macc_pd(polyR, zA, R0);
352 polyS = _mm_add_pd(zA, S2);
353 polyS = _mm_macc_pd(polyS, zA, S1);
354 polyS = _mm_macc_pd(polyS, zA, S0);
356 q = _mm_mul_pd(polyR, gmx_mm_inv_pd(polyS));
357 zA = _mm_mul_pd(_mm_mul_pd(xA, zA), q);
359 zA = _mm_macc_pd(corr1, fexp, zA);
360 zA = _mm_add_pd(zA, xA);
361 zA = _mm_macc_pd(corr2, fexp, zA);
363 /* If mask1 is not set ('B') */
364 corr = _mm_and_pd(mask2, x);
365 xB = _mm_add_pd(x, corr);
366 xB = _mm_sub_pd(xB, one);
367 zB = _mm_mul_pd(xB, xB);
369 polyP1 = _mm_macc_pd(P5, zB, P3);
370 polyP2 = _mm_macc_pd(P4, zB, P2);
371 polyP1 = _mm_macc_pd(polyP1, zB, P1);
372 polyP2 = _mm_macc_pd(polyP2, zB, P0);
373 polyP1 = _mm_macc_pd(polyP1, xB, polyP2);
375 polyQ2 = _mm_macc_pd(Q4, zB, Q2);
376 polyQ1 = _mm_add_pd(zB, Q3);
377 polyQ1 = _mm_macc_pd(polyQ1, zB, Q1);
378 polyQ2 = _mm_macc_pd(polyQ2, zB, Q0);
379 polyQ1 = _mm_macc_pd(polyQ1, xB, polyQ2);
381 fexp = _mm_and_pd(fexp, _mm_cmpneq_pd(fexp, _mm_setzero_pd()));
383 q = _mm_mul_pd(polyP1, gmx_mm_inv_pd(polyQ1));
384 yB = _mm_macc_pd(_mm_mul_pd(xB, zB), q, _mm_mul_pd(corr1, fexp));
386 yB = _mm_nmacc_pd(half, zB, yB);
387 zB = _mm_add_pd(xB, yB);
388 zB = _mm_macc_pd(corr2, fexp, zB);
390 z = _mm_blendv_pd( zB, zA, mask1 );
398 gmx_mm_erf_pd(__m128d x)
400 /* Coefficients for minimax approximation of erf(x)=x*(CAoffset + P(x^2)/Q(x^2)) in range [-0.75,0.75] */
401 const __m128d CAP4 = _mm_set1_pd(-0.431780540597889301512e-4);
402 const __m128d CAP3 = _mm_set1_pd(-0.00578562306260059236059);
403 const __m128d CAP2 = _mm_set1_pd(-0.028593586920219752446);
404 const __m128d CAP1 = _mm_set1_pd(-0.315924962948621698209);
405 const __m128d CAP0 = _mm_set1_pd(0.14952975608477029151);
407 const __m128d CAQ5 = _mm_set1_pd(-0.374089300177174709737e-5);
408 const __m128d CAQ4 = _mm_set1_pd(0.00015126584532155383535);
409 const __m128d CAQ3 = _mm_set1_pd(0.00536692680669480725423);
410 const __m128d CAQ2 = _mm_set1_pd(0.0668686825594046122636);
411 const __m128d CAQ1 = _mm_set1_pd(0.402604990869284362773);
413 const __m128d CAoffset = _mm_set1_pd(0.9788494110107421875);
415 /* Coefficients for minimax approximation of erfc(x)=exp(-x^2)*x*(P(x-1)/Q(x-1)) in range [1.0,4.5] */
416 const __m128d CBP6 = _mm_set1_pd(2.49650423685462752497647637088e-10);
417 const __m128d CBP5 = _mm_set1_pd(0.00119770193298159629350136085658);
418 const __m128d CBP4 = _mm_set1_pd(0.0164944422378370965881008942733);
419 const __m128d CBP3 = _mm_set1_pd(0.0984581468691775932063932439252);
420 const __m128d CBP2 = _mm_set1_pd(0.317364595806937763843589437418);
421 const __m128d CBP1 = _mm_set1_pd(0.554167062641455850932670067075);
422 const __m128d CBP0 = _mm_set1_pd(0.427583576155807163756925301060);
423 const __m128d CBQ7 = _mm_set1_pd(0.00212288829699830145976198384930);
424 const __m128d CBQ6 = _mm_set1_pd(0.0334810979522685300554606393425);
425 const __m128d CBQ5 = _mm_set1_pd(0.2361713785181450957579508850717);
426 const __m128d CBQ4 = _mm_set1_pd(0.955364736493055670530981883072);
427 const __m128d CBQ3 = _mm_set1_pd(2.36815675631420037315349279199);
428 const __m128d CBQ2 = _mm_set1_pd(3.55261649184083035537184223542);
429 const __m128d CBQ1 = _mm_set1_pd(2.93501136050160872574376997993);
432 /* Coefficients for minimax approximation of erfc(x)=exp(-x^2)/x*(P(1/x)/Q(1/x)) in range [4.5,inf] */
433 const __m128d CCP6 = _mm_set1_pd(-2.8175401114513378771);
434 const __m128d CCP5 = _mm_set1_pd(-3.22729451764143718517);
435 const __m128d CCP4 = _mm_set1_pd(-2.5518551727311523996);
436 const __m128d CCP3 = _mm_set1_pd(-0.687717681153649930619);
437 const __m128d CCP2 = _mm_set1_pd(-0.212652252872804219852);
438 const __m128d CCP1 = _mm_set1_pd(0.0175389834052493308818);
439 const __m128d CCP0 = _mm_set1_pd(0.00628057170626964891937);
441 const __m128d CCQ6 = _mm_set1_pd(5.48409182238641741584);
442 const __m128d CCQ5 = _mm_set1_pd(13.5064170191802889145);
443 const __m128d CCQ4 = _mm_set1_pd(22.9367376522880577224);
444 const __m128d CCQ3 = _mm_set1_pd(15.930646027911794143);
445 const __m128d CCQ2 = _mm_set1_pd(11.0567237927800161565);
446 const __m128d CCQ1 = _mm_set1_pd(2.79257750980575282228);
448 const __m128d CCoffset = _mm_set1_pd(0.5579090118408203125);
450 const __m128d one = _mm_set1_pd(1.0);
451 const __m128d two = _mm_set1_pd(2.0);
453 const __m128d signbit = gmx_mm_castsi128_pd( _mm_set_epi32(0x80000000, 0x00000000, 0x80000000, 0x00000000) );
455 __m128d xabs, x2, x4, t, t2, w, w2;
456 __m128d PolyAP0, PolyAP1, PolyAQ0, PolyAQ1;
457 __m128d PolyBP0, PolyBP1, PolyBQ0, PolyBQ1;
458 __m128d PolyCP0, PolyCP1, PolyCQ0, PolyCQ1;
459 __m128d res_erf, res_erfcB, res_erfcC, res_erfc, res;
460 __m128d mask, expmx2;
462 /* Calculate erf() */
463 xabs = gmx_mm_abs_pd(x);
464 x2 = _mm_mul_pd(x, x);
465 x4 = _mm_mul_pd(x2, x2);
467 PolyAP0 = _mm_macc_pd(CAP4, x4, CAP2);
468 PolyAP1 = _mm_macc_pd(CAP3, x4, CAP1);
469 PolyAP0 = _mm_macc_pd(PolyAP0, x4, CAP0);
470 PolyAP0 = _mm_macc_pd(PolyAP1, x2, PolyAP0);
472 PolyAQ1 = _mm_macc_pd(CAQ5, x4, CAQ3);
473 PolyAQ0 = _mm_macc_pd(CAQ4, x4, CAQ2);
474 PolyAQ1 = _mm_macc_pd(PolyAQ1, x4, CAQ1);
475 PolyAQ0 = _mm_macc_pd(PolyAQ0, x4, one);
476 PolyAQ0 = _mm_macc_pd(PolyAQ1, x2, PolyAQ0);
478 res_erf = _mm_macc_pd(PolyAP0, gmx_mm_inv_pd(PolyAQ0), CAoffset);
479 res_erf = _mm_mul_pd(x, res_erf);
481 /* Calculate erfc() in range [1,4.5] */
482 t = _mm_sub_pd(xabs, one);
483 t2 = _mm_mul_pd(t, t);
485 PolyBP0 = _mm_macc_pd(CBP6, t2, CBP4);
486 PolyBP1 = _mm_macc_pd(CBP5, t2, CBP3);
487 PolyBP0 = _mm_macc_pd(PolyBP0, t2, CBP2);
488 PolyBP1 = _mm_macc_pd(PolyBP1, t2, CBP1);
489 PolyBP0 = _mm_macc_pd(PolyBP0, t2, CBP0);
490 PolyBP0 = _mm_macc_pd(PolyBP1, t, PolyBP0);
492 PolyBQ1 = _mm_macc_pd(CBQ7, t2, CBQ5);
493 PolyBQ0 = _mm_macc_pd(CBQ6, t2, CBQ4);
494 PolyBQ1 = _mm_macc_pd(PolyBQ1, t2, CBQ3);
495 PolyBQ0 = _mm_macc_pd(PolyBQ0, t2, CBQ2);
496 PolyBQ1 = _mm_macc_pd(PolyBQ1, t2, CBQ1);
497 PolyBQ0 = _mm_macc_pd(PolyBQ0, t2, one);
498 PolyBQ0 = _mm_macc_pd(PolyBQ1, t, PolyBQ0);
500 res_erfcB = _mm_mul_pd(PolyBP0, gmx_mm_inv_pd(PolyBQ0));
502 res_erfcB = _mm_mul_pd(res_erfcB, xabs);
504 /* Calculate erfc() in range [4.5,inf] */
505 w = gmx_mm_inv_pd(xabs);
506 w2 = _mm_mul_pd(w, w);
508 PolyCP0 = _mm_macc_pd(CCP6, w2, CCP4);
509 PolyCP1 = _mm_macc_pd(CCP5, w2, CCP3);
510 PolyCP0 = _mm_macc_pd(PolyCP0, w2, CCP2);
511 PolyCP1 = _mm_macc_pd(PolyCP1, w2, CCP1);
512 PolyCP0 = _mm_macc_pd(PolyCP0, w2, CCP0);
513 PolyCP0 = _mm_macc_pd(PolyCP1, w, PolyCP0);
515 PolyCQ0 = _mm_macc_pd(CCQ6, w2, CCQ4);
516 PolyCQ1 = _mm_macc_pd(CCQ5, w2, CCQ3);
517 PolyCQ0 = _mm_macc_pd(PolyCQ0, w2, CCQ2);
518 PolyCQ1 = _mm_macc_pd(PolyCQ1, w2, CCQ1);
519 PolyCQ0 = _mm_macc_pd(PolyCQ0, w2, one);
520 PolyCQ0 = _mm_macc_pd(PolyCQ1, w, PolyCQ0);
522 expmx2 = gmx_mm_exp_pd( _mm_or_pd(signbit, x2) );
524 res_erfcC = _mm_macc_pd(PolyCP0, gmx_mm_inv_pd(PolyCQ0), CCoffset);
525 res_erfcC = _mm_mul_pd(res_erfcC, w);
527 mask = _mm_cmpgt_pd(xabs, _mm_set1_pd(4.5));
528 res_erfc = _mm_blendv_pd(res_erfcB, res_erfcC, mask);
530 res_erfc = _mm_mul_pd(res_erfc, expmx2);
532 /* erfc(x<0) = 2-erfc(|x|) */
533 mask = _mm_cmplt_pd(x, _mm_setzero_pd());
534 res_erfc = _mm_blendv_pd(res_erfc, _mm_sub_pd(two, res_erfc), mask);
536 /* Select erf() or erfc() */
537 mask = _mm_cmplt_pd(xabs, one);
538 res = _mm_blendv_pd(_mm_sub_pd(one, res_erfc), res_erf, mask);
545 gmx_mm_erfc_pd(__m128d x)
547 /* Coefficients for minimax approximation of erf(x)=x*(CAoffset + P(x^2)/Q(x^2)) in range [-0.75,0.75] */
548 const __m128d CAP4 = _mm_set1_pd(-0.431780540597889301512e-4);
549 const __m128d CAP3 = _mm_set1_pd(-0.00578562306260059236059);
550 const __m128d CAP2 = _mm_set1_pd(-0.028593586920219752446);
551 const __m128d CAP1 = _mm_set1_pd(-0.315924962948621698209);
552 const __m128d CAP0 = _mm_set1_pd(0.14952975608477029151);
554 const __m128d CAQ5 = _mm_set1_pd(-0.374089300177174709737e-5);
555 const __m128d CAQ4 = _mm_set1_pd(0.00015126584532155383535);
556 const __m128d CAQ3 = _mm_set1_pd(0.00536692680669480725423);
557 const __m128d CAQ2 = _mm_set1_pd(0.0668686825594046122636);
558 const __m128d CAQ1 = _mm_set1_pd(0.402604990869284362773);
560 const __m128d CAoffset = _mm_set1_pd(0.9788494110107421875);
562 /* Coefficients for minimax approximation of erfc(x)=exp(-x^2)*x*(P(x-1)/Q(x-1)) in range [1.0,4.5] */
563 const __m128d CBP6 = _mm_set1_pd(2.49650423685462752497647637088e-10);
564 const __m128d CBP5 = _mm_set1_pd(0.00119770193298159629350136085658);
565 const __m128d CBP4 = _mm_set1_pd(0.0164944422378370965881008942733);
566 const __m128d CBP3 = _mm_set1_pd(0.0984581468691775932063932439252);
567 const __m128d CBP2 = _mm_set1_pd(0.317364595806937763843589437418);
568 const __m128d CBP1 = _mm_set1_pd(0.554167062641455850932670067075);
569 const __m128d CBP0 = _mm_set1_pd(0.427583576155807163756925301060);
570 const __m128d CBQ7 = _mm_set1_pd(0.00212288829699830145976198384930);
571 const __m128d CBQ6 = _mm_set1_pd(0.0334810979522685300554606393425);
572 const __m128d CBQ5 = _mm_set1_pd(0.2361713785181450957579508850717);
573 const __m128d CBQ4 = _mm_set1_pd(0.955364736493055670530981883072);
574 const __m128d CBQ3 = _mm_set1_pd(2.36815675631420037315349279199);
575 const __m128d CBQ2 = _mm_set1_pd(3.55261649184083035537184223542);
576 const __m128d CBQ1 = _mm_set1_pd(2.93501136050160872574376997993);
579 /* Coefficients for minimax approximation of erfc(x)=exp(-x^2)/x*(P(1/x)/Q(1/x)) in range [4.5,inf] */
580 const __m128d CCP6 = _mm_set1_pd(-2.8175401114513378771);
581 const __m128d CCP5 = _mm_set1_pd(-3.22729451764143718517);
582 const __m128d CCP4 = _mm_set1_pd(-2.5518551727311523996);
583 const __m128d CCP3 = _mm_set1_pd(-0.687717681153649930619);
584 const __m128d CCP2 = _mm_set1_pd(-0.212652252872804219852);
585 const __m128d CCP1 = _mm_set1_pd(0.0175389834052493308818);
586 const __m128d CCP0 = _mm_set1_pd(0.00628057170626964891937);
588 const __m128d CCQ6 = _mm_set1_pd(5.48409182238641741584);
589 const __m128d CCQ5 = _mm_set1_pd(13.5064170191802889145);
590 const __m128d CCQ4 = _mm_set1_pd(22.9367376522880577224);
591 const __m128d CCQ3 = _mm_set1_pd(15.930646027911794143);
592 const __m128d CCQ2 = _mm_set1_pd(11.0567237927800161565);
593 const __m128d CCQ1 = _mm_set1_pd(2.79257750980575282228);
595 const __m128d CCoffset = _mm_set1_pd(0.5579090118408203125);
597 const __m128d one = _mm_set1_pd(1.0);
598 const __m128d two = _mm_set1_pd(2.0);
600 const __m128d signbit = gmx_mm_castsi128_pd( _mm_set_epi32(0x80000000, 0x00000000, 0x80000000, 0x00000000) );
602 __m128d xabs, x2, x4, t, t2, w, w2;
603 __m128d PolyAP0, PolyAP1, PolyAQ0, PolyAQ1;
604 __m128d PolyBP0, PolyBP1, PolyBQ0, PolyBQ1;
605 __m128d PolyCP0, PolyCP1, PolyCQ0, PolyCQ1;
606 __m128d res_erf, res_erfcB, res_erfcC, res_erfc, res;
607 __m128d mask, expmx2;
609 /* Calculate erf() */
610 xabs = gmx_mm_abs_pd(x);
611 x2 = _mm_mul_pd(x, x);
612 x4 = _mm_mul_pd(x2, x2);
614 PolyAP0 = _mm_macc_pd(CAP4, x4, CAP2);
615 PolyAP1 = _mm_macc_pd(CAP3, x4, CAP1);
616 PolyAP0 = _mm_macc_pd(PolyAP0, x4, CAP0);
617 PolyAP0 = _mm_macc_pd(PolyAP1, x2, PolyAP0);
619 PolyAQ1 = _mm_macc_pd(CAQ5, x4, CAQ3);
620 PolyAQ0 = _mm_macc_pd(CAQ4, x4, CAQ2);
621 PolyAQ1 = _mm_macc_pd(PolyAQ1, x4, CAQ1);
622 PolyAQ0 = _mm_macc_pd(PolyAQ0, x4, one);
623 PolyAQ0 = _mm_macc_pd(PolyAQ1, x2, PolyAQ0);
625 res_erf = _mm_macc_pd(PolyAP0, gmx_mm_inv_pd(PolyAQ0), CAoffset);
626 res_erf = _mm_mul_pd(x, res_erf);
628 /* Calculate erfc() in range [1,4.5] */
629 t = _mm_sub_pd(xabs, one);
630 t2 = _mm_mul_pd(t, t);
632 PolyBP0 = _mm_macc_pd(CBP6, t2, CBP4);
633 PolyBP1 = _mm_macc_pd(CBP5, t2, CBP3);
634 PolyBP0 = _mm_macc_pd(PolyBP0, t2, CBP2);
635 PolyBP1 = _mm_macc_pd(PolyBP1, t2, CBP1);
636 PolyBP0 = _mm_macc_pd(PolyBP0, t2, CBP0);
637 PolyBP0 = _mm_macc_pd(PolyBP1, t, PolyBP0);
639 PolyBQ1 = _mm_macc_pd(CBQ7, t2, CBQ5);
640 PolyBQ0 = _mm_macc_pd(CBQ6, t2, CBQ4);
641 PolyBQ1 = _mm_macc_pd(PolyBQ1, t2, CBQ3);
642 PolyBQ0 = _mm_macc_pd(PolyBQ0, t2, CBQ2);
643 PolyBQ1 = _mm_macc_pd(PolyBQ1, t2, CBQ1);
644 PolyBQ0 = _mm_macc_pd(PolyBQ0, t2, one);
645 PolyBQ0 = _mm_macc_pd(PolyBQ1, t, PolyBQ0);
647 res_erfcB = _mm_mul_pd(PolyBP0, gmx_mm_inv_pd(PolyBQ0));
649 res_erfcB = _mm_mul_pd(res_erfcB, xabs);
651 /* Calculate erfc() in range [4.5,inf] */
652 w = gmx_mm_inv_pd(xabs);
653 w2 = _mm_mul_pd(w, w);
655 PolyCP0 = _mm_macc_pd(CCP6, w2, CCP4);
656 PolyCP1 = _mm_macc_pd(CCP5, w2, CCP3);
657 PolyCP0 = _mm_macc_pd(PolyCP0, w2, CCP2);
658 PolyCP1 = _mm_macc_pd(PolyCP1, w2, CCP1);
659 PolyCP0 = _mm_macc_pd(PolyCP0, w2, CCP0);
660 PolyCP0 = _mm_macc_pd(PolyCP1, w, PolyCP0);
662 PolyCQ0 = _mm_macc_pd(CCQ6, w2, CCQ4);
663 PolyCQ1 = _mm_macc_pd(CCQ5, w2, CCQ3);
664 PolyCQ0 = _mm_macc_pd(PolyCQ0, w2, CCQ2);
665 PolyCQ1 = _mm_macc_pd(PolyCQ1, w2, CCQ1);
666 PolyCQ0 = _mm_macc_pd(PolyCQ0, w2, one);
667 PolyCQ0 = _mm_macc_pd(PolyCQ1, w, PolyCQ0);
669 expmx2 = gmx_mm_exp_pd( _mm_or_pd(signbit, x2) );
671 res_erfcC = _mm_macc_pd(PolyCP0, gmx_mm_inv_pd(PolyCQ0), CCoffset);
672 res_erfcC = _mm_mul_pd(res_erfcC, w);
674 mask = _mm_cmpgt_pd(xabs, _mm_set1_pd(4.5));
675 res_erfc = _mm_blendv_pd(res_erfcB, res_erfcC, mask);
677 res_erfc = _mm_mul_pd(res_erfc, expmx2);
679 /* erfc(x<0) = 2-erfc(|x|) */
680 mask = _mm_cmplt_pd(x, _mm_setzero_pd());
681 res_erfc = _mm_blendv_pd(res_erfc, _mm_sub_pd(two, res_erfc), mask);
683 /* Select erf() or erfc() */
684 mask = _mm_cmplt_pd(xabs, one);
685 res = _mm_blendv_pd(res_erfc, _mm_sub_pd(one, res_erf), mask);
692 /* Calculate the force correction due to PME analytically.
694 * This routine is meant to enable analytical evaluation of the
695 * direct-space PME electrostatic force to avoid tables.
697 * The direct-space potential should be Erfc(beta*r)/r, but there
698 * are some problems evaluating that:
700 * First, the error function is difficult (read: expensive) to
701 * approxmiate accurately for intermediate to large arguments, and
702 * this happens already in ranges of beta*r that occur in simulations.
703 * Second, we now try to avoid calculating potentials in Gromacs but
704 * use forces directly.
706 * We can simply things slight by noting that the PME part is really
707 * a correction to the normal Coulomb force since Erfc(z)=1-Erf(z), i.e.
709 * V= 1/r - Erf(beta*r)/r
711 * The first term we already have from the inverse square root, so
712 * that we can leave out of this routine.
714 * For pme tolerances of 1e-3 to 1e-8 and cutoffs of 0.5nm to 1.8nm,
715 * the argument beta*r will be in the range 0.15 to ~4. Use your
716 * favorite plotting program to realize how well-behaved Erf(z)/z is
719 * We approximate f(z)=erf(z)/z with a rational minimax polynomial.
720 * However, it turns out it is more efficient to approximate f(z)/z and
721 * then only use even powers. This is another minor optimization, since
722 * we actually WANT f(z)/z, because it is going to be multiplied by
723 * the vector between the two atoms to get the vectorial force. The
724 * fastest flops are the ones we can avoid calculating!
726 * So, here's how it should be used:
729 * 2. Multiply by beta^2, so you get z^2=beta^2*r^2.
730 * 3. Evaluate this routine with z^2 as the argument.
731 * 4. The return value is the expression:
735 * ------------ - --------
738 * 5. Multiply the entire expression by beta^3. This will get you
740 * beta^3*2*exp(-z^2) beta^3*erf(z)
741 * ------------------ - ---------------
744 * or, switching back to r (z=r*beta):
746 * 2*beta*exp(-r^2*beta^2) erf(r*beta)
747 * ----------------------- - -----------
751 * With a bit of math exercise you should be able to confirm that
752 * this is exactly D[Erf[beta*r]/r,r] divided by r another time.
754 * 6. Add the result to 1/r^3, multiply by the product of the charges,
755 * and you have your force (divided by r). A final multiplication
756 * with the vector connecting the two particles and you have your
757 * vectorial force to add to the particles.
761 gmx_mm_pmecorrF_pd(__m128d z2)
763 const __m128d FN10 = _mm_set1_pd(-8.0072854618360083154e-14);
764 const __m128d FN9 = _mm_set1_pd(1.1859116242260148027e-11);
765 const __m128d FN8 = _mm_set1_pd(-8.1490406329798423616e-10);
766 const __m128d FN7 = _mm_set1_pd(3.4404793543907847655e-8);
767 const __m128d FN6 = _mm_set1_pd(-9.9471420832602741006e-7);
768 const __m128d FN5 = _mm_set1_pd(0.000020740315999115847456);
769 const __m128d FN4 = _mm_set1_pd(-0.00031991745139313364005);
770 const __m128d FN3 = _mm_set1_pd(0.0035074449373659008203);
771 const __m128d FN2 = _mm_set1_pd(-0.031750380176100813405);
772 const __m128d FN1 = _mm_set1_pd(0.13884101728898463426);
773 const __m128d FN0 = _mm_set1_pd(-0.75225277815249618847);
775 const __m128d FD5 = _mm_set1_pd(0.000016009278224355026701);
776 const __m128d FD4 = _mm_set1_pd(0.00051055686934806966046);
777 const __m128d FD3 = _mm_set1_pd(0.0081803507497974289008);
778 const __m128d FD2 = _mm_set1_pd(0.077181146026670287235);
779 const __m128d FD1 = _mm_set1_pd(0.41543303143712535988);
780 const __m128d FD0 = _mm_set1_pd(1.0);
783 __m128d polyFN0, polyFN1, polyFD0, polyFD1;
785 z4 = _mm_mul_pd(z2, z2);
787 polyFD1 = _mm_macc_pd(FD5, z4, FD3);
788 polyFD1 = _mm_macc_pd(polyFD1, z4, FD1);
789 polyFD1 = _mm_mul_pd(polyFD1, z2);
790 polyFD0 = _mm_macc_pd(FD4, z4, FD2);
791 polyFD0 = _mm_macc_pd(polyFD0, z4, FD0);
792 polyFD0 = _mm_add_pd(polyFD0, polyFD1);
794 polyFD0 = gmx_mm_inv_pd(polyFD0);
796 polyFN0 = _mm_macc_pd(FN10, z4, FN8);
797 polyFN0 = _mm_macc_pd(polyFN0, z4, FN6);
798 polyFN0 = _mm_macc_pd(polyFN0, z4, FN4);
799 polyFN0 = _mm_macc_pd(polyFN0, z4, FN2);
800 polyFN0 = _mm_macc_pd(polyFN0, z4, FN0);
801 polyFN1 = _mm_macc_pd(FN9, z4, FN7);
802 polyFN1 = _mm_macc_pd(polyFN1, z4, FN5);
803 polyFN1 = _mm_macc_pd(polyFN1, z4, FN3);
804 polyFN1 = _mm_macc_pd(polyFN1, z4, FN1);
805 polyFN0 = _mm_macc_pd(polyFN1, z2, polyFN0);
807 return _mm_mul_pd(polyFN0, polyFD0);
811 /* Calculate the potential correction due to PME analytically.
813 * This routine calculates Erf(z)/z, although you should provide z^2
814 * as the input argument.
816 * Here's how it should be used:
819 * 2. Multiply by beta^2, so you get z^2=beta^2*r^2.
820 * 3. Evaluate this routine with z^2 as the argument.
821 * 4. The return value is the expression:
828 * 5. Multiply the entire expression by beta and switching back to r (z=r*beta):
834 * 6. Subtract the result from 1/r, multiply by the product of the charges,
835 * and you have your potential.
839 gmx_mm_pmecorrV_pd(__m128d z2)
841 const __m128d VN9 = _mm_set1_pd(-9.3723776169321855475e-13);
842 const __m128d VN8 = _mm_set1_pd(1.2280156762674215741e-10);
843 const __m128d VN7 = _mm_set1_pd(-7.3562157912251309487e-9);
844 const __m128d VN6 = _mm_set1_pd(2.6215886208032517509e-7);
845 const __m128d VN5 = _mm_set1_pd(-4.9532491651265819499e-6);
846 const __m128d VN4 = _mm_set1_pd(0.00025907400778966060389);
847 const __m128d VN3 = _mm_set1_pd(0.0010585044856156469792);
848 const __m128d VN2 = _mm_set1_pd(0.045247661136833092885);
849 const __m128d VN1 = _mm_set1_pd(0.11643931522926034421);
850 const __m128d VN0 = _mm_set1_pd(1.1283791671726767970);
852 const __m128d VD5 = _mm_set1_pd(0.000021784709867336150342);
853 const __m128d VD4 = _mm_set1_pd(0.00064293662010911388448);
854 const __m128d VD3 = _mm_set1_pd(0.0096311444822588683504);
855 const __m128d VD2 = _mm_set1_pd(0.085608012351550627051);
856 const __m128d VD1 = _mm_set1_pd(0.43652499166614811084);
857 const __m128d VD0 = _mm_set1_pd(1.0);
860 __m128d polyVN0, polyVN1, polyVD0, polyVD1;
862 z4 = _mm_mul_pd(z2, z2);
864 polyVD1 = _mm_macc_pd(VD5, z4, VD3);
865 polyVD0 = _mm_macc_pd(VD4, z4, VD2);
866 polyVD1 = _mm_macc_pd(polyVD1, z4, VD1);
867 polyVD0 = _mm_macc_pd(polyVD0, z4, VD0);
868 polyVD0 = _mm_macc_pd(polyVD1, z2, polyVD0);
870 polyVD0 = gmx_mm_inv_pd(polyVD0);
872 polyVN1 = _mm_macc_pd(VN9, z4, VN7);
873 polyVN0 = _mm_macc_pd(VN8, z4, VN6);
874 polyVN1 = _mm_macc_pd(polyVN1, z4, VN5);
875 polyVN0 = _mm_macc_pd(polyVN0, z4, VN4);
876 polyVN1 = _mm_macc_pd(polyVN1, z4, VN3);
877 polyVN0 = _mm_macc_pd(polyVN0, z4, VN2);
878 polyVN1 = _mm_macc_pd(polyVN1, z4, VN1);
879 polyVN0 = _mm_macc_pd(polyVN0, z4, VN0);
880 polyVN0 = _mm_macc_pd(polyVN1, z2, polyVN0);
882 return _mm_mul_pd(polyVN0, polyVD0);
887 gmx_mm_sincos_pd(__m128d x,
892 __declspec(align(16))
893 const double sintable[34] =
895 1.00000000000000000e+00, 0.00000000000000000e+00,
896 9.95184726672196929e-01, 9.80171403295606036e-02,
897 9.80785280403230431e-01, 1.95090322016128248e-01,
898 9.56940335732208824e-01, 2.90284677254462331e-01,
899 9.23879532511286738e-01, 3.82683432365089782e-01,
900 8.81921264348355050e-01, 4.71396736825997642e-01,
901 8.31469612302545236e-01, 5.55570233019602178e-01,
902 7.73010453362736993e-01, 6.34393284163645488e-01,
903 7.07106781186547573e-01, 7.07106781186547462e-01,
904 6.34393284163645599e-01, 7.73010453362736882e-01,
905 5.55570233019602289e-01, 8.31469612302545125e-01,
906 4.71396736825997809e-01, 8.81921264348354939e-01,
907 3.82683432365089837e-01, 9.23879532511286738e-01,
908 2.90284677254462276e-01, 9.56940335732208935e-01,
909 1.95090322016128304e-01, 9.80785280403230431e-01,
910 9.80171403295607702e-02, 9.95184726672196818e-01,
911 0.0, 1.00000000000000000e+00
914 const __m128d sintable[17] =
916 _mm_set_pd( 0.0, 1.0 ),
917 _mm_set_pd( sin( 1.0 * (M_PI/2.0) / 16.0), cos( 1.0 * (M_PI/2.0) / 16.0) ),
918 _mm_set_pd( sin( 2.0 * (M_PI/2.0) / 16.0), cos( 2.0 * (M_PI/2.0) / 16.0) ),
919 _mm_set_pd( sin( 3.0 * (M_PI/2.0) / 16.0), cos( 3.0 * (M_PI/2.0) / 16.0) ),
920 _mm_set_pd( sin( 4.0 * (M_PI/2.0) / 16.0), cos( 4.0 * (M_PI/2.0) / 16.0) ),
921 _mm_set_pd( sin( 5.0 * (M_PI/2.0) / 16.0), cos( 5.0 * (M_PI/2.0) / 16.0) ),
922 _mm_set_pd( sin( 6.0 * (M_PI/2.0) / 16.0), cos( 6.0 * (M_PI/2.0) / 16.0) ),
923 _mm_set_pd( sin( 7.0 * (M_PI/2.0) / 16.0), cos( 7.0 * (M_PI/2.0) / 16.0) ),
924 _mm_set_pd( sin( 8.0 * (M_PI/2.0) / 16.0), cos( 8.0 * (M_PI/2.0) / 16.0) ),
925 _mm_set_pd( sin( 9.0 * (M_PI/2.0) / 16.0), cos( 9.0 * (M_PI/2.0) / 16.0) ),
926 _mm_set_pd( sin( 10.0 * (M_PI/2.0) / 16.0), cos( 10.0 * (M_PI/2.0) / 16.0) ),
927 _mm_set_pd( sin( 11.0 * (M_PI/2.0) / 16.0), cos( 11.0 * (M_PI/2.0) / 16.0) ),
928 _mm_set_pd( sin( 12.0 * (M_PI/2.0) / 16.0), cos( 12.0 * (M_PI/2.0) / 16.0) ),
929 _mm_set_pd( sin( 13.0 * (M_PI/2.0) / 16.0), cos( 13.0 * (M_PI/2.0) / 16.0) ),
930 _mm_set_pd( sin( 14.0 * (M_PI/2.0) / 16.0), cos( 14.0 * (M_PI/2.0) / 16.0) ),
931 _mm_set_pd( sin( 15.0 * (M_PI/2.0) / 16.0), cos( 15.0 * (M_PI/2.0) / 16.0) ),
932 _mm_set_pd( 1.0, 0.0 )
936 const __m128d signmask = gmx_mm_castsi128_pd( _mm_set_epi32(0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF) );
937 const __m128i signbit_epi32 = _mm_set1_epi32(0x80000000);
939 const __m128d tabscale = _mm_set1_pd(32.0/M_PI);
940 const __m128d invtabscale0 = _mm_set1_pd(9.81747508049011230469e-02);
941 const __m128d invtabscale1 = _mm_set1_pd(1.96197799156550576057e-08);
942 const __m128i ione = _mm_set1_epi32(1);
943 const __m128i i32 = _mm_set1_epi32(32);
944 const __m128i i16 = _mm_set1_epi32(16);
945 const __m128i tabmask = _mm_set1_epi32(0x3F);
946 const __m128d sinP7 = _mm_set1_pd(-1.0/5040.0);
947 const __m128d sinP5 = _mm_set1_pd(1.0/120.0);
948 const __m128d sinP3 = _mm_set1_pd(-1.0/6.0);
949 const __m128d sinP1 = _mm_set1_pd(1.0);
951 const __m128d cosP6 = _mm_set1_pd(-1.0/720.0);
952 const __m128d cosP4 = _mm_set1_pd(1.0/24.0);
953 const __m128d cosP2 = _mm_set1_pd(-1.0/2.0);
954 const __m128d cosP0 = _mm_set1_pd(1.0);
957 __m128i tabidx, corridx;
958 __m128d xabs, z, z2, polySin, polyCos;
960 __m128d ypoint0, ypoint1;
962 __m128d sinpoint, cospoint;
963 __m128d xsign, ssign, csign;
964 __m128i imask, sswapsign, cswapsign;
967 xsign = _mm_andnot_pd(signmask, x);
968 xabs = _mm_and_pd(x, signmask);
970 scalex = _mm_mul_pd(tabscale, xabs);
971 tabidx = _mm_cvtpd_epi32(scalex);
973 xpoint = _mm_round_pd(scalex, _MM_FROUND_TO_NEAREST_INT);
975 /* Extended precision arithmetics */
976 z = _mm_nmacc_pd(invtabscale0, xpoint, xabs);
977 z = _mm_nmacc_pd(invtabscale1, xpoint, z);
979 /* Range reduction to 0..2*Pi */
980 tabidx = _mm_and_si128(tabidx, tabmask);
982 /* tabidx is now in range [0,..,64] */
983 imask = _mm_cmpgt_epi32(tabidx, i32);
986 corridx = _mm_and_si128(imask, i32);
987 tabidx = _mm_sub_epi32(tabidx, corridx);
989 /* tabidx is now in range [0..32] */
990 imask = _mm_cmpgt_epi32(tabidx, i16);
991 cswapsign = _mm_xor_si128(cswapsign, imask);
992 corridx = _mm_sub_epi32(i32, tabidx);
993 tabidx = _mm_blendv_epi8(tabidx, corridx, imask);
994 /* tabidx is now in range [0..16] */
995 ssign = _mm_cvtepi32_pd( _mm_or_si128( sswapsign, ione ) );
996 csign = _mm_cvtepi32_pd( _mm_or_si128( cswapsign, ione ) );
999 ypoint0 = _mm_load_pd(sintable + 2*_mm_extract_epi32(tabidx, 0));
1000 ypoint1 = _mm_load_pd(sintable + 2*_mm_extract_epi32(tabidx, 1));
1002 ypoint0 = sintable[_mm_extract_epi32(tabidx, 0)];
1003 ypoint1 = sintable[_mm_extract_epi32(tabidx, 1)];
1005 sinpoint = _mm_unpackhi_pd(ypoint0, ypoint1);
1006 cospoint = _mm_unpacklo_pd(ypoint0, ypoint1);
1008 sinpoint = _mm_mul_pd(sinpoint, ssign);
1009 cospoint = _mm_mul_pd(cospoint, csign);
1011 z2 = _mm_mul_pd(z, z);
1013 polySin = _mm_macc_pd(sinP7, z2, sinP5);
1014 polySin = _mm_macc_pd(polySin, z2, sinP3);
1015 polySin = _mm_macc_pd(polySin, z2, sinP1);
1016 polySin = _mm_mul_pd(polySin, z);
1018 polyCos = _mm_macc_pd(cosP6, z2, cosP4);
1019 polyCos = _mm_macc_pd(polyCos, z2, cosP2);
1020 polyCos = _mm_macc_pd(polyCos, z2, cosP0);
1022 *sinval = _mm_xor_pd(_mm_add_pd( _mm_mul_pd(sinpoint, polyCos), _mm_mul_pd(cospoint, polySin) ), xsign);
1023 *cosval = _mm_sub_pd( _mm_mul_pd(cospoint, polyCos), _mm_mul_pd(sinpoint, polySin) );
1029 * IMPORTANT: Do NOT call both sin & cos if you need both results, since each of them
1030 * will then call the sincos() routine and waste a factor 2 in performance!
1033 gmx_mm_sin_pd(__m128d x)
1036 gmx_mm_sincos_pd(x, &s, &c);
1041 * IMPORTANT: Do NOT call both sin & cos if you need both results, since each of them
1042 * will then call the sincos() routine and waste a factor 2 in performance!
1045 gmx_mm_cos_pd(__m128d x)
1048 gmx_mm_sincos_pd(x, &s, &c);
1055 gmx_mm_tan_pd(__m128d x)
1057 __m128d sinval, cosval;
1060 gmx_mm_sincos_pd(x, &sinval, &cosval);
1062 tanval = _mm_mul_pd(sinval, gmx_mm_inv_pd(cosval));
1070 gmx_mm_asin_pd(__m128d x)
1072 /* Same algorithm as cephes library */
1073 const __m128d signmask = gmx_mm_castsi128_pd( _mm_set_epi32(0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF) );
1074 const __m128d limit1 = _mm_set1_pd(0.625);
1075 const __m128d limit2 = _mm_set1_pd(1e-8);
1076 const __m128d one = _mm_set1_pd(1.0);
1077 const __m128d halfpi = _mm_set1_pd(M_PI/2.0);
1078 const __m128d quarterpi = _mm_set1_pd(M_PI/4.0);
1079 const __m128d morebits = _mm_set1_pd(6.123233995736765886130e-17);
1081 const __m128d P5 = _mm_set1_pd(4.253011369004428248960e-3);
1082 const __m128d P4 = _mm_set1_pd(-6.019598008014123785661e-1);
1083 const __m128d P3 = _mm_set1_pd(5.444622390564711410273e0);
1084 const __m128d P2 = _mm_set1_pd(-1.626247967210700244449e1);
1085 const __m128d P1 = _mm_set1_pd(1.956261983317594739197e1);
1086 const __m128d P0 = _mm_set1_pd(-8.198089802484824371615e0);
1088 const __m128d Q4 = _mm_set1_pd(-1.474091372988853791896e1);
1089 const __m128d Q3 = _mm_set1_pd(7.049610280856842141659e1);
1090 const __m128d Q2 = _mm_set1_pd(-1.471791292232726029859e2);
1091 const __m128d Q1 = _mm_set1_pd(1.395105614657485689735e2);
1092 const __m128d Q0 = _mm_set1_pd(-4.918853881490881290097e1);
1094 const __m128d R4 = _mm_set1_pd(2.967721961301243206100e-3);
1095 const __m128d R3 = _mm_set1_pd(-5.634242780008963776856e-1);
1096 const __m128d R2 = _mm_set1_pd(6.968710824104713396794e0);
1097 const __m128d R1 = _mm_set1_pd(-2.556901049652824852289e1);
1098 const __m128d R0 = _mm_set1_pd(2.853665548261061424989e1);
1100 const __m128d S3 = _mm_set1_pd(-2.194779531642920639778e1);
1101 const __m128d S2 = _mm_set1_pd(1.470656354026814941758e2);
1102 const __m128d S1 = _mm_set1_pd(-3.838770957603691357202e2);
1103 const __m128d S0 = _mm_set1_pd(3.424398657913078477438e2);
1108 __m128d zz, ww, z, q, w, y, zz2, ww2;
1115 sign = _mm_andnot_pd(signmask, x);
1116 xabs = _mm_and_pd(x, signmask);
1118 mask = _mm_cmpgt_pd(xabs, limit1);
1120 zz = _mm_sub_pd(one, xabs);
1121 ww = _mm_mul_pd(xabs, xabs);
1122 zz2 = _mm_mul_pd(zz, zz);
1123 ww2 = _mm_mul_pd(ww, ww);
1126 RA = _mm_macc_pd(R4, zz2, R2);
1127 RB = _mm_macc_pd(R3, zz2, R1);
1128 RA = _mm_macc_pd(RA, zz2, R0);
1129 RA = _mm_macc_pd(RB, zz, RA);
1132 SB = _mm_macc_pd(S3, zz2, S1);
1133 SA = _mm_add_pd(zz2, S2);
1134 SA = _mm_macc_pd(SA, zz2, S0);
1135 SA = _mm_macc_pd(SB, zz, SA);
1138 PA = _mm_macc_pd(P5, ww2, P3);
1139 PB = _mm_macc_pd(P4, ww2, P2);
1140 PA = _mm_macc_pd(PA, ww2, P1);
1141 PB = _mm_macc_pd(PB, ww2, P0);
1142 PA = _mm_macc_pd(PA, ww, PB);
1145 QB = _mm_macc_pd(Q4, ww2, Q2);
1146 QA = _mm_add_pd(ww2, Q3);
1147 QA = _mm_macc_pd(QA, ww2, Q1);
1148 QB = _mm_macc_pd(QB, ww2, Q0);
1149 QA = _mm_macc_pd(QA, ww, QB);
1151 RA = _mm_mul_pd(RA, zz);
1152 PA = _mm_mul_pd(PA, ww);
1154 nom = _mm_blendv_pd( PA, RA, mask );
1155 denom = _mm_blendv_pd( QA, SA, mask );
1157 q = _mm_mul_pd( nom, gmx_mm_inv_pd(denom) );
1159 zz = _mm_add_pd(zz, zz);
1160 zz = gmx_mm_sqrt_pd(zz);
1161 z = _mm_sub_pd(quarterpi, zz);
1162 zz = _mm_mul_pd(zz, q);
1163 zz = _mm_sub_pd(zz, morebits);
1164 z = _mm_sub_pd(z, zz);
1165 z = _mm_add_pd(z, quarterpi);
1167 w = _mm_macc_pd(xabs, q, xabs);
1169 z = _mm_blendv_pd( w, z, mask );
1171 mask = _mm_cmpgt_pd(xabs, limit2);
1172 z = _mm_blendv_pd( xabs, z, mask );
1174 z = _mm_xor_pd(z, sign);
1181 gmx_mm_acos_pd(__m128d x)
1183 const __m128d signmask = gmx_mm_castsi128_pd( _mm_set_epi32(0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF) );
1184 const __m128d one = _mm_set1_pd(1.0);
1185 const __m128d half = _mm_set1_pd(0.5);
1186 const __m128d pi = _mm_set1_pd(M_PI);
1187 const __m128d quarterpi0 = _mm_set1_pd(7.85398163397448309616e-1);
1188 const __m128d quarterpi1 = _mm_set1_pd(6.123233995736765886130e-17);
1195 mask1 = _mm_cmpgt_pd(x, half);
1196 z1 = _mm_mul_pd(half, _mm_sub_pd(one, x));
1197 z1 = gmx_mm_sqrt_pd(z1);
1198 z = _mm_blendv_pd( x, z1, mask1 );
1200 z = gmx_mm_asin_pd(z);
1202 z1 = _mm_add_pd(z, z);
1204 z2 = _mm_sub_pd(quarterpi0, z);
1205 z2 = _mm_add_pd(z2, quarterpi1);
1206 z2 = _mm_add_pd(z2, quarterpi0);
1208 z = _mm_blendv_pd(z2, z1, mask1);
1214 gmx_mm_atan_pd(__m128d x)
1216 /* Same algorithm as cephes library */
1217 const __m128d signmask = gmx_mm_castsi128_pd( _mm_set_epi32(0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF) );
1218 const __m128d limit1 = _mm_set1_pd(0.66);
1219 const __m128d limit2 = _mm_set1_pd(2.41421356237309504880);
1220 const __m128d quarterpi = _mm_set1_pd(M_PI/4.0);
1221 const __m128d halfpi = _mm_set1_pd(M_PI/2.0);
1222 const __m128d mone = _mm_set1_pd(-1.0);
1223 const __m128d morebits1 = _mm_set1_pd(0.5*6.123233995736765886130E-17);
1224 const __m128d morebits2 = _mm_set1_pd(6.123233995736765886130E-17);
1226 const __m128d P4 = _mm_set1_pd(-8.750608600031904122785E-1);
1227 const __m128d P3 = _mm_set1_pd(-1.615753718733365076637E1);
1228 const __m128d P2 = _mm_set1_pd(-7.500855792314704667340E1);
1229 const __m128d P1 = _mm_set1_pd(-1.228866684490136173410E2);
1230 const __m128d P0 = _mm_set1_pd(-6.485021904942025371773E1);
1232 const __m128d Q4 = _mm_set1_pd(2.485846490142306297962E1);
1233 const __m128d Q3 = _mm_set1_pd(1.650270098316988542046E2);
1234 const __m128d Q2 = _mm_set1_pd(4.328810604912902668951E2);
1235 const __m128d Q1 = _mm_set1_pd(4.853903996359136964868E2);
1236 const __m128d Q0 = _mm_set1_pd(1.945506571482613964425E2);
1239 __m128d mask1, mask2;
1242 __m128d P_A, P_B, Q_A, Q_B;
1244 sign = _mm_andnot_pd(signmask, x);
1245 x = _mm_and_pd(x, signmask);
1247 mask1 = _mm_cmpgt_pd(x, limit1);
1248 mask2 = _mm_cmpgt_pd(x, limit2);
1250 t1 = _mm_mul_pd(_mm_add_pd(x, mone), gmx_mm_inv_pd(_mm_sub_pd(x, mone)));
1251 t2 = _mm_mul_pd(mone, gmx_mm_inv_pd(x));
1253 y = _mm_and_pd(mask1, quarterpi);
1254 y = _mm_or_pd( _mm_and_pd(mask2, halfpi), _mm_andnot_pd(mask2, y) );
1256 x = _mm_or_pd( _mm_and_pd(mask1, t1), _mm_andnot_pd(mask1, x) );
1257 x = _mm_or_pd( _mm_and_pd(mask2, t2), _mm_andnot_pd(mask2, x) );
1259 z = _mm_mul_pd(x, x);
1260 z2 = _mm_mul_pd(z, z);
1262 P_A = _mm_macc_pd(P4, z2, P2);
1263 P_B = _mm_macc_pd(P3, z2, P1);
1264 P_A = _mm_macc_pd(P_A, z2, P0);
1265 P_A = _mm_macc_pd(P_B, z, P_A);
1268 Q_B = _mm_macc_pd(Q4, z2, Q2);
1269 Q_A = _mm_add_pd(z2, Q3);
1270 Q_A = _mm_macc_pd(Q_A, z2, Q1);
1271 Q_B = _mm_macc_pd(Q_B, z2, Q0);
1272 Q_A = _mm_macc_pd(Q_A, z, Q_B);
1274 z = _mm_mul_pd(z, P_A);
1275 z = _mm_mul_pd(z, gmx_mm_inv_pd(Q_A));
1276 z = _mm_macc_pd(z, x, x);
1278 t1 = _mm_and_pd(mask1, morebits1);
1279 t1 = _mm_or_pd( _mm_and_pd(mask2, morebits2), _mm_andnot_pd(mask2, t1) );
1281 z = _mm_add_pd(z, t1);
1282 y = _mm_add_pd(y, z);
1284 y = _mm_xor_pd(y, sign);
1291 gmx_mm_atan2_pd(__m128d y, __m128d x)
1293 const __m128d pi = _mm_set1_pd(M_PI);
1294 const __m128d minuspi = _mm_set1_pd(-M_PI);
1295 const __m128d halfpi = _mm_set1_pd(M_PI/2.0);
1296 const __m128d minushalfpi = _mm_set1_pd(-M_PI/2.0);
1298 __m128d z, z1, z3, z4;
1300 __m128d maskx_lt, maskx_eq;
1301 __m128d masky_lt, masky_eq;
1302 __m128d mask1, mask2, mask3, mask4, maskall;
1304 maskx_lt = _mm_cmplt_pd(x, _mm_setzero_pd());
1305 masky_lt = _mm_cmplt_pd(y, _mm_setzero_pd());
1306 maskx_eq = _mm_cmpeq_pd(x, _mm_setzero_pd());
1307 masky_eq = _mm_cmpeq_pd(y, _mm_setzero_pd());
1309 z = _mm_mul_pd(y, gmx_mm_inv_pd(x));
1310 z = gmx_mm_atan_pd(z);
1312 mask1 = _mm_and_pd(maskx_eq, masky_lt);
1313 mask2 = _mm_andnot_pd(maskx_lt, masky_eq);
1314 mask3 = _mm_andnot_pd( _mm_or_pd(masky_lt, masky_eq), maskx_eq);
1315 mask4 = _mm_and_pd(masky_eq, maskx_lt);
1317 maskall = _mm_or_pd( _mm_or_pd(mask1, mask2), _mm_or_pd(mask3, mask4) );
1319 z = _mm_andnot_pd(maskall, z);
1320 z1 = _mm_and_pd(mask1, minushalfpi);
1321 z3 = _mm_and_pd(mask3, halfpi);
1322 z4 = _mm_and_pd(mask4, pi);
1324 z = _mm_or_pd( _mm_or_pd(z, z1), _mm_or_pd(z3, z4) );
1326 w = _mm_blendv_pd(pi, minuspi, masky_lt);
1327 w = _mm_and_pd(w, maskx_lt);
1329 w = _mm_andnot_pd(maskall, w);
1331 z = _mm_add_pd(z, w);
1336 #endif /*_gmx_math_x86_avx_128_fma_double_h_ */