mbsim  4.0.0
MBSim Kernel
composite_function.h
1/* Copyright (C) 2004-2014 MBSim Development Team
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * Contact: martin.o.foerg@gmail.com
18 */
19
20#ifndef _NESTED_FUNCTION_H_
21#define _NESTED_FUNCTION_H_
22
23#include "mbsim/functions/function.h"
24
25namespace MBSim {
26
27 template<typename Sig> class CompositeFunction;
28
41 template<typename Ret, typename Argo, typename Argi>
42 class CompositeFunction<Ret(Argo(Argi))> : public Function<Ret(Argi)> {
43 using B = Function<Ret(Argi)>;
44 public:
45 CompositeFunction() = default;
46 CompositeFunction(Function<Ret(Argo)> *fo_, Function<Argo(Argi)> *fi_) {
47 setOuterFunction(fo_);
48 setInnerFunction(fi_);
49 }
50 ~CompositeFunction() override {
51 delete fo1;
52 delete fo2;
53 for (auto & i : fi) delete i;
54 }
55 int getArgSize() const override {
56 return fi[0]->getArgSize();
57 }
58 std::pair<int, int> getRetSize() const override {
59 return fo1?fo1->getRetSize():fo2->getRetSize();
60 }
61 Ret operator()(const Argi &arg) override {
62 return fo1?(*fo1)((*fi[0])(arg)):(*fo2)((*fi[0])(arg),(*fi[1])(arg));
63 }
64 typename B::DRetDArg parDer(const Argi &arg) override {
65 return fo1?fo1->parDer((*fi[0])(arg))*fi[0]->parDer(arg):fo2->parDer1((*fi[0])(arg),(*fi[1])(arg))*fi[0]->parDer(arg)+fo2->parDer2((*fi[0])(arg),(*fi[1])(arg))*fi[1]->parDer(arg);
66 }
67 typename B::DRetDArg parDerDirDer(const Argi &argDir, const Argi &arg) override {
68 return fo1?fo1->parDerDirDer(fi[0]->parDer(arg)*argDir,(*fi[0])(arg))*fi[0]->parDer(arg)+fo1->parDer((*fi[0])(arg))*fi[0]->parDerDirDer(argDir,arg):fo2->parDer1DirDer1(fi[0]->parDer(arg)*argDir,(*fi[0])(arg),(*fi[0])(arg))*fi[0]->parDer(arg)+fo2->parDer1DirDer2(fi[1]->parDer(arg)*argDir,(*fi[0])(arg),(*fi[0])(arg))*fi[0]->parDer(arg)+fo2->parDer2DirDer1(fi[0]->parDer(arg)*argDir,(*fi[0])(arg),(*fi[0])(arg))*fi[1]->parDer(arg)+fo2->parDer2DirDer2(fi[1]->parDer(arg)*argDir,(*fi[0])(arg),(*fi[0])(arg))*fi[1]->parDer(arg)+fo2->parDer1((*fi[0])(arg),(*fi[1])(arg))*fi[0]->parDerDirDer(argDir,arg)+fo2->parDer2((*fi[0])(arg),(*fi[1])(arg))*fi[1]->parDerDirDer(argDir,arg);
69 }
70 void setOuterFunction(Function<Ret(Argo)> *fo_) {
71 fo1 = fo_;
72 fo1->setParent(this);
73 fo1->setName("Outer");
74 }
75 void setOuterFunction(Function<Ret(Argo,Argo)> *fo_) {
76 fo2 = fo_;
77 fo2->setParent(this);
78 fo2->setName("Outer");
79 }
80 void setInnerFunction(Function<Argo(Argi)> *fi_) {
81 fi_->setParent(this);
82 fi_->setName("Inner");
83 fi.resize(1,fi_);
84 }
85 void addInnerFunction(Function<Argo(Argi)> *fi_) {
86 fi_->setParent(this);
87 fi_->setName("Inner");
88 fi.push_back(fi_);
89 }
90 void initializeUsingXML(xercesc::DOMElement *element) override {
91 xercesc::DOMElement *e=MBXMLUtils::E(element)->getFirstElementChildNamed(MBSIM%"innerFunction");
92 if(e) setInnerFunction(ObjectFactory::createAndInit<Function<Argo(Argi)>>(e->getFirstElementChild()));
93 else {
94 e=MBXMLUtils::E(element)->getFirstElementChildNamed(MBSIM%"innerFunctions")->getFirstElementChild();
95 for(int i=0; i<2; i++) {
96 addInnerFunction(ObjectFactory::createAndInit<Function<Argo(Argi)>>(e));
97 e=e->getNextElementSibling();
98 }
99 }
100 e=MBXMLUtils::E(element)->getFirstElementChildNamed(MBSIM%"outerFunction");
101 if(fi.size()==1)
102 setOuterFunction(ObjectFactory::createAndInit<Function<Ret(Argo)>>(e->getFirstElementChild()));
103 else if(fi.size()==2)
104 setOuterFunction(ObjectFactory::createAndInit<Function<Ret(Argo,Argo)>>(e->getFirstElementChild()));
105 }
106 void init(Element::InitStage stage, const InitConfigSet &config) override {
107 Function<Ret(Argi)>::init(stage, config);
108 if(fo1) fo1->init(stage, config);
109 if(fo2) fo2->init(stage, config);
110 for (auto & i : fi) i->init(stage, config);
111 }
112 private:
113 Function<Ret(Argo)> *fo1{nullptr};
114 Function<Ret(Argo,Argo)> *fo2{nullptr};
115 std::vector<Function<Argo(Argi)>*> fi;
116 };
117}
118
119#endif
void init(Element::InitStage stage, const InitConfigSet &config) override
plots time series header
Definition: composite_function.h:106
Definition: composite_function.h:27
InitStage
The stages of the initialization.
Definition: element.h:62
Definition: function.h:53
static ContainerType * createAndInit(const xercesc::DOMElement *element)
Definition: objectfactory.h:103
namespace MBSim
Definition: bilateral_constraint.cc:30