4#include "fmatvec/function.h"
8#include <boost/uuid/uuid.hpp>
9#include <boost/uuid/uuid_generators.hpp>
10#include <boost/container/small_vector.hpp>
12#include <fmatvec/stream.h>
15FMATVEC_MSVC_DISABLEW4251_BEGIN
19class IndependentVariable;
26 template<
class T>
class Constant;
27 FMATVEC_EXPORT SymbolicExpression substScalar(
const SymbolicExpression &se,
const IndependentVariable& a,
const SymbolicExpression &b);
30template<
class... Arg>
class Eval;
39 template<
class... Arg>
friend class Eval;
40 friend class EvalHelper;
51 static const struct ConstructSymbol{} constructSymbol;
73 static void garbageCollect();
100#if defined(FMATVEC_DEBUG) && !defined(SWIG)
101 static signed long evalOperationsCount;
210 static constexpr size_t N { 12 };
217 using Arg = boost::container::small_vector<double*,N>;
218 std::function<void(
double*,
const Arg&)> func;
224template<
class Func,
class ArgS>
245template<
class Func,
class Arg1S,
class Arg2S>
249 const Arg1S &arg1,
const Arg2S &arg2);
273template<
class Type1,
class Type2>
292 inline virtual bool isConstantInt()
const;
300 virtual std::vector<ByteCode>::iterator dumpByteCode(std::vector<ByteCode> &byteCode,
301 std::map<
const Vertex*, std::vector<AST::ByteCode>::iterator> &existingVertex)
const=0;
320 return a.std::shared_ptr<const AST::Vertex>::get() < b.std::shared_ptr<const AST::Vertex>::get();
323 using MapIVSE = std::map<IndependentVariable, SymbolicExpression, LessIV>;
335class FMATVEC_EXPORT
Constant :
public Vertex,
public std::enable_shared_from_this<Constant<T>> {
343 inline const T& getValue()
const;
344 std::vector<ByteCode>::iterator dumpByteCode(std::vector<ByteCode> &byteCode,
345 std::map<
const Vertex*, std::vector<AST::ByteCode>::iterator> &existingVertex)
const override;
355 static std::map<CacheKey, std::weak_ptr<const Constant>> cache;
376class FMATVEC_EXPORT
Symbol :
public Vertex,
public std::enable_shared_from_this<Symbol> {
381 static IndependentVariable create(
const boost::uuids::uuid& uuid_=boost::uuids::random_generator()());
385 inline void setValue(
double x_)
const;
387 std::string getUUIDStr()
const;
389 std::vector<ByteCode>::iterator dumpByteCode(std::vector<ByteCode> &byteCode,
390 std::map<
const Vertex*, std::vector<AST::ByteCode>::iterator> &existingVertex)
const override;
396 Symbol(
const boost::uuids::uuid& uuid_);
398 mutable double x = 0.0;
399 boost::uuids::uuid uuid;
400 using CacheKey = boost::uuids::uuid;
401 static std::map<CacheKey, std::weak_ptr<const Symbol>> cache;
413 virtual double operator()(
const ByteCode::Arg &arg) = 0;
414 virtual double dirDer(
const ByteCode::Arg &arg) = 0;
415 virtual double dirDerDirDer(
const ByteCode::Arg &arg) = 0;
421 double operator()(
const ByteCode::Arg &arg)
override {
422 return (*func)(*arg[0]);
424 double dirDer(
const ByteCode::Arg &arg)
override {
425 return func->dirDer(*arg[1], *arg[0]);
427 double dirDerDirDer(
const ByteCode::Arg &arg)
override {
428 return func->dirDerDirDer(*arg[1], *arg[2], *arg[0]);
438 argV.resize(argSize);
439 dir1V.resize(argSize);
440 dir2V.resize(argSize);
442 double operator()(
const ByteCode::Arg &arg)
override {
443 for(
size_t i=0; i<argV.size(); ++i)
445 return (*func)(argV);
447 double dirDer(
const ByteCode::Arg &arg)
override {
448 size_t argVsize=argV.size();
449 for(
size_t i=0; i<argVsize; ++i)
451 for(
size_t i=0; i<argVsize; ++i)
452 dir1V(i) = *arg[i+argVsize];
453 return func->dirDer(dir1V, argV);
455 double dirDerDirDer(
const ByteCode::Arg &arg)
override {
456 size_t argVsize=argV.size();
457 for(
size_t i=0; i<argVsize; ++i)
459 for(
size_t i=0; i<argVsize; ++i)
460 dir1V(i) = *arg[i+argVsize];
461 for(
size_t i=0; i<argVsize; ++i)
462 dir2V(i) = *arg[i+2*argVsize];
463 return func->dirDerDirDer(dir1V, dir2V, argV);
475 double operator()(
const ByteCode::Arg &arg)
override {
476 return (*func)(*arg[0], *arg[1]);
478 double dirDer(
const ByteCode::Arg &arg)
override {
479 return func->dirDer1(*arg[2], *arg[0], *arg[1]) +
480 func->dirDer2(*arg[3], *arg[0], *arg[1]);
482 double dirDerDirDer(
const ByteCode::Arg &arg)
override {
483 return func->dirDer1DirDer1(*arg[2], *arg[4], *arg[0], *arg[1]) +
484 func->dirDer2DirDer1(*arg[5], *arg[2], *arg[0], *arg[1]) +
485 func->dirDer2DirDer1(*arg[3], *arg[4], *arg[0], *arg[1]) +
486 func->dirDer2DirDer2(*arg[3], *arg[5], *arg[0], *arg[1]);
496 argV.resize(argSize);
497 dir1V.resize(argSize);
498 dir2V.resize(argSize);
500 double operator()(
const ByteCode::Arg &arg)
override {
501 for(
size_t i=0; i<argV.size(); ++i)
503 return (*func)(argV, *arg[argV.size()]);
505 double dirDer(
const ByteCode::Arg &arg)
override {
506 auto argVsize=argV.size();
507 for(
size_t i=0; i<argVsize; ++i)
509 for(
size_t i=0; i<argVsize; ++i)
510 dir1V(i) = *arg[i+1+argVsize];
511 return func->dirDer1(dir1V , argV, *arg[argVsize]) +
512 func->dirDer2(*arg[2*argVsize+1], argV, *arg[argVsize]);
514 double dirDerDirDer(
const ByteCode::Arg &arg)
override {
515 auto argVsize=argV.size();
516 for(
size_t i=0; i<argVsize; ++i)
518 for(
size_t i=0; i<argVsize; ++i)
519 dir1V(i) = *arg[i+1+argVsize];
520 for(
size_t i=0; i<argVsize; ++i)
521 dir2V(i) = *arg[i+2+2*argVsize];
522 return func->dirDer1DirDer1(dir1V, dir2V, argV, *arg[argVsize]) +
523 func->dirDer2DirDer1(*arg[1+2*argVsize], dir2V , argV, *arg[argVsize]) +
524 func->dirDer2DirDer1(*arg[2+3*argVsize], dir1V , argV, *arg[argVsize]) +
525 func->dirDer2DirDer2(*arg[1+2*argVsize], *arg[2+3*argVsize], argV, *arg[argVsize]);
538 argV.resize(argSize);
539 dir1V.resize(argSize);
540 dir2V.resize(argSize);
542 double operator()(
const ByteCode::Arg &arg)
override {
543 for(
size_t i=0; i<argV.size(); ++i)
545 return (*func)(*arg[0], argV);
547 double dirDer(
const ByteCode::Arg &arg)
override {
548 auto argVsize=argV.size();
549 for(
size_t i=0; i<argVsize; ++i)
551 for(
size_t i=0; i<argVsize; ++i)
552 dir1V(i) = *arg[i+2+argVsize];
553 return func->dirDer1(*arg[argVsize+1], *arg[0], argV) +
554 func->dirDer2(dir1V , *arg[0], argV);
556 double dirDerDirDer(
const ByteCode::Arg &arg)
override {
557 auto argVsize=argV.size();
558 for(
size_t i=0; i<argVsize; ++i)
560 for(
size_t i=0; i<argVsize; ++i)
561 dir1V(i) = *arg[i+2+argVsize];
562 for(
size_t i=0; i<argVsize; ++i)
563 dir2V(i) = *arg[i+3+2*argVsize];
564 return func->dirDer1DirDer1(*arg[argVsize+1], *arg[2*argVsize+2], *arg[0], argV) +
565 func->dirDer2DirDer1(dir2V , *arg[argVsize+1] , *arg[0], argV) +
566 func->dirDer2DirDer1(dir1V , *arg[2*argVsize+2], *arg[0], argV) +
567 func->dirDer2DirDer2(dir1V , dir2V , *arg[0], argV);
576template<
class Type1,
class Type2>
580 int argaSize,
int argbSize) : func(func_) {
581 argV1.resize(argaSize);
582 argV2.resize(argbSize);
583 dir1V1.resize(argaSize);
584 dir1V2.resize(argbSize);
585 dir2V1.resize(argaSize);
586 dir2V2.resize(argbSize);
588 double operator()(
const ByteCode::Arg &arg)
override {
589 auto argV1size = argV1.size();
590 auto argV2size = argV2.size();
591 for(
int i=0; i<argV1size; ++i)
593 for(
int i=0; i<argV2size; ++i)
594 argV2(i)=*arg[argV1size+i];
595 return (*func)(argV1, argV2);
597 double dirDer(
const ByteCode::Arg &arg)
override {
598 auto argV1size = argV1.size();
599 auto argV2size = argV2.size();
600 for(
int i=0; i<argV1size; ++i)
602 for(
int i=0; i<argV2size; ++i)
603 argV2(i)=*arg[argV1size+i];
604 for(
size_t i=0; i<argV1size; ++i)
605 dir1V1(i) = *arg[argV1size+argV2size+i];
606 for(
size_t i=0; i<argV2size; ++i)
607 dir1V2(i) = *arg[2*argV1size+argV2size+i];
608 return func->dirDer1(dir1V1, argV1, argV2) +
609 func->dirDer2(dir1V2, argV1, argV2);
611 double dirDerDirDer(
const ByteCode::Arg &arg)
override {
612 auto argV1size = argV1.size();
613 auto argV2size = argV2.size();
614 for(
int i=0; i<argV1size; ++i)
616 for(
int i=0; i<argV2size; ++i)
617 argV2(i)=*arg[argV1size+i];
618 for(
size_t i=0; i<argV1size; ++i)
619 dir1V1(i) = *arg[argV1size+argV2size+i];
620 for(
size_t i=0; i<argV2size; ++i)
621 dir1V2(i) = *arg[2*argV1size+argV2size+i];
622 for(
size_t i=0; i<argV1size; ++i)
623 dir2V1(i) = *arg[2*argV1size+2*argV2size+i];
624 for(
size_t i=0; i<argV2size; ++i)
625 dir2V2(i) = *arg[3*argV1size+2*argV2size+i];
626 return func->dirDer1DirDer1(dir1V1, dir2V1, argV1, argV2) +
627 func->dirDer2DirDer1(dir2V2, dir1V1, argV1, argV2) +
628 func->dirDer2DirDer1(dir1V2, dir2V1, argV1, argV2) +
629 func->dirDer2DirDer2(dir1V2, dir2V2, argV1, argV2);
647 const std::vector<SymbolicExpression> &argS,
648 const std::vector<SymbolicExpression> &dir1S={},
649 const std::vector<SymbolicExpression> &dir2S={});
652 std::vector<ByteCode>::iterator dumpByteCode(std::vector<ByteCode> &byteCode,
654 std::vector<AST::ByteCode>::iterator> &existingVertex)
const override;
660 const std::vector<SymbolicExpression> &argS,
661 const std::vector<SymbolicExpression> &dir1S,
662 const std::vector<SymbolicExpression> &dir2S);
666 const std::vector<SymbolicExpression> argS;
667 const std::vector<SymbolicExpression> dir1S;
668 const std::vector<SymbolicExpression> dir2S;
670 using CacheKey = std::tuple<std::weak_ptr<ScalarFunctionWrapArg>,
671 std::vector<std::weak_ptr<const Vertex>>,
672 std::vector<std::weak_ptr<const Vertex>>,
673 std::vector<std::weak_ptr<const Vertex>> >;
675 bool operator()(
const CacheKey& l,
const CacheKey& r)
const;
677 std::owner_less<std::weak_ptr<const Vertex>> ol;
678 std::owner_less<std::weak_ptr<const ScalarFunctionWrapArg>> olf;
680 static std::map<CacheKey, std::weak_ptr<const NativeFunction>,
CacheKeyComp> cache;
686class FMATVEC_EXPORT
Operation :
public Vertex,
public std::enable_shared_from_this<Operation> {
691 fmatvec::getBoostSpiritQiRule<SymbolicExpression>();
693 fmatvec::getBoostSpiritKarmaRule<SymbolicExpression>();
697 enum Operator { Plus, Minus, Mult, Div, Pow, Log, Sqrt, Neg, Sin, Cos, Tan, Sinh, Cosh, Tanh, ASin, ACos, ATan, ATan2, ASinh, ACosh, ATanh, Exp, Sign, Heaviside, Abs, Min, Max, Condition };
698 static SymbolicExpression create(Operator op_,
const std::vector<SymbolicExpression> &child_);
701 Operator getOp()
const {
return op; }
702 const std::vector<SymbolicExpression>& getChilds()
const {
return child; }
703 std::vector<ByteCode>::iterator dumpByteCode(std::vector<ByteCode> &byteCode,
704 std::map<
const Vertex*, std::vector<AST::ByteCode>::iterator> &existingVertex)
const override;
710 Operation(Operator op_,
const std::vector<SymbolicExpression> &child_);
711 bool equal(
const SymbolicExpression &b, MapIVSE &m)
const override;
713 std::vector<SymbolicExpression> child;
714 using CacheKey = std::pair<Operator, std::vector<std::weak_ptr<const Vertex>>>;
716 bool operator()(
const CacheKey& l,
const CacheKey& r)
const;
718 std::owner_less<std::weak_ptr<const Vertex>> ol;
720 static std::map<CacheKey, std::weak_ptr<const Operation>,
CacheKeyComp> cache;
723 std::string funcName;
725 std::function<void(
double*,
const ByteCode::Arg&)> func;
728 static const std::map<Operator, OpMap> opMap;
734 return AST::NativeFunction::create(std::make_shared<AST::ScalarFunctionWrapArgS>(func), std::vector<SymbolicExpression>{arg});
738SymbolicExpression SymbolicFuncWrapArg1<double(Vector<Type, double>), Vector<Type, SymbolicExpression>>::call(
740 const Vector<Type, SymbolicExpression> &arg) {
741 std::vector<SymbolicExpression> argV(arg.size());
742 for(
int i=0; i<arg.size(); ++i)
744 return AST::NativeFunction::create(std::make_shared<AST::ScalarFunctionWrapArgV<Type>>(func, arg.size()), argV);
747inline SymbolicExpression SymbolicFuncWrapArg2<double(
double,
double), SymbolicExpression, SymbolicExpression>::call(
749 const SymbolicExpression &arg1,
const SymbolicExpression &arg2) {
750 return AST::NativeFunction::create(std::make_shared<AST::ScalarFunctionWrapArgSS>(func), std::vector<SymbolicExpression>{arg1,arg2});
754SymbolicExpression SymbolicFuncWrapArg2<double(Vector<Type,double>,
double), Vector<Type, SymbolicExpression>, SymbolicExpression>::call(
755 const std::shared_ptr<Function<
double(Vector<Type,double>,
double)>> &func,
756 const Vector<Type, SymbolicExpression> &arg1,
const SymbolicExpression &arg2) {
757 std::vector<SymbolicExpression> arg(arg1.size()+1);
758 for(
int i=0; i<arg1.size(); ++i)
760 arg[arg1.size()]=arg2;
761 return AST::NativeFunction::create(std::make_shared<AST::ScalarFunctionWrapArgVS<Type>>(func, arg1.size()), arg);
765SymbolicExpression SymbolicFuncWrapArg2<double(
double,Vector<Type,double>), SymbolicExpression, Vector<Type, SymbolicExpression>>::call(
766 const std::shared_ptr<Function<
double(
double,Vector<Type,double>)>> &func,
767 const SymbolicExpression &arg1,
const Vector<Type, SymbolicExpression> &arg2) {
768 std::vector<SymbolicExpression> arg(1+arg2.size());
770 for(
int i=0; i<arg2.size(); ++i)
772 return AST::NativeFunction::create(std::make_shared<AST::ScalarFunctionWrapArgSV<Type>>(func, arg2.size()), arg);
775template<
class Type1,
class Type2>
776SymbolicExpression SymbolicFuncWrapArg2<double(Vector<Type1,double>,Vector<Type2,double>), Vector<Type1, SymbolicExpression>, Vector<Type2, SymbolicExpression>>::call(
777 const std::shared_ptr<Function<
double(Vector<Type1,double>,Vector<Type2,double>)>> &func,
778 const Vector<Type1, SymbolicExpression> &arg1,
const Vector<Type2, SymbolicExpression> &arg2) {
779 std::vector<SymbolicExpression> arg(arg1.size()+arg2.size());
780 for(
int i=0; i<arg1.size(); ++i)
782 for(
int i=0; i<arg2.size(); ++i)
783 arg[arg1.size()+i]=arg2(i);
784 return AST::NativeFunction::create(std::make_shared<AST::ScalarFunctionWrapArgVV<Type1,Type2>>(func, arg1.size(), arg2.size()), arg);
792 std::cerr<<
"ABORT: See LessIV: have you called std::min/max instead of fmatvev::min/max with type SymbolicExpression?"<<std::endl;
793 assert(((
void)
"See LessIV: have you called std::min/max instead of fmatvev::min/max with type SymbolicExpression?",
false));
798 static_cast<const AST::Symbol*
>(get())->setValue(x);
805template<> boost::spirit::karma::rule<std::ostream_iterator<char>,
IndependentVariable()>& getBoostSpiritKarmaRule<IndependentVariable>();
806template<> boost::spirit::karma::rule<std::ostream_iterator<char>,
SymbolicExpression()>& getBoostSpiritKarmaRule<SymbolicExpression>();
815FMATVEC_MSVC_DISABLEW4251_END
A vertex of the AST representing a constant (long or double)
Definition: ast.h:335
bool isConstantInt() const override
Rreturn true if this Vertex is a constant integer.
const T & getValue() const
Get the constant value of the vertex.
Definition: ast.h:369
A vertex of the AST representing an arbitary function.
Definition: ast.h:644
A vertex of the AST representing an operation.
Definition: ast.h:686
Operator
Defined operations.
Definition: ast.h:697
A vertex of the AST representing a independent variable.
Definition: ast.h:376
void setValue(double x_) const
Definition: ast.h:404
A abstract class for a Vertex of the AST (abstract syntax tree).
Definition: ast.h:283
virtual SymbolicExpression parDer(const IndependentVariable &x) const =0
Generate a new AST being the partial derivate of this AST with respect to the variable x.
virtual bool isConstantInt() const
Rreturn true if this Vertex is a constant integer.
Definition: ast.h:327
Definition: symbolic.h:160
Definition: function.h:202
IndependentVariable(const std::string &str)
Creates a IndependentVariable variable from the specified string (the string is a serialized Independ...
friend FMATVEC_EXPORT std::istream & operator>>(std::istream &s, IndependentVariable &v)
Create/initialize a IndependentVariable from a stream using deserialization.
IndependentVariable & operator^=(double x)
Set the double value of the independent value.
Definition: ast.h:797
SymbolicExpression(const std::string &str)
Creates a expression form the specified string (the string must be a serialized SymbolicExpression).
Namespace fmatvec.
Definition: _memory.cc:28
SymbolicExpression parDer(const SymbolicExpression &dep, const IndependentVariable &indep)
Definition: ast.cc:299
ostream & operator<<(ostream &s, const SymbolicExpression &se)
Write a SymbolicExpression to a stream using serialization.
Definition: ast.cc:190