@@ -639,6 +639,52 @@ real exp(real const &x) | |||||
return x1; | return x1; | ||||
} | } | ||||
real floor(real const &x) | |||||
{ | |||||
/* Strategy for floor(x): | |||||
* - if negative, return -ceil(-x) | |||||
* - if zero or negative zero, return x | |||||
* - if less than one, return zero | |||||
* - otherwise, if e is the exponent, clear all bits except the | |||||
* first e. */ | |||||
if (x < -real::R_0) | |||||
return -ceil(-x); | |||||
if (!x) | |||||
return x; | |||||
if (x < real::R_1) | |||||
return real::R_0; | |||||
real ret = x; | |||||
int exponent = x.m_signexp - (1 << 30) + 1; | |||||
for (int i = 0; i < real::BIGITS; i++) | |||||
{ | |||||
if (exponent <= 0) | |||||
ret.m_mantissa[i] = 0; | |||||
else if (exponent < 8 * (int)sizeof(uint16_t)) | |||||
ret.m_mantissa[i] &= ~((1 << (16 - exponent)) - 1); | |||||
exponent -= 8 * sizeof(uint16_t); | |||||
} | |||||
return ret; | |||||
} | |||||
real ceil(real const &x) | |||||
{ | |||||
/* Strategy for ceil(x): | |||||
* - if negative, return -floor(-x) | |||||
* - if x == floor(x), return x | |||||
* - otherwise, return floor(x) + 1 */ | |||||
if (x < -real::R_0) | |||||
return -floor(-x); | |||||
real ret = floor(x); | |||||
if (x == ret) | |||||
return ret; | |||||
else | |||||
return ret + real::R_1; | |||||
} | |||||
real sin(real const &x) | real sin(real const &x) | ||||
{ | { | ||||
real ret = 0.0, fact = 1.0, xn = x, x2 = x * x; | real ret = 0.0, fact = 1.0, xn = x, x2 = x * x; | ||||
@@ -69,6 +69,9 @@ public: | |||||
friend real log(real const &x); | friend real log(real const &x); | ||||
friend real exp(real const &x); | friend real exp(real const &x); | ||||
friend real floor(real const &x); | |||||
friend real ceil(real const &x); | |||||
friend real sin(real const &x); | friend real sin(real const &x); | ||||
friend real cos(real const &x); | friend real cos(real const &x); | ||||
friend real asin(real const &x); | friend real asin(real const &x); | ||||
@@ -239,13 +239,13 @@ LOLUNIT_FIXTURE(RealTest) | |||||
LOLUNIT_TEST(AsinAcos) | LOLUNIT_TEST(AsinAcos) | ||||
{ | { | ||||
double tests[14] = | |||||
double tests[] = | |||||
{ | { | ||||
-1024.0, -1023.0, -513.0, -512.0, -511.0, -1.0, -0.0, | -1024.0, -1023.0, -513.0, -512.0, -511.0, -1.0, -0.0, | ||||
0.0, 1.0, 511.0, 512.0, 513.0, 1023.0, 1024.0 | 0.0, 1.0, 511.0, 512.0, 513.0, 1023.0, 1024.0 | ||||
}; | }; | ||||
for (int n = 0; n < 14; n++) | |||||
for (unsigned int n = 0; n < sizeof(tests) / sizeof(*tests); n++) | |||||
{ | { | ||||
double a = tests[n] / 1024; | double a = tests[n] / 1024; | ||||
double b = sin(asin((real)a)); | double b = sin(asin((real)a)); | ||||
@@ -256,6 +256,45 @@ LOLUNIT_FIXTURE(RealTest) | |||||
LOLUNIT_ASSERT_DOUBLES_EQUAL(c, a, 1e-100); | LOLUNIT_ASSERT_DOUBLES_EQUAL(c, a, 1e-100); | ||||
} | } | ||||
} | } | ||||
LOLUNIT_TEST(FloorCeil) | |||||
{ | |||||
double tests[] = | |||||
{ | |||||
-2.0, -2.0, -2.0, | |||||
-1.5, -2.0, -1.0, | |||||
-1.0, -1.0, -1.0, | |||||
-0.0, -0.0, -0.0, | |||||
0.0, 0.0, 0.0, | |||||
0.25, 0.0, 1.0, | |||||
0.375, 0.0, 1.0, | |||||
0.5, 0.0, 1.0, | |||||
1.0, 1.0, 1.0, | |||||
1.5, 1.0, 2.0, | |||||
2.0, 2.0, 2.0, | |||||
2.5, 2.0, 3.0, | |||||
3.0, 3.0, 3.0, | |||||
8192.0, 8192.0, 8192.0, | |||||
8192.03125, 8192.0, 8193.0, | |||||
8192.5, 8192.0, 8193.0, | |||||
8193.0, 8193.0, 8193.0, | |||||
549755813888.0, 549755813888.0, 549755813888.0, | |||||
549755813888.03125, 549755813888.0, 549755813889.0, | |||||
549755813888.5, 549755813888.0, 549755813889.0, | |||||
549755813889.0, 549755813889.0, 549755813889.0, | |||||
}; | |||||
for (unsigned int n = 0; n < sizeof(tests) / sizeof(*tests); n += 3) | |||||
{ | |||||
double a0 = floor((real)tests[n]); | |||||
double b0 = tests[n + 1]; | |||||
double a1 = ceil((real)tests[n]); | |||||
double b1 = tests[n + 2]; | |||||
LOLUNIT_ASSERT_EQUAL(b0, a0); | |||||
LOLUNIT_ASSERT_EQUAL(b1, a1); | |||||
} | |||||
} | |||||
}; | }; | ||||
} /* namespace lol */ | } /* namespace lol */ | ||||