Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/arm-optimized-routines/math/test/ulp_wrappers.h
48255 views
1
/*
2
* Function wrappers for ulp.
3
*
4
* Copyright (c) 2022-2024, Arm Limited.
5
* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
6
*/
7
8
/* clang-format off */
9
10
#if __aarch64__ && __linux__
11
#include <arm_neon.h>
12
#endif
13
14
#include <stdbool.h>
15
16
/* Wrappers for sincos. */
17
static float sincosf_sinf(float x) {(void)cosf(x); return sinf(x);}
18
static float sincosf_cosf(float x) {(void)sinf(x); return cosf(x);}
19
static double sincos_sin(double x) {(void)cos(x); return sin(x);}
20
static double sincos_cos(double x) {(void)sin(x); return cos(x);}
21
#if USE_MPFR
22
static 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); }
23
static 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); }
24
static 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); }
25
static 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); }
26
# if MPFR_VERSION < MPFR_VERSION_NUM(4, 2, 0)
27
static int mpfr_tanpi (mpfr_t ret, const mpfr_t arg, mpfr_rnd_t rnd) {
28
MPFR_DECL_INIT (frd, 1080);
29
mpfr_const_pi (frd, GMP_RNDN);
30
mpfr_mul (frd, frd, arg, GMP_RNDN);
31
return mpfr_tan (ret, frd, GMP_RNDN);
32
}
33
static int mpfr_sinpi (mpfr_t ret, const mpfr_t arg, mpfr_rnd_t rnd) {
34
MPFR_DECL_INIT (frd, 1080);
35
mpfr_const_pi (frd, GMP_RNDN);
36
mpfr_mul (frd, frd, arg, GMP_RNDN);
37
return mpfr_sin (ret, frd, GMP_RNDN);
38
}
39
40
static int mpfr_cospi (mpfr_t ret, const mpfr_t arg, mpfr_rnd_t rnd) {
41
MPFR_DECL_INIT (frd, 1080);
42
mpfr_const_pi (frd, GMP_RNDN);
43
mpfr_mul (frd, frd, arg, GMP_RNDN);
44
return mpfr_cos (ret, frd, GMP_RNDN);
45
}
46
# endif
47
# if WANT_EXPERIMENTAL_MATH
48
static int wrap_mpfr_powi(mpfr_t ret, const mpfr_t x, const mpfr_t y, mpfr_rnd_t rnd) {
49
mpfr_t y2;
50
mpfr_init(y2);
51
mpfr_trunc(y2, y);
52
return mpfr_pow(ret, x, y2, rnd);
53
}
54
# endif
55
#endif
56
57
float modff_frac(float x) { float i; return modff(x, &i); }
58
float modff_int(float x) { float i; modff(x, &i); return i; }
59
double modf_frac(double x) { double i; return modf(x, &i); }
60
double modf_int(double x) { double i; modf(x, &i); return i; }
61
long double modfl_frac(long double x) { long double i; return modfl(x, &i); }
62
long double modfl_int(long double x) { long double i; modfl(x, &i); return i; }
63
64
/* Wrappers for vector functions. */
65
#if __aarch64__ && __linux__
66
static float Z_expf_1u(float x) { return _ZGVnN4v_expf_1u(argf(x))[0]; }
67
static float Z_exp2f_1u(float x) { return _ZGVnN4v_exp2f_1u(argf(x))[0]; }
68
#endif
69
70
/* clang-format on */
71
72
/* No wrappers for scalar routines, but TEST_SIG will emit them. */
73
#define ZSNF1_WRAP(func)
74
#define ZSNF2_WRAP(func)
75
#define ZSND1_WRAP(func)
76
#define ZSND2_WRAP(func)
77
78
#define ZVNF1_WRAP(func) \
79
static float Z_##func##f (float x) \
80
{ \
81
return _ZGVnN4v_##func##f (argf (x))[0]; \
82
}
83
#define ZVNF2_WRAP(func) \
84
static float Z_##func##f (float x, float y) \
85
{ \
86
return _ZGVnN4vv_##func##f (argf (x), argf (y))[0]; \
87
}
88
#define ZVND1_WRAP(func) \
89
static double Z_##func (double x) { return _ZGVnN2v_##func (argd (x))[0]; }
90
#define ZVND2_WRAP(func) \
91
static double Z_##func (double x, double y) \
92
{ \
93
return _ZGVnN2vv_##func (argd (x), argd (y))[0]; \
94
}
95
96
#if WANT_TRIGPI_TESTS
97
float
98
arm_math_sincospif_sin (float x)
99
{
100
float s, c;
101
arm_math_sincospif (x, &s, &c);
102
return s;
103
}
104
float
105
arm_math_sincospif_cos (float x)
106
{
107
float s, c;
108
arm_math_sincospif (x, &s, &c);
109
return c;
110
}
111
double
112
arm_math_sincospi_sin (double x)
113
{
114
double s, c;
115
arm_math_sincospi (x, &s, &c);
116
return s;
117
}
118
double
119
arm_math_sincospi_cos (double x)
120
{
121
double s, c;
122
arm_math_sincospi (x, &s, &c);
123
return c;
124
}
125
#endif
126
127
#if __aarch64__ && __linux__
128
129
# if WANT_TRIGPI_TESTS
130
ZVNF1_WRAP (cospi)
131
ZVND1_WRAP (cospi)
132
ZVNF1_WRAP (sinpi)
133
ZVND1_WRAP (sinpi)
134
ZVNF1_WRAP (tanpi)
135
ZVND1_WRAP (tanpi)
136
137
double
138
v_sincospi_sin (double x)
139
{
140
double s[2], c[2];
141
_ZGVnN2vl8l8_sincospi (vdupq_n_f64 (x), s, c);
142
return s[0];
143
}
144
double
145
v_sincospi_cos (double x)
146
{
147
double s[2], c[2];
148
_ZGVnN2vl8l8_sincospi (vdupq_n_f64 (x), s, c);
149
return c[0];
150
}
151
float
152
v_sincospif_sin (float x)
153
{
154
float s[4], c[4];
155
_ZGVnN4vl4l4_sincospif (vdupq_n_f32 (x), s, c);
156
return s[0];
157
}
158
float
159
v_sincospif_cos (float x)
160
{
161
float s[4], c[4];
162
_ZGVnN4vl4l4_sincospif (vdupq_n_f32 (x), s, c);
163
return c[0];
164
}
165
# endif // WANT_TRIGPI_TESTS
166
167
float
168
v_sincosf_sin (float x)
169
{
170
float s[4], c[4];
171
_ZGVnN4vl4l4_sincosf (vdupq_n_f32 (x), s, c);
172
return s[0];
173
}
174
float
175
v_sincosf_cos (float x)
176
{
177
float s[4], c[4];
178
_ZGVnN4vl4l4_sincosf (vdupq_n_f32 (x), s, c);
179
return c[0];
180
}
181
float
182
v_cexpif_sin (float x)
183
{
184
return _ZGVnN4v_cexpif (vdupq_n_f32 (x)).val[0][0];
185
}
186
float
187
v_cexpif_cos (float x)
188
{
189
return _ZGVnN4v_cexpif (vdupq_n_f32 (x)).val[1][0];
190
}
191
float
192
v_modff_frac (float x)
193
{
194
float y[4];
195
return _ZGVnN4vl4_modff (vdupq_n_f32 (x), y)[0];
196
}
197
float
198
v_modff_int (float x)
199
{
200
float y[4];
201
_ZGVnN4vl4_modff (vdupq_n_f32 (x), y);
202
return y[0];
203
}
204
double
205
v_sincos_sin (double x)
206
{
207
double s[2], c[2];
208
_ZGVnN2vl8l8_sincos (vdupq_n_f64 (x), s, c);
209
return s[0];
210
}
211
double
212
v_sincos_cos (double x)
213
{
214
double s[2], c[2];
215
_ZGVnN2vl8l8_sincos (vdupq_n_f64 (x), s, c);
216
return c[0];
217
}
218
double
219
v_cexpi_sin (double x)
220
{
221
return _ZGVnN2v_cexpi (vdupq_n_f64 (x)).val[0][0];
222
}
223
double
224
v_cexpi_cos (double x)
225
{
226
return _ZGVnN2v_cexpi (vdupq_n_f64 (x)).val[1][0];
227
}
228
double
229
v_modf_frac (double x)
230
{
231
double y[2];
232
return _ZGVnN2vl8_modf (vdupq_n_f64 (x), y)[0];
233
}
234
double
235
v_modf_int (double x)
236
{
237
double y[2];
238
_ZGVnN2vl8_modf (vdupq_n_f64 (x), y);
239
return y[0];
240
}
241
#endif // __aarch64__ && __linux__
242
243
#if WANT_SVE_TESTS
244
# define ZSVNF1_WRAP(func) \
245
static float Z_sv_##func##f (svbool_t pg, float x) \
246
{ \
247
return svretf (_ZGVsMxv_##func##f (svargf (x), pg), pg); \
248
}
249
# define ZSVNF2_WRAP(func) \
250
static float Z_sv_##func##f (svbool_t pg, float x, float y) \
251
{ \
252
return svretf (_ZGVsMxvv_##func##f (svargf (x), svargf (y), pg), pg); \
253
}
254
# define ZSVND1_WRAP(func) \
255
static double Z_sv_##func (svbool_t pg, double x) \
256
{ \
257
return svretd (_ZGVsMxv_##func (svargd (x), pg), pg); \
258
}
259
# define ZSVND2_WRAP(func) \
260
static double Z_sv_##func (svbool_t pg, double x, double y) \
261
{ \
262
return svretd (_ZGVsMxvv_##func (svargd (x), svargd (y), pg), pg); \
263
}
264
265
# if WANT_TRIGPI_TESTS
266
ZSVNF1_WRAP (cospi)
267
ZSVND1_WRAP (cospi)
268
ZSVNF1_WRAP (sinpi)
269
ZSVND1_WRAP (sinpi)
270
ZSVNF1_WRAP (tanpi)
271
ZSVND1_WRAP (tanpi)
272
double
273
sv_sincospi_sin (svbool_t pg, double x)
274
{
275
double s[svcntd ()], c[svcntd ()];
276
_ZGVsMxvl8l8_sincospi (svdup_f64 (x), s, c, pg);
277
return svretd (svld1 (pg, s), pg);
278
}
279
double
280
sv_sincospi_cos (svbool_t pg, double x)
281
{
282
double s[svcntd ()], c[svcntd ()];
283
_ZGVsMxvl8l8_sincospi (svdup_f64 (x), s, c, pg);
284
return svretd (svld1 (pg, c), pg);
285
}
286
float
287
sv_sincospif_sin (svbool_t pg, float x)
288
{
289
float s[svcntw ()], c[svcntw ()];
290
_ZGVsMxvl4l4_sincospif (svdup_f32 (x), s, c, pg);
291
return svretf (svld1 (pg, s), pg);
292
}
293
float
294
sv_sincospif_cos (svbool_t pg, float x)
295
{
296
float s[svcntw ()], c[svcntw ()];
297
_ZGVsMxvl4l4_sincospif (svdup_f32 (x), s, c, pg);
298
return svretf (svld1 (pg, c), pg);
299
}
300
# endif // WANT_TRIGPI_TESTS
301
302
float
303
sv_sincosf_sin (svbool_t pg, float x)
304
{
305
float s[svcntw ()], c[svcntw ()];
306
_ZGVsMxvl4l4_sincosf (svdup_f32 (x), s, c, pg);
307
return svretf (svld1 (pg, s), pg);
308
}
309
float
310
sv_sincosf_cos (svbool_t pg, float x)
311
{
312
float s[svcntw ()], c[svcntw ()];
313
_ZGVsMxvl4l4_sincosf (svdup_f32 (x), s, c, pg);
314
return svretf (svld1 (pg, c), pg);
315
}
316
float
317
sv_cexpif_sin (svbool_t pg, float x)
318
{
319
return svretf (svget2 (_ZGVsMxv_cexpif (svdup_f32 (x), pg), 0), pg);
320
}
321
float
322
sv_cexpif_cos (svbool_t pg, float x)
323
{
324
return svretf (svget2 (_ZGVsMxv_cexpif (svdup_f32 (x), pg), 1), pg);
325
}
326
float
327
sv_modff_frac (svbool_t pg, float x)
328
{
329
float i[svcntw ()];
330
return svretf (_ZGVsMxvl4_modff (svdup_f32 (x), i, pg), pg);
331
}
332
float
333
sv_modff_int (svbool_t pg, float x)
334
{
335
float i[svcntw ()];
336
_ZGVsMxvl4_modff (svdup_f32 (x), i, pg);
337
return svretf (svld1 (pg, i), pg);
338
}
339
double
340
sv_sincos_sin (svbool_t pg, double x)
341
{
342
double s[svcntd ()], c[svcntd ()];
343
_ZGVsMxvl8l8_sincos (svdup_f64 (x), s, c, pg);
344
return svretd (svld1 (pg, s), pg);
345
}
346
double
347
sv_sincos_cos (svbool_t pg, double x)
348
{
349
double s[svcntd ()], c[svcntd ()];
350
_ZGVsMxvl8l8_sincos (svdup_f64 (x), s, c, pg);
351
return svretd (svld1 (pg, c), pg);
352
}
353
double
354
sv_cexpi_sin (svbool_t pg, double x)
355
{
356
return svretd (svget2 (_ZGVsMxv_cexpi (svdup_f64 (x), pg), 0), pg);
357
}
358
double
359
sv_cexpi_cos (svbool_t pg, double x)
360
{
361
return svretd (svget2 (_ZGVsMxv_cexpi (svdup_f64 (x), pg), 1), pg);
362
}
363
double
364
sv_modf_frac (svbool_t pg, double x)
365
{
366
double i[svcntd ()];
367
return svretd (_ZGVsMxvl8_modf (svdup_f64 (x), i, pg), pg);
368
}
369
double
370
sv_modf_int (svbool_t pg, double x)
371
{
372
double i[svcntd ()];
373
_ZGVsMxvl8_modf (svdup_f64 (x), i, pg);
374
return svretd (svld1 (pg, i), pg);
375
}
376
377
# if WANT_EXPERIMENTAL_MATH
378
379
/* Our implementations of powi/powk are too imprecise to verify
380
against any established pow implementation. Instead we have the
381
following simple implementation, against which it is enough to
382
maintain bitwise reproducibility. Note the test framework expects
383
the reference impl to be of higher precision than the function
384
under test. For instance this means that the reference for
385
double-precision powi will be passed a long double, so to check
386
bitwise reproducibility we have to cast it back down to
387
double. This is fine since a round-trip to higher precision and
388
back down is correctly rounded. */
389
# define DECL_POW_INT_REF(NAME, DBL_T, FLT_T, INT_T) \
390
static DBL_T __attribute__ ((unused)) NAME (DBL_T in_val, DBL_T y) \
391
{ \
392
INT_T n = (INT_T) round (y); \
393
FLT_T acc = 1.0; \
394
bool want_recip = n < 0; \
395
n = n < 0 ? -n : n; \
396
\
397
for (FLT_T c = in_val; n; c *= c, n >>= 1) \
398
{ \
399
if (n & 0x1) \
400
{ \
401
acc *= c; \
402
} \
403
} \
404
if (want_recip) \
405
{ \
406
acc = 1.0 / acc; \
407
} \
408
return acc; \
409
}
410
411
DECL_POW_INT_REF (ref_powif, double, float, int)
412
DECL_POW_INT_REF (ref_powi, long double, double, int)
413
static float
414
Z_sv_powi (svbool_t pg, float x, float y)
415
{
416
return svretf (_ZGVsMxvv_powi (svargf (x), svdup_s32 ((int) round (y)), pg),
417
pg);
418
}
419
static double
420
Z_sv_powk (svbool_t pg, double x, double y)
421
{
422
return svretd (_ZGVsMxvv_powk (svargd (x), svdup_s64 ((long) round (y)), pg),
423
pg);
424
}
425
426
# endif // WANT_EXPERIMENTAL_MATH
427
#endif // WANT_SVE_TESTS
428
429
#include "test/ulp_wrappers_gen.h"
430
431