2024-09-01 14:56:38 +08:00
|
|
|
|
#include "../include/math.h"
|
2024-09-01 16:43:58 +08:00
|
|
|
|
#include "../include/ctype.h"
|
2024-09-01 14:56:38 +08:00
|
|
|
|
|
2024-09-08 22:43:05 +08:00
|
|
|
|
static const double ivln10hi =
|
|
|
|
|
4.34294481878168880939e-01, /* 0x3fdbcb7b, 0x15200000 */
|
|
|
|
|
ivln10lo = 2.50829467116452752298e-11, /* 0x3dbb9438, 0xca9aadd5 */
|
|
|
|
|
log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */
|
|
|
|
|
log10_2lo = 3.69423907715893078616e-13, /* 0x3D59FEF3, 0x11F12B36 */
|
|
|
|
|
Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */
|
|
|
|
|
Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */
|
|
|
|
|
Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */
|
|
|
|
|
Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */
|
|
|
|
|
Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
|
|
|
|
|
Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
|
|
|
|
|
Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
|
2024-09-01 14:56:38 +08:00
|
|
|
|
|
2024-09-08 22:43:05 +08:00
|
|
|
|
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
|
|
|
|
|
__asm__ ("subl %5,%1\n\tsbbl %3,%0" \
|
|
|
|
|
: "=r" ((USItype) (sh)), \
|
|
|
|
|
"=&r" ((USItype) (sl)) \
|
|
|
|
|
: "0" ((USItype) (ah)), \
|
|
|
|
|
"g" ((USItype) (bh)), \
|
|
|
|
|
"1" ((USItype) (al)), \
|
|
|
|
|
"g" ((USItype) (bl)))
|
|
|
|
|
#define umul_ppmm(w1, w0, u, v) \
|
|
|
|
|
__asm__ ("mull %3" \
|
|
|
|
|
: "=a" ((USItype) (w0)), \
|
|
|
|
|
"=d" ((USItype) (w1)) \
|
|
|
|
|
: "%0" ((USItype) (u)), \
|
|
|
|
|
"rm" ((USItype) (v)))
|
|
|
|
|
#define udiv_qrnnd(q, r, n1, n0, dv) \
|
|
|
|
|
__asm__ ("divl %4" \
|
|
|
|
|
: "=a" ((USItype) (q)), \
|
|
|
|
|
"=d" ((USItype) (r)) \
|
|
|
|
|
: "0" ((USItype) (n0)), \
|
|
|
|
|
"1" ((USItype) (n1)), \
|
|
|
|
|
"rm" ((USItype) (dv)))
|
|
|
|
|
#define count_leading_zeros(count, x) \
|
|
|
|
|
do { \
|
|
|
|
|
USItype __cbtmp; \
|
|
|
|
|
__asm__ ("bsrl %1,%0" \
|
|
|
|
|
: "=r" (__cbtmp) : "rm" ((USItype) (x))); \
|
|
|
|
|
(count) = __cbtmp ^ 31; \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
static unsigned rand_seed = 1;
|
|
|
|
|
static unsigned short max_bit = 32;
|
|
|
|
|
static unsigned short randlevel = 1;
|
|
|
|
|
|
|
|
|
|
#define __negdi2(a) (-(a))
|
|
|
|
|
|
|
|
|
|
static UDWtype __udivmoddi4(UDWtype n, UDWtype d, UDWtype *rp) {
|
|
|
|
|
DWunion ww;
|
|
|
|
|
DWunion nn, dd;
|
|
|
|
|
DWunion rr;
|
|
|
|
|
UWtype d0, d1, n0, n1, n2;
|
|
|
|
|
UWtype q0, q1;
|
|
|
|
|
UWtype b, bm;
|
|
|
|
|
|
|
|
|
|
nn.ll = n;
|
|
|
|
|
dd.ll = d;
|
|
|
|
|
|
|
|
|
|
d0 = dd.s.low;
|
|
|
|
|
d1 = dd.s.high;
|
|
|
|
|
n0 = nn.s.low;
|
|
|
|
|
n1 = nn.s.high;
|
|
|
|
|
|
|
|
|
|
#if !defined(UDIV_NEEDS_NORMALIZATION)
|
|
|
|
|
if (d1 == 0) {
|
|
|
|
|
if (d0 > n1) {
|
|
|
|
|
/* 0q = nn / 0D */
|
|
|
|
|
|
|
|
|
|
udiv_qrnnd(q0, n0, n1, n0, d0);
|
|
|
|
|
q1 = 0;
|
|
|
|
|
|
|
|
|
|
/* Remainder in n0. */
|
|
|
|
|
} else {
|
|
|
|
|
/* qq = NN / 0d */
|
|
|
|
|
|
|
|
|
|
if (d0 == 0)
|
|
|
|
|
d0 = 1 / d0; /* Divide intentionally by zero. */
|
|
|
|
|
|
|
|
|
|
udiv_qrnnd(q1, n1, 0, n1, d0);
|
|
|
|
|
udiv_qrnnd(q0, n0, n1, n0, d0);
|
|
|
|
|
|
|
|
|
|
/* Remainder in n0. */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rp != 0) {
|
|
|
|
|
rr.s.low = n0;
|
|
|
|
|
rr.s.high = 0;
|
|
|
|
|
*rp = rr.ll;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else /* UDIV_NEEDS_NORMALIZATION */
|
|
|
|
|
|
|
|
|
|
if (d1 == 0)
|
|
|
|
|
{
|
|
|
|
|
if (d0 > n1)
|
|
|
|
|
{
|
|
|
|
|
/* 0q = nn / 0D */
|
|
|
|
|
|
|
|
|
|
count_leading_zeros (bm, d0);
|
|
|
|
|
|
|
|
|
|
if (bm != 0)
|
|
|
|
|
{
|
|
|
|
|
/* Normalize, i.e. make the most significant bit of the
|
|
|
|
|
denominator set. */
|
|
|
|
|
|
|
|
|
|
d0 = d0 << bm;
|
|
|
|
|
n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
|
|
|
|
|
n0 = n0 << bm;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
udiv_qrnnd (q0, n0, n1, n0, d0);
|
|
|
|
|
q1 = 0;
|
|
|
|
|
|
|
|
|
|
/* Remainder in n0 >> bm. */
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* qq = NN / 0d */
|
|
|
|
|
|
|
|
|
|
if (d0 == 0)
|
|
|
|
|
d0 = 1 / d0; /* Divide intentionally by zero. */
|
|
|
|
|
|
|
|
|
|
count_leading_zeros (bm, d0);
|
|
|
|
|
|
|
|
|
|
if (bm == 0)
|
|
|
|
|
{
|
|
|
|
|
/* From (n1 >= d0) /\ (the most significant bit of d0 is set),
|
|
|
|
|
conclude (the most significant bit of n1 is set) /\ (the
|
|
|
|
|
leading quotient digit q1 = 1).
|
|
|
|
|
|
|
|
|
|
This special case is necessary, not an optimization.
|
|
|
|
|
(Shifts counts of W_TYPE_SIZE are undefined.) */
|
|
|
|
|
|
|
|
|
|
n1 -= d0;
|
|
|
|
|
q1 = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Normalize. */
|
|
|
|
|
|
|
|
|
|
b = W_TYPE_SIZE - bm;
|
|
|
|
|
|
|
|
|
|
d0 = d0 << bm;
|
|
|
|
|
n2 = n1 >> b;
|
|
|
|
|
n1 = (n1 << bm) | (n0 >> b);
|
|
|
|
|
n0 = n0 << bm;
|
|
|
|
|
|
|
|
|
|
udiv_qrnnd (q1, n1, n2, n1, d0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* n1 != d0... */
|
|
|
|
|
|
|
|
|
|
udiv_qrnnd (q0, n0, n1, n0, d0);
|
|
|
|
|
|
|
|
|
|
/* Remainder in n0 >> bm. */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rp != 0)
|
|
|
|
|
{
|
|
|
|
|
rr.s.low = n0 >> bm;
|
|
|
|
|
rr.s.high = 0;
|
|
|
|
|
*rp = rr.ll;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif /* UDIV_NEEDS_NORMALIZATION */
|
|
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
if (d1 > n1) {
|
|
|
|
|
/* 00 = nn / DD */
|
|
|
|
|
|
|
|
|
|
q0 = 0;
|
|
|
|
|
q1 = 0;
|
|
|
|
|
|
|
|
|
|
/* Remainder in n1n0. */
|
|
|
|
|
if (rp != 0) {
|
|
|
|
|
rr.s.low = n0;
|
|
|
|
|
rr.s.high = n1;
|
|
|
|
|
*rp = rr.ll;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* 0q = NN / dd */
|
|
|
|
|
|
|
|
|
|
count_leading_zeros(bm, d1);
|
|
|
|
|
if (bm == 0) {
|
|
|
|
|
/* From (n1 >= d1) /\ (the most significant bit of d1 is set),
|
|
|
|
|
conclude (the most significant bit of n1 is set) /\ (the
|
|
|
|
|
quotient digit q0 = 0 or 1).
|
|
|
|
|
|
|
|
|
|
This special case is necessary, not an optimization. */
|
|
|
|
|
|
|
|
|
|
/* The condition on the next line takes advantage of that
|
|
|
|
|
n1 >= d1 (true due to program flow). */
|
|
|
|
|
if (n1 > d1 || n0 >= d0) {
|
|
|
|
|
q0 = 1;
|
|
|
|
|
sub_ddmmss(n1, n0, n1, n0, d1, d0);
|
|
|
|
|
} else
|
|
|
|
|
q0 = 0;
|
|
|
|
|
|
|
|
|
|
q1 = 0;
|
|
|
|
|
|
|
|
|
|
if (rp != 0) {
|
|
|
|
|
rr.s.low = n0;
|
|
|
|
|
rr.s.high = n1;
|
|
|
|
|
*rp = rr.ll;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
UWtype m1, m0;
|
|
|
|
|
/* Normalize. */
|
|
|
|
|
|
|
|
|
|
b = W_TYPE_SIZE - bm;
|
|
|
|
|
|
|
|
|
|
d1 = (d1 << bm) | (d0 >> b);
|
|
|
|
|
d0 = d0 << bm;
|
|
|
|
|
n2 = n1 >> b;
|
|
|
|
|
n1 = (n1 << bm) | (n0 >> b);
|
|
|
|
|
n0 = n0 << bm;
|
|
|
|
|
|
|
|
|
|
udiv_qrnnd(q0, n1, n2, n1, d1);
|
|
|
|
|
umul_ppmm(m1, m0, q0, d0);
|
|
|
|
|
|
|
|
|
|
if (m1 > n1 || (m1 == n1 && m0 > n0)) {
|
|
|
|
|
q0--;
|
|
|
|
|
sub_ddmmss(m1, m0, m1, m0, d1, d0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
q1 = 0;
|
|
|
|
|
|
|
|
|
|
/* Remainder in (n1n0 - m1m0) >> bm. */
|
|
|
|
|
if (rp != 0) {
|
|
|
|
|
sub_ddmmss(n1, n0, n1, n0, m1, m0);
|
|
|
|
|
rr.s.low = (n1 << b) | (n0 >> bm);
|
|
|
|
|
rr.s.high = n1 >> bm;
|
|
|
|
|
*rp = rr.ll;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ww.s.low = q0;
|
|
|
|
|
ww.s.high = q1;
|
|
|
|
|
return ww.ll;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__attribute__((used)) long long __moddi3(long long u, long long v) {
|
|
|
|
|
int c = 0;
|
|
|
|
|
DWunion uu, vv;
|
|
|
|
|
DWtype w;
|
|
|
|
|
|
|
|
|
|
uu.ll = u;
|
|
|
|
|
vv.ll = v;
|
|
|
|
|
|
|
|
|
|
if (uu.s.high < 0) {
|
|
|
|
|
c = ~c;
|
|
|
|
|
uu.ll = __negdi2 (uu.ll);
|
|
|
|
|
}
|
|
|
|
|
if (vv.s.high < 0)
|
|
|
|
|
vv.ll = __negdi2 (vv.ll);
|
|
|
|
|
|
|
|
|
|
__udivmoddi4(uu.ll, vv.ll, (UDWtype *) &w);
|
|
|
|
|
if (c)
|
|
|
|
|
w = __negdi2 (w);
|
|
|
|
|
return w;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rand() {
|
2024-09-01 14:56:38 +08:00
|
|
|
|
unsigned short i = 0;
|
2024-09-08 22:43:05 +08:00
|
|
|
|
while (i < randlevel)
|
|
|
|
|
rand_seed = rand_seed * 1103515245 + 12345, rand_seed <<= max_bit, i++;
|
|
|
|
|
return (rand_seed >>= max_bit);
|
2024-09-01 14:56:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-09-08 22:43:05 +08:00
|
|
|
|
void srand(unsigned seed) {
|
|
|
|
|
rand_seed = seed;
|
2024-09-01 14:56:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-09-08 22:43:05 +08:00
|
|
|
|
void smax(unsigned short max_b) {
|
|
|
|
|
max_b = (sizeof(unsigned long long) * 8) - (max_b % (sizeof(unsigned long long) * 8));
|
|
|
|
|
max_bit = (max_b == 0) ? (sizeof(unsigned long long) * 8 / 2) : (max_b);
|
2024-09-01 14:56:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-09-08 22:43:05 +08:00
|
|
|
|
void srandlevel(unsigned short randlevel_) {
|
|
|
|
|
if (randlevel_ != 0)
|
|
|
|
|
randlevel = randlevel_;
|
2024-09-01 14:56:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-09-08 22:43:05 +08:00
|
|
|
|
int32_t abs(int32_t x) {
|
|
|
|
|
return (x < 0) ? (-x) : (x);
|
2024-09-01 14:56:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-09-08 22:43:05 +08:00
|
|
|
|
double pow(double a, long long b) {
|
|
|
|
|
char t = 0;
|
|
|
|
|
if (b < 0)b = -b, t = 1;
|
|
|
|
|
double ans = 1;
|
|
|
|
|
while (b) {
|
|
|
|
|
if (b & 1)ans *= a;
|
|
|
|
|
a *= a;
|
|
|
|
|
b >>= 1;
|
2024-09-01 14:56:38 +08:00
|
|
|
|
}
|
2024-09-08 22:43:05 +08:00
|
|
|
|
if (t)return (1.0 / ans);
|
|
|
|
|
else return ans;
|
2024-09-01 14:56:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//快速整数平方
|
2024-09-08 22:43:05 +08:00
|
|
|
|
unsigned long long ull_pow(unsigned long long a, unsigned long long b) {
|
|
|
|
|
unsigned long long ans = 1;
|
|
|
|
|
while (b) {
|
|
|
|
|
if (b & 1)ans *= a;
|
|
|
|
|
a *= a;
|
|
|
|
|
b >>= 1;
|
2024-09-01 14:56:38 +08:00
|
|
|
|
}
|
2024-09-08 22:43:05 +08:00
|
|
|
|
return ans;
|
2024-09-01 14:56:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2024-09-08 22:43:05 +08:00
|
|
|
|
double sqrt(double x) {
|
|
|
|
|
if (x == 0)return 0.0;
|
|
|
|
|
double xk = 1.0, xk1 = 0.0;
|
|
|
|
|
while (xk != xk1)xk1 = xk, xk = (xk + x / xk) / 2.0;
|
|
|
|
|
return xk;
|
2024-09-01 14:56:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//快速求算数平方根(速度快,精度低)
|
2024-09-08 22:43:05 +08:00
|
|
|
|
float q_sqrt(float number) {
|
|
|
|
|
long i;
|
|
|
|
|
float x, y;
|
|
|
|
|
const float f = 1.5F;
|
|
|
|
|
x = number * 0.5F;
|
|
|
|
|
y = number;
|
|
|
|
|
i = *(long *) (&y);
|
|
|
|
|
i = 0x5f3759df - (i >> 1);
|
|
|
|
|
y = *(float *) (&i);
|
|
|
|
|
y = y * (f - (x * y * y));
|
|
|
|
|
y = y * (f - (x * y * y));
|
|
|
|
|
return number * y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double mod(double x, double y) {
|
2024-09-01 16:43:58 +08:00
|
|
|
|
return x - (int32_t)(x / y) * y;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-08 22:43:05 +08:00
|
|
|
|
double sin(double x) {
|
|
|
|
|
x = mod(x, 2 * PI);
|
|
|
|
|
double sum = x;
|
|
|
|
|
double term = x;
|
|
|
|
|
int n = 1;
|
2024-09-01 16:43:58 +08:00
|
|
|
|
bool sign = true;
|
|
|
|
|
while (term > F64_EPSILON || term < -F64_EPSILON) {
|
2024-09-08 22:43:05 +08:00
|
|
|
|
n += 2;
|
2024-09-01 16:43:58 +08:00
|
|
|
|
term *= x * x / (n * (n - 1));
|
2024-09-08 22:43:05 +08:00
|
|
|
|
sum += sign ? -term : term;
|
|
|
|
|
sign = !sign;
|
2024-09-01 16:43:58 +08:00
|
|
|
|
}
|
|
|
|
|
return sum;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-08 22:43:05 +08:00
|
|
|
|
double cos(double x) {
|
|
|
|
|
x = mod(x, 2 * PI);
|
|
|
|
|
double sum = 1;
|
|
|
|
|
double term = 1;
|
|
|
|
|
int n = 0;
|
2024-09-01 16:43:58 +08:00
|
|
|
|
bool sign = true;
|
|
|
|
|
while (term > F64_EPSILON || term < -F64_EPSILON) {
|
2024-09-08 22:43:05 +08:00
|
|
|
|
n += 2;
|
2024-09-01 16:43:58 +08:00
|
|
|
|
term *= x * x / (n * (n - 1));
|
2024-09-08 22:43:05 +08:00
|
|
|
|
sum += sign ? -term : term;
|
|
|
|
|
sign = !sign;
|
2024-09-01 16:43:58 +08:00
|
|
|
|
}
|
|
|
|
|
return sum;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double tan(double x) {
|
|
|
|
|
return sin(x) / cos(x);
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-08 22:43:05 +08:00
|
|
|
|
double asin(double x) {
|
|
|
|
|
double sum = x;
|
2024-09-01 16:43:58 +08:00
|
|
|
|
double term = x;
|
2024-09-08 22:43:05 +08:00
|
|
|
|
int n = 1;
|
2024-09-01 16:43:58 +08:00
|
|
|
|
while (term > F64_EPSILON || term < -F64_EPSILON) {
|
|
|
|
|
term *= (x * x * (2 * n - 1) * (2 * n - 1)) / (2 * n * (2 * n + 1));
|
2024-09-08 22:43:05 +08:00
|
|
|
|
sum += term;
|
2024-09-01 16:43:58 +08:00
|
|
|
|
n++;
|
|
|
|
|
}
|
|
|
|
|
return sum;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double acos(double x) {
|
|
|
|
|
return PI / 2 - asin(x);
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-08 22:43:05 +08:00
|
|
|
|
double atan(double x) {
|
|
|
|
|
double sum = x;
|
|
|
|
|
double term = x;
|
|
|
|
|
int n = 1;
|
2024-09-01 16:43:58 +08:00
|
|
|
|
bool sign = true;
|
|
|
|
|
while (term > F64_EPSILON || term < -F64_EPSILON) {
|
|
|
|
|
term *= x * x * (2 * n - 1) / (2 * n + 1);
|
2024-09-08 22:43:05 +08:00
|
|
|
|
sum += sign ? -term : term;
|
|
|
|
|
sign = !sign;
|
2024-09-01 16:43:58 +08:00
|
|
|
|
n++;
|
|
|
|
|
}
|
|
|
|
|
return sum;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-08 22:43:05 +08:00
|
|
|
|
double atan2(double y, double x) {
|
2024-09-01 16:43:58 +08:00
|
|
|
|
if (x > 0) return atan(y / x);
|
|
|
|
|
if (x < 0 && y >= 0) return atan(y / x) + PI;
|
|
|
|
|
if (x < 0 && y < 0) return atan(y / x) - PI;
|
|
|
|
|
if (x == 0 && y > 0) return PI / 2;
|
|
|
|
|
if (x == 0 && y < 0) return -PI / 2;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2024-09-08 22:43:05 +08:00
|
|
|
|
|
|
|
|
|
double floor(double x) {
|
|
|
|
|
int flag = 1;
|
|
|
|
|
if (fabs(x) == x) {
|
|
|
|
|
flag = 0;
|
|
|
|
|
}
|
|
|
|
|
if (flag) {
|
|
|
|
|
double r = (x); // 如果小于,则返回x-1的整数部分
|
|
|
|
|
double s;
|
|
|
|
|
modf(r, &s);
|
|
|
|
|
return s - 1;
|
|
|
|
|
} else {
|
|
|
|
|
double r = (x); // 如果大于等于,则返回x的整数部分
|
|
|
|
|
double s;
|
|
|
|
|
modf(r, &s);
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double modf(double x, double *iptr) {
|
|
|
|
|
union {
|
|
|
|
|
double f;
|
|
|
|
|
uint64_t i;
|
|
|
|
|
} u = {x};
|
|
|
|
|
uint64_t mask;
|
|
|
|
|
int e = (int) (u.i >> 52 & 0x7ff) - 0x3ff;
|
|
|
|
|
|
|
|
|
|
/* no fractional part */
|
|
|
|
|
if (e >= 52) {
|
|
|
|
|
*iptr = x;
|
|
|
|
|
if (e == 0x400 && u.i << 12 != 0) /* nan */
|
|
|
|
|
return x;
|
|
|
|
|
u.i &= 1ULL << 63;
|
|
|
|
|
return u.f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* no integral part*/
|
|
|
|
|
if (e < 0) {
|
|
|
|
|
u.i &= 1ULL << 63;
|
|
|
|
|
*iptr = u.f;
|
|
|
|
|
return x;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mask = -1ULL >> 12 >> e;
|
|
|
|
|
if ((u.i & mask) == 0) {
|
|
|
|
|
*iptr = x;
|
|
|
|
|
u.i &= 1ULL << 63;
|
|
|
|
|
return u.f;
|
|
|
|
|
}
|
|
|
|
|
u.i &= ~mask;
|
|
|
|
|
*iptr = u.f;
|
|
|
|
|
return x - u.f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double fabs(double x) {
|
|
|
|
|
union {
|
|
|
|
|
double f;
|
|
|
|
|
uint64_t i;
|
|
|
|
|
} u = {x};
|
|
|
|
|
u.i &= -1ULL / 2;
|
|
|
|
|
return u.f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double ceil(double x) {
|
|
|
|
|
int flag = 0;
|
|
|
|
|
if (fabs(x) == x) {
|
|
|
|
|
flag = 1;
|
|
|
|
|
}
|
|
|
|
|
if (flag) {
|
|
|
|
|
double r = (x); // 如果小于,则返回x-1的整数部分
|
|
|
|
|
double s;
|
|
|
|
|
modf(r, &s);
|
|
|
|
|
return s + 1;
|
|
|
|
|
} else {
|
|
|
|
|
double r = (x); // 如果大于等于,则返回x的整数部分
|
|
|
|
|
double s;
|
|
|
|
|
modf(r, &s);
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define __negdi2(a) (-(a))
|
|
|
|
|
|
|
|
|
|
long long __divdi3(long long u, long long v) {
|
|
|
|
|
int c = 0;
|
|
|
|
|
DWunion uu, vv;
|
|
|
|
|
DWtype w;
|
|
|
|
|
|
|
|
|
|
uu.ll = u;
|
|
|
|
|
vv.ll = v;
|
|
|
|
|
|
|
|
|
|
if (uu.s.high < 0) {
|
|
|
|
|
c = ~c;
|
|
|
|
|
uu.ll = __negdi2 (uu.ll);
|
|
|
|
|
}
|
|
|
|
|
if (vv.s.high < 0) {
|
|
|
|
|
c = ~c;
|
|
|
|
|
vv.ll = __negdi2 (vv.ll);
|
|
|
|
|
}
|
|
|
|
|
w = __udivmoddi4(uu.ll, vv.ll, (UDWtype *) 0);
|
|
|
|
|
if (c)
|
|
|
|
|
w = __negdi2 (w);
|
|
|
|
|
return w;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double frexp(double x, int *e) {
|
|
|
|
|
union {
|
|
|
|
|
double d;
|
|
|
|
|
uint64_t i;
|
|
|
|
|
} y = {x};
|
|
|
|
|
int ee = y.i >> 52 & 0x7ff;
|
|
|
|
|
|
|
|
|
|
if (!ee) {
|
|
|
|
|
if (x) {
|
|
|
|
|
x = frexp(x * 0x1p64, e);
|
|
|
|
|
*e -= 64;
|
|
|
|
|
} else
|
|
|
|
|
*e = 0;
|
|
|
|
|
return x;
|
|
|
|
|
} else if (ee == 0x7ff) {
|
|
|
|
|
return x;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*e = ee - 0x3fe;
|
|
|
|
|
y.i &= 0x800fffffffffffffull;
|
|
|
|
|
y.i |= 0x3fe0000000000000ull;
|
|
|
|
|
return y.d;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double scalbn(double x, int n) {
|
|
|
|
|
union {
|
|
|
|
|
double f;
|
|
|
|
|
uint64_t i;
|
|
|
|
|
} u;
|
|
|
|
|
double y = x;
|
|
|
|
|
|
|
|
|
|
if (n > 1023) {
|
|
|
|
|
y *= 0x1p1023;
|
|
|
|
|
n -= 1023;
|
|
|
|
|
if (n > 1023) {
|
|
|
|
|
y *= 0x1p1023;
|
|
|
|
|
n -= 1023;
|
|
|
|
|
if (n > 1023)
|
|
|
|
|
n = 1023;
|
|
|
|
|
}
|
|
|
|
|
} else if (n < -1022) {
|
|
|
|
|
y *= 0x1p-1022;
|
|
|
|
|
n += 1022;
|
|
|
|
|
if (n < -1022) {
|
|
|
|
|
y *= 0x1p-1022;
|
|
|
|
|
n += 1022;
|
|
|
|
|
if (n < -1022)
|
|
|
|
|
n = -1022;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
u.i = (uint64_t)(0x3ff + n) << 52;
|
|
|
|
|
x = y * u.f;
|
|
|
|
|
return x;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double scalbln(double x, long n) {
|
|
|
|
|
if (n > INT_MAX)
|
|
|
|
|
n = INT_MAX;
|
|
|
|
|
else if (n < INT_MIN)
|
|
|
|
|
n = INT_MIN;
|
|
|
|
|
return scalbn(x, n);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double ldexp(double x, int n) { return scalbn(x, n); }
|
|
|
|
|
|
|
|
|
|
float scalbnf(float x, int n) {
|
|
|
|
|
union {
|
|
|
|
|
float f;
|
|
|
|
|
uint32_t i;
|
|
|
|
|
} u;
|
|
|
|
|
float y = x;
|
|
|
|
|
|
|
|
|
|
if (n > 127) {
|
|
|
|
|
y *= 0x1p127f;
|
|
|
|
|
n -= 127;
|
|
|
|
|
if (n > 127) {
|
|
|
|
|
y *= 0x1p127f;
|
|
|
|
|
n -= 127;
|
|
|
|
|
if (n > 127)
|
|
|
|
|
n = 127;
|
|
|
|
|
}
|
|
|
|
|
} else if (n < -126) {
|
|
|
|
|
y *= 0x1p-126f * 0x1p24f;
|
|
|
|
|
n += 126 - 24;
|
|
|
|
|
if (n < -126) {
|
|
|
|
|
y *= 0x1p-126f * 0x1p24f;
|
|
|
|
|
n += 126 - 24;
|
|
|
|
|
if (n < -126)
|
|
|
|
|
n = -126;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
u.i = (uint32_t)(0x7f + n) << 23;
|
|
|
|
|
x = y * u.f;
|
|
|
|
|
return x;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double fmod(double x, double y) {
|
|
|
|
|
return x - (x / y) * y;
|
|
|
|
|
/*
|
|
|
|
|
union {
|
|
|
|
|
double f;
|
|
|
|
|
uint64_t i;
|
|
|
|
|
} ux = {x}, uy = {y};
|
|
|
|
|
int ex = ux.i >> 52 & 0x7ff;
|
|
|
|
|
int ey = uy.i >> 52 & 0x7ff;
|
|
|
|
|
int sx = ux.i >> 63;
|
|
|
|
|
uint64_t i;
|
|
|
|
|
|
|
|
|
|
uint64_t uxi = ux.i;
|
|
|
|
|
|
|
|
|
|
if (uy.i << 1 == 0 || isnan(y) || ex == 0x7ff)
|
|
|
|
|
return (x * y) / (x * y);
|
|
|
|
|
if (uxi << 1 <= uy.i << 1) {
|
|
|
|
|
if (uxi << 1 == uy.i << 1)
|
|
|
|
|
return 0 * x;
|
|
|
|
|
return x;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ex) {
|
|
|
|
|
for (i = uxi << 12; i >> 63 == 0; ex--, i <<= 1);
|
|
|
|
|
uxi <<= -ex + 1;
|
|
|
|
|
} else {
|
|
|
|
|
uxi &= -1ULL >> 12;
|
|
|
|
|
uxi |= 1ULL << 52;
|
|
|
|
|
}
|
|
|
|
|
if (!ey) {
|
|
|
|
|
for (i = uy.i << 12; i >> 63 == 0; ey--, i <<= 1);
|
|
|
|
|
uy.i <<= -ey + 1;
|
|
|
|
|
} else {
|
|
|
|
|
uy.i &= -1ULL >> 12;
|
|
|
|
|
uy.i |= 1ULL << 52;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (; ex > ey; ex--) {
|
|
|
|
|
i = uxi - uy.i;
|
|
|
|
|
if (i >> 63 == 0) {
|
|
|
|
|
if (i == 0)
|
|
|
|
|
return 0 * x;
|
|
|
|
|
uxi = i;
|
|
|
|
|
}
|
|
|
|
|
uxi <<= 1;
|
|
|
|
|
}
|
|
|
|
|
i = uxi - uy.i;
|
|
|
|
|
if (i >> 63 == 0) {
|
|
|
|
|
if (i == 0)
|
|
|
|
|
return 0 * x;
|
|
|
|
|
uxi = i;
|
|
|
|
|
}
|
|
|
|
|
for (; uxi >> 52 == 0; uxi <<= 1, ex--);
|
|
|
|
|
|
|
|
|
|
if (ex > 0) {
|
|
|
|
|
uxi -= 1ULL << 52;
|
|
|
|
|
uxi |= (uint64_t) ex << 52;
|
|
|
|
|
} else {
|
|
|
|
|
uxi >>= -ex + 1;
|
|
|
|
|
}
|
|
|
|
|
uxi |= (uint64_t) sx << 63;
|
|
|
|
|
ux.i = uxi;
|
|
|
|
|
return ux.f;
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double exp(double x) {
|
|
|
|
|
|
|
|
|
|
x = 1.0 + x / 256;
|
|
|
|
|
|
|
|
|
|
x *= x;
|
|
|
|
|
x *= x;
|
|
|
|
|
x *= x;
|
|
|
|
|
x *= x;
|
|
|
|
|
|
|
|
|
|
x *= x;
|
|
|
|
|
x *= x;
|
|
|
|
|
x *= x;
|
|
|
|
|
x *= x;
|
|
|
|
|
|
|
|
|
|
return x;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double log10(double x) {
|
|
|
|
|
union {
|
|
|
|
|
double f;
|
|
|
|
|
uint64_t i;
|
|
|
|
|
} u = {x};
|
|
|
|
|
double hfsq, f, s, z, R, w, t1, t2, dk, y, hi, lo, val_hi, val_lo;
|
|
|
|
|
uint32_t hx;
|
|
|
|
|
int k;
|
|
|
|
|
|
|
|
|
|
hx = u.i >> 32;
|
|
|
|
|
k = 0;
|
|
|
|
|
if (hx < 0x00100000 || hx >> 31) {
|
|
|
|
|
if (u.i << 1 == 0)
|
|
|
|
|
return -1 / (x * x); /* log(+-0)=-inf */
|
|
|
|
|
if (hx >> 31)
|
|
|
|
|
return (x - x) / 0.0; /* log(-#) = NaN */
|
|
|
|
|
/* subnormal number, scale x up */
|
|
|
|
|
k -= 54;
|
|
|
|
|
x *= 0x1p54;
|
|
|
|
|
u.f = x;
|
|
|
|
|
hx = u.i >> 32;
|
|
|
|
|
} else if (hx >= 0x7ff00000) {
|
|
|
|
|
return x;
|
|
|
|
|
} else if (hx == 0x3ff00000 && u.i << 32 == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
/* reduce x into [sqrt(2)/2, sqrt(2)] */
|
|
|
|
|
hx += 0x3ff00000 - 0x3fe6a09e;
|
|
|
|
|
k += (int) (hx >> 20) - 0x3ff;
|
|
|
|
|
hx = (hx & 0x000fffff) + 0x3fe6a09e;
|
|
|
|
|
u.i = (uint64_t) hx << 32 | (u.i & 0xffffffff);
|
|
|
|
|
x = u.f;
|
|
|
|
|
|
|
|
|
|
f = x - 1.0;
|
|
|
|
|
hfsq = 0.5 * f * f;
|
|
|
|
|
s = f / (2.0 + f);
|
|
|
|
|
z = s * s;
|
|
|
|
|
w = z * z;
|
|
|
|
|
t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
|
|
|
|
|
t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
|
|
|
|
|
R = t2 + t1;
|
|
|
|
|
|
|
|
|
|
/* See log2.c for details. */
|
|
|
|
|
/* hi+lo = f - hfsq + s*(hfsq+R) ~ log(1+f) */
|
|
|
|
|
hi = f - hfsq;
|
|
|
|
|
u.f = hi;
|
|
|
|
|
u.i &= (uint64_t) - 1 << 32;
|
|
|
|
|
hi = u.f;
|
|
|
|
|
lo = f - hi - hfsq + s * (hfsq + R);
|
|
|
|
|
|
|
|
|
|
/* val_hi+val_lo ~ log10(1+f) + k*log10(2) */
|
|
|
|
|
val_hi = hi * ivln10hi;
|
|
|
|
|
dk = k;
|
|
|
|
|
y = dk * log10_2hi;
|
|
|
|
|
val_lo = dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Extra precision in for adding y is not strictly needed
|
|
|
|
|
* since there is no very large cancellation near x = sqrt(2) or
|
|
|
|
|
* x = 1/sqrt(2), but we do it anyway since it costs little on CPUs
|
|
|
|
|
* with some parallelism and it reduces the error for many args.
|
|
|
|
|
*/
|
|
|
|
|
w = y + val_hi;
|
|
|
|
|
val_lo += (y - w) + val_hi;
|
|
|
|
|
val_hi = w;
|
|
|
|
|
|
|
|
|
|
return val_lo + val_hi;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double log2(float x) {
|
|
|
|
|
long *a;
|
|
|
|
|
double o;
|
|
|
|
|
a = (long *) &x;
|
|
|
|
|
o = (double) *a;
|
|
|
|
|
o = o / POW223 - 126.928071372;
|
|
|
|
|
return o;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double log(double a) {
|
|
|
|
|
int N = 15;//我们取了前15+1项来估算
|
|
|
|
|
int k, nk;
|
|
|
|
|
double x, xx, y;
|
|
|
|
|
x = (a - 1) / (a + 1);
|
|
|
|
|
xx = x * x;
|
|
|
|
|
nk = 2 * N + 1;
|
|
|
|
|
y = 1.0 / nk;
|
|
|
|
|
for (k = N; k > 0; k--) {
|
|
|
|
|
nk = nk - 2;
|
|
|
|
|
y = 1.0 / nk + xx * y;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return 2.0 * x * y;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned long long __udivdi3(unsigned long long u, unsigned long long v) {
|
|
|
|
|
return __udivmoddi4(u, v, (UDWtype *) 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned long long __umoddi3(unsigned long long u, unsigned long long v) {
|
|
|
|
|
UDWtype w;
|
|
|
|
|
|
|
|
|
|
__udivmoddi4(u, v, &w);
|
|
|
|
|
return w;
|
|
|
|
|
}
|