Browse Source

core: implement floor() and ceil() for real numbers.

legacy
Sam Hocevar sam 13 years ago
parent
commit
064856b443
3 changed files with 90 additions and 2 deletions
  1. +46
    -0
      src/real.cpp
  2. +3
    -0
      src/real.h
  3. +41
    -2
      test/unit/real.cpp

+ 46
- 0
src/real.cpp View File

@@ -639,6 +639,52 @@ real exp(real const &x)
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 ret = 0.0, fact = 1.0, xn = x, x2 = x * x;


+ 3
- 0
src/real.h View File

@@ -69,6 +69,9 @@ public:
friend real log(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 cos(real const &x);
friend real asin(real const &x);


+ 41
- 2
test/unit/real.cpp View File

@@ -239,13 +239,13 @@ LOLUNIT_FIXTURE(RealTest)

LOLUNIT_TEST(AsinAcos)
{
double tests[14] =
double tests[] =
{
-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
};

for (int n = 0; n < 14; n++)
for (unsigned int n = 0; n < sizeof(tests) / sizeof(*tests); n++)
{
double a = tests[n] / 1024;
double b = sin(asin((real)a));
@@ -256,6 +256,45 @@ LOLUNIT_FIXTURE(RealTest)
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 */


Loading…
Cancel
Save