diff --git a/libnum/include/num/num.h b/libnum/include/num/num.h index 94fe6fb..f1d37e2 100644 --- a/libnum/include/num/num.h +++ b/libnum/include/num/num.h @@ -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; diff --git a/libnum/test/isel_num16.cpp b/libnum/test/isel_num16.cpp index fb727ba..63c9d5a 100644 --- a/libnum/test/isel_num16.cpp +++ b/libnum/test/isel_num16.cpp @@ -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" */ diff --git a/libnum/test/isel_num32.cpp b/libnum/test/isel_num32.cpp index b406894..f2df4e7 100644 --- a/libnum/test/isel_num32.cpp +++ b/libnum/test/isel_num32.cpp @@ -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" */ diff --git a/libnum/test/isel_num8.cpp b/libnum/test/isel_num8.cpp index 61a74bf..6aec4e6 100644 --- a/libnum/test/isel_num8.cpp +++ b/libnum/test/isel_num8.cpp @@ -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" */ diff --git a/libnum/test/unit_scalar.cpp b/libnum/test/unit_scalar.cpp index 6a56f3d..34e7474 100644 --- a/libnum/test/unit_scalar.cpp +++ b/libnum/test/unit_scalar.cpp @@ -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);