8bool Irrational::Basis::operator<(
const Basis& other)
const {
9 if (radicand != other.radicand)
return radicand < other.radicand;
10 if (pi_power != other.pi_power)
return pi_power < other.pi_power;
11 return e_power < other.e_power;
14bool Irrational::Basis::operator==(
const Basis& other)
const {
15 return radicand == other.radicand && pi_power == other.pi_power &&
16 e_power == other.e_power;
19bool Irrational::Basis::is_constant()
const {
20 return radicand == BigInt(1) && pi_power.is_zero() && e_power.is_zero();
25 using Factors = std::pair<BigInt, BigInt>;
26 if (n.is_zero())
return Factors{BigInt(0), BigInt(1)};
27 const BigInt root = n.sqrt();
28 if (root * root == n)
return Factors{root, BigInt(1)};
32 for (BigInt divisor(2); divisor <= remainder / divisor; divisor += one) {
33 auto step =
context.consume_steps(1,
"Irrational::sqrt_checked");
35 const BigInt square = divisor * divisor;
36 while ((remainder % square).
is_zero()) {
37 step =
context.consume_steps(1,
"Irrational::sqrt_checked");
43 return Factors{std::move(perfect), std::move(remainder)};
48 const std::string
operation =
"Irrational::sqrt_checked";
49 auto step =
context.consume_steps(1, operation);
53 if (n.is_negative()) {
55 "negative square root radicand", operation);
57 if (!std::isfinite(coefficient)) {
59 "square root coefficient must be finite", operation);
61 auto bits =
context.require_integer_bits(n.bit_length(), operation);
66 Rational exact = Rational::from_double(coefficient);
67 bits =
context.require_integer_bits(exact.get_numerator().bit_length(), operation);
71 bits =
context.require_integer_bits(exact.get_denominator().bit_length(), operation);
76 result.type_ = Type::SQRT;
77 if (exact.is_zero() || n.is_zero()) {
80 auto factors = extract_square_factors(n,
context);
84 exact = exact *
Rational(factors.value().first);
85 bits =
context.require_integer_bits(exact.get_numerator().bit_length(), operation);
90 basis.radicand = std::move(factors.value().second);
91 result.numerator_.emplace(std::move(
basis), std::move(exact));
93 }
catch (
const std::bad_alloc&) {
95 "square root allocation failed", operation);
101 return sqrt_checked(n, coefficient,
context);
104Irrational Irrational::pi(lmmc_real_t coefficient) {
106 result.type_ = Type::PI;
108 basis.pi_power = BigInt(1);
109 add_term(result.numerator_,
basis, Rational::from_double(coefficient));
113Irrational Irrational::e(lmmc_real_t coefficient) {
115 result.type_ = Type::E;
117 basis.e_power = BigInt(1);
118 add_term(result.numerator_,
basis, Rational::from_double(coefficient));
122Irrational Irrational::constant(lmmc_real_t
value) {
123 return constant(Rational::from_double(
value));
128 add_term(result.numerator_, Basis{},
value);
132bool Irrational::is_zero()
const {
133 return numerator_.empty();
138 if (numerator_.size() == denominator_.size()) {
139 const Rational ratio = numerator_.begin()->second / denominator_.begin()->second;
140 auto numerator = numerator_.begin();
142 for (; numerator != numerator_.end(); ++numerator, ++
denominator) {
144 numerator->second !=
denominator->second * ratio)
break;
146 if (numerator == numerator_.end())
return ratio;
149 "irrational value is not rational",
150 "Irrational::as_rational_checked");
153bool Irrational::is_rational()
const {
154 return as_rational_checked().has_value();
157void Irrational::simplify() {
163 if (denominator_.size() > 1) {
164 for (
const auto& term : denominator_) {
165 if (!term.first.pi_power.is_zero() || !term.first.e_power.is_zero())
169 auto rational = as_rational_checked();
172 denominator_.clear();
173 denominator_.emplace(Basis{},
Rational(1));
175 }
else if (denominator_.size() == 1 && denominator_.begin()->first.is_constant()) {
176 const Rational divisor = denominator_.begin()->second;
177 for (
auto& term : numerator_) term.second = term.second / divisor;
178 denominator_.begin()->second =
Rational(1);
static Result failure(CasErrc code, std::string message, std::string operation={})
bool is_zero(const SymbolicExpr &expression)
ComputationContext const std::string & operation
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
@ Rational
Rational numbers
const std::vector< FGLMPoly > & basis
const std::string const ExprPtr & value
const ExprPtr & denominator
ExprResult rational(const Rational &value)