15 if (!std::isfinite(
value)) {
16 throw std::invalid_argument(
"approximate number must be finite");
19 const auto formatted = std::to_chars(
20 token, token +
sizeof(token),
value, std::chars_format::general);
21 if (formatted.ec != std::errc{}) {
22 throw std::logic_error(
"finite double formatting failed");
24 return Rational(std::string(token, formatted.ptr));
31 constexpr const char*
operation =
"LMCAS.constant";
37 "constant factory returned null",
41 }
catch (
const std::bad_alloc&) {
43 "constant allocation failed",
45 }
catch (
const std::exception& error) {
51std::shared_ptr<SymbolicExpr> SymbolicExpr::number(
int n) {
57std::shared_ptr<SymbolicExpr> SymbolicExpr::number(
double n) {
62std::shared_ptr<SymbolicExpr> SymbolicExpr::number(
const BigInt&
value) {
67std::shared_ptr<SymbolicExpr> SymbolicExpr::number(
const Rational&
value) {
72std::shared_ptr<SymbolicExpr> SymbolicExpr::infinity(
int sign) {
75 std::vector<std::shared_ptr<const SymbolicNode>>{});
77 return sign < 0 ?
multiply(number(-1), expression) : expression;
80std::shared_ptr<SymbolicExpr> SymbolicExpr::sqrt(
81 std::shared_ptr<SymbolicExpr> operand) {
82 if (!operand || !operand->impl_->root) {
83 throw std::invalid_argument(
"sqrt operand cannot be null");
90std::shared_ptr<SymbolicExpr> SymbolicExpr::multiply(
91 std::shared_ptr<SymbolicExpr> left,
92 std::shared_ptr<SymbolicExpr>
right) {
93 if (!left || !left->impl_->root || !
right || !
right->impl_->root) {
94 throw std::invalid_argument(
"multiply operands cannot be null");
96 std::vector<std::shared_ptr<const SymbolicNode>> operands{
97 left->impl_->root,
right->impl_->root};
102std::shared_ptr<SymbolicExpr> SymbolicExpr::add(
103 std::shared_ptr<SymbolicExpr> left,
104 std::shared_ptr<SymbolicExpr>
right) {
105 if (!left || !left->impl_->root || !
right || !
right->impl_->root) {
106 throw std::invalid_argument(
"add operands cannot be null");
108 std::vector<std::shared_ptr<const SymbolicNode>> operands{
109 left->impl_->root,
right->impl_->root};
114std::shared_ptr<SymbolicExpr> SymbolicExpr::power(
115 std::shared_ptr<SymbolicExpr> base,
116 std::shared_ptr<SymbolicExpr>
exponent) {
118 throw std::invalid_argument(
"power operands cannot be null");
124std::shared_ptr<SymbolicExpr> SymbolicExpr::sin(
125 std::shared_ptr<SymbolicExpr> operand) {
126 if (!operand || !operand->impl_->root) {
127 throw std::invalid_argument(
"sin operand cannot be null");
132 std::vector<std::shared_ptr<const SymbolicNode>>{operand->impl_->root}));
135std::shared_ptr<SymbolicExpr> SymbolicExpr::cos(
136 std::shared_ptr<SymbolicExpr> operand) {
137 if (!operand || !operand->impl_->root) {
138 throw std::invalid_argument(
"cos operand cannot be null");
143 std::vector<std::shared_ptr<const SymbolicNode>>{operand->impl_->root}));
146std::shared_ptr<SymbolicExpr> SymbolicExpr::tan(
147 std::shared_ptr<SymbolicExpr> operand) {
148 if (!operand || !operand->impl_->root) {
149 throw std::invalid_argument(
"tan operand cannot be null");
154 std::vector<std::shared_ptr<const SymbolicNode>>{operand->impl_->root}));
157std::shared_ptr<SymbolicExpr> SymbolicExpr::ln(
158 std::shared_ptr<SymbolicExpr> operand) {
159 if (!operand || !operand->impl_->root) {
160 throw std::invalid_argument(
"ln operand cannot be null");
165 std::vector<std::shared_ptr<const SymbolicNode>>{operand->impl_->root}));
168std::shared_ptr<SymbolicExpr> SymbolicExpr::exp(
169 std::shared_ptr<SymbolicExpr> operand) {
170 if (!operand || !operand->impl_->root) {
171 throw std::invalid_argument(
"exp operand cannot be null");
176 std::vector<std::shared_ptr<const SymbolicNode>>{operand->impl_->root}));
179std::shared_ptr<SymbolicExpr> SymbolicExpr::lambertw(
180 std::shared_ptr<SymbolicExpr> operand) {
181 if (!operand || !operand->impl_->root) {
182 throw std::invalid_argument(
"lambertw operand cannot be null");
187 std::vector<std::shared_ptr<const SymbolicNode>>{operand->impl_->root}));
190std::shared_ptr<SymbolicExpr> SymbolicExpr::log(
191 std::shared_ptr<SymbolicExpr>
value,
192 std::shared_ptr<SymbolicExpr> base) {
193 if (!
value || !
value->impl_->root || !base || !base->impl_->root) {
194 throw std::invalid_argument(
"log operands cannot be null");
199 std::vector<std::shared_ptr<const SymbolicNode>>{
200 value->impl_->root, base->impl_->root}));
203std::shared_ptr<SymbolicExpr> SymbolicExpr::atan2(
204 std::shared_ptr<SymbolicExpr> y,
205 std::shared_ptr<SymbolicExpr> x) {
206 if (!y || !y->impl_->root || !x || !x->impl_->root) {
207 throw std::invalid_argument(
"atan2 operands cannot be null");
212 std::vector<std::shared_ptr<const SymbolicNode>>{y->impl_->root, x->impl_->root}));
215std::shared_ptr<SymbolicExpr> SymbolicExpr::root_of(
216 std::shared_ptr<SymbolicExpr> polynomial,
217 const std::string& variable_name,
219 if (!polynomial || !polynomial->impl_->root) {
220 throw std::invalid_argument(
"root_of polynomial cannot be null");
222 if (index < 0)
throw std::invalid_argument(
"root_of index cannot be negative");
224 polynomial, variable_name,
static_cast<std::size_t
>(index));
225 if (!result)
throw std::invalid_argument(result.error().message);
226 return std::move(result.value());
229std::shared_ptr<SymbolicExpr> SymbolicExpr::eq(
230 std::shared_ptr<SymbolicExpr> left,
231 std::shared_ptr<SymbolicExpr>
right) {
232 if (!left || !left->impl_->root || !
right || !
right->impl_->root) {
233 throw std::invalid_argument(
"eq operands cannot be null");
237 left->impl_->root,
right->impl_->root, RelationalNode::Op::EQ));
240std::shared_ptr<SymbolicExpr> SymbolicExpr::matrix(
241 const std::vector<std::vector<std::shared_ptr<SymbolicExpr>>>& elements) {
242 if (elements.empty()) {
243 throw std::invalid_argument(
"matrix requires at least one row");
245 const std::size_t column_count = elements.front().size();
246 if (column_count == 0) {
247 throw std::invalid_argument(
"matrix requires at least one column");
250 std::vector<std::vector<std::shared_ptr<const SymbolicNode>>> node_elements;
251 node_elements.reserve(elements.size());
252 for (
const auto& row : elements) {
253 if (row.size() != column_count) {
254 throw std::invalid_argument(
255 "matrix rows must have the same number of columns");
257 std::vector<std::shared_ptr<const SymbolicNode>> node_row;
258 node_row.reserve(row.size());
259 for (
const auto&
element : row) {
261 throw std::invalid_argument(
"matrix elements cannot be null");
263 node_row.push_back(
element->impl_->root);
265 node_elements.push_back(std::move(node_row));
271std::shared_ptr<SymbolicExpr> SymbolicExpr::variable(
272 const std::string&
name) {
277std::shared_ptr<SymbolicExpr> SymbolicExpr::divide(
const std::shared_ptr<SymbolicExpr>&
num,
const std::shared_ptr<SymbolicExpr>& den) {
278 return SymbolicExpr::multiply(
num, SymbolicExpr::power(den, SymbolicExpr::number(-1)));
281std::shared_ptr<SymbolicExpr> SymbolicExpr::make_integral(
282 const std::shared_ptr<SymbolicExpr>& expression,
284 if (!expression)
return nullptr;
const std::variant< BigInt, Rational > & value() const noexcept
NumberNode(const BigInt &v)
const std::variant< BigInt, Rational > value_
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(std::shared_ptr< SymbolicExpr > value)
Rational decimal_rational(lmmc_real_t value)
Node multiply(const Node &left, const Node &right)
int sign(const Rational &value)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
ExpressionResult constant_expression(const char *name)
std::shared_ptr< const Node > make_node(Args &&... args)
ComputationContext const std::string & operation
std::shared_ptr< SymbolicExpr > num(int value)
const std::string & variable
@ Rational
Rational numbers
Result< std::shared_ptr< SymbolicExpr > > ExpressionResult
Result of an operation that produces a symbolic expression.
RootOfConstructionResult make_rootof_checked(const std::shared_ptr< SymbolicExpr > &polynomial, const std::string &variable, std::size_t index, ComputationContext &context)
const std::string const ExprPtr & value
__attribute__((visibility("default"))) Result< EqvProfile > eqv_profile_from_name(const std const std::string & name
符号表达式主类 SymbolicExpr 及其工厂方法,运算接口.