1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
// Copyright Naoki Shibata and contributors 2010 - 2025.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <string.h>
#ifdef __cplusplus
#include <tlfloat/tlfloat.h>
using namespace tlfloat;
#endif
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic ignored "-Wuninitialized"
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#pragma GCC diagnostic ignored "-Wattributes"
#endif
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wvla-cxx-extension"
#pragma clang diagnostic ignored "-Wuninitialized"
#pragma clang diagnostic ignored "-Wtautological-compare"
#endif
#define DENORMAL_DBL_MIN (4.9406564584124654418e-324)
#define POSITIVE_INFINITY INFINITY
#define NEGATIVE_INFINITY (-INFINITY)
#define DENORMAL_FLT_MIN (1.4012984643248170709e-45f)
#define POSITIVE_INFINITYf ((float)INFINITY)
#define NEGATIVE_INFINITYf (-(float)INFINITY)
#ifndef M_PIf
# define M_PIf ((float)M_PI)
#endif
#ifdef __cplusplus
extern "C" {
#endif
extern int enableFlushToZero;
double flushToZero(double y);
int xisnumber(double x);
int isPlusZero(double x);
int isMinusZero(double x);
int xisnan(double x);
double sign(double d);
int isnumberf(float x);
int isPlusZerof(float x);
int isMinusZerof(float x);
int xisnanf(float x);
float signf(float d);
int readln(int fd, char *buf, int cnt);
#define XRAND_MAX (INT64_C(0x100000000) * (double)INT64_C(0x100000000))
void xsrand(uint64_t s);
uint64_t xrand();
void memrand(void *p, int size);
// The following functions are meant to be inlined
static double u2d(uint64_t u) {
double d = 0;
memcpy(&d, &u, sizeof(d));
return d;
}
static uint64_t d2u(double d) {
uint64_t u = 0;
memcpy(&u, &d, sizeof(u));
return u;
}
static float u2f(uint32_t u) {
float f = 0;
memcpy(&f, &u, sizeof(f));
return f;
}
static uint32_t f2u(float d) {
uint32_t u = 0;
memcpy(&u, &d, sizeof(u));
return u;
}
static int startsWith(char *str, char *prefix) {
while(*prefix != '\0') if (*str++ != *prefix++) return 0;
return *prefix == '\0';
}
//
#ifdef USEMPFR
int cmpDenormdp(double x, mpfr_t fry);
double countULPdp(double d, mpfr_t c);
double countULP2dp(double d, mpfr_t c);
int cmpDenormsp(float x, mpfr_t fry);
double countULPsp(float d, mpfr_t c);
double countULP2sp(float d, mpfr_t c);
#if MPFR_VERSION < MPFR_VERSION_NUM(4, 2, 0)
void mpfr_sinpi(mpfr_t ret, mpfr_t arg, mpfr_rnd_t rnd);
void mpfr_cospi(mpfr_t ret, mpfr_t arg, mpfr_rnd_t rnd);
#endif
void mpfr_lgamma_nosign(mpfr_t ret, mpfr_t arg, mpfr_rnd_t rnd);
#endif
#ifdef __cplusplus
}
template<typename T>
static double countULP(T ot, const T& oc,
const int nbmant, const T& fltmin, const T& fltmax,
const bool checkSignedZero=false, const double abound=0.0) {
if (isnan_(oc) && isnan_(ot)) return 0;
if (isnan_(oc) || isnan_(ot)) return 10001;
if (isinf_(oc) && !isinf_(ot)) return INFINITY;
const T halffltmin = mul_(fltmin, T(0.5));
const bool ciszero = fabs_(oc) < halffltmin, cisinf = fabs_(oc) > fltmax;
if (cisinf && isinf_(ot) && signbit_(oc) == signbit_(ot)) return 0;
if (ciszero && ot != 0) return 10000;
if (checkSignedZero && ciszero && ot == 0 && signbit_(oc) != signbit_(ot)) return 10002;
double v = 0;
if (isinf_(ot) && !isinf_(oc)) {
ot = copysign_(fltmax, ot);
v = 1;
}
const int ec = ilogb_(oc);
auto e = fabs_(oc - ot);
if (e < abound) return 0;
return double(div_(e, fmax_(ldexp_(T(1), ec + 1 - nbmant), fltmin))) + v;
}
#endif
|