LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
exact_constant_bounds.cpp
浏览该文件的文档.
2#include <new>
3#include <stdexcept>
4
5namespace LMCAS::detail {
6namespace {
8
9/**
10 * @brief 用交错部分和夹逼 atan(x)。
11 *
12 * |x|≤1/2 时相邻项绝对值递减;相邻交错部分和夹住 atan(x),差值恰为首个省略项。
13 */
14Bounds small_atan(const Rational& x, std::size_t precision,
15 const ExactBoundArithmetic& arithmetic) {
16 const Rational target(BigInt(1), arithmetic.dyadic_scale(precision));
17 if (x.is_zero()) return {Rational(0), Rational(0)};
18 if (x.get_numerator().is_negative()) {
19 auto bounds = small_atan(-x, precision, arithmetic);
20 return {-bounds.second, -bounds.first};
21 }
22 const Rational square = arithmetic.mul(x, x);
23 Rational power = x;
24 Rational sum = x;
25 BigInt odd(1);
26 bool subtract = true;
27 for (;;) {
28 arithmetic.step();
29 arithmetic.growth(odd.bit_length(), 2);
30 odd += BigInt(2);
31 power = arithmetic.mul(power, square);
32 const Rational omitted = arithmetic.div(power, Rational(odd));
33 const Rational adjacent = subtract ? arithmetic.sub(sum, omitted)
34 : arithmetic.add(sum, omitted);
35 if (!arithmetic.less(target, omitted)) {
36 return subtract ? Bounds{adjacent, sum} : Bounds{sum, adjacent};
37 }
38 sum = adjacent;
39 subtract = !subtract;
40 }
41}
42
43Bounds pi_bounds(std::size_t precision, const ExactBoundArithmetic& arithmetic) {
44 /**
45 * @brief 以小参数 atan 区间构造 π 界。
46 *
47 * 每个 atan 区间宽度≤2^-(p+5),组合宽度≤(16+4)*2^-(p+5)<2^-p。
48 */
49 const auto internal = arithmetic.growth(precision, 5);
50 auto fifth = small_atan(Rational(1, 5), internal, arithmetic);
51 auto two_thirty_ninth = small_atan(Rational(1, 239), internal, arithmetic);
52 return {arithmetic.sub(arithmetic.mul(Rational(16), fifth.first),
53 arithmetic.mul(Rational(4), two_thirty_ninth.second)),
54 arithmetic.sub(arithmetic.mul(Rational(16), fifth.second),
55 arithmetic.mul(Rational(4), two_thirty_ninth.first))};
56}
57
58Bounds atan_bounds(const Rational& x, std::size_t precision,
59 const ExactBoundArithmetic& arithmetic) {
60 arithmetic.step();
61 if (x.get_numerator().is_negative()) {
62 auto bounds = atan_bounds(-x, precision, arithmetic);
63 return {-bounds.second, -bounds.first};
64 }
65 if (!arithmetic.less(Rational(1, 2), x))
66 return small_atan(x, precision, arithmetic);
67 const auto internal = arithmetic.growth(precision, 2);
68 auto pi = pi_bounds(internal, arithmetic);
69 if (arithmetic.less(Rational(1), x)) {
70 auto reciprocal = atan_bounds(arithmetic.div(Rational(1), x), internal, arithmetic);
71 return {arithmetic.sub(arithmetic.div(pi.first, Rational(2)), reciprocal.second),
72 arithmetic.sub(arithmetic.div(pi.second, Rational(2)), reciprocal.first)};
73 }
74 const Rational transformed = arithmetic.div(arithmetic.sub(x, Rational(1)),
75 arithmetic.add(x, Rational(1)));
76 auto correction = small_atan(transformed, internal, arithmetic);
77 return {arithmetic.add(arithmetic.div(pi.first, Rational(4)), correction.first),
78 arithmetic.add(arithmetic.div(pi.second, Rational(4)), correction.second)};
79}
80
81template<class Function>
83 Function&& function) {
84 try {
86 arithmetic.step();
87 return function(arithmetic);
88 } catch (const CasError& error) {
89 return Result<Bounds>::failure(error);
90 } catch (const std::bad_alloc&) {
92 "constant enclosure allocation failed", operation);
93 } catch (const std::length_error&) {
95 "constant enclosure size exceeded", operation);
96 }
97}
98}
99
101 const Rational& value, std::size_t precision_bits, ComputationContext& context) {
102 return checked_bounds(context, "exact.atan.bounds", [&](const ExactBoundArithmetic& arithmetic) {
103 return atan_bounds(value, precision_bits, arithmetic);
104 });
105}
106
108 std::size_t precision_bits, ComputationContext& context) {
109 return checked_bounds(context, "exact.pi.bounds", [&](const ExactBoundArithmetic& arithmetic) {
110 return pi_bounds(precision_bits, arithmetic);
111 });
112}
113
115 std::size_t precision_bits, ComputationContext& context) {
116 return checked_bounds(context, "exact.e.bounds", [&](const ExactBoundArithmetic& arithmetic) {
117 const Rational target(BigInt(1), arithmetic.dyadic_scale(precision_bits));
118 BigInt n(1);
119 Rational term(1); /**< 级数项 1/n!。 */
120 Rational sum(2); /**< 含 k=0 项的部分和 S_n。 */
121 for (;;) {
122 arithmetic.step();
123 const Rational tail = arithmetic.div(term, Rational(n));
124 if (!arithmetic.less(target, tail))
125 return Bounds{sum, arithmetic.add(sum, tail)};
126 arithmetic.growth(n.bit_length(), 1);
127 n += BigInt(1);
128 term = arithmetic.div(term, Rational(n));
129 sum = arithmetic.add(sum, term);
130 }
131 });
132}
133}
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 add(const Rational &a, const Rational &b) const
Rational div(const Rational &a, const Rational &b) const
bool less(const Rational &a, const Rational &b) const
BigInt dyadic_scale(std::size_t precision) const
Rational sub(const Rational &a, const Rational &b) const
Bounds pi_bounds(std::size_t precision, const ExactBoundArithmetic &arithmetic)
Bounds small_atan(const Rational &x, std::size_t precision, const ExactBoundArithmetic &arithmetic)
用交错部分和夹逼 atan(x)。
Bounds atan_bounds(const Rational &x, std::size_t precision, const ExactBoundArithmetic &arithmetic)
Result< Bounds > checked_bounds(ComputationContext &context, const char *operation, Function &&function)
多元 Hensel 提升(单变量步)
Result< ExactConstantInterval > exact_e_bounds(std::size_t precision_bits, ComputationContext &context)
std::pair< Rational, Rational > ExactConstantInterval
Result< ExactConstantInterval > exact_atan_bounds(const Rational &value, std::size_t precision_bits, ComputationContext &context)
ComputationContext const std::string & operation
Result< ExactConstantInterval > exact_pi_bounds(std::size_t precision_bits, ComputationContext &context)
std::size_t std::size_t ComputationContext & context
const ExprPtr & target
ExprResult pi()
const std::string const ExprPtr & value
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)