1#ifndef _fmatvec_symbolic_h_
2#define _fmatvec_symbolic_h_
7#include <boost/hana/type.hpp>
14template<
class Dep,
class ATIndep>
15Dep
parDer(
const Dep &dep,
const ATIndep &indep) {
17 if constexpr (std::is_same_v<Dep, SymbolicExpression>) {
19 else if constexpr (Dep::isVector)
20 ret.resize(dep.size());
22 ret.resize(dep.rows(), dep.cols());
25 for(; d!=dep.end(); ++d, ++r)
30template<
class ATDep,
class ATIndep>
31Vector<Fixed<3>, ATDep>
parDer(
const Matrix<Rotation, Fixed<3>, Fixed<3>, ATDep> &R,
const ATIndep &x) {
32 Matrix<General, Fixed<3>, Fixed<3>, ATDep> Rs;
33 for(
int r=0; r<3; ++r)
34 for(
int c=0; c<3; ++c)
36 auto retTilde=Rs*
trans(R);
37 Vector<Fixed<3>, ATDep> ret;
44template<
class DepShape,
class IndepShape,
class ATDep,
class ATIndep>
45Matrix<General, DepShape, IndepShape, ATDep>
parDer(
const Vector<DepShape, ATDep> &dep,
const Vector<IndepShape, ATIndep> &indep) {
46 Matrix<General, DepShape, IndepShape, ATDep> ret(dep.size(), indep.size());
47 for(
int r=0; r<dep.size(); ++r)
48 for(
int c=0; c<indep.size(); ++c)
49 ret(r,c)=
parDer(dep(r), indep(c));
53template<
class IndepShape,
class ATDep,
class ATIndep>
54RowVector<IndepShape, ATDep>
parDer(
const ATDep &dep,
const Vector<IndepShape, ATIndep> &indep) {
55 RowVector<IndepShape, ATDep> ret(indep.size());
56 for(
int r=0; r<indep.size(); ++r)
57 ret(r)=
parDer(dep, indep(r));
61template<
class ATDep,
class Shape,
class ATIndep>
62Matrix<General, Fixed<3>, Shape, ATDep>
parDer(
const Matrix<Rotation, Fixed<3>, Fixed<3>, ATDep> &R,
const Vector<Shape, ATIndep> &x) {
63 Matrix<General, Fixed<3>, Shape, ATDep> ret(3,x.size());
64 for(
int i=0; i<x.size(); ++i)
65 ret.set(i,
parDer(R, x(i)));
69template<
class Dep,
class ATDep,
class ATIndep>
70Dep dirDer(
const Dep &dep,
const ATDep &indepdir,
const ATIndep &indep) {
71 return parDer(dep, indep)*indepdir;
74template<
class ATDep,
class ATIndep>
75Vector<Fixed<3>, ATDep> dirDer(
const Matrix<Rotation, Fixed<3>, Fixed<3>, ATDep> &R,
const ATDep &indepdir,
const ATIndep &indep) {
76 return parDer(R, indep)*indepdir;
79template<
class Dep,
class ShapeIndep,
class ATDep,
class ATIndep>
80Dep dirDer(
const Dep &dep,
const Vector<ShapeIndep, ATDep> &indepdir,
const Vector<ShapeIndep, ATIndep> &indep) {
82 if constexpr (std::is_same_v<Dep, SymbolicExpression>) {
85 else if constexpr (Dep::isVector)
86 ret<<=Dep(dep.size(), INIT, 0.0);
88 ret<<=Dep(dep.rows(), dep.cols(), INIT, 0.0);
89 for(
int i=0; i<indep.size(); ++i)
90 ret+=
parDer(dep, indep(i))*indepdir(i);
94template<
class ATDep,
class ShapeIndep,
class ATIndep>
95Vector<Fixed<3>, ATDep> dirDer(
const Matrix<Rotation, Fixed<3>, Fixed<3>, ATDep> &dep,
const Vector<ShapeIndep, ATDep> &indepdir,
const Vector<ShapeIndep, ATIndep> &indep) {
96 return parDer(dep, indep)*indepdir;
100template<
class Ret,
class A,
class B>
101Ret subst(
const Ret &src,
const A &a,
const B &b) {
102 if constexpr (!std::is_same_v<A, IndependentVariable>) {
103 if constexpr (A::isVector) {
104 if(a.size()!=b.size())
105 throw std::runtime_error(
"The size of the independent and the dependent substitution variable does not match.");
108 if(a.rows()!=b.rows() || a.cols()!=b.cols())
109 throw std::runtime_error(
"The size of the independent and the dependent substitution variable does not match.");
113 if constexpr (std::is_same_v<Ret, SymbolicExpression> && std::is_same_v<A, IndependentVariable>) {
114 return AST::substScalar(src, a, b);
116 if constexpr (std::is_same_v<Ret, SymbolicExpression> && !std::is_same_v<A, IndependentVariable>) {
120 for(; aIt<a.end(); ++aIt, ++bIt)
121 ret=subst(ret, *aIt, *bIt);
124 if constexpr (!std::is_same_v<Ret, SymbolicExpression> && std::is_same_v<A, IndependentVariable>) {
126 for(
auto retIt=ret.begin(); retIt<ret.end(); ++retIt)
127 *retIt=subst(*retIt, a, b);
130 if constexpr (!std::is_same_v<Ret, SymbolicExpression> && !std::is_same_v<A, IndependentVariable>) {
132 for(
auto retIt=ret.begin(); retIt<ret.end(); ++retIt) {
135 for(; aIt<a.end(); ++aIt, ++bIt)
136 *retIt=subst(*retIt, *aIt, *bIt);
144template<
class Dst,
class Src>
145Dst& operator^=(Dst &dst,
const Src &src) {
146 auto dstIt=dst.begin();
147 auto srcIt=src.begin();
148 for(; dstIt<dst.end(); ++dstIt, ++srcIt)
159template<
class... Arg>
163 using SymTuple = std::tuple<Arg...>;
165 using NumTuple = std::tuple<typename ReplaceAT<Arg, double>::Type...>;
167 using NumRetType = std::conditional_t<std::tuple_size_v<NumTuple> == 1, std::tuple_element_t<0,NumTuple>, NumTuple>;
172 Eval<Arg...>& operator=(
const Eval &src) =
delete;
173 Eval<Arg...>& operator=(
Eval &&src) =
delete;
177 Eval(
const Arg&... arg);
180 inline const NumRetType& operator()()
const;
185 std::set<std::shared_ptr<const AST::Symbol>> symbolStore;
189 void walkAT(
const SymTuple &symTuple, NumTuple &numTuple,
194 std::vector<AST::ByteCode> byteCode;
197 void ctorByteCode(
const Arg&... arg);
198 inline void callByteCode()
const;
201template<
class... Arg>
204template<
class... Arg>
206 ctorByteCode(arg...);
209template<
class... Arg>
210auto Eval<Arg...>::operator()() const -> const NumRetType& {
213 if constexpr (std::tuple_size_v<NumTuple> == 1)
214 return std::get<0>(numTuple);
219template<
class... Arg>
221void Eval<Arg...>::walkAT(
const SymTuple &symTuple, NumTuple &numTuple,
222 const std::function<
void(
const SymbolicExpression&,
double&)> &func) {
225 auto &sym = std::get<I>(symTuple);
226 auto &num = std::get<I>(numTuple);
228 using Sym = std::tuple_element_t<I,SymTuple>;
230 if constexpr (std::is_same_v<Sym, SymbolicExpression>)
235 if constexpr (Sym::isVector)
236 num.resize(sym.size());
238 num.resize(sym.rows(), sym.cols());
240 auto symIt=sym.begin();
241 auto numIt=num.begin();
242 for(; symIt!=sym.end(); ++symIt, ++numIt)
243 func(*symIt, *numIt);
247 if constexpr (I+1<std::tuple_size_v<SymTuple>)
248 walkAT<I+1>(symTuple, numTuple, func);
251template<
class... Arg>
252void Eval<Arg...>::ctorByteCode(
const Arg&... arg) {
254 size_t byteCodeCount=0;
255 std::set<const AST::Vertex*> existingVertex1;
256 walkAT(SymTuple(arg...), numTuple, [&byteCodeCount, &existingVertex1](
auto &sym,
auto &num) {
257 sym->walkVertex([&byteCodeCount, &existingVertex1](const std::shared_ptr<const AST::Vertex>& v) {
258 if(!existingVertex1.insert(v.get()).second) return;
260 if(auto s=std::dynamic_pointer_cast<const AST::Symbol>(v); s)
267 byteCode.reserve(byteCodeCount);
268 std::map<const AST::Vertex*, std::vector<AST::ByteCode>::iterator> existingVertex;
271 walkAT(SymTuple(arg...), numTuple, [
this, &existingVertex](
auto &sym,
auto &num) {
272 sym->walkVertex([this, &existingVertex](const std::shared_ptr<const AST::Vertex>& v) {
273 if(auto s=std::dynamic_pointer_cast<const AST::Symbol>(v); s) {
274 symbolStore.insert(s);
275 s->dumpByteCode(byteCode, existingVertex);
281 std::vector< std::vector<AST::ByteCode>::iterator > exprRet;
282 walkAT(SymTuple(arg...), numTuple, [
this, &existingVertex, &exprRet](
auto &sym,
auto &num) {
283 exprRet.emplace_back(sym->dumpByteCode(byteCode, existingVertex));
287 auto exprRetIt = exprRet.begin();
288 walkAT(SymTuple(arg...), numTuple, [
this, &exprRet, &exprRetIt](
auto &sym,
auto &num) {
289 byteCode.emplace_back(1);
290 auto it = --byteCode.end();
291 it->func = [](double* r, const AST::ByteCode::Arg& a) { *r = *a[0]; };
292 it->argsPtr = { (*(exprRetIt++))->retPtr };
297template<
class... Arg>
298void Eval<Arg...>::callByteCode()
const {
299#if defined(FMATVEC_DEBUG) && !defined(SWIG)
300 SymbolicExpression::evalOperationsCount = byteCode.size();
302 std::for_each(byteCode.begin(), byteCode.end(), [](
const AST::ByteCode &bc){
303 bc.func(bc.retPtr, bc.argsPtr);
307template<
class RetN,
class ArgN>
311 func(func_), idx(idx_) {}
312 double operator()(
const ArgN &arg)
override {
313 return (*func)(arg)(idx);
315 double dirDer(
const ArgN &argDir,
const ArgN &arg)
override {
316 return func->dirDer(argDir, arg)(idx);
318 double dirDerDirDer(
const ArgN &argDir_1,
const ArgN &argDir_2,
const ArgN &arg)
override {
319 return func->dirDerDirDer(argDir_1, argDir_2, arg)(idx);
326template<
class RetN,
class Arg1N,
class Arg2N>
330 func(func_), idx(idx_) {}
331 double operator()(
const Arg1N &arg1,
const Arg2N &arg2)
override {
332 return (*func)(arg1,arg2)(idx);
334 double dirDer1(
const Arg1N &dir1,
const Arg1N &arg1,
const Arg2N &arg2)
override {
335 return func->dirDer1(dir1, arg1, arg2)(idx);
337 double dirDer2(
const Arg2N &dir2,
const Arg1N &arg1,
const Arg2N &arg2)
override {
338 return func->dirDer2(dir2, arg1, arg2)(idx);
340 double dirDer1DirDer1(
const Arg1N &dir1_1,
const Arg1N &dir1_2,
const Arg1N &arg1,
const Arg2N &arg2)
override {
341 return func->dirDer1DirDer1(dir1_1, dir1_2, arg1, arg2)(idx);
343 double dirDer2DirDer1(
const Arg2N &dir2_1,
const Arg1N &dir1_2,
const Arg1N &arg1,
const Arg2N &arg2)
override {
344 return func->dirDer2DirDer1(dir2_1, dir1_2, arg1, arg2)(idx);
346 double dirDer2DirDer2(
const Arg2N &dir2_1,
const Arg2N &dir2_2,
const Arg1N &arg1,
const Arg2N &arg2)
override {
347 return func->dirDer2DirDer2(dir2_1, dir2_2, arg1, arg2)(idx);
354template<
class RetN,
class ArgN>
358 func(func_), row(row_), col(col_) {}
359 double operator()(
const ArgN &arg)
override {
360 return (*func)(arg)(row,col);
362 double dirDer(
const ArgN &argDir,
const ArgN &arg)
override {
363 return func->dirDer(argDir, arg)(row,col);
365 double dirDerDirDer(
const ArgN &argDir_1,
const ArgN &argDir_2,
const ArgN &arg)
override {
366 return func->dirDerDirDer(argDir_1, argDir_2, arg)(row,col);
374template<
class RetN,
class Arg1N,
class Arg2N>
378 func(func_), row(row_), col(col_) {}
379 double operator()(
const Arg1N &arg1,
const Arg2N &arg2)
override {
380 return (*func)(arg1,arg2)(row,col);
382 double dirDer1(
const Arg1N &dir1,
const Arg1N &arg1,
const Arg2N &arg2)
override {
383 return func->dirDer1(dir1, arg1, arg2)(row,col);
385 double dirDer2(
const Arg2N &dir2,
const Arg1N &arg1,
const Arg2N &arg2)
override {
386 return func->dirDer2(dir2, arg1, arg2)(row,col);
388 double dirDer1DirDer1(
const Arg1N &dir1_1,
const Arg1N &dir1_2,
const Arg1N &arg1,
const Arg2N &arg2)
override {
389 return func->dirDer1DirDer1(dir1_1, dir1_2, arg1, arg2)(row,col);
391 double dirDer2DirDer1(
const Arg2N &dir2_1,
const Arg1N &dir1_2,
const Arg1N &arg1,
const Arg2N &arg2)
override {
392 return func->dirDer2DirDer1(dir2_1, dir1_2, arg1, arg2)(row,col);
394 double dirDer2DirDer2(
const Arg2N &dir2_1,
const Arg2N &dir2_2,
const Arg1N &arg1,
const Arg2N &arg2)
override {
395 return func->dirDer2DirDer2(dir2_1, dir2_2, arg1, arg2)(row,col);
403template<
class Func,
class ArgS>
406 using RetN =
typename std::function<Func>::result_type;
410 auto hasSize = boost::hana::is_valid([](
auto&& vec) ->
decltype(vec.size()) {});
413 if constexpr (hasSize(ret)) {
415 int size=func->getRetSize().first;
416 if(size==0 && size1!=0)
419 size=(*func)(ArgN()).size();
421 for(
int i=0; i<size; ++i)
428 auto size=func->getRetSize();
429 if(size.first==0 && size1!=0)
431 else if(size.first==0)
432 size.first=(*func)(ArgN()).rows();
433 if(size.second==0 && size2!=0)
435 else if(size.second==0)
436 size.second=(*func)(ArgN()).cols();
437 ret.resize(size.first, size.second);
438 for(
int r=0; r<size.first; ++r)
439 for(
int c=0; c<size.second; ++c)
440 ret(r,c) = AST::SymbolicFuncWrapArg1<double(ArgN), ArgS>::call(std::make_shared<FunctionWrap1MatRetToScalar<RetN,ArgN>>(
446template<
class Func,
class Arg1S,
class Arg2S>
447typename ReplaceAT<typename std::function<Func>::result_type,SymbolicExpression>::Type symbolicFuncWrapVecAndMatRet(
448 const std::shared_ptr<Function<Func>> &func,
const Arg1S &arg1,
const Arg2S &arg2,
int size1=0,
int size2=0) {
449 using RetN =
typename std::function<Func>::result_type;
450 using RetS =
typename ReplaceAT<RetN,SymbolicExpression>::Type;
451 using Arg1N =
typename ReplaceAT<Arg1S,double>::Type;
452 using Arg2N =
typename ReplaceAT<Arg2S,double>::Type;
454 auto hasSize = boost::hana::is_valid([](
auto&& vec) ->
decltype(vec.size()) {});
457 if constexpr (hasSize(ret)) {
459 int size=func->getRetSize().first;
460 if(size==0 && size1!=0)
463 size=(*func)(Arg1N(), Arg2N()).size();
465 for(
int i=0; i<size; ++i)
466 ret(i) = AST::SymbolicFuncWrapArg2<double(Arg1N,Arg2N), Arg1S, Arg2S>::
467 call(std::make_shared<FunctionWrap2VecRetToScalar<RetN,Arg1N,Arg2N>>(func, i), arg1, arg2);
472 auto size=func->getRetSize();
473 if(size.first==0 && size1!=0)
475 else if(size.first==0)
476 size.first=(*func)(Arg1N(),Arg2N()).rows();
477 if(size.second==0 && size2!=0)
479 else if(size.second==0)
480 size.second=(*func)(Arg1N(),Arg2N()).cols();
481 ret.resize(size.first, size.second);
482 for(
int r=0; r<size.first; ++r)
483 for(
int c=0; c<size.second; ++c)
484 ret(r,c) = AST::SymbolicFuncWrapArg2<double(Arg1N,Arg2N), Arg1S, Arg2S>::
485 call(std::make_shared<FunctionWrap2MatRetToScalar<RetN,Arg1N,Arg2N>>(func, r, c), arg1, arg2);
495template<
class Func,
class ArgS>
498 using RetN =
typename std::function<Func>::result_type;
500 if constexpr (std::is_same_v<RetN, double>)
503 return symbolicFuncWrapVecAndMatRet<Func, ArgS>(func, arg, size1, size2);
511template<
class Func,
class Arg1S,
class Arg2S>
514 using RetN =
typename std::function<Func>::result_type;
517 if constexpr (std::is_same_v<RetN, double>)
520 return symbolicFuncWrapVecAndMatRet<Func, Arg1S, Arg2S>(func, arg1, arg2, size1, size2);
Definition: symbolic.h:160
Definition: symbolic.h:355
Definition: symbolic.h:308
Definition: symbolic.h:375
Definition: symbolic.h:327
Definition: function.h:202
Namespace fmatvec.
Definition: _memory.cc:28
RowVector< Row, AT > trans(const Vector< Row, AT > &x)
Transpose of a vector.
Definition: linear_algebra.h:1723
SymbolicExpression parDer(const SymbolicExpression &dep, const IndependentVariable &indep)
Definition: ast.cc:299
ReplaceAT< typenamestd::function< Func >::result_type, SymbolicExpression >::Type symbolicFunc(const std::shared_ptr< Function< Func > > &func, const ArgS &arg, int size1=0, int size2=0)
Definition: symbolic.h:496