xref: /freebsd/contrib/arm-optimized-routines/math/aarch64/sve/cexpi.c (revision f3087bef11543b42e0d69b708f367097a4118d24)
1 /*
2  * Double-precision vector cexpi function.
3  *
4  * Copyright (c) 2023-2024, Arm Limited.
5  * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
6  */
7 
8 #include "sv_math.h"
9 #include "sv_sincos_common.h"
10 #include "test_defs.h"
11 
12 static svfloat64x2_t NOINLINE
special_case(svfloat64_t x,svbool_t special,svfloat64x2_t y)13 special_case (svfloat64_t x, svbool_t special, svfloat64x2_t y)
14 {
15   return svcreate2 (sv_call_f64 (sin, x, svget2 (y, 0), special),
16 		    sv_call_f64 (cos, x, svget2 (y, 1), special));
17 }
18 
19 /* Double-precision vector function allowing calculation of both sin and cos in
20    one function call, using shared argument reduction and separate polynomials.
21    Largest observed error is for sin, 3.22 ULP:
22    sv_cexpi_sin (0x1.d70eef40f39b1p+12) got -0x1.ffe9537d5dbb7p-3
23 				       want -0x1.ffe9537d5dbb4p-3.  */
24 svfloat64x2_t
_ZGVsMxv_cexpi(svfloat64_t x,svbool_t pg)25 _ZGVsMxv_cexpi (svfloat64_t x, svbool_t pg)
26 {
27   const struct sv_sincos_data *d = ptr_barrier (&sv_sincos_data);
28   svbool_t special = check_ge_rangeval (pg, x, d);
29 
30   svfloat64x2_t sc = sv_sincos_inline (pg, x, d);
31 
32   if (unlikely (svptest_any (pg, special)))
33     return special_case (x, special, sc);
34   return sc;
35 }
36 
37 TEST_DISABLE_FENV (_ZGVsMxv_cexpi_sin)
38 TEST_DISABLE_FENV (_ZGVsMxv_cexpi_cos)
39 TEST_ULP (_ZGVsMxv_cexpi_sin, 2.73)
40 TEST_ULP (_ZGVsMxv_cexpi_cos, 2.73)
41 #define SV_CEXPI_INTERVAL(lo, hi, n)                                          \
42   TEST_INTERVAL (_ZGVsMxv_cexpi_sin, lo, hi, n)                               \
43   TEST_INTERVAL (_ZGVsMxv_cexpi_cos, lo, hi, n)
44 SV_CEXPI_INTERVAL (0, 0x1p23, 500000)
45 SV_CEXPI_INTERVAL (-0, -0x1p23, 500000)
46 SV_CEXPI_INTERVAL (0x1p23, inf, 10000)
47 SV_CEXPI_INTERVAL (-0x1p23, -inf, 10000)
48 CLOSE_SVE_ATTR
49