1 //-----------------------------------------------------------------------------
2 // An expression in our symbolic algebra system, used to write, linearize,
3 // and solve our constraint equations.
4 //
5 // Copyright 2008-2013 Jonathan Westhues.
6 //-----------------------------------------------------------------------------
7 
8 #ifndef __EXPR_H
9 #define __EXPR_H
10 
11 class Expr;
12 
13 class Expr {
14 public:
15 
16     enum {
17         // A parameter, by the hParam handle
18         PARAM          =  0,
19         // A parameter, by a pointer straight in to the param table (faster,
20         // if we know that the param table won't move around)
21         PARAM_PTR      =  1,
22 
23         CONSTANT       = 20,
24 
25         PLUS           = 100,
26         MINUS          = 101,
27         TIMES          = 102,
28         DIV            = 103,
29         NEGATE         = 104,
30         SQRT           = 105,
31         SQUARE         = 106,
32         SIN            = 107,
33         COS            = 108,
34         ASIN           = 109,
35         ACOS           = 110,
36 
37         // Special helpers for when we're parsing an expression from text.
38         // Initially, literals (like a constant number) appear in the same
39         // format as they will in the finished expression, but the operators
40         // are different until the parser fixes things up (and builds the
41         // tree from the flat list that the lexer outputs).
42         ALL_RESOLVED   = 1000,
43         PAREN          = 1001,
44         BINARY_OP      = 1002,
45         UNARY_OP       = 1003
46     };
47 
48     int op;
49     Expr    *a;
50     union {
51         double  v;
52         hParam  parh;
53         Param  *parp;
54         Expr    *b;
55 
56         // For use while parsing
57         char    c;
58     };
59 
Expr()60     Expr() { }
Expr(double val)61     Expr(double val) : op(CONSTANT) { v = val; }
62 
AllocExpr(void)63     static inline Expr *AllocExpr(void)
64         { return (Expr *)AllocTemporary(sizeof(Expr)); }
65 
66     static Expr *From(hParam p);
67     static Expr *From(double v);
68 
69     Expr *AnyOp(int op, Expr *b);
Plus(Expr * b_)70     inline Expr *Plus (Expr *b_) { return AnyOp(PLUS,  b_); }
Minus(Expr * b_)71     inline Expr *Minus(Expr *b_) { return AnyOp(MINUS, b_); }
Times(Expr * b_)72     inline Expr *Times(Expr *b_) { return AnyOp(TIMES, b_); }
Div(Expr * b_)73     inline Expr *Div  (Expr *b_) { return AnyOp(DIV,   b_); }
74 
Negate(void)75     inline Expr *Negate(void) { return AnyOp(NEGATE, NULL); }
Sqrt(void)76     inline Expr *Sqrt  (void) { return AnyOp(SQRT,   NULL); }
Square(void)77     inline Expr *Square(void) { return AnyOp(SQUARE, NULL); }
Sin(void)78     inline Expr *Sin   (void) { return AnyOp(SIN,    NULL); }
Cos(void)79     inline Expr *Cos   (void) { return AnyOp(COS,    NULL); }
ASin(void)80     inline Expr *ASin  (void) { return AnyOp(ASIN,   NULL); }
ACos(void)81     inline Expr *ACos  (void) { return AnyOp(ACOS,   NULL); }
82 
83     Expr *PartialWrt(hParam p);
84     double Eval(void);
85     uint64_t ParamsUsed(void);
86     bool DependsOn(hParam p);
87     static bool Tol(double a, double b);
88     Expr *FoldConstants(void);
89     void Substitute(hParam oldh, hParam newh);
90 
91     static const hParam NO_PARAMS, MULTIPLE_PARAMS;
92     hParam ReferencedParams(ParamList *pl);
93 
94     void ParamsToPointers(void);
95 
96     std::string Print(void);
97 
98     // number of child nodes: 0 (e.g. constant), 1 (sqrt), or 2 (+)
99     int Children(void);
100     // total number of nodes in the tree
101     int Nodes(void);
102 
103     // Make a simple copy
104     Expr *DeepCopy(void);
105     // Make a copy, with the parameters (usually referenced by hParam)
106     // resolved to pointers to the actual value. This speeds things up
107     // considerably.
108     Expr *DeepCopyWithParamsAsPointers(IdList<Param,hParam> *firstTry,
109         IdList<Param,hParam> *thenTry);
110 
111     static Expr *From(const char *in, bool popUpError);
112     static void  Lex(const char *in);
113     static Expr *Next(void);
114     static void  Consume(void);
115 
116     static void PushOperator(Expr *e);
117     static Expr *PopOperator(void);
118     static Expr *TopOperator(void);
119     static void PushOperand(Expr *e);
120     static Expr *PopOperand(void);
121 
122     static void Reduce(void);
123     static void ReduceAndPush(Expr *e);
124     static int Precedence(Expr *e);
125 
126     static int Precedence(int op);
127     static void Parse(void);
128 };
129 
130 class ExprVector {
131 public:
132     Expr *x, *y, *z;
133 
134     static ExprVector From(Expr *x, Expr *y, Expr *z);
135     static ExprVector From(Vector vn);
136     static ExprVector From(hParam x, hParam y, hParam z);
137     static ExprVector From(double x, double y, double z);
138 
139     ExprVector Plus(ExprVector b);
140     ExprVector Minus(ExprVector b);
141     Expr *Dot(ExprVector b);
142     ExprVector Cross(ExprVector b);
143     ExprVector ScaledBy(Expr *s);
144     ExprVector WithMagnitude(Expr *s);
145     Expr *Magnitude(void);
146 
147     Vector Eval(void);
148 };
149 
150 class ExprQuaternion {
151 public:
152     Expr *w, *vx, *vy, *vz;
153 
154     static ExprQuaternion From(Expr *w, Expr *vx, Expr *vy, Expr *vz);
155     static ExprQuaternion From(Quaternion qn);
156     static ExprQuaternion From(hParam w, hParam vx, hParam vy, hParam vz);
157 
158     ExprVector RotationU(void);
159     ExprVector RotationV(void);
160     ExprVector RotationN(void);
161 
162     ExprVector Rotate(ExprVector p);
163     ExprQuaternion Times(ExprQuaternion b);
164 
165     Expr *Magnitude(void);
166 };
167 
168 #endif
169 
170