[PATCH v4 2/4] aarch64: Add vector implementations of sin routines

Szabolcs Nagy szabolcs.nagy@arm.com
Wed Jul 5 16:46:53 GMT 2023


The 06/28/2023 12:19, Joe Ramsay via Libc-alpha wrote:
> +++ b/sysdeps/aarch64/fpu/sin_advsimd.c
> @@ -0,0 +1,106 @@
> +/* Double-precision vector (Advanced SIMD) sin function.
...
> +float64x2_t VPCS_ATTR V_NAME_D1 (sin) (float64x2_t x)
> +{
> +  const struct data *d = ptr_barrier (&data);
> +  float64x2_t n, r, r2, r3, r4, y, t1, t2, t3;
> +  uint64x2_t odd, cmp, eqz;
> +
> +#if WANT_SIMD_EXCEPT
> +  /* Detect |x| <= TinyBound or |x| >= RangeVal. If fenv exceptions are to be
> +     triggered correctly, set any special lanes to 1 (which is neutral w.r.t.
> +     fenv). These lanes will be fixed by special-case handler later.  */
> +  uint64x2_t ir = vreinterpretq_u64_f64 (vabsq_f64 (x));
> +  cmp = vcgeq_u64 (vsubq_u64 (ir, TinyBound), Thresh);
> +  r = vbslq_f64 (cmp, vreinterpretq_f64_u64 (cmp), x);
> +#else
> +  r = x;
> +  cmp = vcageq_f64 (d->range_val, x);
> +  cmp = vceqzq_u64 (cmp); /* cmp = ~cmp.  */
> +#endif
> +  eqz = vceqzq_f64 (x);
> +
> +  /* n = rint(|x|/pi).  */
> +  n = vfmaq_f64 (d->shift, d->inv_pi, r);
> +  odd = vshlq_n_u64 (vreinterpretq_u64_f64 (n), 63);
> +  n = vsubq_f64 (n, d->shift);
> +
> +  /* r = |x| - n*pi  (range reduction into -pi/2 .. pi/2).  */
> +  r = vfmsq_f64 (r, d->pi_1, n);
> +  r = vfmsq_f64 (r, d->pi_2, n);
> +  r = vfmsq_f64 (r, d->pi_3, n);
> +
> +  /* sin(r) poly approx.  */
> +  r2 = vmulq_f64 (r, r);
> +  r3 = vmulq_f64 (r2, r);
> +  r4 = vmulq_f64 (r2, r2);
> +
> +  t1 = vfmaq_f64 (C (4), C (5), r2);
> +  t2 = vfmaq_f64 (C (2), C (3), r2);
> +  t3 = vfmaq_f64 (C (0), C (1), r2);
> +
> +  y = vfmaq_f64 (t1, C (6), r4);
> +  y = vfmaq_f64 (t2, y, r4);
> +  y = vfmaq_f64 (t3, y, r4);
> +  y = vfmaq_f64 (r, y, r3);
> +
> +  /* Sign of 0 is discarded by polynomial, so copy it back here.  */
> +  if (__glibc_unlikely (v_any_u64 (eqz)))
> +    y = vbslq_f64 (eqz, x, y);

this check is for dealing with the sin(-0.0) case.

but -ffast-math can already break the sign of 0 and libmvec
symbols are supposed to be used with -ffast-math (at least via
gcc auto vectorizer).

so do we need to provide quality guarantees beyond -ffast-math
in libmvec? or can we ignore math tests that check for the sign
of 0 and change the code accordingly.

the wiki does not seem to cover this under "C99 compliance":
https://sourceware.org/glibc/wiki/libmvec


> +
> +  if (__glibc_unlikely (v_any_u64 (cmp)))
> +    return special_case (x, y, odd, cmp);
> +  return vreinterpretq_f64_u64 (veorq_u64 (vreinterpretq_u64_f64 (y), odd));
> +}


More information about the Libc-alpha mailing list