Add new methods for RealAlgebraicNumber (#7907)
authorGereon Kremer <gkremer@stanford.edu>
Mon, 10 Jan 2022 21:29:45 +0000 (13:29 -0800)
committerGitHub <noreply@github.com>
Mon, 10 Jan 2022 21:29:45 +0000 (15:29 -0600)
This PR adds some new methods for the RealAlgebraicNumber class: division, computing the (multiplicative) inverse and a specialization of std::hash.

src/util/real_algebraic_number_poly_imp.cpp
src/util/real_algebraic_number_poly_imp.h
test/unit/util/real_algebraic_number_black.cpp

index 58af261934ad5c4e64cbd2e9390652b45f0c0360..d92d917dc192fed804b668f27ade56be144e8a5d 100644 (file)
@@ -149,6 +149,16 @@ RealAlgebraicNumber operator*(const RealAlgebraicNumber& lhs,
 {
   return lhs.getValue() * rhs.getValue();
 }
+RealAlgebraicNumber operator/(const RealAlgebraicNumber& lhs,
+                              const RealAlgebraicNumber& rhs)
+{
+#ifdef CVC5_POLY_IMP
+  Assert(!isZero(rhs)) << "Can not divide by zero";
+  return lhs.getValue() / rhs.getValue();
+#else
+  return lhs;
+#endif
+}
 
 RealAlgebraicNumber& operator+=(RealAlgebraicNumber& lhs,
                                 const RealAlgebraicNumber& rhs)
@@ -172,5 +182,26 @@ RealAlgebraicNumber& operator*=(RealAlgebraicNumber& lhs,
 int sgn(const RealAlgebraicNumber& ran) { return sgn(ran.getValue()); }
 bool isZero(const RealAlgebraicNumber& ran) { return is_zero(ran.getValue()); }
 bool isOne(const RealAlgebraicNumber& ran) { return is_one(ran.getValue()); }
+RealAlgebraicNumber inverse(const RealAlgebraicNumber& ran)
+{
+#ifdef CVC5_POLY_IMP
+  Assert(!isZero(ran)) << "Can not invert zero";
+  return inverse(ran.getValue());
+#else
+  return ran;
+#endif
+}
 
 }  // namespace cvc5
+
+namespace std {
+size_t hash<cvc5::RealAlgebraicNumber>::operator()(
+    const cvc5::RealAlgebraicNumber& ran) const
+{
+#ifdef CVC5_POLY_IMP
+  return lp_algebraic_number_hash_approx(ran.getValue().get_internal(), 2);
+#else
+  return 0;
+#endif
+}
+}  // namespace std
index d71d0eae7eb1baffa45955b47e6a1880b2349b55..dcb45c036dcd3a3d5f461f8fb02162d9f1eae5df 100644 (file)
@@ -128,6 +128,9 @@ RealAlgebraicNumber operator-(const RealAlgebraicNumber& ran);
 /** Multiply two real algebraic numbers. */
 RealAlgebraicNumber operator*(const RealAlgebraicNumber& lhs,
                               const RealAlgebraicNumber& rhs);
+/** Divide two real algebraic numbers. */
+RealAlgebraicNumber operator/(const RealAlgebraicNumber& lhs,
+                              const RealAlgebraicNumber& rhs);
 
 /** Add and assign two real algebraic numbers. */
 RealAlgebraicNumber& operator+=(RealAlgebraicNumber& lhs,
@@ -146,7 +149,25 @@ int sgn(const RealAlgebraicNumber& ran);
 bool isZero(const RealAlgebraicNumber& ran);
 /** Check whether a real algebraic number is one. */
 bool isOne(const RealAlgebraicNumber& ran);
+/** Compute the inverse of a real algebraic number. */
+RealAlgebraicNumber inverse(const RealAlgebraicNumber& ran);
+
+using RealAlgebraicNumberHashFunction = std::hash<RealAlgebraicNumber>;
 
 }  // namespace cvc5
 
+namespace std {
+template <>
+struct hash<cvc5::RealAlgebraicNumber>
+{
+  /**
+   * Computes a hash of the given real algebraic number. Given that the internal
+   * representation of real algebraic numbers are inherently mutable (th
+   * interval may be refined for comparisons) we hash a well-defined rational
+   * approximation.
+   */
+  size_t operator()(const cvc5::RealAlgebraicNumber& ran) const;
+};
+}  // namespace std
+
 #endif /* CVC5__REAL_ALGEBRAIC_NUMBER_H */
index 8969091bdb9ebe7f70a839fd1e3bbe53a760ad22..3744f834625d7d394f47ab56c9ae12369a4f02a8 100644 (file)
@@ -37,7 +37,7 @@ TEST_F(TestUtilBlackRealAlgebraicNumber, creation)
   ASSERT_TRUE(sqrt2 < RealAlgebraicNumber(Integer(2)));
 }
 
-TEST_F(TestUtilBlackRealAlgebraicNumber, comprison)
+TEST_F(TestUtilBlackRealAlgebraicNumber, comparison)
 {
   RealAlgebraicNumber msqrt3({-3, 0, 1}, -2, -1);
   RealAlgebraicNumber msqrt2({-2, 0, 1}, -2, -1);
@@ -79,5 +79,16 @@ TEST_F(TestUtilBlackRealAlgebraicNumber, arithmetic)
   ASSERT_EQ(-msqrt2 + sqrt2, sqrt2 + sqrt2);
   ASSERT_EQ(msqrt2 * sqrt2, RealAlgebraicNumber(Integer(-2)));
 }
+
+TEST_F(TestUtilBlackRealAlgebraicNumber, division)
+{
+  RealAlgebraicNumber msqrt2({-2, 0, 1}, -2, -1);
+  RealAlgebraicNumber sqrt2({-2, 0, 1}, 1, 2);
+  RealAlgebraicNumber mone({1, 1}, -2, 0);
+
+  ASSERT_EQ(msqrt2 / sqrt2, mone);
+  ASSERT_TRUE(isOne(sqrt2 / sqrt2));
+}
+
 }  // namespace test
 }  // namespace cvc5