libnum: add floor/ceil/frac functions, and int limits

This commit is contained in:
Lephenixnoir 2022-08-04 10:18:28 +01:00
parent 10cf9951a0
commit ec1593d4f8
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
5 changed files with 122 additions and 0 deletions

View File

@ -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;

View File

@ -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" */

View File

@ -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" */

View File

@ -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" */

View File

@ -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);