LMCAS
Lamina Computer Algebra System
Toggle main menu visibility
载入中...
搜索中...
未找到
normalization_numeric_powers.cpp
浏览该文件的文档.
1
#include "
internal/normalization_utils.hpp
"
2
#include <cstdint>
3
4
namespace
LMCAS
{
5
namespace
{
6
std::shared_ptr<const NumberNode>
reciprocal_exact_number
(
const
NumberNode
& number) {
7
if
(
const
auto
*
integer
= std::get_if<BigInt>(&number.
value
())) {
8
return
detail::make_node<NumberNode>
(Rational(BigInt(1), *
integer
));
9
}
10
if
(
const
auto
*
rational
= std::get_if<Rational>(&number.
value
())) {
11
if
(!
rational
->get_numerator().is_zero()) {
12
return
detail::make_node<NumberNode>
(
13
Rational(
rational
->get_denominator(),
rational
->get_numerator()));
14
}
15
}
16
return
nullptr
;
17
}
18
19
std::shared_ptr<const NumberNode>
small_exact_power
(
const
NumberNode
& base,
20
const
BigInt&
exponent
) {
21
const
auto
count =
exponent
.abs().try_to_uint64();
22
if
(
const
auto
*
integer
= std::get_if<BigInt>(&base.
value
())) {
23
BigInt
value
(1);
24
for
(std::uint64_t k = 0; k < *count; ++k)
value
=
value
* *
integer
;
25
return
detail::make_node<NumberNode>
(
value
);
26
}
27
if
(
const
auto
*
rational
= std::get_if<Rational>(&base.
value
())) {
28
Rational
value
(1);
29
for
(std::uint64_t k = 0; k < *count; ++k)
value
=
value
* *
rational
;
30
return
detail::make_node<NumberNode>
(
value
);
31
}
32
return
nullptr
;
33
}
34
35
std::shared_ptr<const SymbolicNode>
integer_numeric_power
(
36
const
std::shared_ptr<const NumberNode>& base,
const
BigInt&
exponent
) {
37
const
bool
small =
exponent
> BigInt(-64) &&
exponent
< BigInt(64);
38
if
(
exponent
== BigInt(-1)) {
39
return
reciprocal_exact_number
(*base);
40
}
41
if
(
exponent
.is_zero()) {
42
return
detail::make_node<NumberNode>
(BigInt(1));
43
}
44
if
(!small) {
45
return
nullptr
;
46
}
47
auto
powered =
small_exact_power
(*base,
exponent
);
48
if
(!powered) {
49
return
nullptr
;
50
}
51
if
(
exponent
> BigInt(0)) {
52
return
powered;
53
}
54
return
reciprocal_exact_number
(*powered);
55
}
56
57
bool
is_half_exponent
(
const
NumberNode
&
exponent
) {
58
if
(
const
auto
*
rational
= std::get_if<Rational>(&
exponent
.value())) {
59
return
*
rational
== Rational(1, 2);
60
}
61
return
false
;
62
}
63
64
std::shared_ptr<const SymbolicNode>
extract_small_square_factor
(
65
const
BigInt&
value
,
const
BigInt& root,
detail::RewriteBudget
* budget) {
66
if
(
value
<= BigInt(0) ||
value
>= BigInt(1000000)) {
67
return
nullptr
;
68
}
69
for
(BigInt factor = root; factor >= BigInt(2); factor -= BigInt(1)) {
70
const
BigInt square = factor * factor;
71
if
(!(
value
% square).is_zero()) {
72
continue
;
73
}
74
if
(budget) { budget->
require_nodes
(5); }
75
auto
coefficient =
detail::make_node<NumberNode>
(factor);
76
auto
radicand =
detail::make_node<NumberNode>
(
value
/ square);
77
auto
half =
detail::make_node<NumberNode>
(Rational(1, 2));
78
auto
radical =
detail::make_node<PowerNode>
(radicand, half);
79
return
SymbolicFactory::create_multiply
({coefficient, radical}, budget);
80
}
81
return
nullptr
;
82
}
83
84
std::shared_ptr<const SymbolicNode>
half_numeric_power
(
85
const
NumberNode
& base,
detail::RewriteBudget
* budget) {
86
if
(
const
auto
*
integer
= std::get_if<BigInt>(&base.
value
())) {
87
if
(*
integer
< BigInt(0)) {
88
return
nullptr
;
89
}
90
const
BigInt root =
integer
->sqrt();
91
if
(root * root == *
integer
) {
92
return
detail::make_node<NumberNode>
(root);
93
}
94
return
extract_small_square_factor
(*
integer
, root, budget);
95
}
96
if
(
auto
root =
normalization_exact_square_root
(base)) {
97
return
root;
98
}
99
return
nullptr
;
100
}
101
}
102
103
std::shared_ptr<const NumberNode>
normalization_exact_square_root
(
const
NumberNode
& number) {
104
if
(
const
auto
*
integer
= std::get_if<BigInt>(&number.
value
())) {
105
if
(*
integer
< BigInt(0)) {
106
return
nullptr
;
107
}
108
const
BigInt root =
integer
->sqrt();
109
if
(root * root == *
integer
) {
110
return
detail::make_node<NumberNode>
(root);
111
}
112
return
nullptr
;
113
}
114
const
auto
*
rational
= std::get_if<Rational>(&number.
value
());
115
if
(!
rational
|| *
rational
< Rational(0)) {
116
return
nullptr
;
117
}
118
const
BigInt numerator =
rational
->get_numerator().sqrt();
119
const
BigInt
denominator
=
rational
->get_denominator().sqrt();
120
if
(numerator * numerator !=
rational
->get_numerator()) {
121
return
nullptr
;
122
}
123
if
(
denominator
*
denominator
!=
rational
->get_denominator()) {
124
return
nullptr
;
125
}
126
return
detail::make_node<NumberNode>
(Rational(numerator,
denominator
));
127
}
128
129
std::shared_ptr<const SymbolicNode>
normalization_imaginary_power
(
130
const
BigInt&
exponent
,
detail::RewriteBudget
* budget) {
131
BigInt remainder =
exponent
% BigInt(4);
132
if
(remainder.is_negative()) remainder += BigInt(4);
133
if
(budget) { budget->
require_nodes
(3); }
134
if
(remainder.is_zero()) {
135
return
detail::make_node<NumberNode>
(BigInt(1));
136
}
137
if
(remainder == BigInt(2)) {
138
return
detail::make_node<NumberNode>
(BigInt(-1));
139
}
140
auto
imaginary =
detail::make_node<PowerNode>
(
141
detail::make_node<NumberNode>
(BigInt(-1)),
142
detail::make_node<NumberNode>
(Rational(1, 2)));
143
if
(remainder == BigInt(1)) {
144
return
imaginary;
145
}
146
return
make_normalized_multiply_node
(
147
{
detail::make_node<NumberNode>
(BigInt(-1)), imaginary}, budget);
148
}
149
150
std::shared_ptr<const SymbolicNode>
normalization_numeric_power
(
151
const
std::shared_ptr<const NumberNode>& base,
152
const
std::shared_ptr<const NumberNode>&
exponent
,
detail::RewriteBudget
* budget) {
153
if
(budget) { budget->
require_nodes
(1); }
154
BigInt
integer
;
155
if
(
try_get_integer_value
(
exponent
,
integer
)) {
156
if
(
auto
value
= integer_numeric_power(base,
integer
)) {
157
return
value
;
158
}
159
}
else
if
(is_half_exponent(*
exponent
)) {
160
if
(
auto
value
= half_numeric_power(*base, budget)) {
161
return
value
;
162
}
163
}
164
const
auto
*
rational
= std::get_if<Rational>(&
exponent
->value());
165
if
(!
rational
|| !base->is_negative_one()) {
166
return
nullptr
;
167
}
168
if
(
rational
->get_denominator() != BigInt(2)) {
169
return
nullptr
;
170
}
171
return
normalization_imaginary_power
(
rational
->get_numerator(), budget);
172
}
173
}
LMCAS::NumberNode
定义
numbers.hpp:8
LMCAS::NumberNode::value
const std::variant< BigInt, Rational > & value() const noexcept
定义
numbers.hpp:21
LMCAS::SymbolicFactory::create_multiply
static std::shared_ptr< const SymbolicNode > create_multiply(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建乘法节点,自动扁平化嵌套乘法并消除单位元.
定义
symbolic_factory.cpp:83
LMCAS::detail::RewriteBudget
定义
rewrite_budget.hpp:15
LMCAS::detail::RewriteBudget::require_nodes
void require_nodes(std::size_t nodes) const
定义
rewrite_budget.cpp:119
LMCAS::anonymous_namespace{normalization_numeric_powers.cpp}::small_exact_power
std::shared_ptr< const NumberNode > small_exact_power(const NumberNode &base, const BigInt &exponent)
定义
normalization_numeric_powers.cpp:19
LMCAS::anonymous_namespace{normalization_numeric_powers.cpp}::half_numeric_power
std::shared_ptr< const SymbolicNode > half_numeric_power(const NumberNode &base, detail::RewriteBudget *budget)
定义
normalization_numeric_powers.cpp:84
LMCAS::anonymous_namespace{normalization_numeric_powers.cpp}::integer_numeric_power
std::shared_ptr< const SymbolicNode > integer_numeric_power(const std::shared_ptr< const NumberNode > &base, const BigInt &exponent)
定义
normalization_numeric_powers.cpp:35
LMCAS::anonymous_namespace{normalization_numeric_powers.cpp}::is_half_exponent
bool is_half_exponent(const NumberNode &exponent)
定义
normalization_numeric_powers.cpp:57
LMCAS::anonymous_namespace{normalization_numeric_powers.cpp}::reciprocal_exact_number
std::shared_ptr< const NumberNode > reciprocal_exact_number(const NumberNode &number)
定义
normalization_numeric_powers.cpp:6
LMCAS::anonymous_namespace{normalization_numeric_powers.cpp}::extract_small_square_factor
std::shared_ptr< const SymbolicNode > extract_small_square_factor(const BigInt &value, const BigInt &root, detail::RewriteBudget *budget)
定义
normalization_numeric_powers.cpp:64
LMCAS::detail::make_node
std::shared_ptr< const Node > make_node(Args &&... args)
定义
base.hpp:123
LMCAS
定义
assumption.hpp:11
LMCAS::integer
ExprResult integer(Integer)=delete
LMCAS::try_get_integer_value
bool try_get_integer_value(const std::shared_ptr< const NumberNode > &node, BigInt &value)
定义
normalization_utils.cpp:39
LMCAS::normalization_imaginary_power
std::shared_ptr< const SymbolicNode > normalization_imaginary_power(const BigInt &exponent, detail::RewriteBudget *budget=nullptr)
定义
normalization_numeric_powers.cpp:129
LMCAS::normalization_exact_square_root
std::shared_ptr< const NumberNode > normalization_exact_square_root(const NumberNode &number)
定义
normalization_numeric_powers.cpp:103
LMCAS::exponent
const ExprPtr & exponent
定义
expr.hpp:215
LMCAS::normalization_numeric_power
std::shared_ptr< const SymbolicNode > normalization_numeric_power(const std::shared_ptr< const NumberNode > &base, const std::shared_ptr< const NumberNode > &exponent, detail::RewriteBudget *budget=nullptr)
定义
normalization_numeric_powers.cpp:150
LMCAS::value
const std::string const ExprPtr & value
定义
expr.hpp:293
LMCAS::make_normalized_multiply_node
std::shared_ptr< const SymbolicNode > make_normalized_multiply_node(const std::vector< std::shared_ptr< const SymbolicNode > > &operands, detail::RewriteBudget *budget=nullptr)
定义
normalization_utils.cpp:83
LMCAS::denominator
const ExprPtr & denominator
定义
expr.hpp:200
LMCAS::rational
ExprResult rational(const Rational &value)
定义
expr_values.cpp:82
normalization_utils.hpp
src
normalization_numeric_powers.cpp
生成于
, 为 LMCAS使用
1.18.0