commit b0ed875484aa33cc54d614c2b6bba13a449fd64b
parent 4ad66c4a2aef4a47840477bb90de003b4127d608
Author: Henry Wilson <henry@henryandlizzy.uk>
Date: Fri, 8 Nov 2024 02:32:20 +0000
imprecise: Min-max based integer range type
Diffstat:
1 file changed, 58 insertions(+), 0 deletions(-)
diff --git a/src/imprecise.cpp b/src/imprecise.cpp
@@ -0,0 +1,58 @@
+#include <iostream>
+#include <stdexcept>
+
+int sign(int x) noexcept
+{
+ return x < 0 ? -1 : !!x;
+}
+
+struct imprecise
+{
+ imprecise(int l, int h)
+ : low{l}
+ , high{h}
+ {
+ if (l > h)
+ throw std::domain_error{"imprecise: low > high"};
+ }
+
+ imprecise operator +(imprecise rhs) const noexcept
+ {
+ return {low + rhs.low, high + rhs.high};
+ }
+
+ imprecise operator *(imprecise rhs) const noexcept
+ {
+ int h = high * rhs.high;
+ int l = low * rhs.low;
+ if (h > l)
+ return {l, h};
+ return {h, l};
+ }
+
+ imprecise square() const noexcept
+ {
+ if (sign(low) == sign(high))
+ return *this * *this;
+ return {0, std::max(low*low, high*high)};
+ }
+ bool operator ==(imprecise const& rhs) const = default;
+ bool operator !=(imprecise const& rhs) const = default;
+
+private:
+ int low, high;
+ friend std::ostream& operator <<(std::ostream& os, imprecise rhs);
+};
+
+std::ostream& operator <<(std::ostream& os, imprecise rhs)
+{
+ return os << rhs.low << ".." << rhs.high;
+}
+
+int main()
+{
+ std::cout << imprecise{-1,1} + imprecise{-1,1} << '\n';
+ std::cout << imprecise{1,2}.square() << '\n';
+ std::cout << imprecise{-2,-1}.square() << '\n';
+ std::cout << imprecise{-1,1}.square() << '\n';
+}