xref: /freebsd/contrib/arm-optimized-routines/pl/math/v_cexpi_3u5.c (revision 5a02ffc32e777041dd2dad4e651ed2a0865a0a5d)
1 /*
2  * Double-precision vector sincos function - return-by-value interface.
3  *
4  * Copyright (c) 2023, Arm Limited.
5  * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
6  */
7 
8 #include "v_sincos_common.h"
9 #include "v_math.h"
10 #include "pl_test.h"
11 
12 static float64x2x2_t VPCS_ATTR NOINLINE
special_case(float64x2_t x,uint64x2_t special,float64x2x2_t y)13 special_case (float64x2_t x, uint64x2_t special, float64x2x2_t y)
14 {
15   return (float64x2x2_t){ v_call_f64 (sin, x, y.val[0], special),
16 			  v_call_f64 (cos, x, y.val[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    v_sincos_sin (0x1.d70eef40f39b1p+12) got -0x1.ffe9537d5dbb7p-3
23 				       want -0x1.ffe9537d5dbb4p-3.  */
24 VPCS_ATTR float64x2x2_t
_ZGVnN2v_cexpi(float64x2_t x)25 _ZGVnN2v_cexpi (float64x2_t x)
26 {
27   const struct v_sincos_data *d = ptr_barrier (&v_sincos_data);
28   uint64x2_t special = check_ge_rangeval (x, d);
29 
30   float64x2x2_t sc = v_sincos_inline (x, d);
31 
32   if (unlikely (v_any_u64 (special)))
33     return special_case (x, special, sc);
34   return sc;
35 }
36 
37 PL_TEST_ULP (_ZGVnN2v_cexpi_sin, 2.73)
38 PL_TEST_ULP (_ZGVnN2v_cexpi_cos, 2.73)
39 #define V_CEXPI_INTERVAL(lo, hi, n)                                           \
40   PL_TEST_INTERVAL (_ZGVnN2v_cexpi_sin, lo, hi, n)                            \
41   PL_TEST_INTERVAL (_ZGVnN2v_cexpi_cos, lo, hi, n)
42 V_CEXPI_INTERVAL (0, 0x1p23, 500000)
43 V_CEXPI_INTERVAL (-0, -0x1p23, 500000)
44 V_CEXPI_INTERVAL (0x1p23, inf, 10000)
45 V_CEXPI_INTERVAL (-0x1p23, -inf, 10000)
46