LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
symbolic_geometry_vector.cpp
浏览该文件的文档.
5
6#include <algorithm>
7#include <cmath>
8#include <limits>
9#include <stdexcept>
10#include <utility>
11
12namespace LMCAS {
13using namespace geometry_detail;
14
15namespace {
16
18 const std::shared_ptr<SymbolicExpr>& expr,
20 const std::string& operation)
21{
22 if (!expr || !LMCAS::detail::node(expr)) {
25 "numeric expression cannot be null",
26 operation);
27 }
28 auto evaluated = evaluate_numeric(*expr, NumericBindings{}, context);
29 if (!evaluated) {
30 if (evaluated.error().code == CasErrc::Cancelled ||
31 evaluated.error().code == CasErrc::ResourceLimit) {
32 return Result<double>::failure(evaluated.error());
33 }
36 "expression is not finite numeric in the supported domain",
37 operation);
38 }
39 if (!evaluated.value().is_finite() ||
40 !std::isfinite(evaluated.value().value)) {
43 "expression is not finite numeric in the supported domain",
44 operation);
45 }
46 return Result<double>::success(evaluated.value().value);
47}
48
50 double magnitude, double& scale, double& norm_squared,
51 double& dot, double& correction)
52{
53 if (magnitude <= scale) return;
54 const double ratio = scale == 0.0 ? 0.0 : scale / magnitude;
55 norm_squared *= ratio * ratio;
56 dot *= ratio;
57 correction *= ratio;
58 scale = magnitude;
59}
60
62 double left, double right, double& dot, double& correction)
63{
64 const double product = left * right;
65 const double corrected = product - correction;
66 const double next = dot + corrected;
67 correction = (next - dot) - corrected;
68 dot = next;
69}
70
71}
72
73
74std::shared_ptr<SymbolicExpr> vector_dot(
75 const std::vector<std::shared_ptr<SymbolicExpr>>& a,
76 const std::vector<std::shared_ptr<SymbolicExpr>>& b
77) {
78 auto checked = vector_dot_checked(a, b);
79 if (!checked) {
80 throw std::invalid_argument("vector_dot: " + checked.error().message);
81 }
82 return checked.value();
83}
84
86 const std::vector<std::shared_ptr<SymbolicExpr>>& a,
87 const std::vector<std::shared_ptr<SymbolicExpr>>& b,
89) {
90 const std::string operation = "vector_dot";
91 auto input = validate_same_dimension_vectors(a, b, context, operation);
92 if (!input) return ExpressionResult::failure(input.error());
93 std::vector<std::shared_ptr<const SymbolicNode>> sum_terms;
94 for (size_t i = 0; i < a.size(); ++i) {
95 auto step = context.consume_steps(1, operation);
96 if (!step) return ExpressionResult::failure(step.error());
97 sum_terms.push_back(LMCAS::detail::node(SymbolicExpr::multiply(a[i], b[i])));
98 }
101}
102
104 const std::vector<std::shared_ptr<SymbolicExpr>>& a,
105 const std::vector<std::shared_ptr<SymbolicExpr>>& b
106) {
108 return vector_dot_checked(a, b, context);
109}
110
111std::vector<std::shared_ptr<SymbolicExpr>> vector_cross(
112 const std::vector<std::shared_ptr<SymbolicExpr>>& a,
113 const std::vector<std::shared_ptr<SymbolicExpr>>& b
114) {
115 auto checked = vector_cross_checked(a, b);
116 if (!checked) {
117 throw std::invalid_argument("vector_cross: " + checked.error().message);
118 }
119 return checked.value();
120}
121
123 const std::vector<std::shared_ptr<SymbolicExpr>>& a,
124 const std::vector<std::shared_ptr<SymbolicExpr>>& b,
126) {
127 const std::string operation = "vector_cross";
128 auto step = context.consume_steps(1, operation);
129 if (!step) return VectorExprListResult::failure(step.error());
130 if (a.size() != 3 || b.size() != 3) {
133 "cross product requires 3-dimensional vectors",
134 operation);
135 }
136 auto a_check = validate_symbolic_vector(a, "left vector", operation);
137 if (!a_check) return VectorExprListResult::failure(a_check.error());
138 auto b_check = validate_symbolic_vector(b, "right vector", operation);
139 if (!b_check) return VectorExprListResult::failure(b_check.error());
140 auto x = SymbolicExpr::add(SymbolicExpr::multiply(a[1], b[2]), SymbolicExpr::multiply(SymbolicExpr::number(-1), SymbolicExpr::multiply(a[2], b[1])));
141 auto y = SymbolicExpr::add(SymbolicExpr::multiply(a[2], b[0]), SymbolicExpr::multiply(SymbolicExpr::number(-1), SymbolicExpr::multiply(a[0], b[2])));
142 auto z = SymbolicExpr::add(SymbolicExpr::multiply(a[0], b[1]), SymbolicExpr::multiply(SymbolicExpr::number(-1), SymbolicExpr::multiply(a[1], b[0])));
143 return VectorExprListResult::success({x, y, z});
144}
145
147 const std::vector<std::shared_ptr<SymbolicExpr>>& a,
148 const std::vector<std::shared_ptr<SymbolicExpr>>& b
149) {
152}
153
154
156 const std::vector<std::shared_ptr<SymbolicExpr>>& a,
157 const std::vector<std::shared_ptr<SymbolicExpr>>& b,
159) {
160 const std::string operation = "vector_angle";
161 auto input = validate_same_dimension_vectors(a, b, context, operation);
162 if (!input) return VectorAngleResult::failure(input.error());
163 double scale_a = 0.0;
164 double scale_b = 0.0;
165 double norm_a_scaled = 0.0;
166 double norm_b_scaled = 0.0;
167 double dot_scaled = 0.0;
168 double dot_correction = 0.0;
169 for (size_t i = 0; i < a.size(); ++i) {
170 auto step = context.consume_steps(1, operation);
171 if (!step) return VectorAngleResult::failure(step.error());
172 auto na_result = symbolic_vector_finite_numeric(a[i], context, operation);
173 if (!na_result) return VectorAngleResult::failure(na_result.error());
174 auto nb_result = symbolic_vector_finite_numeric(b[i], context, operation);
175 if (!nb_result) return VectorAngleResult::failure(nb_result.error());
176 const double na = na_result.value();
177 const double nb = nb_result.value();
178 const double abs_a = std::abs(na);
179 const double abs_b = std::abs(nb);
180
181 rescale_angle_component(
182 abs_a, scale_a, norm_a_scaled, dot_scaled, dot_correction);
183 rescale_angle_component(
184 abs_b, scale_b, norm_b_scaled, dot_scaled, dot_correction);
185 if (scale_a != 0.0) {
186 const double normalized = na / scale_a;
187 norm_a_scaled += normalized * normalized;
188 }
189 if (scale_b != 0.0) {
190 const double normalized = nb / scale_b;
191 norm_b_scaled += normalized * normalized;
192 }
193 if (scale_a != 0.0 && scale_b != 0.0) {
194 accumulate_angle_product(
195 na / scale_a, nb / scale_b, dot_scaled, dot_correction);
196 }
197 }
198 if (scale_a == 0.0 || scale_b == 0.0) {
201 "angle is undefined for zero-length vectors",
202 operation);
203 }
204 const double denominator =
205 std::sqrt(norm_a_scaled) * std::sqrt(norm_b_scaled);
206 double cosv = dot_scaled / denominator;
207 if (!std::isfinite(cosv)) {
210 "vector angle normalization produced a non-finite result",
211 operation);
212 }
213 if (cosv > 1.0) cosv = 1.0;
214 else if (cosv < -1.0) cosv = -1.0;
215 return VectorAngleResult::success(std::acos(cosv));
216}
217
219 const std::vector<std::shared_ptr<SymbolicExpr>>& a,
220 const std::vector<std::shared_ptr<SymbolicExpr>>& b
221) {
224}
225
226}
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
void accumulate_angle_product(double left, double right, double &dot, double &correction)
Result< double > symbolic_vector_finite_numeric(const std::shared_ptr< SymbolicExpr > &expr, ComputationContext &context, const std::string &operation)
void rescale_angle_component(double magnitude, double &scale, double &norm_squared, double &dot, double &correction)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::shared_ptr< const Node > make_node(Args &&... args)
Result< void > validate_symbolic_vector(const std::vector< std::shared_ptr< SymbolicExpr > > &vector, const std::string &name, const std::string &operation)
Result< void > validate_same_dimension_vectors(const std::vector< std::shared_ptr< SymbolicExpr > > &a, const std::vector< std::shared_ptr< SymbolicExpr > > &b, ComputationContext &context, const std::string &operation)
VectorExprListResult vector_cross_checked(const std::vector< std::shared_ptr< SymbolicExpr > > &a, const std::vector< std::shared_ptr< SymbolicExpr > > &b, ComputationContext &context)
std::shared_ptr< SymbolicExpr > vector_dot(const std::vector< std::shared_ptr< SymbolicExpr > > &a, const std::vector< std::shared_ptr< SymbolicExpr > > &b)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
std::vector< std::shared_ptr< SymbolicExpr > > vector_cross(const std::vector< std::shared_ptr< SymbolicExpr > > &a, const std::vector< std::shared_ptr< SymbolicExpr > > &b)
Result< double > VectorAngleResult
const MultiPoly & b
Result< std::shared_ptr< SymbolicExpr > > ExpressionResult
Result of an operation that produces a symbolic expression.
__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
const ExprPtr & right
VectorAngleResult vector_angle_checked(const std::vector< std::shared_ptr< SymbolicExpr > > &a, const std::vector< std::shared_ptr< SymbolicExpr > > &b, ComputationContext &context)
Result< std::vector< std::shared_ptr< SymbolicExpr > > > VectorExprListResult
const ExprPtr & denominator
Result< ApproxReal > evaluate_numeric(const SymbolicExpr &expression, const NumericBindings &bindings={})
std::unordered_map< std::string, double > NumericBindings
ExpressionResult vector_dot_checked(const std::vector< std::shared_ptr< SymbolicExpr > > &a, const std::vector< std::shared_ptr< SymbolicExpr > > &b, ComputationContext &context)
内部 AST 定义。