codac 1.5.6
Loading...
Searching...
No Matches
codac2_AnalyticFunction_impl.h
Go to the documentation of this file.
1
9
10namespace codac2
11{
12 inline EvalMode operator&(EvalMode a, EvalMode b)
13 { return static_cast<EvalMode>(static_cast<int>(a) & static_cast<int>(b)); }
14
15 inline EvalMode operator|(EvalMode a, EvalMode b)
16 { return static_cast<EvalMode>(static_cast<int>(a) | static_cast<int>(b)); }
17
18
19 // Public methods
20
21 template<typename T>
22 requires std::is_base_of_v<AnalyticTypeBase,T>
23 template<typename... X>
24 inline AnalyticExprWrapper<T> AnalyticFunction<T>::operator()(const X&... x) const
25 {
26 return { this->FunctionBase<AnalyticExpr<T>>::operator()(x...) };
27 }
28
29 template<typename T>
30 requires std::is_base_of_v<AnalyticTypeBase,T>
31 template<typename... Args>
32 inline auto AnalyticFunction<T>::real_eval(const Args&... x) const
33 {
34 return eval(x...).mid();
35 }
36
37 template<typename T>
38 requires std::is_base_of_v<AnalyticTypeBase,T>
39 template<typename... Args>
40 inline typename T::Domain AnalyticFunction<T>::eval(const EvalMode& m, const Args&... x) const
41 {
42 check_valid_inputs(x...);
43
44 switch(m)
45 {
46 case EvalMode::NATURAL:
47 {
48 return eval_<true>(x...).a;
49 }
50
51 case EvalMode::CENTERED:
52 {
53 auto x_ = eval_<false>(x...);
54 auto flatten_x = cart_prod(x...);
55 assert(x_.da.rows() == x_.a.size() && x_.da.cols() == flatten_x.size());
56
57 if constexpr(std::is_same_v<T,ScalarType>)
58 return x_.m + (x_.da*(flatten_x-flatten_x.mid()))[0];
59 else
60 return x_.m + (x_.da*(flatten_x-flatten_x.mid())).col(0);
61 }
62
63 case EvalMode::DEFAULT:
64 default:
65 {
66 auto x_ = eval_<false>(x...);
67
68 if(x_.da.size() == 0) // if the centered form is not available for this expression
69 return eval(EvalMode::NATURAL, x...);
70
71 else
72 {
73 auto flatten_x = cart_prod(x...);
74 if constexpr(std::is_same_v<T,ScalarType>)
75 return x_.a & (x_.m + (x_.da*(flatten_x-flatten_x.mid()))[0]);
76 else
77 {
78 assert(x_.da.rows() == x_.a.size() && x_.da.cols() == flatten_x.size());
79 return x_.a & (x_.m + (x_.da*(flatten_x-flatten_x.mid())).col(0));
80 }
81 }
82 }
83 }
84 }
85
86 template<typename T>
87 requires std::is_base_of_v<AnalyticTypeBase,T>
88 template<typename... Args>
89 inline typename T::Domain AnalyticFunction<T>::eval(const Args&... x) const
90 {
91 return eval(EvalMode::NATURAL | EvalMode::CENTERED, x...);
92 }
93
94 template<typename T>
95 requires std::is_base_of_v<AnalyticTypeBase,T>
96 template<typename... Args>
97 inline auto AnalyticFunction<T>::diff(const Args&... x) const
98 {
99 check_valid_inputs(x...);
100 return eval_<false>(x...).da;
101 }
102
103 template<typename T>
104 requires std::is_base_of_v<AnalyticTypeBase,T>
105 inline Index AnalyticFunction<T>::output_size() const
106 {
107 if constexpr(std::is_same_v<T,ScalarType>)
108 return 1;
109
110 else if constexpr(std::is_same_v<T,VectorType>)
111 {
112 assert_release(this->args().size() == 1 && "unable (yet) to compute output size for multi-arg functions");
113
114 // A dump evaluation is performed to estimate the dimension
115 // of the image of this function. A natural evaluation is assumed
116 // to be faster.
117
118 if(dynamic_cast<ScalarVar*>(this->args()[0].get())) // if the argument is scalar
119 return eval(EvalMode::NATURAL, Interval()).size();
120 else
121 return eval(EvalMode::NATURAL, IntervalVector(this->input_size())).size();
122 }
123
124 else
125 {
126 assert_release(false && "unable to estimate output size");
127 return 0;
128 }
129 }
130
131 template<typename U>
132 std::ostream& operator<<(std::ostream& os, [[maybe_unused]] const AnalyticFunction<U>& f)
133 {
134 if constexpr(std::is_same_v<U,ScalarType>)
135 os << "scalar function";
136 else if constexpr(std::is_same_v<U,VectorType>)
137 os << "vector function";
138 return os;
139 }
140
141 // Protected methods
142
143 template<typename T>
144 requires std::is_base_of_v<AnalyticTypeBase,T>
145 template<typename D>
146 inline void AnalyticFunction<T>::add_value_to_arg_map(ValuesMap& v, const D& x, Index i) const
147 {
148 assert(i >= 0 && i < (Index)this->args().size());
149 assert_release(size_of(x) == this->args()[i]->size() && "provided arguments do not match function inputs");
150
151 IntervalMatrix d = IntervalMatrix::zero(size_of(x), this->args().total_size());
152
153 Index p = 0, j = 0;
154 for( ; j < i ; j++)
155 p += this->args()[j]->size();
156
157 for(Index k = p ; k < p+size_of(x) ; k++)
158 d(k-p,k) = 1.;
159
160 using D_DOMAIN = typename ValueType<D>::Type;
161
162 v[this->args()[i]->unique_id()] =
163 std::make_shared<D_DOMAIN>(typename D_DOMAIN::Domain(x).mid(), x, d, true);
164 }
165
166 template<typename T>
167 requires std::is_base_of_v<AnalyticTypeBase,T>
168 template<typename... Args>
169 inline void AnalyticFunction<T>::fill_from_args(ValuesMap& v, const Args&... x) const
170 {
171 Index i = 0;
172 (add_value_to_arg_map(v, x, i++), ...);
173 }
174
175 template<typename T>
176 requires std::is_base_of_v<AnalyticTypeBase,T>
177 template<typename D>
178 inline void AnalyticFunction<T>::intersect_value_from_arg_map(const ValuesMap& v, D& x, Index i) const
179 {
180 assert(v.find(this->args()[i]->unique_id()) != v.end() && "argument cannot be found");
181 x &= std::dynamic_pointer_cast<typename ValueType<D>::Type>(v.at(this->args()[i]->unique_id()))->a;
182 }
183
184 template<typename T>
185 requires std::is_base_of_v<AnalyticTypeBase,T>
186 template<typename... Args>
187 inline void AnalyticFunction<T>::intersect_from_args(const ValuesMap& v, Args&... x) const
188 {
189 Index i = 0;
190 (intersect_value_from_arg_map(v, x, i++), ...);
191 }
192
193 template<typename T>
194 requires std::is_base_of_v<AnalyticTypeBase,T>
195 template<bool NATURAL_EVAL,typename... Args>
196 inline auto AnalyticFunction<T>::eval_(const Args&... x) const
197 {
198 ValuesMap v;
199
200 if constexpr(sizeof...(Args) == 0)
201 return this->expr()->fwd_eval(v, 0, NATURAL_EVAL);
202
203 else
204 {
205 fill_from_args(v, x...);
206 return this->expr()->fwd_eval(v, cart_prod(x...).size(), NATURAL_EVAL); // todo: improve size computation
207 }
208 }
209
210 template<typename T>
211 requires std::is_base_of_v<AnalyticTypeBase,T>
212 template<typename... Args>
213 inline void AnalyticFunction<T>::check_valid_inputs(const Args&... x) const
214 {
215 [[maybe_unused]] Index n = 0;
216 ((n += size_of(x)), ...);
217
218 assert_release(this->_args.total_size() == n &&
219 "Invalid arguments: wrong number of input arguments");
220 }
221}
Interval class, for representing closed and connected subsets of .
Definition codac2_Interval.h:62
std::ostream & operator<<(std::ostream &os, const BoolInterval &x)
Streams out a BoolInterval.
Definition codac2_BoolInterval.h:45