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';
+}