1#define _USE_MATH_DEFINES
42 auto mul = std::dynamic_pointer_cast<const MultiplyNode>(operand);
43 if (!
mul ||
mul->operands().size() != 2) {
46 bool found_neg_one =
false;
47 std::shared_ptr<const SymbolicNode> other_operand;
48 for (
const auto& mul_op :
mul->operands()) {
49 auto step =
context.consume_steps(1,
"inference.arithmetic");
50 if (!step)
throw step.error();
52 std::dynamic_pointer_cast<const NumberNode>(mul_op);
53 if (number && number->is_negative_one()) {
57 other_operand = mul_op;
59 return found_neg_one ? other_operand :
nullptr;
63 if (node.operands().size() != 2) {
66 for (
const auto& operand : node.operands()) {
67 auto step =
context.consume_steps(1,
"inference.arithmetic");
68 if (!step)
throw step.error();
69 auto mul = std::dynamic_pointer_cast<const MultiplyNode>(operand);
70 if (!
mul ||
mul->operands().size() != 2) {
73 for (
const auto& factor :
mul->operands()) {
74 auto step =
context.consume_steps(1,
"inference.arithmetic");
75 if (!step)
throw step.error();
77 std::dynamic_pointer_cast<const NumberNode>(factor);
78 if (number && number->is_negative_one()) {
87 const InferenceEngine& engine,
90 bool all_have_property =
true;
92 for (
const auto& operand : node.operands()) {
93 auto step =
context.consume_steps(1,
"inference.arithmetic");
94 if (!step)
throw step.error();
101 auto queried = engine.query_sign_of_checked(op_expr,
target,
context);
105 op_result = queried.value();
111 all_have_property =
false;
115 if (all_have_property) {
123 const InferenceEngine& engine,
124 const SymbolicExpr& minuend_expr,
125 const SymbolicExpr& subtrahend_expr,
127 auto min_pos_result =
129 if (!min_pos_result) {
130 return min_pos_result;
132 const Tribool min_pos = min_pos_result.value();
133 auto min_neg_result =
135 if (!min_neg_result) {
136 return min_neg_result;
138 const Tribool min_neg = min_neg_result.value();
139 auto sub_pos_result =
141 if (!sub_pos_result) {
142 return sub_pos_result;
144 const Tribool sub_pos = sub_pos_result.value();
145 auto sub_neg_result =
147 if (!sub_neg_result) {
148 return sub_neg_result;
150 const Tribool sub_neg = sub_neg_result.value();
164 const InferenceEngine& engine,
165 const SymbolicExpr& minuend_expr,
166 const SymbolicExpr& subtrahend_expr,
170 if (!min_nn_result) {
171 return min_nn_result;
173 const Tribool min_nn = min_nn_result.value();
176 if (!sub_np_result) {
177 return sub_np_result;
179 const Tribool sub_np = sub_np_result.value();
190 if (!min_np_result) {
191 return min_np_result;
193 const Tribool min_np = min_np_result.value();
196 if (!sub_nn_result) {
197 return sub_nn_result;
199 const Tribool sub_nn = sub_nn_result.value();
214 if (node.operands().empty()) {
218 auto sub_result = infer_subtraction_sign_checked(node,
target,
context);
233 }
catch (
const CasError& error) {
235 }
catch (
const std::bad_alloc&) {
238 "addition sign inference allocation failed",
239 "infer_add_sign_checked");
240 }
catch (
const std::exception& ex) {
244 "infer_add_sign_checked");
251 if (
node.operands().size() != 2) {
255 std::shared_ptr<const SymbolicNode> minuend_node;
256 std::shared_ptr<const SymbolicNode> subtrahend_node;
258 for (
const auto& operand :
node.operands()) {
259 auto step =
context.consume_steps(1,
"inference.arithmetic");
260 if (!step)
throw step.error();
263 subtrahend_node = inner;
265 minuend_node = operand;
269 if (!minuend_node || !subtrahend_node) {
276 return impl_->subtraction_sign(*
this, minuend_expr, subtrahend_expr,
target,
context);
277 }
catch (
const CasError& error) {
279 }
catch (
const std::bad_alloc&) {
282 "subtraction sign inference allocation failed",
283 "infer_subtraction_sign_checked");
284 }
catch (
const std::exception& ex) {
288 "infer_subtraction_sign_checked");
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(Tribool value)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
inline ::LMCAS::SymbolicExpr expression_from_node(SymbolicNodePtr root)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExprResult mul(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
Tribool
Tri-state logic value for property queries.
@ Unknown
Property cannot be determined
@ True
Property definitely holds
@ False
Property definitely does not hold
const std::string const ExprPtr & value
Result< Tribool > InferenceTriboolResult
Sign
Sign classification for symbols and expressions.
InferenceTriboolResult weak_subtraction_sign(const InferenceEngine &engine, const SymbolicExpr &minuend_expr, const SymbolicExpr &subtrahend_expr, Sign target, ComputationContext &context) const
static Tribool nonnegative_sign(Sign target)
static std::shared_ptr< const SymbolicNode > subtrahend(const std::shared_ptr< const SymbolicNode > &operand, ComputationContext &context)
InferenceTriboolResult sum_sign(const InferenceEngine &engine, const AddNode &node, Sign target, ComputationContext &context) const
InferenceTriboolResult subtraction_sign(const InferenceEngine &engine, const SymbolicExpr &minuend_expr, const SymbolicExpr &subtrahend_expr, Sign target, ComputationContext &context) const
static bool has_negated_operand(const AddNode &node, ComputationContext &context)
static Tribool known_sign(int value, Sign target)