diff options
Diffstat (limited to 'src/nanosecond.inl')
-rw-r--r-- | src/nanosecond.inl | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/src/nanosecond.inl b/src/nanosecond.inl new file mode 100644 index 00000000..6527dc02 --- /dev/null +++ b/src/nanosecond.inl @@ -0,0 +1,118 @@ +#pragma once +#include "compat/assert.hpp" +#include "nanosecond.hpp" + +namespace floormat { + +template<typename T> +requires (std::is_same_v<T, double>) +Ns operator*(const Ns& lhs, T b) +{ + constexpr double max{uint64_t{1} << 53}; + auto a = lhs.stamp; + fm_assert(b >= 0); + fm_assert(b <= max); + auto x = double(a) * b; + fm_assert(x >= 0); + fm_assert(x <= max); + return Ns{(uint64_t)x}; +} + +constexpr Ns operator+(const Ns& lhs, const Ns& rhs) +{ + constexpr auto max = (uint64_t)-1; + auto a = lhs.stamp, b = rhs.stamp; + fm_assert(max - a >= b); + return Ns{a + b}; +} + +constexpr Ns operator-(const Ns& lhs, const Ns& rhs) +{ + auto a = lhs.stamp, b = rhs.stamp; + fm_assert(a >= b); + return Ns{a - b}; +} + +template<typename T> +requires (std::is_integral_v<T> && std::is_unsigned_v<T>) +constexpr Ns operator*(const Ns& lhs, T rhs) +{ + auto a = lhs.stamp, b = uint64_t{rhs}; + auto x = a * b; + fm_assert(b == 0 || x / b == a); + return Ns{x}; +} + +template<typename T> +requires (std::is_integral_v<T> && std::is_signed_v<T> && sizeof(T) < sizeof(uint64_t)) +constexpr Ns operator*(const Ns& lhs, T rhs) +{ + fm_assert(rhs >= T{0}); + auto b = uint64_t(rhs); + auto x = lhs.stamp * b; + fm_assert(b == 0 || x / b == lhs.stamp); + return Ns{x}; +} + +template<typename T> +constexpr Ns operator*(T lhs, const Ns& rhs) +{ + return rhs * lhs; +} + +template<typename T> +requires std::is_same_v<float, T> +constexpr Ns operator*(const Ns& lhs, T rhs) +{ + constexpr float max{uint64_t{1} << 24}; + auto a = lhs.stamp; + auto x = float(a) * float{rhs}; + fm_assert(x >= 0); + fm_assert(x <= max); + return Ns{uint64_t(x)}; +} + +constexpr uint64_t operator/(const Ns& lhs, const Ns& rhs) +{ + auto a = lhs.stamp, b = rhs.stamp; + fm_assert(b != 0); + return a / b; +} + +constexpr Ns operator/(const Ns& lhs, uint64_t b) +{ + auto a = lhs.stamp; + fm_assert(b != 0); + return Ns{a / b}; +} + +constexpr uint64_t operator%(const Ns& lhs, const Ns& rhs) +{ + auto a = lhs.stamp, b = rhs.stamp; + fm_assert(b != 0); + return a % b; +} + +constexpr Ns operator%(const Ns& lhs, uint64_t b) +{ + auto a = lhs.stamp; + fm_assert(b != 0); + return Ns{a % b}; +} + +constexpr Ns& operator+=(Ns& lhs, const Ns& rhs) +{ + constexpr auto max = (uint64_t)-1; + auto b = rhs.stamp; + fm_assert(max - lhs.stamp >= b); + lhs.stamp += b; + return lhs; +} + +constexpr std::strong_ordering operator<=>(const Ns& lhs, const Ns& rhs) +{ + auto a = lhs.stamp, b = rhs.stamp; + return a <=> b; +} + +} // namespace floormat |