LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
solve_polynomial_quadratic.cpp
浏览该文件的文档.
4#include <stdexcept>
5
6namespace LMCAS {
7using namespace polynomial_solver_detail;
8
10std::vector<std::shared_ptr<SymbolicExpr>> solve_quadratic_internal(
11 const std::shared_ptr<SymbolicExpr>& a, const std::shared_ptr<SymbolicExpr>& b,
12 const std::shared_ptr<SymbolicExpr>& c, ComputationContext& context) {
13 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
14 (context).limits().max_ast_nodes, "transform");
15 auto b2 = SymbolicExpr::power(b, num(2));
16 auto four_ac = SymbolicExpr::multiply(num(4), SymbolicExpr::multiply(a, c));
17 auto delta = detail::make_expression_ptr(detail::normalize_node(detail::node(sub(b2, four_ac)), transform_budget));
18
19 auto neg_b = negate(b);
20 auto two_a = SymbolicExpr::multiply(num(2), a);
21 if (delta && delta->is_zero()) {
22 return { detail::make_expression_ptr(detail::normalize_node(detail::node(SymbolicExpr::divide(neg_b, two_a)), transform_budget)) };
23 }
24
25 auto sqrt_delta = SymbolicExpr::sqrt(delta);
27 auto exact_delta = detail::exact_rational_value(detail::node(delta));
28 if (exact_b && *exact_b != Rational(0) &&
29 exact_delta && *exact_delta > Rational(0)) {
30 auto numerator = *exact_b < Rational(0)
31 ? SymbolicExpr::add(neg_b, sqrt_delta)
32 : sub(neg_b, sqrt_delta);
34 detail::node(SymbolicExpr::divide(numerator, two_a)), transform_budget));
36 detail::node(SymbolicExpr::divide(
37 SymbolicExpr::multiply(num(2), c), numerator)), transform_budget));
38 return {x1, x2};
39 }
40 auto x1 = detail::make_expression_ptr(detail::normalize_node(detail::node(SymbolicExpr::divide(SymbolicExpr::add(neg_b, sqrt_delta), two_a)), transform_budget));
41 auto x2 = detail::make_expression_ptr(detail::normalize_node(detail::node(SymbolicExpr::divide(sub(neg_b, sqrt_delta), two_a)), transform_budget));
42
43 return { x1, x2 };
44}
45}
46
47std::vector<std::shared_ptr<SymbolicExpr>> polynomial_solver_detail::solve_biquadratic_impl(
48 const std::shared_ptr<SymbolicExpr>& a,
49 const std::shared_ptr<SymbolicExpr>& b,
50 const std::shared_ptr<SymbolicExpr>& c,
51 const std::string&, ComputationContext& context) {
52 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
53 (context).limits().max_ast_nodes, "transform");
54 auto a_simplified = detail::make_expression_ptr(detail::normalize_node(detail::node(a), transform_budget));
55 if (a_simplified->get_number_value_is_zero()) {
56 auto b_simplified = detail::make_expression_ptr(detail::normalize_node(detail::node(b), transform_budget));
57 if (!b_simplified->get_number_value_is_zero()) {
59 }
60
61 auto c_simplified = detail::make_expression_ptr(detail::normalize_node(detail::node(c), transform_budget));
62 if (c_simplified->get_number_value_is_zero()) {
63 throw std::invalid_argument(
64 "solve_biquadratic: identically zero equation has no finite root list");
65 }
66 if (is_purely_numeric(c_simplified)) {
67 return {};
68 }
69 throw std::invalid_argument(
70 "solve_biquadratic: equation is independent of the requested variable");
71 }
72
73 auto u_roots = solve_quadratic_internal(a, b, c, context);
74
75 std::vector<std::shared_ptr<SymbolicExpr>> results;
76 for (const auto& u : u_roots) {
77 auto pos_root = detail::make_expression_ptr(detail::normalize_node(detail::node(SymbolicExpr::sqrt(u)), transform_budget));
78 auto neg_root = detail::make_expression_ptr(detail::normalize_node(detail::node(negate(SymbolicExpr::sqrt(u))), transform_budget));
79 results.push_back(pos_root);
80 results.push_back(neg_root);
81 }
82
83 return results;
84}
85
86std::vector<std::shared_ptr<SymbolicExpr>> solve_biquadratic(
87 const std::shared_ptr<SymbolicExpr>& a,
88 const std::shared_ptr<SymbolicExpr>& b,
89 const std::shared_ptr<SymbolicExpr>& c,
90 const std::string& variable) {
93}
94
95}
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::optional< Rational > exact_rational_value(const NumberNode &number)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::shared_ptr< SymbolicExpr > num(int value)
std::vector< std::shared_ptr< SymbolicExpr > > solve_biquadratic_impl(const std::shared_ptr< SymbolicExpr > &a, const std::shared_ptr< SymbolicExpr > &b, const std::shared_ptr< SymbolicExpr > &c, const std::string &variable, ComputationContext &context)
std::shared_ptr< SymbolicExpr > sub(const std::shared_ptr< SymbolicExpr > &a, const std::shared_ptr< SymbolicExpr > &b)
std::shared_ptr< SymbolicExpr > negate(const std::shared_ptr< SymbolicExpr > &expr)
bool is_purely_numeric(const std::shared_ptr< SymbolicExpr > &expr)
std::vector< std::shared_ptr< SymbolicExpr > > solve_quadratic_internal(const std::shared_ptr< SymbolicExpr > &a, const std::shared_ptr< SymbolicExpr > &b, const std::shared_ptr< SymbolicExpr > &c, ComputationContext &context)
const std::string & variable
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
const VectorField const VectorField & c
const MultiPoly & b
__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
std::vector< std::shared_ptr< SymbolicExpr > > solve_biquadratic(const std::shared_ptr< SymbolicExpr > &a, const std::shared_ptr< SymbolicExpr > &b, const std::shared_ptr< SymbolicExpr > &c, const std::string &variable)
__attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string & u