double pwl(ExprState es, List <Expr> args) { double x = args[0].Eval(es); double x0 = args[1].Eval(es); double y0 = args[2].Eval(es); if (x < x0) { return(y0); } double x1 = args[3].Eval(es); double y1 = args[4].Eval(es); int i = 5; while (true) { if (x < x1) { return(y0 + (x - x0) * (y1 - y0) / (x1 - x0)); } if (i + 1 >= args.Count) { break; } x0 = x1; y0 = y1; x1 = args[i].Eval(es); y1 = args[i + 1].Eval(es); i += 2; } return(y1); }
public double Eval(ExprState es) { Expr left = null; Expr right = null; if (Children != null && Children.Count > 0) { left = Children[0]; if (Children.Count == 2) { right = Children[Children.Count - 1]; } } switch (type) { case EXPR_TYPE.E_ADD: return(left.Eval(es) + right.Eval(es)); case EXPR_TYPE.E_SUB: return(left.Eval(es) - right.Eval(es)); case EXPR_TYPE.E_MUL: return(left.Eval(es) * right.Eval(es)); case EXPR_TYPE.E_DIV: return(left.Eval(es) / right.Eval(es)); case EXPR_TYPE.E_POW: return(Math.Pow(left.Eval(es), right.Eval(es))); case EXPR_TYPE.E_UMINUS: return(-left.Eval(es)); case EXPR_TYPE.E_VAL: return(value); case EXPR_TYPE.E_T: return(es.Time); case EXPR_TYPE.E_SIN: return(Math.Sin(left.Eval(es))); case EXPR_TYPE.E_COS: return(Math.Cos(left.Eval(es))); case EXPR_TYPE.E_ABS: return(Math.Abs(left.Eval(es))); case EXPR_TYPE.E_EXP: return(Math.Exp(left.Eval(es))); case EXPR_TYPE.E_LOG: return(Math.Log(left.Eval(es))); case EXPR_TYPE.E_SQRT: return(Math.Sqrt(left.Eval(es))); case EXPR_TYPE.E_TAN: return(Math.Tan(left.Eval(es))); case EXPR_TYPE.E_MIN: { int i; double x = left.Eval(es); for (i = 1; i < Children.Count; i++) { x = Math.Min(x, Children[i].Eval(es)); } return(x); } case EXPR_TYPE.E_MAX: { int i; double x = left.Eval(es); for (i = 1; i < Children.Count; i++) { x = Math.Max(x, Children[i].Eval(es)); } return(x); } case EXPR_TYPE.E_CLAMP: return(Math.Min(Math.Max(left.Eval(es), Children[1].Eval(es)), Children[2].Eval(es))); case EXPR_TYPE.E_STEP: { double x = left.Eval(es); if (right == null) { return((x < 0) ? 0 : 1); } return((x > right.Eval(es)) ? 0 : (x < 0) ? 0 : 1); } case EXPR_TYPE.E_SELECT: { double x = left.Eval(es); return(Children[x > 0 ? 2 : 1].Eval(es)); } case EXPR_TYPE.E_TRIANGLE: { double x = posmod(left.Eval(es), Math.PI * 2) / Math.PI; return((x < 1) ? -1 + x * 2 : 3 - x * 2); } case EXPR_TYPE.E_SAWTOOTH: { double x = posmod(left.Eval(es), Math.PI * 2) / Math.PI; return(x - 1); } case EXPR_TYPE.E_MOD: return(left.Eval(es) % right.Eval(es)); case EXPR_TYPE.E_PWL: return(pwl(es, Children)); default: if (type >= EXPR_TYPE.E_A) { return(es.Values[type - EXPR_TYPE.E_A]); } Console.WriteLine("unknown\n"); break; } return(0); }