stator
A math, geometry, and utility library
runtime.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2017 Marcus N Campbell Bannerman <[email protected]>
3 
4  This file is part of stator.
5 
6  stator is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  stator is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with stator. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #pragma once
21 
23 #include <stator/repr.hpp>
24 
25 #include <memory>
26 #include <sstream>
27 
28 
29 #ifdef STATOR_USE_BOOST_SHARED_PTR
30 # include <boost/shared_ptr.hpp>
31 namespace sym {
32  using boost::shared_ptr;
33  using boost::make_shared;
34  using boost::dynamic_pointer_cast;
35 }
36 #else
37 namespace sym {
38  using std::shared_ptr;
39  using std::make_shared;
40  using std::dynamic_pointer_cast;
41 }
42 #endif
43 
44 namespace sym {
45  class RTBase;
46  struct Expr;
47 }
48 
49 namespace stator {
50  template<class Config = DefaultReprConfig> std::string repr(const sym::RTBase&);
51  template<class Config = DefaultReprConfig> std::string repr(const sym::Expr&);
52 }
53 
54 namespace sym {
55  template<class Op> struct UnaryOp<Expr, Op>;
56  template<class Op> struct BinaryOp<Expr, Op, Expr>;
57 
59 
68  struct Expr : public shared_ptr<const RTBase>, public SymbolicOperator {
69  typedef shared_ptr<const RTBase> Base;
70 
71  Expr() {}
72  Expr(const std::shared_ptr<const RTBase>& p) : Base(p) {}
73  Expr(const char*);
74  Expr(const std::string&);
75 
76  Expr(const RTBase&);
77 
78  //Type conversion constructors from compile-time objects
79  Expr(const double&);
80 
81  template<std::intmax_t Num, std::intmax_t Denom>
82  Expr(const C<Num, Denom>& c);
83 
84  template<typename ...Args>
85  Expr(const Var<Args...> v);
86 
87  template<class Op, class Arg_t>
88  Expr(const UnaryOp<Arg_t, Op>&);
89 
90  template<class LHS_t, class Op, class RHS_t>
91  Expr(const BinaryOp<LHS_t, Op, RHS_t>&);
92 
93  Expr(const detail::NoIdentity&) { stator_throw() << "This should never be called as NoIdentity is not a usable type";}
94 
95  bool operator==(const Expr&) const;
96  bool operator!=(const Expr& o) const { return !(*this == o); }
97  bool operator==(const detail::NoIdentity&) const { return false; }
98  explicit operator bool() const { return Base::operator bool(); }
99 
100  template<class T> T as() const;
101  };
102 
103  namespace detail {
111  virtual Expr visit(const double&) = 0;
112  virtual Expr visit(const VarRT&) = 0;
113  virtual Expr visit(const UnaryOp<Expr, detail::Sine>& ) = 0;
114  virtual Expr visit(const UnaryOp<Expr, detail::Cosine>& ) = 0;
115  virtual Expr visit(const UnaryOp<Expr, detail::Log>& ) = 0;
116  virtual Expr visit(const UnaryOp<Expr, detail::Exp>& ) = 0;
117  virtual Expr visit(const UnaryOp<Expr, detail::Absolute>& ) = 0;
118  virtual Expr visit(const UnaryOp<Expr, detail::Arbsign>& ) = 0;
119  virtual Expr visit(const BinaryOp<Expr, detail::Add, Expr>& ) = 0;
120  virtual Expr visit(const BinaryOp<Expr, detail::Subtract, Expr>& ) = 0;
121  virtual Expr visit(const BinaryOp<Expr, detail::Multiply, Expr>& ) = 0;
122  virtual Expr visit(const BinaryOp<Expr, detail::Divide, Expr>& ) = 0;
123  virtual Expr visit(const BinaryOp<Expr, detail::Power, Expr>& ) = 0;
124  };
125 
126 
134  template<typename Derived>
136  inline virtual Expr visit(const double& x) { return static_cast<Derived*>(this)->apply(x); }
137  inline virtual Expr visit(const VarRT& x) { return static_cast<Derived*>(this)->apply(x); }
138 
139  inline virtual Expr visit(const UnaryOp<Expr, detail::Sine>& x)
140  { return static_cast<Derived*>(this)->apply(x); }
141  inline virtual Expr visit(const UnaryOp<Expr, detail::Cosine>& x)
142  { return static_cast<Derived*>(this)->apply(x); }
143  inline virtual Expr visit(const UnaryOp<Expr, detail::Log>& x)
144  { return static_cast<Derived*>(this)->apply(x); }
145  inline virtual Expr visit(const UnaryOp<Expr, detail::Exp>& x)
146  { return static_cast<Derived*>(this)->apply(x); }
147  inline virtual Expr visit(const UnaryOp<Expr, detail::Absolute>& x)
148  { return static_cast<Derived*>(this)->apply(x); }
149  inline virtual Expr visit(const UnaryOp<Expr, detail::Arbsign>& x)
150  { return static_cast<Derived*>(this)->apply(x); }
152  { return static_cast<Derived*>(this)->apply(x); }
154  { return static_cast<Derived*>(this)->apply(x); }
156  { return static_cast<Derived*>(this)->apply(x); }
158  { return static_cast<Derived*>(this)->apply(x); }
160  { return static_cast<Derived*>(this)->apply(x); }
161  };
162  }
163 
171  class RTBase : public SymbolicOperator, public std::enable_shared_from_this<RTBase> {
172  public:
173  inline virtual ~RTBase() {}
174 
175  virtual Expr clone() const = 0;
176 
177  virtual bool operator==(const Expr o) const = 0;
178 
179  virtual Expr visit(detail::VisitorInterface& c) const = 0;
180  };
181 
185  template<class Derived>
186  class RTBaseHelper : public RTBase {
187  public:
188  Expr clone() const {
189  return Expr(std::make_shared<Derived>(static_cast<const Derived&>(*this)));
190  }
191 
192  bool operator==(const Expr o) const {
193  auto other = dynamic_pointer_cast<const Derived>(o);
194  if (!other)
195  return false;
196  return *static_cast<const Derived*>(this) == *other;
197  }
198  };
199 
201  template<>
202  class Var<Dynamic> : public RTBaseHelper<Var<Dynamic> >, public Dynamic {
203  public:
204  inline Var(const char v) : idx(v) {}
205 
206  template<typename ...Args>
207  Var(const Var<Args...> v):
208  idx(Var<Args...>::idx)
209  {}
210 
211  inline bool operator==(const VarRT& o) const {
212  return idx == o.idx;
213  }
214 
215  inline Relation<VarRT, Expr> operator=(const Expr& f) const {
216  return Relation<VarRT, Expr>(*this, f);
217  }
218 
219  inline char getidx() const { return idx; }
220 
221  char idx;
222 
223  inline Expr visit(detail::VisitorInterface& c) const;
224  };
225 
232  template<class ...Args1, class ...Args2,
233  typename = typename std::enable_if<std::is_base_of<Dynamic, Var<Args1...> >::value || std::is_base_of<Dynamic, Var<Args2...> >::value>::type >
235  return Expr(v1.getidx() == v2.getidx());
236  }
237 
238 
239  template<typename T>
241  public:
242  ConstantRT(const T& v): _val(v) {}
243 
244  bool operator==(const Expr o) const;
245 
246  Expr visit(detail::VisitorInterface& c) const;
247 
248  const T& get() const { return _val; }
249 
250  private:
251  T _val;
252  };
253 
254  namespace detail {
255  template<class LHS_t>
256  class CompareConstantsVisitor : public VisitorHelper<CompareConstantsVisitor<LHS_t> > {
257  public:
258  CompareConstantsVisitor(const LHS_t& l) : _l(l), _value(false) {}
259 
260  template<class T> Expr apply(const T& rhs) {
261  return worker(rhs, detail::select_overload{});
262  }
263 
264  //This implementation is available whenever the two types have a comparison operator defined
265  template<class T>
266  auto worker(const T& rhs, detail::choice<0>) -> decltype(LHS_t() == rhs, Expr())
267  {
268  _value = _l == rhs;
269  return Expr();
270  }
271 
272  //If they don't have a comparison operator defined, we assume
273  //they are not comparable
274  template<class T>
276  { return Expr(); }
277 
278  const LHS_t& _l;
279  bool _value;
280  };
281  }
282 
283  template<class T>
284  bool ConstantRT<T>::operator==(const Expr o) const {
286  o->visit(visitor);
287  return visitor._value;
288  }
289 
290 
294  template<typename Op>
295  struct UnaryOp<Expr,Op> : public RTBaseHelper<UnaryOp<Expr,Op> >, public Dynamic {
296  UnaryOp(const Expr& arg): _arg(arg) {}
297 
298  Expr clone() const {
299  return Expr(std::make_shared<UnaryOp>(_arg->clone()));
300  }
301 
302  bool operator==(const UnaryOp<Expr,Op>& o) const {
303  return (_arg == o._arg);
304  }
305 
306  Expr getArg() const {
307  return _arg;
308  }
309 
310  Expr visit(detail::VisitorInterface& c) const;
311 
313  };
314 
317  template<typename Op>
318  struct BinaryOp<Expr, Op, Expr> : public RTBaseHelper<BinaryOp<Expr, Op, Expr> >, public Dynamic {
319  BinaryOp(const Expr& lhs, const Expr& rhs): _l(lhs), _r(rhs) {}
320 
321  Expr clone() const {
322  return Expr(std::make_shared<BinaryOp>(_l->clone(), _r->clone()));
323  }
324 
325  bool operator==(const BinaryOp& o) const {
326  return (_l == o._l) && (_r == o._r);
327  }
328 
329  Expr getLHS() const {
330  return _l;
331  }
332 
333  Expr getRHS() const {
334  return _r;
335  }
336 
337  Expr visit(detail::VisitorInterface& c) const;
338 
341  };
342 
343  inline Expr::Expr(const RTBase& v) : Base(v.clone()) {}
344 
345  inline Expr::Expr(const double& v) : Base(std::make_shared<ConstantRT<double> >(v)) {}
346 
347  template<std::intmax_t Num, std::intmax_t Denom>
348  Expr::Expr(const C<Num, Denom>& c) : Base(std::make_shared<ConstantRT<double> >(double(Num) / Denom)) {}
349 
350  template<class Op, class Arg_t>
351  Expr::Expr(const UnaryOp<Arg_t, Op>& op) : Expr(std::make_shared<UnaryOp<Expr, Op> >(op._arg)) {}
352 
353  template<class LHS_t, class Op, class RHS_t>
354  Expr::Expr(const BinaryOp<LHS_t, Op, RHS_t>& op) : Expr(std::make_shared<BinaryOp<Expr, Op, Expr> >(op._l, op._r)) {}
355 
356  template<typename ...Args>
357  Expr::Expr(const Var<Args...> v) : Base(std::make_shared<VarRT>(v)) {}
358 
359  template<class T>
360  T Expr::as() const {
361  auto* ptr = dynamic_cast<const ConstantRT<T>*>(Base::get());
362  if (!ptr)
363  stator_throw() << "Invalid as<>(), expression is as follows:" << *this;
364 
365  return ptr->get();
366  }
367 
368  inline bool Expr::operator==(const Expr& e) const {
369  return (*(*this)) == e;
370  }
371 
372  template<class Op>
374 
375  template<class Op>
377 
378  template<class T>
380 
381  inline Expr Var<Dynamic>::visit(detail::VisitorInterface& c) const { return c.visit(*this); }
382 
383  namespace detail {
384  template<typename Visitor, typename LHS_t, typename Op>
385  struct DoubleDispatch2: public VisitorHelper<DoubleDispatch2<Visitor, LHS_t, Op> > {
386  DoubleDispatch2(const LHS_t& LHS, Visitor& visitor) : _LHS(LHS), _visitor(visitor) {}
387 
388  template<class RHS_t>
389  Expr apply(const RHS_t& RHS) { return _visitor.dd_visit(_LHS, RHS, Op()); }
390 
391  private:
392  const LHS_t& _LHS;
393  Visitor& _visitor;
394  };
395 
396  template<typename Visitor, typename Op>
397  struct DoubleDispatch1: public VisitorHelper<DoubleDispatch1<Visitor, Op> > {
398  DoubleDispatch1(const Expr& RHS, Visitor& visitor):
399  _RHS(RHS), _visitor(visitor) {}
400 
401  template<class LHS_t>
402  Expr apply(const LHS_t& lhs) {
403  DoubleDispatch2<Visitor, LHS_t, Op> visitor(lhs, _visitor);
404  return _RHS->visit(visitor);
405  }
406 
407  private:
408  Expr _RHS;
409  Visitor& _visitor;
410  };
411 
412  struct SimplifyRT : VisitorHelper<SimplifyRT> {
413  template<class Op>
414  struct UnaryEval : VisitorHelper<UnaryEval<Op> > {
415  Expr apply(const double& arg) { return Op::apply(arg); }
416  template<class T> Expr apply(const T& arg) { return Expr(); }
417  };
418 
419  //Direct evaluation of doubles
420  template<class T1, class T2, class Op>
421  Expr dd_visit(const T1& l, const T2& r, Op) {
422  if (IsSymbolic<decltype(store(Op::apply(l, r)))>::value)
423  return Expr();
424  return Expr(store(Op::apply(l, r)));
425  }
426 
427  //Direct evaluation of doubles
428  template<class T2>
429  Expr dd_visit(const double& l, const T2& r, detail::Subtract) {
430  if (l == 0)
431  return Expr(-r);
432 
433  if (IsSymbolic<decltype(store(detail::Subtract::apply(l, r)))>::value)
434  return Expr();
435  return Expr(store(detail::Subtract::apply(l, r)));
436  }
437 
438  //Direct evaluation of doubles
440  if (dynamic_cast<const ConstantRT<double>*>(r.getLHS().get()))
441  return Expr(BinaryOp<Expr, detail::Multiply, Expr>(l * static_cast<const ConstantRT<double>*>(r.getLHS().get())->get(), r.getRHS()));
442 
443  if (dynamic_cast<const ConstantRT<double>*>(r.getRHS().get()))
444  return Expr(BinaryOp<Expr, detail::Multiply, Expr>(l * static_cast<const ConstantRT<double>*>(r.getRHS().get())->get(), r.getLHS()));
445  return Expr();
446  }
447 
449  if (dynamic_cast<const ConstantRT<double>*>(r.getLHS().get()))
450  return Expr(BinaryOp<Expr, detail::Multiply, Expr>(l * static_cast<const ConstantRT<double>*>(r.getLHS().get())->get(), r.getRHS()));
451 
452  if (dynamic_cast<const ConstantRT<double>*>(r.getRHS().get()))
453  return Expr(BinaryOp<Expr, detail::Multiply, Expr>(l * static_cast<const ConstantRT<double>*>(r.getRHS().get())->get(), r.getLHS()));
454  return Expr();
455  }
456 
457  //By default return the blank (use
458  template<class T>
459  Expr apply(const T& v) {
460  return Expr();
461  }
462 
463  template<typename Op>
465  //Simplify the argument
466  Expr arg = op.getArg()->visit(*this);
467  //Try evaluating the unary expression
468  UnaryEval<Op> visitor;
469  Expr ret = (arg ? arg : op.getArg())->visit(visitor);
470  if (ret)
471  return ret;
472  if (arg)
473  return Expr(std::make_shared<UnaryOp<Expr, Op> >(arg));
474  return Expr();
475  }
476 
477  //For binary operators, try to collapse them
478  template<typename Op>
480  Expr l = op.getLHS()->visit(*this);
481  bool lchanged = !!l;
482  if (!l) l = op._l;
483 
484  Expr r = op.getRHS()->visit(*this);
485  bool rchanged = !!r;
486  if (!r) r = op._r;
487 
488  if (l == typename Op::left_zero())
489  return typename Op::left_zero();
490  if (l == typename Op::left_identity())
491  return r;
492  if (r == typename Op::right_zero())
493  return typename Op::right_zero();
494  if (r == typename Op::right_identity())
495  return l;
496 
497  //Try direct simplification via application
498  DoubleDispatch1<SimplifyRT, Op> visitor(r, *this);
499  Expr ret = l->visit(visitor);
500  if (ret)
501  return ret;
502 
503  if (lchanged || rchanged)
504  return Expr(std::make_shared<BinaryOp<Expr, Op, Expr> >(l, r));
505 
506  return Expr();
507  }
508  };
509  }
510 
511  inline Expr simplify(const Expr& f) {
512  detail::SimplifyRT visitor;
513  Expr result = f->visit(visitor);
514  return result ? result : f;
515  }
516 
517  namespace detail {
518  struct SubstituteRT : VisitorHelper<SubstituteRT> {
519  SubstituteRT(VarRT var, Expr replacement): _var(var), _replacement(replacement) {}
520 
521  //By default, just return an empty Expr, and let the helper function return the original expression
522  template<class T>
523  Expr apply(const T& v)
524  { return Expr(); }
525 
526  //Variable matching
527  Expr apply(const VarRT& v) {
528  if (v == _var)
529  return _replacement;
530  return Expr();
531  }
532 
533  template<typename Op>
535  Expr arg = op.getArg()->visit(*this);
536  return arg ? Expr(Op::apply(arg)) : op.shared_from_this();
537  }
538 
539  template<typename Op>
541  Expr l = op.getLHS()->visit(*this);
542  Expr r = op.getRHS()->visit(*this);
543 
544  if (l || r)
545  return Expr(Op::apply(l ? l : op._l, r ? r : op._r));
546  else
547  return Expr();
548  }
549 
550  VarRT _var;
552  };
553  }
554 
555  template<class Var, class Arg>
556  Expr sub(const Expr& f, const Relation<Var, Arg>& rel) {
557  detail::SubstituteRT visitor(rel._var, rel._val);
558  Expr result = f->visit(visitor);
559  return (result) ? result : f;
560  }
561 
562  namespace detail {
563  struct DerivativeRT : VisitorHelper<DerivativeRT> {
564  DerivativeRT(VarRT var): _var(var) {}
565 
566  //The commented out code here is a double dispatch
567  //implementation of derivatives; however, it has a huge compile
568  //time cost.
569 
570 
572  // implementation for unary operators.
573  //
574  // This visitor is used to determine the type of the argument.
575  //*/
576  //template<class Op>
577  //struct UnaryEval : VisitorHelper<UnaryEval<Op> > {
578  // UnaryEval(VarRT var): _var(var) {}
579  // template<class T> Expr apply(const T& arg) { return derivative(Op::apply(arg), _var); }
580  // VarRT _var;
581  //};
582  //
584  //template<class Op, class LHS_t, class RHS_t>
585  //Expr dd_visit(const LHS_t& l, const RHS_t& r) {
586  // auto e = Op::apply(l, r);
587  // return derivative(e, _var);
588  //}
589 
590  template<class T, typename = typename std::enable_if<IsConstant<T>::value>::type>
591  Expr apply(const T& v) {
592  return ConstantRT<double>(0);
593  }
594 
595  Expr apply(const VarRT& v) {
596  return Expr((v == _var) ? 1 : 0);
597  }
598 
599  template<class Op>
601  return derivative(v, _var);
602  //UnaryEval<Op> visitor(_var);
603  //return v.getArg()->visit(visitor);
604  }
605 
606  template<typename Op>
608  //DoubleDispatch1<DerivativeRT, Op> visitor(op.getRHS(), *this);
609  //return op.getLHS()->visit(visitor);
610  return derivative(op,_var);
611  }
612 
613  VarRT _var;
614  };
615  }
616 
617  template<class Var>
618  Expr derivative(const Expr& f, const Var v) {
619  detail::DerivativeRT visitor(v);
620  return f->visit(visitor);
621  }
622 
623  namespace detail {
624  struct IsConstantVisitor: public VisitorHelper<IsConstantVisitor> {
625  template<class T>
626  Expr apply(const T& a) {
627  _value = IsConstant<T>::value;
628  return Expr();
629  }
630 
631  template<class Op>
633  //If the argument is constant, then so is this
634  a.getArg()->visit(*this);
635  return Expr();
636  }
637 
638  template<class Op>
640  //If the two arguments are constant, then so is this.
641  o.getLHS()->visit(*this);
642  //If the LHS is constant, then check the RHS
643  if (_value) o.getRHS()->visit(*this);
644  return Expr();
645  }
646 
647  bool _value = false;
648  };
649  }
650 
651  bool is_constant(const Expr& a) {
653  a->visit(visitor);
654  return visitor._value;
655  }
656 
657  namespace detail {
658  struct FastSubRT : VisitorHelper<FastSubRT> {
659  FastSubRT(VarRT var, double replacement): _var(var), _replacement(replacement) {}
660 
661  //By default, throw an exception!
662  template<class T>
663  Expr apply(const T& v) { stator_throw() << "fast_sub cannot operate on this (" << stator::repr(v) << ") expression"; }
664 
665  Expr apply(const double& v) {
666  _intermediate = v;
667  return Expr();
668  }
669 
670  //Variable matching
671  Expr apply(const VarRT& v) {
672  if (v == _var) {
673  _intermediate = _replacement;
674  return Expr();
675  }
676  stator_throw() << "Unexpected variable " << stator::repr(v) << " for fast_sub";
677  }
678 
679  template<typename Op>
680  auto apply(const UnaryOp<Expr, Op>& op) -> decltype(double(Op::apply(0.0)), Expr()) {
681  op.getArg()->visit(*this);
682  _intermediate = Op::apply(_intermediate);
683  return Expr();
684  }
685 
686  template<typename Op>
688  op.getLHS()->visit(*this);
689  double lval = _intermediate;
690  op.getRHS()->visit(*this);
691  _intermediate = Op::apply(lval, _intermediate);
692  return Expr();
693  }
694 
695  VarRT _var;
696  double _replacement;
698  };
699  }
700 
701  template<class Var>
702  double fast_sub(const Expr& f, const Relation<Var, double>& rel) {
703  detail::FastSubRT visitor(rel._var, rel._val);
704  f->visit(visitor);
705  return visitor._intermediate;
706  }
707 }
Var(const char v)
Definition: runtime.hpp:204
T as() const
Definition: runtime.hpp:360
bool operator==(const UnaryOp< Expr, Op > &o) const
Definition: runtime.hpp:302
const Arg & _val
Definition: symbolic.hpp:80
Expr apply(const VarRT &v)
Definition: runtime.hpp:595
bool operator==(const Expr o) const
Definition: runtime.hpp:192
DoubleDispatch2(const LHS_t &LHS, Visitor &visitor)
Definition: runtime.hpp:386
Expr apply(const BinaryOp< Expr, Op, Expr > &op)
Definition: runtime.hpp:479
A CRTP helper base class which transforms the visitor interface into a call to the derived classes ap...
Definition: runtime.hpp:135
auto apply(const UnaryOp< Expr, Op > &op) -> decltype(double(Op::apply(0.0)), Expr())
Definition: runtime.hpp:680
virtual Expr visit(const UnaryOp< Expr, detail::Exp > &x)
Definition: runtime.hpp:145
A class which recursively inherits from itself to allow ambiguous function definition ordering...
Definition: config.hpp:65
virtual Expr visit(const double &)=0
bool is_constant(const Expr &a)
Definition: runtime.hpp:651
Symbolic representation of a variable.
Definition: symbolic.hpp:94
char getidx() const
Definition: runtime.hpp:219
detail::C_wrap< stator::constant_ratio::e >::type e
A symbolic/compile-time rational approximation of .
Definition: constants.hpp:59
virtual Expr visit(const BinaryOp< Expr, detail::Power, Expr > &x)
Definition: runtime.hpp:159
bool operator==(const Expr o) const
Definition: runtime.hpp:284
Expr apply(const UnaryOp< Expr, Op > &op)
Definition: runtime.hpp:464
Expr apply(const T &v)
Definition: runtime.hpp:663
bool operator==(const Expr &) const
Definition: runtime.hpp:368
virtual Expr visit(const BinaryOp< Expr, detail::Add, Expr > &x)
Definition: runtime.hpp:151
DoubleDispatch1(const Expr &RHS, Visitor &visitor)
Definition: runtime.hpp:398
Abstract interface class for all runtime symbolic classes.
Definition: runtime.hpp:171
constexpr bool operator==(const C< n1, d1 > &, const C< n2, d2 > &)
Definition: constants.hpp:121
static auto apply(const L &l, const R &r) -> STATOR_AUTORETURN(l - r)
Expr dd_visit(const T1 &l, const T2 &r, Op)
Definition: runtime.hpp:421
Expr apply(const LHS_t &lhs)
Definition: runtime.hpp:402
UnaryOp(const Expr &arg)
Definition: runtime.hpp:296
Expr apply(const double &arg)
Definition: runtime.hpp:415
std::enable_if< std::is_integral< T >::value, std::string >::type repr(T a)
Definition: repr.hpp:111
f _r
Definition: simplify.hpp:337
CompareConstantsVisitor(const LHS_t &l)
Definition: runtime.hpp:258
A class representing a compile-time rational constant (i.e., std::ratio).
Definition: constants.hpp:31
double fast_sub(const Expr &f, const Relation< Var, double > &rel)
Definition: runtime.hpp:702
Main header for the stator::symbolic library.
Specialisation of Var for runtime variables.
Definition: runtime.hpp:202
Expr visit(detail::VisitorInterface &c) const
Definition: runtime.hpp:379
Expr apply(const RHS_t &RHS)
Definition: runtime.hpp:389
Expr clone() const
Definition: runtime.hpp:188
Expr apply(const double &v)
Definition: runtime.hpp:665
Template argument for dynamic types, as well as their base class.
Definition: symbolic.hpp:66
Relation< VarRT, Expr > operator=(const Expr &f) const
Definition: runtime.hpp:215
Specialisation of BinaryOp for runtime arguments (Expr).
Definition: runtime.hpp:318
Symbolic representation of a binary symbolic operation.
Definition: binary_ops.hpp:33
SubstituteRT(VarRT var, Expr replacement)
Definition: runtime.hpp:519
Expr simplify(const Expr &f)
Definition: runtime.hpp:511
char getidx() const
Definition: symbolic.hpp:102
Expr apply(const T &v)
Definition: runtime.hpp:459
Symbolic representation of a variable substitution.
Definition: symbolic.hpp:76
Expr apply(const UnaryOp< Expr, Op > &op)
Definition: runtime.hpp:534
The generic holder/smart pointer for a runtime Abstract Syntax Tree (AST) (expression).
Definition: runtime.hpp:68
Var(const Var< Args... > v)
Definition: runtime.hpp:207
FastSubRT(VarRT var, double replacement)
Definition: runtime.hpp:659
BinaryOp(const Expr &lhs, const Expr &rhs)
Definition: runtime.hpp:319
virtual Expr visit(const UnaryOp< Expr, detail::Arbsign > &x)
Definition: runtime.hpp:149
Expr(const detail::NoIdentity &)
Definition: runtime.hpp:93
bool operator!=(const Expr &o) const
Definition: runtime.hpp:96
The stator symbolic math library.
Expr apply(const BinaryOp< Expr, Op, Expr > &op)
Definition: runtime.hpp:607
Expr dd_visit(const BinaryOp< Expr, detail::Multiply, Expr > &r, const double &l, detail::Multiply)
Definition: runtime.hpp:448
virtual Expr visit(const BinaryOp< Expr, detail::Divide, Expr > &x)
Definition: runtime.hpp:157
bool operator==(const BinaryOp &o) const
Definition: runtime.hpp:325
Expr apply(const BinaryOp< Expr, Op, Expr > &op)
Definition: runtime.hpp:540
Expr apply(const UnaryOp< Expr, Op > &v)
Definition: runtime.hpp:600
virtual ~RTBase()
Definition: runtime.hpp:173
virtual Expr visit(const BinaryOp< Expr, detail::Multiply, Expr > &x)
Definition: runtime.hpp:155
Expr dd_visit(const double &l, const BinaryOp< Expr, detail::Multiply, Expr > &r, detail::Multiply)
Definition: runtime.hpp:439
virtual Expr visit(const VarRT &x)
Definition: runtime.hpp:137
bool operator==(const VarRT &o) const
Definition: runtime.hpp:211
virtual Expr visit(const double &x)
Definition: runtime.hpp:136
Abstract interface class for the visitor programming pattern for Expr types.
Definition: runtime.hpp:110
Expr apply(const BinaryOp< Expr, Op, Expr > &o)
Definition: runtime.hpp:639
virtual Expr visit(const UnaryOp< Expr, detail::Cosine > &x)
Definition: runtime.hpp:141
Expr apply(const BinaryOp< Expr, Op, Expr > &op)
Definition: runtime.hpp:687
const RHS _r
Definition: binary_ops.hpp:35
Expr apply(const VarRT &v)
Definition: runtime.hpp:671
CRTP helper base class which implements some of the common boilerplate code for runtime symbolic type...
Definition: runtime.hpp:186
virtual Expr visit(const UnaryOp< Expr, detail::Sine > &x)
Definition: runtime.hpp:139
Expr dd_visit(const double &l, const T2 &r, detail::Subtract)
Definition: runtime.hpp:429
auto sub(BinaryOp< LHS, Op, RHS > f, Relation< Var, Arg > x) -> STATOR_AUTORETURN_BYVALUE(Op::apply(sub(f._l, x), sub(f._r, x)))
Expr apply(const UnaryOp< Expr, Op > &a)
Definition: runtime.hpp:632
Expr worker(const T &rhs, detail::choice< 1 >)
Definition: runtime.hpp:275
Expr apply(const T &v)
Visitor to allow the compile time derivative implementation for unary operators.
Definition: runtime.hpp:591
const LHS _l
Definition: binary_ops.hpp:34
Specialisation of unary operator for runtime arguments and use in runtime expressions (Expr)...
Definition: runtime.hpp:295
auto derivative(const Expression &)
Performs a symbolic derivative on the expression.
The stator library namespace.
Definition: frontpage.dox:243
virtual Expr visit(const BinaryOp< Expr, detail::Subtract, Expr > &x)
Definition: runtime.hpp:153
#define stator_throw()
Definition: exception.hpp:26
A type trait to denote symbolic terms (i.e., one that is not yet immediately evaluable to a "normal" ...
Definition: symbolic.hpp:50
const Var _var
Definition: symbolic.hpp:79
Var< Dynamic > VarRT
Definition: runtime.hpp:58
ConstantRT(const T &v)
Definition: runtime.hpp:242
Type trait to determine if a certain type is a constant.
Definition: symbolic.hpp:132
shared_ptr< const RTBase > Base
Definition: runtime.hpp:69
Symbolic representation of a unary operator (i.e., sin(x)).
Definition: unary_ops.hpp:30
A class used to start the ambiguous function definition ordering calculation.
Definition: config.hpp:76
virtual Expr visit(const UnaryOp< Expr, detail::Log > &x)
Definition: runtime.hpp:143
bool operator==(const detail::NoIdentity &) const
Definition: runtime.hpp:97
Expr apply(const VarRT &v)
Definition: runtime.hpp:527
Expr apply(const T &v)
Definition: runtime.hpp:523
Expr(const std::shared_ptr< const RTBase > &p)
Definition: runtime.hpp:72
virtual Expr visit(const UnaryOp< Expr, detail::Absolute > &x)
Definition: runtime.hpp:147
auto store(const T &val) -> decltype(store_impl(val, select_overload
Definition: config.hpp:94
auto worker(const T &rhs, detail::choice< 0 >) -> decltype(LHS_t()==rhs, Expr())
Definition: runtime.hpp:266