//----------------------------------------------------------------------------- // An expression in our symbolic algebra system, used to write, linearize, // and solve our constraint equations. // // Copyright 2008-2013 Jonathan Westhues. //----------------------------------------------------------------------------- #ifndef SOLVESPACE_EXPR_H #define SOLVESPACE_EXPR_H class Expr { public: enum class Op : uint32_t { // A parameter, by the hParam handle PARAM = 0, // A parameter, by a pointer straight in to the param table (faster, // if we know that the param table won't move around) PARAM_PTR = 1, // Operands CONSTANT = 20, VARIABLE = 21, // Binary ops PLUS = 100, MINUS = 101, TIMES = 102, DIV = 103, // Unary ops NEGATE = 104, SQRT = 105, SQUARE = 106, SIN = 107, COS = 108, ASIN = 109, ACOS = 110, }; Op op; Expr *a; union { double v; hParam parh; Param *parp; Expr *b; }; Expr() = default; Expr(double val) : op(Op::CONSTANT) { v = val; } static inline Expr *AllocExpr() { return (Expr *)AllocTemporary(sizeof(Expr)); } static Expr *From(hParam p); static Expr *From(double v); Expr *AnyOp(Op op, Expr *b); inline Expr *Plus (Expr *b_) { return AnyOp(Op::PLUS, b_); } inline Expr *Minus(Expr *b_) { return AnyOp(Op::MINUS, b_); } inline Expr *Times(Expr *b_) { return AnyOp(Op::TIMES, b_); } inline Expr *Div (Expr *b_) { return AnyOp(Op::DIV, b_); } inline Expr *Negate() { return AnyOp(Op::NEGATE, NULL); } inline Expr *Sqrt () { return AnyOp(Op::SQRT, NULL); } inline Expr *Square() { return AnyOp(Op::SQUARE, NULL); } inline Expr *Sin () { return AnyOp(Op::SIN, NULL); } inline Expr *Cos () { return AnyOp(Op::COS, NULL); } inline Expr *ASin () { return AnyOp(Op::ASIN, NULL); } inline Expr *ACos () { return AnyOp(Op::ACOS, NULL); } Expr *PartialWrt(hParam p) const; double Eval() const; uint64_t ParamsUsed() const; bool DependsOn(hParam p) const; static bool Tol(double a, double b); Expr *FoldConstants(); void Substitute(hParam oldh, hParam newh); static const hParam NO_PARAMS, MULTIPLE_PARAMS; hParam ReferencedParams(ParamList *pl) const; void ParamsToPointers(); std::string Print() const; // number of child nodes: 0 (e.g. constant), 1 (sqrt), or 2 (+) int Children() const; // total number of nodes in the tree int Nodes() const; // Make a simple copy Expr *DeepCopy() const; // Make a copy, with the parameters (usually referenced by hParam) // resolved to pointers to the actual value. This speeds things up // considerably. Expr *DeepCopyWithParamsAsPointers(IdList *firstTry, IdList *thenTry) const; static Expr *Parse(const std::string &input, std::string *error); static Expr *From(const std::string &input, bool popUpError); }; class ExprVector { public: Expr *x, *y, *z; static ExprVector From(Expr *x, Expr *y, Expr *z); static ExprVector From(Vector vn); static ExprVector From(hParam x, hParam y, hParam z); static ExprVector From(double x, double y, double z); ExprVector Plus(ExprVector b) const; ExprVector Minus(ExprVector b) const; Expr *Dot(ExprVector b) const; ExprVector Cross(ExprVector b) const; ExprVector ScaledBy(Expr *s) const; ExprVector WithMagnitude(Expr *s) const; Expr *Magnitude() const; Vector Eval() const; }; class ExprQuaternion { public: Expr *w, *vx, *vy, *vz; static ExprQuaternion From(Expr *w, Expr *vx, Expr *vy, Expr *vz); static ExprQuaternion From(Quaternion qn); static ExprQuaternion From(hParam w, hParam vx, hParam vy, hParam vz); ExprVector RotationU() const; ExprVector RotationV() const; ExprVector RotationN() const; ExprVector Rotate(ExprVector p) const; ExprQuaternion Times(ExprQuaternion b) const; Expr *Magnitude() const; }; #endif