libnum: add floor/ceil/frac functions, and int limits
This commit is contained in:
parent
10cf9951a0
commit
ec1593d4f8
|
@ -90,6 +90,18 @@ struct num8
|
|||
v %= other.v;
|
||||
return *this;
|
||||
}
|
||||
inline constexpr num8 floor() {
|
||||
return num8(0);
|
||||
}
|
||||
/* Warning: num8::ceil() always overflows! */
|
||||
inline constexpr num8 ceil() {
|
||||
return num8(0);
|
||||
}
|
||||
inline constexpr num8 frac() {
|
||||
num8 x;
|
||||
x.v = v;
|
||||
return x;
|
||||
}
|
||||
|
||||
/* Comparisons with int */
|
||||
|
||||
|
@ -109,6 +121,9 @@ struct num8
|
|||
return i + !v <= 0;
|
||||
}
|
||||
|
||||
/* Limits as int */
|
||||
static constexpr int minInt = 0;
|
||||
static constexpr int maxInt = 0;
|
||||
/* Limits as double */
|
||||
static constexpr double minDouble = 0.0;
|
||||
static constexpr double maxDouble = double(0xff) / 256;
|
||||
|
@ -173,6 +188,21 @@ struct num16
|
|||
v %= other.v;
|
||||
return *this;
|
||||
}
|
||||
inline constexpr num16 floor() {
|
||||
num16 x;
|
||||
x.v = v & 0xff00;
|
||||
return x;
|
||||
}
|
||||
inline constexpr num16 ceil() {
|
||||
num16 x;
|
||||
x.v = ((v - 1) | 0xff) + 1;
|
||||
return x;
|
||||
}
|
||||
inline constexpr num16 frac() {
|
||||
num16 x;
|
||||
x.v = v & 0xff;
|
||||
return x;
|
||||
}
|
||||
|
||||
/* Comparisons with int */
|
||||
|
||||
|
@ -195,6 +225,9 @@ struct num16
|
|||
return (v >> 8) + ((v & 0xff) != 0) > i;
|
||||
}
|
||||
|
||||
/* Limits as int */
|
||||
static constexpr int minInt = 0;
|
||||
static constexpr int maxInt = 0x7f;
|
||||
/* Limits as double */
|
||||
static constexpr double minDouble = -128.0;
|
||||
static constexpr double maxDouble = double(0x7fff) / 256;
|
||||
|
@ -264,6 +297,21 @@ struct num32
|
|||
v %= other.v;
|
||||
return *this;
|
||||
}
|
||||
inline constexpr num32 floor() {
|
||||
num32 x;
|
||||
x.v = v & 0xffff0000;
|
||||
return x;
|
||||
}
|
||||
inline constexpr num32 ceil() {
|
||||
num32 x;
|
||||
x.v = ((v - 1) | 0xffff) + 1;
|
||||
return x;
|
||||
}
|
||||
inline constexpr num32 frac() {
|
||||
num32 x;
|
||||
x.v = v & 0xffff;
|
||||
return x;
|
||||
}
|
||||
|
||||
/* Comparisons with int */
|
||||
|
||||
|
@ -283,6 +331,9 @@ struct num32
|
|||
return (v >> 16) + ((v & 0xffff) != 0) > i;
|
||||
}
|
||||
|
||||
/* Limits as int */
|
||||
static constexpr int minInt = 0;
|
||||
static constexpr int maxInt = 0x7fff;
|
||||
/* Limits as double */
|
||||
static constexpr double minDouble = -32768.0;
|
||||
static constexpr double maxDouble = double(0x7fffffff) / 65536;
|
||||
|
@ -360,7 +411,25 @@ struct num64
|
|||
v %= other.v;
|
||||
return *this;
|
||||
}
|
||||
inline constexpr num64 floor() {
|
||||
num64 x;
|
||||
x.v = v & 0xffffffff00000000ull;
|
||||
return x;
|
||||
}
|
||||
inline constexpr num64 ceil() {
|
||||
num64 x;
|
||||
x.v = ((v - 1) | 0xffffffffull) + 1;
|
||||
return x;
|
||||
}
|
||||
inline constexpr num64 frac() {
|
||||
num64 x;
|
||||
x.v = v & 0xffffffffull;
|
||||
return x;
|
||||
}
|
||||
|
||||
/* Limits as int */
|
||||
static constexpr int minInt = 0;
|
||||
static constexpr int maxInt = 0x7fffffff;
|
||||
/* Limits as double; note that the double doesn't have enough precision to
|
||||
represent the entirety of the maximum value. */
|
||||
static constexpr double minDouble = -2147483648.0;
|
||||
|
|
|
@ -75,4 +75,22 @@ bool num16_lt_0(num16 x)
|
|||
return x < num16(0);
|
||||
}
|
||||
|
||||
// num16_floor: [and] && %<=3
|
||||
num16 num16_floor(num16 x)
|
||||
{
|
||||
return x.floor();
|
||||
}
|
||||
|
||||
// num16_ceil: %<=4
|
||||
num16 num16_ceil(num16 x)
|
||||
{
|
||||
return x.ceil();
|
||||
}
|
||||
|
||||
// num16_frac: [extu.b] && %=1
|
||||
num16 num16_frac(num16 x)
|
||||
{
|
||||
return x.frac();
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
|
|
@ -75,4 +75,22 @@ bool num32_lt_0(num32 x)
|
|||
return x < num32(0);
|
||||
}
|
||||
|
||||
// num32_floor: %<=2+[mov.l]
|
||||
num32 num32_floor(num32 x)
|
||||
{
|
||||
return x.floor();
|
||||
}
|
||||
|
||||
// num32_ceil: %<=4
|
||||
num32 num32_ceil(num32 x)
|
||||
{
|
||||
return x.ceil();
|
||||
}
|
||||
|
||||
// num32_frac: [extu.w] && %=1
|
||||
num32 num32_frac(num32 x)
|
||||
{
|
||||
return x.frac();
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
|
|
@ -47,4 +47,10 @@ bool num8_gt(num8 x, int i)
|
|||
return x > i;
|
||||
}
|
||||
|
||||
// num8_floor: %=0
|
||||
num8 num8_floor(num8 x)
|
||||
{
|
||||
return x.floor();
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
|
|
@ -76,6 +76,8 @@ int main(void)
|
|||
c.CHECK(num8(num32(x)) == x);
|
||||
c.CHECK(num8(num64(x)) == x);
|
||||
c.CHECK(-x + x == 0);
|
||||
c.CHECK(x.floor() == 0 && x.ceil() == 0 /* overflow */);
|
||||
c.CHECK(x.frac() == x);
|
||||
});
|
||||
|
||||
printf("Testing binary laws on num8...\n");
|
||||
|
@ -93,6 +95,9 @@ int main(void)
|
|||
c.CHECK(num16(num32(x)) == x);
|
||||
c.CHECK(num16(num64(x)) == x);
|
||||
c.CHECK(-x + x == 0);
|
||||
c.CHECK(x.floor() <= x && ((int)x == num16::maxInt || x <= x.ceil()));
|
||||
c.CHECK((x.ceil() - x.floor()) == num16(x != num16((int)x)));
|
||||
c.CHECK(x.floor() + x.frac() == x);
|
||||
});
|
||||
|
||||
printf("Testing binary laws on num16...\n");
|
||||
|
@ -109,6 +114,9 @@ int main(void)
|
|||
c.CHECK(num32(num16(x)).v >> 8 == (int16_t)(x.v >> 8));
|
||||
c.CHECK(num32(num64(x)) == x);
|
||||
c.CHECK(-x + x == 0);
|
||||
c.CHECK(x.floor() <= x && ((int)x == num32::maxInt || x <= x.ceil()));
|
||||
c.CHECK((x.ceil() - x.floor()) == num32(x != num32((int)x)));
|
||||
c.CHECK(x.floor() + x.frac() == x);
|
||||
});
|
||||
|
||||
printf("Testing binary laws on num32...\n");
|
||||
|
@ -125,6 +133,9 @@ int main(void)
|
|||
c.CHECK(num64(num16(x)).v >> 24 == (int16_t)(x.v >> 24));
|
||||
c.CHECK(num64(num32(x)).v >> 16 == (int32_t)(x.v >> 16));
|
||||
c.CHECK(-x + x == num64(0));
|
||||
c.CHECK(x.floor() <= x && ((int)x == num64::maxInt || x <= x.ceil()));
|
||||
c.CHECK((x.ceil() - x.floor()) == num64(x != num64((int)x)));
|
||||
c.CHECK(x.floor() + x.frac() == x);
|
||||
});
|
||||
|
||||
return (success ? 0 : 1);
|
||||
|
|
Loading…
Reference in New Issue