Path: blob/main/contrib/arm-optimized-routines/math/test/ulp_wrappers.h
48255 views
/*1* Function wrappers for ulp.2*3* Copyright (c) 2022-2024, Arm Limited.4* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception5*/67/* clang-format off */89#if __aarch64__ && __linux__10#include <arm_neon.h>11#endif1213#include <stdbool.h>1415/* Wrappers for sincos. */16static float sincosf_sinf(float x) {(void)cosf(x); return sinf(x);}17static float sincosf_cosf(float x) {(void)sinf(x); return cosf(x);}18static double sincos_sin(double x) {(void)cos(x); return sin(x);}19static double sincos_cos(double x) {(void)sin(x); return cos(x);}20#if USE_MPFR21static int sincos_mpfr_sin(mpfr_t y, const mpfr_t x, mpfr_rnd_t r) { mpfr_cos(y,x,r); return mpfr_sin(y,x,r); }22static int sincos_mpfr_cos(mpfr_t y, const mpfr_t x, mpfr_rnd_t r) { mpfr_sin(y,x,r); return mpfr_cos(y,x,r); }23static int modf_mpfr_frac(mpfr_t f, const mpfr_t x, mpfr_rnd_t r) { MPFR_DECL_INIT(i, 80); return mpfr_modf(i,f,x,r); }24static int modf_mpfr_int(mpfr_t i, const mpfr_t x, mpfr_rnd_t r) { MPFR_DECL_INIT(f, 80); return mpfr_modf(i,f,x,r); }25# if MPFR_VERSION < MPFR_VERSION_NUM(4, 2, 0)26static int mpfr_tanpi (mpfr_t ret, const mpfr_t arg, mpfr_rnd_t rnd) {27MPFR_DECL_INIT (frd, 1080);28mpfr_const_pi (frd, GMP_RNDN);29mpfr_mul (frd, frd, arg, GMP_RNDN);30return mpfr_tan (ret, frd, GMP_RNDN);31}32static int mpfr_sinpi (mpfr_t ret, const mpfr_t arg, mpfr_rnd_t rnd) {33MPFR_DECL_INIT (frd, 1080);34mpfr_const_pi (frd, GMP_RNDN);35mpfr_mul (frd, frd, arg, GMP_RNDN);36return mpfr_sin (ret, frd, GMP_RNDN);37}3839static int mpfr_cospi (mpfr_t ret, const mpfr_t arg, mpfr_rnd_t rnd) {40MPFR_DECL_INIT (frd, 1080);41mpfr_const_pi (frd, GMP_RNDN);42mpfr_mul (frd, frd, arg, GMP_RNDN);43return mpfr_cos (ret, frd, GMP_RNDN);44}45# endif46# if WANT_EXPERIMENTAL_MATH47static int wrap_mpfr_powi(mpfr_t ret, const mpfr_t x, const mpfr_t y, mpfr_rnd_t rnd) {48mpfr_t y2;49mpfr_init(y2);50mpfr_trunc(y2, y);51return mpfr_pow(ret, x, y2, rnd);52}53# endif54#endif5556float modff_frac(float x) { float i; return modff(x, &i); }57float modff_int(float x) { float i; modff(x, &i); return i; }58double modf_frac(double x) { double i; return modf(x, &i); }59double modf_int(double x) { double i; modf(x, &i); return i; }60long double modfl_frac(long double x) { long double i; return modfl(x, &i); }61long double modfl_int(long double x) { long double i; modfl(x, &i); return i; }6263/* Wrappers for vector functions. */64#if __aarch64__ && __linux__65static float Z_expf_1u(float x) { return _ZGVnN4v_expf_1u(argf(x))[0]; }66static float Z_exp2f_1u(float x) { return _ZGVnN4v_exp2f_1u(argf(x))[0]; }67#endif6869/* clang-format on */7071/* No wrappers for scalar routines, but TEST_SIG will emit them. */72#define ZSNF1_WRAP(func)73#define ZSNF2_WRAP(func)74#define ZSND1_WRAP(func)75#define ZSND2_WRAP(func)7677#define ZVNF1_WRAP(func) \78static float Z_##func##f (float x) \79{ \80return _ZGVnN4v_##func##f (argf (x))[0]; \81}82#define ZVNF2_WRAP(func) \83static float Z_##func##f (float x, float y) \84{ \85return _ZGVnN4vv_##func##f (argf (x), argf (y))[0]; \86}87#define ZVND1_WRAP(func) \88static double Z_##func (double x) { return _ZGVnN2v_##func (argd (x))[0]; }89#define ZVND2_WRAP(func) \90static double Z_##func (double x, double y) \91{ \92return _ZGVnN2vv_##func (argd (x), argd (y))[0]; \93}9495#if WANT_TRIGPI_TESTS96float97arm_math_sincospif_sin (float x)98{99float s, c;100arm_math_sincospif (x, &s, &c);101return s;102}103float104arm_math_sincospif_cos (float x)105{106float s, c;107arm_math_sincospif (x, &s, &c);108return c;109}110double111arm_math_sincospi_sin (double x)112{113double s, c;114arm_math_sincospi (x, &s, &c);115return s;116}117double118arm_math_sincospi_cos (double x)119{120double s, c;121arm_math_sincospi (x, &s, &c);122return c;123}124#endif125126#if __aarch64__ && __linux__127128# if WANT_TRIGPI_TESTS129ZVNF1_WRAP (cospi)130ZVND1_WRAP (cospi)131ZVNF1_WRAP (sinpi)132ZVND1_WRAP (sinpi)133ZVNF1_WRAP (tanpi)134ZVND1_WRAP (tanpi)135136double137v_sincospi_sin (double x)138{139double s[2], c[2];140_ZGVnN2vl8l8_sincospi (vdupq_n_f64 (x), s, c);141return s[0];142}143double144v_sincospi_cos (double x)145{146double s[2], c[2];147_ZGVnN2vl8l8_sincospi (vdupq_n_f64 (x), s, c);148return c[0];149}150float151v_sincospif_sin (float x)152{153float s[4], c[4];154_ZGVnN4vl4l4_sincospif (vdupq_n_f32 (x), s, c);155return s[0];156}157float158v_sincospif_cos (float x)159{160float s[4], c[4];161_ZGVnN4vl4l4_sincospif (vdupq_n_f32 (x), s, c);162return c[0];163}164# endif // WANT_TRIGPI_TESTS165166float167v_sincosf_sin (float x)168{169float s[4], c[4];170_ZGVnN4vl4l4_sincosf (vdupq_n_f32 (x), s, c);171return s[0];172}173float174v_sincosf_cos (float x)175{176float s[4], c[4];177_ZGVnN4vl4l4_sincosf (vdupq_n_f32 (x), s, c);178return c[0];179}180float181v_cexpif_sin (float x)182{183return _ZGVnN4v_cexpif (vdupq_n_f32 (x)).val[0][0];184}185float186v_cexpif_cos (float x)187{188return _ZGVnN4v_cexpif (vdupq_n_f32 (x)).val[1][0];189}190float191v_modff_frac (float x)192{193float y[4];194return _ZGVnN4vl4_modff (vdupq_n_f32 (x), y)[0];195}196float197v_modff_int (float x)198{199float y[4];200_ZGVnN4vl4_modff (vdupq_n_f32 (x), y);201return y[0];202}203double204v_sincos_sin (double x)205{206double s[2], c[2];207_ZGVnN2vl8l8_sincos (vdupq_n_f64 (x), s, c);208return s[0];209}210double211v_sincos_cos (double x)212{213double s[2], c[2];214_ZGVnN2vl8l8_sincos (vdupq_n_f64 (x), s, c);215return c[0];216}217double218v_cexpi_sin (double x)219{220return _ZGVnN2v_cexpi (vdupq_n_f64 (x)).val[0][0];221}222double223v_cexpi_cos (double x)224{225return _ZGVnN2v_cexpi (vdupq_n_f64 (x)).val[1][0];226}227double228v_modf_frac (double x)229{230double y[2];231return _ZGVnN2vl8_modf (vdupq_n_f64 (x), y)[0];232}233double234v_modf_int (double x)235{236double y[2];237_ZGVnN2vl8_modf (vdupq_n_f64 (x), y);238return y[0];239}240#endif // __aarch64__ && __linux__241242#if WANT_SVE_TESTS243# define ZSVNF1_WRAP(func) \244static float Z_sv_##func##f (svbool_t pg, float x) \245{ \246return svretf (_ZGVsMxv_##func##f (svargf (x), pg), pg); \247}248# define ZSVNF2_WRAP(func) \249static float Z_sv_##func##f (svbool_t pg, float x, float y) \250{ \251return svretf (_ZGVsMxvv_##func##f (svargf (x), svargf (y), pg), pg); \252}253# define ZSVND1_WRAP(func) \254static double Z_sv_##func (svbool_t pg, double x) \255{ \256return svretd (_ZGVsMxv_##func (svargd (x), pg), pg); \257}258# define ZSVND2_WRAP(func) \259static double Z_sv_##func (svbool_t pg, double x, double y) \260{ \261return svretd (_ZGVsMxvv_##func (svargd (x), svargd (y), pg), pg); \262}263264# if WANT_TRIGPI_TESTS265ZSVNF1_WRAP (cospi)266ZSVND1_WRAP (cospi)267ZSVNF1_WRAP (sinpi)268ZSVND1_WRAP (sinpi)269ZSVNF1_WRAP (tanpi)270ZSVND1_WRAP (tanpi)271double272sv_sincospi_sin (svbool_t pg, double x)273{274double s[svcntd ()], c[svcntd ()];275_ZGVsMxvl8l8_sincospi (svdup_f64 (x), s, c, pg);276return svretd (svld1 (pg, s), pg);277}278double279sv_sincospi_cos (svbool_t pg, double x)280{281double s[svcntd ()], c[svcntd ()];282_ZGVsMxvl8l8_sincospi (svdup_f64 (x), s, c, pg);283return svretd (svld1 (pg, c), pg);284}285float286sv_sincospif_sin (svbool_t pg, float x)287{288float s[svcntw ()], c[svcntw ()];289_ZGVsMxvl4l4_sincospif (svdup_f32 (x), s, c, pg);290return svretf (svld1 (pg, s), pg);291}292float293sv_sincospif_cos (svbool_t pg, float x)294{295float s[svcntw ()], c[svcntw ()];296_ZGVsMxvl4l4_sincospif (svdup_f32 (x), s, c, pg);297return svretf (svld1 (pg, c), pg);298}299# endif // WANT_TRIGPI_TESTS300301float302sv_sincosf_sin (svbool_t pg, float x)303{304float s[svcntw ()], c[svcntw ()];305_ZGVsMxvl4l4_sincosf (svdup_f32 (x), s, c, pg);306return svretf (svld1 (pg, s), pg);307}308float309sv_sincosf_cos (svbool_t pg, float x)310{311float s[svcntw ()], c[svcntw ()];312_ZGVsMxvl4l4_sincosf (svdup_f32 (x), s, c, pg);313return svretf (svld1 (pg, c), pg);314}315float316sv_cexpif_sin (svbool_t pg, float x)317{318return svretf (svget2 (_ZGVsMxv_cexpif (svdup_f32 (x), pg), 0), pg);319}320float321sv_cexpif_cos (svbool_t pg, float x)322{323return svretf (svget2 (_ZGVsMxv_cexpif (svdup_f32 (x), pg), 1), pg);324}325float326sv_modff_frac (svbool_t pg, float x)327{328float i[svcntw ()];329return svretf (_ZGVsMxvl4_modff (svdup_f32 (x), i, pg), pg);330}331float332sv_modff_int (svbool_t pg, float x)333{334float i[svcntw ()];335_ZGVsMxvl4_modff (svdup_f32 (x), i, pg);336return svretf (svld1 (pg, i), pg);337}338double339sv_sincos_sin (svbool_t pg, double x)340{341double s[svcntd ()], c[svcntd ()];342_ZGVsMxvl8l8_sincos (svdup_f64 (x), s, c, pg);343return svretd (svld1 (pg, s), pg);344}345double346sv_sincos_cos (svbool_t pg, double x)347{348double s[svcntd ()], c[svcntd ()];349_ZGVsMxvl8l8_sincos (svdup_f64 (x), s, c, pg);350return svretd (svld1 (pg, c), pg);351}352double353sv_cexpi_sin (svbool_t pg, double x)354{355return svretd (svget2 (_ZGVsMxv_cexpi (svdup_f64 (x), pg), 0), pg);356}357double358sv_cexpi_cos (svbool_t pg, double x)359{360return svretd (svget2 (_ZGVsMxv_cexpi (svdup_f64 (x), pg), 1), pg);361}362double363sv_modf_frac (svbool_t pg, double x)364{365double i[svcntd ()];366return svretd (_ZGVsMxvl8_modf (svdup_f64 (x), i, pg), pg);367}368double369sv_modf_int (svbool_t pg, double x)370{371double i[svcntd ()];372_ZGVsMxvl8_modf (svdup_f64 (x), i, pg);373return svretd (svld1 (pg, i), pg);374}375376# if WANT_EXPERIMENTAL_MATH377378/* Our implementations of powi/powk are too imprecise to verify379against any established pow implementation. Instead we have the380following simple implementation, against which it is enough to381maintain bitwise reproducibility. Note the test framework expects382the reference impl to be of higher precision than the function383under test. For instance this means that the reference for384double-precision powi will be passed a long double, so to check385bitwise reproducibility we have to cast it back down to386double. This is fine since a round-trip to higher precision and387back down is correctly rounded. */388# define DECL_POW_INT_REF(NAME, DBL_T, FLT_T, INT_T) \389static DBL_T __attribute__ ((unused)) NAME (DBL_T in_val, DBL_T y) \390{ \391INT_T n = (INT_T) round (y); \392FLT_T acc = 1.0; \393bool want_recip = n < 0; \394n = n < 0 ? -n : n; \395\396for (FLT_T c = in_val; n; c *= c, n >>= 1) \397{ \398if (n & 0x1) \399{ \400acc *= c; \401} \402} \403if (want_recip) \404{ \405acc = 1.0 / acc; \406} \407return acc; \408}409410DECL_POW_INT_REF (ref_powif, double, float, int)411DECL_POW_INT_REF (ref_powi, long double, double, int)412static float413Z_sv_powi (svbool_t pg, float x, float y)414{415return svretf (_ZGVsMxvv_powi (svargf (x), svdup_s32 ((int) round (y)), pg),416pg);417}418static double419Z_sv_powk (svbool_t pg, double x, double y)420{421return svretd (_ZGVsMxvv_powk (svargd (x), svdup_s64 ((long) round (y)), pg),422pg);423}424425# endif // WANT_EXPERIMENTAL_MATH426#endif // WANT_SVE_TESTS427428#include "test/ulp_wrappers_gen.h"429430431