10void Irrational::add_term(Terms& terms,
const Basis&
basis,
const Rational& coefficient) {
11 if (coefficient.is_zero())
return;
12 auto inserted = terms.emplace(
basis, coefficient);
13 if (inserted.second)
return;
14 auto&
value = inserted.first->second;
16 if (
value.is_zero()) terms.erase(inserted.first);
19Irrational::Terms Irrational::multiply_terms(
const Terms& left,
const Terms&
right) {
21 for (
const auto&
a : left) {
22 for (
const auto&
b :
right) {
23 const BigInt common = BigInt::gcd(
a.first.radicand,
b.first.radicand);
25 basis.radicand = (
a.first.radicand / common) * (
b.first.radicand / common);
26 basis.pi_power =
a.first.pi_power +
b.first.pi_power;
27 basis.e_power =
a.first.e_power +
b.first.e_power;
34Irrational Irrational::operator+(
const Irrational& other)
const {
36 if (denominator_ == other.denominator_) {
37 result.numerator_ = numerator_;
38 result.denominator_ = denominator_;
39 for (
const auto& term : other.numerator_) {
40 add_term(result.numerator_, term.first, term.second);
43 result.numerator_ = multiply_terms(numerator_, other.denominator_);
44 const Terms
right = multiply_terms(other.numerator_, denominator_);
45 for (
const auto& term :
right) add_term(result.numerator_, term.first, term.second);
46 result.denominator_ = multiply_terms(denominator_, other.denominator_);
52Irrational Irrational::operator-(
const Irrational& other)
const {
53 return *
this + (-other);
56Irrational Irrational::operator*(
const Irrational& other)
const {
58 result.numerator_ = multiply_terms(numerator_, other.numerator_);
59 result.denominator_ = multiply_terms(denominator_, other.denominator_);
64Irrational Irrational::operator*(
const Rational& scalar)
const {
65 Irrational result = *
this;
66 if (scalar.is_zero()) {
67 result.numerator_.clear();
69 for (
auto& term : result.numerator_) term.second = term.second * scalar;
74Irrational Irrational::operator*(lmmc_real_t scalar)
const {
75 return *
this * Rational::from_double(scalar);
78Irrational Irrational::operator/(
const Irrational& other)
const {
79 if (other.is_zero())
throw std::domain_error(
"Irrational: division by zero");
81 result.numerator_ = multiply_terms(numerator_, other.denominator_);
82 result.denominator_ = multiply_terms(denominator_, other.numerator_);
87Irrational Irrational::operator-()
const {
91Irrational Irrational::pow(
const BigInt&
exponent)
const {
93 Irrational result = constant(
Rational(1));
94 Irrational base = *
this;
95 while (!remaining.is_zero()) {
96 if (remaining.is_odd()) result = result * base;
98 if (!remaining.is_zero()) base = base * base;
103bool Irrational::operator==(
const Irrational& other)
const {
104 if (denominator_ == other.denominator_)
return numerator_ == other.numerator_;
105 return multiply_terms(numerator_, other.denominator_) ==
106 multiply_terms(other.numerator_, denominator_);
109bool Irrational::operator<(
const Irrational& other)
const {
110 auto left = as_rational_checked();
111 auto right = other.as_rational_checked();
112 if (left &&
right)
return left.value() <
right.value();
113 if (*
this == other)
return false;
114 return to_double() < other.to_double();
117bool Irrational::operator<=(
const Irrational& other)
const {
118 return *
this < other || *
this == other;
121bool Irrational::operator>(
const Irrational& other)
const {
122 return other < *
this;
125bool Irrational::operator>=(
const Irrational& other)
const {
126 return other <= *
this;
129bool Irrational::is_positive()
const {
130 return constant(
Rational(0)) < *
this;
133bool Irrational::is_negative()
const {
134 return *
this < constant(
Rational(0));
143 std::optional<Bounds>
pi;
144 std::optional<Bounds>
e;
151 auto found =
radicals.find(radicand);
152 if (found !=
radicals.end())
return found->second;
154 if (radicand.is_negative() || radicand.is_zero())
156 "nonpositive normalized radicand",
"Irrational::sign_checked"};
157 if (radicand == BigInt(1))
158 return radicals.emplace(radicand,
Bounds{Rational(1), Rational(1)}).first->second;
162 if (shift > std::numeric_limits<mp_size_t>::max())
164 "radical shift size exceeded",
"Irrational::sign_checked"};
165 const BigInt scaled = radicand << static_cast<mp_size_t>(shift);
167 const BigInt
lower = scaled.sqrt();
173 Rational(
upper, scale)}).first->second;
177 auto& cached = use_pi ?
pi :
e;
181 if (!bounds)
throw bounds.error();
182 cached = std::move(bounds.value());
194 Bounds result{Rational(1), Rational(1)};
195 while (!remaining.is_zero()) {
210 for (
const auto& term : terms) {
217 if (term.second.is_zero()) {
continue; }
219 transcendental |= !term.first.pi_power.is_zero() ||
220 !term.first.e_power.is_zero();
226 const auto lower = bounds.first.get_numerator();
227 if (!
lower.is_zero() && !
lower.is_negative()) {
return 1; }
228 if (bounds.second.get_numerator().is_negative()) {
return -1; }
244 if (denominator_sign != 0) {
246 const auto numerator_bounds = terms_bounds(numerator,
round);
248 if (numerator_sign != 0) {
252 if (transcendental &&
precision == 4096) {
254 "pi/e enclosure did not separate zero at 4096 bits", operation);
256 if (
precision > std::numeric_limits<std::size_t>::max() / 2) {
258 "refinement size exceeded", operation);
265std::pair<Rational, Rational> Irrational::terms_bounds(
266 const Terms& terms, EnclosureRound&
round) {
267 auto& arithmetic =
round.arithmetic;
268 EnclosureRound::Bounds sum{Rational(0), Rational(0)};
269 for (
const auto& term : terms) {
271 if (term.second.is_zero())
continue;
272 auto basis =
round.radical(term.first.radicand);
273 if (!term.first.pi_power.is_zero())
276 if (!term.first.e_power.is_zero())
279 if (term.second.get_numerator().is_negative()) std::swap(
basis.first,
basis.second);
280 sum.first = arithmetic.add(sum.first, arithmetic.mul(term.second,
basis.first));
281 sum.second = arithmetic.add(sum.second, arithmetic.mul(term.second,
basis.second));
287 const char*
operation =
"Irrational::sign_checked";
291 arithmetic.require(
context.require_expansion_terms(numerator_.size(), operation));
292 arithmetic.require(
context.require_expansion_terms(denominator_.size(), operation));
293 bool transcendental =
false;
294 const bool numerator_zero = EnclosureRound::validate_terms(
295 numerator_, arithmetic, transcendental);
296 const bool denominator_zero = EnclosureRound::validate_terms(
297 denominator_, arithmetic, transcendental);
298 if (denominator_zero) {
301 return EnclosureRound::refine_sign(numerator_, denominator_, numerator_zero,
302 transcendental,
context, arithmetic, operation);
305 }
catch (
const std::bad_alloc&) {
307 }
catch (
const std::length_error&) {
322 Irrational result = *
this;
324 for (
auto& term : result.numerator_) {
325 auto step =
context.consume_steps(1,
"Irrational::abs_checked");
327 term.second = -term.second;
331 }
catch (
const std::bad_alloc&) {
333 "absolute value allocation failed",
"Irrational::abs_checked");
334 }
catch (
const std::length_error&) {
336 "absolute value size exceeded",
"Irrational::abs_checked");
345Irrational Irrational::abs()
const {
346 auto result = abs_checked();
347 if (result)
return std::move(result.value());
348 const auto& error = result.error();
349 const std::string message = error.operation +
": " + error.message;
350 switch (error.code) {
354 default:
throw std::runtime_error(message);
static Result failure(CasErrc code, std::string message, std::string operation={})
常数及根式包围区间共用的内部算术策略。 保守界覆盖未约分 Rational 的交叉乘积及结果;受检入口统一捕获 CasError,仅返回完整结果。
Rational mul(const Rational &a, const Rational &b) const
std::size_t growth(std::size_t a, std::size_t b) const
Rational div(const Rational &a, const Rational &b) const
BigInt dyadic_scale(std::size_t precision) const
void bits(std::size_t count) const
int sign(const Rational &value)
Result< ExactConstantInterval > exact_e_bounds(std::size_t precision_bits, ComputationContext &context)
std::pair< Rational, Rational > ExactConstantInterval
ComputationContext const std::string & operation
Result< ExactConstantInterval > exact_pi_bounds(std::size_t precision_bits, ComputationContext &context)
__attribute__((visibility("default"))) ExprResult function(const std __attribute__((visibility("default"))) ExprResult finite_set(std ExprPtr upper
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
@ Rational
Rational numbers
__attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::shared_ptr< SymbolicExpr > & a
const std::vector< FGLMPoly > & basis
const std::string const ExprPtr & value
const ExprPtr & denominator
ExprResult round(const ExprPtr &expression, ComputationContext &context)
Bounds multiply_positive(const Bounds &a, const Bounds &b)
static Result< Sign > refine_sign(const Terms &numerator, const Terms &denominator, bool numerator_zero, bool transcendental, ComputationContext &context, detail::ExactBoundArithmetic &arithmetic, const char *operation)
std::optional< Bounds > pi
static int separated_sign(const Bounds &bounds)
detail::ExactConstantInterval Bounds
const Bounds & constant(bool use_pi)
std::optional< Bounds > e
ComputationContext & context
detail::ExactBoundArithmetic arithmetic
const Bounds & radical(const BigInt &radicand)
std::map< BigInt, Bounds > radicals
static bool validate_terms(const Terms &terms, detail::ExactBoundArithmetic &arithmetic, bool &transcendental)
EnclosureRound(ComputationContext &context, std::size_t precision)
Bounds power(Bounds base, const BigInt &exponent)