LMCAS
Lamina Computer Algebra System
Toggle main menu visibility
载入中...
搜索中...
未找到
numeric_evaluation_nodes.cpp
浏览该文件的文档.
1
#include "
internal/numeric_evaluation_support.hpp
"
2
#include "
root_of_identity.hpp
"
3
#include <algorithm>
4
#include <cmath>
5
6
namespace
LMCAS::detail
{
7
8
Result<ApproxReal>
NumericEvaluator::number
(
const
NumberNode
&
node
) {
9
double
value
= 0.0;
10
try
{
11
if
(std::holds_alternative<BigInt>(
node
.value())) {
12
value
= std::get<BigInt>(
node
.value()).to_double();
13
}
else
{
14
value
= std::get<Rational>(
node
.value()).to_double();
15
}
16
}
catch
(
const
std::exception& error) {
17
return
numeric_failure
(
CasErrc::NumericFailure
, error.what());
18
}
19
if
(!std::isfinite(
value
)) {
20
return
numeric_failure
(
CasErrc::NumericFailure
,
21
"exact number cannot be represented as a finite double"
);
22
}
23
return
numeric_approximation
(
value
);
24
}
25
26
Result<ApproxReal>
NumericEvaluator::variable
(
const
VariableNode
&
node
) {
27
if
(
node
.is_constant() && (
node
.name() ==
"pi"
||
node
.name() ==
"π"
)) {
28
return
numeric_approximation
(
static_cast<
double
>
(LMMC_CONST_PI));
29
}
30
if
(
node
.is_constant() &&
node
.name() ==
"e"
) {
31
return
numeric_approximation
(std::exp(1.0));
32
}
33
if
(
node
.is_constant() &&
node
.name() ==
"phi"
) {
34
return
numeric_approximation
((1.0 + std::sqrt(5.0)) / 2.0);
35
}
36
auto
it =
bindings_
.find(
node
.name());
37
if
(it ==
bindings_
.end()) {
38
return
numeric_failure
(
CasErrc::UnboundSymbol
,
39
"no numeric binding for symbol '"
+
node
.name() +
"'"
);
40
}
41
if
(!std::isfinite(it->second)) {
42
return
numeric_failure
(
CasErrc::NumericFailure
,
"numeric binding is not finite"
);
43
}
44
return
Result<ApproxReal>::success
(
45
ApproxReal
{it->second, 0.0,
NumericStatus::Finite
});
46
}
47
48
Result<ApproxReal>
NumericEvaluator::sum
(
const
AddNode
&
node
) {
49
double
value
= 0.0;
50
bool
infinite =
false
;
51
for
(
const
auto
& operand :
node
.operands()) {
52
auto
evaluated =
evaluate
(operand);
53
if
(!evaluated)
return
evaluated;
54
value
+= evaluated.value().value;
55
infinite = infinite || !evaluated.value().is_finite();
56
if
(std::isinf(
value
) && !infinite) {
57
return
numeric_failure
(
CasErrc::NumericFailure
,
"numeric evaluation produced a nonfinite result"
);
58
}
59
}
60
if
(std::isinf(
value
) && infinite) {
61
return
Result<ApproxReal>::success
(
ApproxReal
{
62
value
, 0.0,
value
> 0 ?
NumericStatus::PositiveInfinity
:
NumericStatus::NegativeInfinity
});
63
}
64
return
numeric_approximation
(
value
);
65
}
66
67
Result<ApproxReal>
NumericEvaluator::product
(
const
MultiplyNode
&
node
) {
68
const
bool
exact_constants = std::all_of(
node
.operands().begin(),
node
.operands().end(),
69
[](
const
auto
& operand) {
70
if (dynamic_cast<const NumberNode*>(operand.get())) return true;
71
const auto* power = dynamic_cast<const PowerNode*>(operand.get());
72
const auto* exponent = power
73
? dynamic_cast<const NumberNode*>(power->exponent().get()) : nullptr;
74
return exponent && exponent->is_negative_one() &&
75
dynamic_cast<const NumberNode*>(power->base().get());
76
});
77
if
(exact_constants) {
78
Rational
value
(1);
79
for
(
const
auto
& operand :
node
.operands()) {
80
const
auto
*
power
=
dynamic_cast<
const
PowerNode
*
>
(operand.get());
81
const
auto
*
number
=
dynamic_cast<
const
NumberNode
*
>
(
82
power
?
power
->base().get() : operand.get());
83
auto
step =
context_
.
consume_steps
(
power
? 3 : 1,
"evaluate_numeric"
);
84
if
(!step)
return
Result<ApproxReal>::failure
(step.error());
85
Rational factor = std::holds_alternative<BigInt>(
number
->value())
86
? Rational(std::get<BigInt>(
number
->value()))
87
: std::get<Rational>(
number
->value());
88
if
(
power
) {
89
if
(factor.is_zero()) {
90
return
numeric_failure
(
CasErrc::DomainError
,
"zero cannot be raised to a non-positive power"
);
91
}
92
factor = Rational(factor.get_denominator(), factor.get_numerator());
93
}
94
value
=
value
* factor;
95
auto
numerator_bits =
context_
.
require_integer_bits
(
96
value
.get_numerator().bit_length(),
"evaluate_numeric"
);
97
if
(!numerator_bits)
return
Result<ApproxReal>::failure
(numerator_bits.error());
98
auto
denominator_bits =
context_
.
require_integer_bits
(
99
value
.get_denominator().bit_length(),
"evaluate_numeric"
);
100
if
(!denominator_bits)
return
Result<ApproxReal>::failure
(denominator_bits.error());
101
}
102
try
{
103
return
numeric_approximation
(
value
.to_double());
104
}
catch
(
const
std::exception& error) {
105
return
numeric_failure
(
CasErrc::NumericFailure
, error.what());
106
}
107
}
108
double
value
= 1.0;
109
bool
infinite =
false
;
110
for
(
const
auto
& operand :
node
.operands()) {
111
auto
evaluated =
evaluate
(operand);
112
if
(!evaluated)
return
evaluated;
113
const
double
factor = evaluated.value().value;
114
const
double
multiplied =
value
* factor;
115
if
(multiplied == 0.0 &&
value
!= 0.0 && factor != 0.0) {
116
return
numeric_failure
(
CasErrc::NumericFailure
,
"numeric multiplication underflow"
);
117
}
118
value
= multiplied;
119
infinite = infinite || !evaluated.value().is_finite();
120
if
(std::isinf(
value
) && !infinite) {
121
return
numeric_failure
(
CasErrc::NumericFailure
,
"numeric evaluation produced a nonfinite result"
);
122
}
123
}
124
if
(std::isinf(
value
) && infinite) {
125
return
Result<ApproxReal>::success
(
ApproxReal
{
126
value
, 0.0,
value
> 0 ?
NumericStatus::PositiveInfinity
:
NumericStatus::NegativeInfinity
});
127
}
128
return
numeric_approximation
(
value
);
129
}
130
131
Result<ApproxReal>
NumericEvaluator::atan2
(
const
FunctionNode
&
node
) {
132
if
(
node
.arguments().size() != 2) {
133
return
numeric_failure
(
CasErrc::InvalidArgument
,
"atan2 requires two arguments"
);
134
}
135
auto
y =
evaluate
(
node
.arguments()[0]);
136
if
(!y)
return
y;
137
auto
x =
evaluate
(
node
.arguments()[1]);
138
if
(!x)
return
x;
139
return
numeric_approximation
(std::atan2(y.value().value, x.value().value));
140
}
141
142
Result<ApproxReal>
NumericEvaluator::extremum
(
const
FunctionNode
&
node
) {
143
if
(
node
.arguments().empty()) {
144
return
numeric_failure
(
CasErrc::InvalidArgument
,
"min/max requires an argument"
);
145
}
146
auto
first =
evaluate
(
node
.arguments().front());
147
if
(!first)
return
first;
148
double
value
= first.value().value;
149
for
(std::size_t i = 1; i <
node
.arguments().size(); ++i) {
150
auto
next =
evaluate
(
node
.arguments()[i]);
151
if
(!next)
return
next;
152
value
=
node
.type() ==
FunctionNode::FuncType::Max
153
? std::max(
value
, next.value().value)
154
: std::min(
value
, next.value().value);
155
}
156
return
numeric_approximation
(
value
);
157
}
158
159
Result<ApproxReal>
NumericEvaluator::norm
(
const
std::array<const PowerNode*, 2>& squares) {
160
auto
first =
evaluate
(squares[0]->base());
161
if
(!first)
return
first;
162
if
(!squares[1])
return
numeric_approximation
(std::abs(first.value().value));
163
auto
second =
evaluate
(squares[1]->base());
164
if
(!second)
return
second;
165
return
numeric_approximation
(std::hypot(first.value().value, second.value().value));
166
}
167
168
Result<ApproxReal>
NumericEvaluator::root
(
const
std::shared_ptr<const SymbolicNode>&
node
) {
169
auto
root_expression =
LMCAS::detail::make_expression_ptr
(
node
);
170
auto
root
=
rootof_evaluate_checked
(root_expression,
context_
);
171
if
(!
root
)
return
Result<ApproxReal>::failure
(
root
.error());
172
return
numeric_approximation
(
root
.value());
173
}
174
175
}
LMCAS::AddNode
加法节点,表示多个操作数的求和。
定义
arithmetic.hpp:55
LMCAS::ComputationContext::consume_steps
Result< void > consume_steps(std::size_t amount=1, const std::string &operation={})
定义
computation_context.hpp:112
LMCAS::ComputationContext::require_integer_bits
Result< void > require_integer_bits(std::size_t amount, const std::string &operation={}) const
定义
computation_context.hpp:151
LMCAS::FunctionNode
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
定义
functions.hpp:10
LMCAS::FunctionNode::FuncType::Max
@ Max
最大值 max(a, b)。
定义
functions.hpp:26
LMCAS::MultiplyNode
乘法节点,表示多个操作数的乘积。
定义
arithmetic.hpp:134
LMCAS::NumberNode
定义
numbers.hpp:8
LMCAS::PowerNode
幂运算节点,表示 base^exponent。
定义
arithmetic.hpp:218
LMCAS::Result
定义
result.hpp:39
LMCAS::Result::failure
static Result failure(CasErrc code, std::string message, std::string operation={})
定义
result.hpp:52
LMCAS::Result::success
static Result success(T value)
定义
result.hpp:48
LMCAS::VariableNode
变量节点,表示一个符号变量。
定义
arithmetic.hpp:10
LMCAS::detail::NumericEvaluator::variable
Result< ApproxReal > variable(const VariableNode &node)
定义
numeric_evaluation_nodes.cpp:26
LMCAS::detail::NumericEvaluator::sum
Result< ApproxReal > sum(const AddNode &node)
定义
numeric_evaluation_nodes.cpp:48
LMCAS::detail::NumericEvaluator::norm
Result< ApproxReal > norm(const std::array< const PowerNode *, 2 > &squares)
定义
numeric_evaluation_nodes.cpp:159
LMCAS::detail::NumericEvaluator::number
Result< ApproxReal > number(const NumberNode &node)
定义
numeric_evaluation_nodes.cpp:8
LMCAS::detail::NumericEvaluator::extremum
Result< ApproxReal > extremum(const FunctionNode &node)
定义
numeric_evaluation_nodes.cpp:142
LMCAS::detail::NumericEvaluator::root
Result< ApproxReal > root(const std::shared_ptr< const SymbolicNode > &node)
定义
numeric_evaluation_nodes.cpp:168
LMCAS::detail::NumericEvaluator::atan2
Result< ApproxReal > atan2(const FunctionNode &node)
定义
numeric_evaluation_nodes.cpp:131
LMCAS::detail::NumericEvaluator::bindings_
const NumericBindings & bindings_
定义
numeric_evaluation_support.hpp:21
LMCAS::detail::NumericEvaluator::evaluate
Result< ApproxReal > evaluate(const std::shared_ptr< const SymbolicNode > &node)
定义
numeric_evaluation.cpp:36
LMCAS::detail::NumericEvaluator::context_
ComputationContext & context_
定义
numeric_evaluation_support.hpp:22
LMCAS::detail::NumericEvaluator::power
Result< ApproxReal > power(const PowerNode &node)
定义
numeric_evaluation_power.cpp:71
LMCAS::detail::NumericEvaluator::product
Result< ApproxReal > product(const MultiplyNode &node)
定义
numeric_evaluation_nodes.cpp:67
LMCAS::detail
多元 Hensel 提升(单变量步)
定义
assumption_context.hpp:31
LMCAS::detail::make_expression_ptr
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
定义
base.hpp:111
LMCAS::detail::node
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
定义
base.hpp:91
LMCAS::detail::numeric_failure
Result< ApproxReal > numeric_failure(CasErrc code, std::string message)
定义
numeric_evaluation.cpp:24
LMCAS::detail::numeric_approximation
Result< ApproxReal > numeric_approximation(double value)
定义
numeric_evaluation.cpp:28
LMCAS::rootof_evaluate_checked
RootOfEvaluationResult rootof_evaluate_checked(const std::shared_ptr< SymbolicExpr > &rootof_expr, ComputationContext &context)
定义
root_of_identity.cpp:152
LMCAS::CasErrc::UnboundSymbol
@ UnboundSymbol
定义
result.hpp:15
LMCAS::CasErrc::InvalidArgument
@ InvalidArgument
定义
result.hpp:13
LMCAS::CasErrc::NumericFailure
@ NumericFailure
定义
result.hpp:27
LMCAS::CasErrc::DomainError
@ DomainError
定义
result.hpp:16
LMCAS::NumericStatus::Finite
@ Finite
定义
numeric_value.hpp:5
LMCAS::NumericStatus::NegativeInfinity
@ NegativeInfinity
定义
numeric_value.hpp:5
LMCAS::NumericStatus::PositiveInfinity
@ PositiveInfinity
定义
numeric_value.hpp:5
LMCAS::value
const std::string const ExprPtr & value
定义
expr.hpp:293
numeric_evaluation_support.hpp
root_of_identity.hpp
精确 RootOf 标识构造及受检数值求值。
LMCAS::ApproxReal
定义
numeric_value.hpp:7
src
numeric_evaluation_nodes.cpp
生成于
, 为 LMCAS使用
1.18.0