18 const std::shared_ptr<SymbolicExpr>& expr,
20 const std::string& operation)
25 "numeric expression cannot be null",
36 "expression is not finite numeric in the supported domain",
39 if (!evaluated.value().is_finite() ||
40 !std::isfinite(evaluated.value().value)) {
43 "expression is not finite numeric in the supported domain",
50 double magnitude,
double& scale,
double& norm_squared,
51 double& dot,
double& correction)
53 if (magnitude <= scale)
return;
54 const double ratio = scale == 0.0 ? 0.0 : scale / magnitude;
55 norm_squared *= ratio * ratio;
62 double left,
double right,
double& dot,
double& correction)
64 const double product = left *
right;
65 const double corrected = product - correction;
66 const double next = dot + corrected;
67 correction = (next - dot) - corrected;
75 const std::vector<std::shared_ptr<SymbolicExpr>>&
a,
76 const std::vector<std::shared_ptr<SymbolicExpr>>&
b
80 throw std::invalid_argument(
"vector_dot: " + checked.error().message);
82 return checked.value();
86 const std::vector<std::shared_ptr<SymbolicExpr>>&
a,
87 const std::vector<std::shared_ptr<SymbolicExpr>>&
b,
90 const std::string operation =
"vector_dot";
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);
104 const std::vector<std::shared_ptr<SymbolicExpr>>&
a,
105 const std::vector<std::shared_ptr<SymbolicExpr>>&
b
112 const std::vector<std::shared_ptr<SymbolicExpr>>&
a,
113 const std::vector<std::shared_ptr<SymbolicExpr>>&
b
117 throw std::invalid_argument(
"vector_cross: " + checked.error().message);
119 return checked.value();
123 const std::vector<std::shared_ptr<SymbolicExpr>>&
a,
124 const std::vector<std::shared_ptr<SymbolicExpr>>&
b,
127 const std::string operation =
"vector_cross";
128 auto step =
context.consume_steps(1, operation);
130 if (
a.size() != 3 ||
b.size() != 3) {
133 "cross product requires 3-dimensional vectors",
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])));
147 const std::vector<std::shared_ptr<SymbolicExpr>>&
a,
148 const std::vector<std::shared_ptr<SymbolicExpr>>&
b
156 const std::vector<std::shared_ptr<SymbolicExpr>>&
a,
157 const std::vector<std::shared_ptr<SymbolicExpr>>&
b,
160 const std::string operation =
"vector_angle";
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);
172 auto na_result = symbolic_vector_finite_numeric(
a[i],
context, operation);
174 auto nb_result = symbolic_vector_finite_numeric(
b[i],
context, operation);
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);
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;
189 if (scale_b != 0.0) {
190 const double normalized = nb / scale_b;
191 norm_b_scaled += normalized * normalized;
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);
198 if (scale_a == 0.0 || scale_b == 0.0) {
201 "angle is undefined for zero-length vectors",
205 std::sqrt(norm_a_scaled) * std::sqrt(norm_b_scaled);
207 if (!std::isfinite(cosv)) {
210 "vector angle normalization produced a non-finite result",
213 if (cosv > 1.0) cosv = 1.0;
214 else if (cosv < -1.0) cosv = -1.0;
219 const std::vector<std::shared_ptr<SymbolicExpr>>&
a,
220 const std::vector<std::shared_ptr<SymbolicExpr>>&
b
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
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
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)