*
* A multi-precision rational constant.
*/
+#include <cln/integer_io.h>
+
#include <sstream>
#include <string>
}
}
+Rational::Rational(const char* s, uint32_t base)
+{
+ try
+ {
+ cln::cl_read_flags flags;
+ flags.rational_base = base;
+ flags.lsyntax = cln::lsyntax_standard;
+
+ const char* p = strchr(s, '/');
+ /* read_rational() does not support the case where the denominator is
+ * negative. In this case we read the numerator and denominator via
+ * read_integer() and build a rational out of two integers. */
+ if (p)
+ {
+ flags.syntax = cln::syntax_integer;
+ auto num = cln::read_integer(flags, s, p, nullptr);
+ auto den = cln::read_integer(flags, p + 1, nullptr, nullptr);
+ d_value = num / den;
+ }
+ else
+ {
+ flags.syntax = cln::syntax_rational;
+ d_value = read_rational(flags, s, NULL, NULL);
+ }
+ }
+ catch (...)
+ {
+ std::stringstream ss;
+ ss << "Rational() failed to parse value \"" << s << "\" in base=" << base;
+ throw std::invalid_argument(ss.str());
+ }
+}
+
+Rational::Rational(const std::string& s, uint32_t base)
+ : Rational(s.c_str(), base)
+{
+}
+
int Rational::sgn() const
{
if (cln::zerop(d_value))
/**
* Constructs a Rational from a C string in a given base (defaults to 10).
*
- * Throws std::invalid_argument if the string is not a valid rational.
- * For more information about what is a valid rational string,
- * see CLN's documentation for read_rational.
+ * Throws std::invalid_argument if the string is not a valid rational, i.e.,
+ * if it does not match sign{digit}+/sign{digit}+.
*/
- explicit Rational(const char* s, unsigned base = 10)
- {
- cln::cl_read_flags flags;
-
- flags.syntax = cln::syntax_rational;
- flags.lsyntax = cln::lsyntax_standard;
- flags.rational_base = base;
- try
- {
- d_value = read_rational(flags, s, NULL, NULL);
- }
- catch (...)
- {
- std::stringstream ss;
- ss << "Rational() failed to parse value \"" << s << "\" in base=" << base;
- throw std::invalid_argument(ss.str());
- }
- }
- Rational(const std::string& s, unsigned base = 10)
- {
- cln::cl_read_flags flags;
-
- flags.syntax = cln::syntax_rational;
- flags.lsyntax = cln::lsyntax_standard;
- flags.rational_base = base;
- try
- {
- d_value = read_rational(flags, s.c_str(), NULL, NULL);
- }
- catch (...)
- {
- std::stringstream ss;
- ss << "Rational() failed to parse value \"" << s << "\" in base=" << base;
- throw std::invalid_argument(ss.str());
- }
- }
+ explicit Rational(const char* s, uint32_t base = 10);
+ Rational(const std::string& s, uint32_t base = 10);
/**
* Creates a Rational from another Rational, q, by performing a deep copy.
ASSERT_NO_THROW(d_solver.mkReal(val2, val2));
ASSERT_NO_THROW(d_solver.mkReal(val3, val3));
ASSERT_NO_THROW(d_solver.mkReal(val4, val4));
+ ASSERT_NO_THROW(d_solver.mkReal("-1/-1"));
+ ASSERT_NO_THROW(d_solver.mkReal("1/-1"));
+ ASSERT_NO_THROW(d_solver.mkReal("-1/1"));
+ ASSERT_NO_THROW(d_solver.mkReal("1/1"));
+ ASSERT_THROW(d_solver.mkReal("/-5"), CVC5ApiException);
}
TEST_F(TestApiBlackSolver, mkRegexpAll)