#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <mpfr.h>
#include <time.h>
#include <float.h>
#include <limits.h>
#include <assert.h>
#if defined(POWER64_UNDEF_USE_EXTERN_INLINES)
#include <features.h>
#ifdef __USE_EXTERN_INLINES
#undef __USE_EXTERN_INLINES
#endif
#endif
#include <math.h>
#include <quadmath.h>
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/random.h>
#include "sleef.h"
#include "f128util.h"
#define DORENAME
#include "rename.h"
#define POSITIVE_INFINITY INFINITY
#define NEGATIVE_INFINITY (-INFINITY)
int isnumberq(Sleef_quad x) { return !isinfq(x) && !isnanq(x); }
int isPlusZeroq(Sleef_quad x) { return x == 0 && copysignq(1, x) == 1; }
int isMinusZeroq(Sleef_quad x) { return x == 0 && copysignq(1, x) == -1; }
mpfr_t fra, frb, frc, frd;
double countULP(Sleef_quad d, mpfr_t c) {
Sleef_quad c2 = mpfr_get_f128(c, GMP_RNDN);
if (c2 == 0 && d != 0) return 10000;
if (isnanq(c2) && isnanq(d)) return 0;
if (isnanq(c2) || isnanq(d)) return 10001;
if (c2 == POSITIVE_INFINITY && d == POSITIVE_INFINITY) return 0;
if (c2 == NEGATIVE_INFINITY && d == NEGATIVE_INFINITY) return 0;
if (!isnumberq(c2) && !isnumberq(d)) return 0;
int e;
frexpq(mpfr_get_f128(c, GMP_RNDN), &e);
mpfr_set_f128(frb, fmaxq(ldexpq(1.0, e-113), FLT128_DENORM_MIN), GMP_RNDN);
mpfr_set_f128(frd, d, GMP_RNDN);
mpfr_sub(fra, frd, c, GMP_RNDN);
mpfr_div(fra, fra, frb, GMP_RNDN);
double u = fabs(mpfr_get_d(fra, GMP_RNDN));
return u;
}
double countULP2(Sleef_quad d, mpfr_t c) {
Sleef_quad c2 = mpfr_get_f128(c, GMP_RNDN);
if (c2 == 0 && d != 0) return 10000;
if (isnanq(c2) && isnanq(d)) return 0;
if (isnanq(c2) || isnanq(d)) return 10001;
if (c2 == POSITIVE_INFINITY && d == POSITIVE_INFINITY) return 0;
if (c2 == NEGATIVE_INFINITY && d == NEGATIVE_INFINITY) return 0;
if (!isnumberq(c2) && !isnumberq(d)) return 0;
int e;
frexpq(mpfr_get_f128(c, GMP_RNDN), &e);
mpfr_set_f128(frb, fmaxq(ldexpq(1.0, e-113), FLT128_MIN), GMP_RNDN);
mpfr_set_f128(frd, d, GMP_RNDN);
mpfr_sub(fra, frd, c, GMP_RNDN);
mpfr_div(fra, fra, frb, GMP_RNDN);
double u = fabs(mpfr_get_d(fra, GMP_RNDN));
return u;
}
typedef union {
Sleef_quad d;
__int128 u128;
uint64_t u[2];
} conv_t;
Sleef_quad rnd() {
conv_t c;
switch(random() & 15) {
case 0: return INFINITY;
case 1: return -INFINITY;
}
syscall(SYS_getrandom, &c.u128, sizeof(c.u128), 0);
return c.d;
}
Sleef_quad rnd_fr() {
conv_t c;
do {
syscall(SYS_getrandom, &c.u128, sizeof(c.u128), 0);
} while(!isnumberq(c.d));
return c.d;
}
Sleef_quad rnd_zo() {
conv_t c;
do {
syscall(SYS_getrandom, &c.u128, sizeof(c.u128), 0);
} while(!isnumberq(c.d) || c.d < -1 || 1 < c.d);
return c.d;
}
void sinpifr(mpfr_t ret, Sleef_quad d) {
mpfr_t frpi, frd;
mpfr_inits(frpi, frd, NULL);
mpfr_const_pi(frpi, GMP_RNDN);
mpfr_set_d(frd, 1.0, GMP_RNDN);
mpfr_mul(frpi, frpi, frd, GMP_RNDN);
mpfr_set_f128(frd, d, GMP_RNDN);
mpfr_mul(frd, frpi, frd, GMP_RNDN);
mpfr_sin(ret, frd, GMP_RNDN);
mpfr_clears(frpi, frd, NULL);
}
void cospifr(mpfr_t ret, Sleef_quad d) {
mpfr_t frpi, frd;
mpfr_inits(frpi, frd, NULL);
mpfr_const_pi(frpi, GMP_RNDN);
mpfr_set_d(frd, 1.0, GMP_RNDN);
mpfr_mul(frpi, frpi, frd, GMP_RNDN);
mpfr_set_f128(frd, d, GMP_RNDN);
mpfr_mul(frd, frpi, frd, GMP_RNDN);
mpfr_cos(ret, frd, GMP_RNDN);
mpfr_clears(frpi, frd, NULL);
}
int main(int argc,char **argv)
{
mpfr_t frw, frx, fry, frz;
mpfr_set_default_prec(2048);
mpfr_inits(fra, frb, frc, frd, frw, frx, fry, frz, NULL);
conv_t cd;
Sleef_quad d, t, d2, zo;
int cnt, ecnt = 0;
srandom(time(NULL));
#if 0#endif
const Sleef_quad rangemax = 1e+9;
for(cnt = 0;ecnt < 1000;cnt++) {
switch(cnt & 7) {
case 0:
d = rnd();
d2 = rnd();
zo = rnd();
break;
case 1:
cd.d = rint((2 * (double)random() / RAND_MAX - 1) * 1e+10) * M_PI_4;
cd.u128 += (random() & 0xff) - 0x7f;
d = cd.d;
d2 = rnd();
zo = rnd();
break;
default:
d = rnd_fr();
d2 = rnd_fr();
zo = rnd_zo();
break;
}
Sleef_quad2 sc = xsincospiq_u05(d);
Sleef_quad2 sc2 = xsincospiq_u35(d);
{
const double rangemax2 = 1e+9;
sinpifr(frx, d);
double u0 = countULP2(t = sc.x, frx);
if (u0 != 0 && ((fabs(d) <= rangemax2 && u0 > 0.505) || fabs(t) > 1 || !isnumberq(t))) {
printf("Pure C sincospiq_u05 sin arg="); printf128(d); printf(" ulp=%.20g\n", u0);
fflush(stdout); ecnt++;
}
double u1 = countULP2(t = sc2.x, frx);
if (u1 != 0 && ((fabs(d) <= rangemax2 && u1 > 2.0) || fabs(t) > 1 || !isnumberq(t))) {
printf("Pure C sincospiq_u35 sin arg=%.30Lg ulp=%.20g\n", (long double)d, u1);
fflush(stdout); ecnt++;
}
}
{
const double rangemax2 = 1e+9;
cospifr(frx, d);
double u0 = countULP2(t = sc.y, frx);
if (u0 != 0 && ((fabs(d) <= rangemax2 && u0 > 0.505) || fabs(t) > 1 || !isnumberq(t))) {
printf("Pure C sincospiq_u05 cos arg=%.30Lg ulp=%.20g\n", (long double)d, u0);
fflush(stdout); ecnt++;
}
double u1 = countULP2(t = sc.y, frx);
if (u1 != 0 && ((fabs(d) <= rangemax2 && u1 > 2.0) || fabs(t) > 1 || !isnumberq(t))) {
printf("Pure C sincospiq_u35 cos arg=%.30Lg ulp=%.20g\n", (long double)d, u1);
fflush(stdout); ecnt++;
}
}
#if 0#endif
}
}