AMDiS  0.1
The Adaptive Multi-Dimensional Simulation Toolbox
Arithmetic.hpp
1 #pragma once
2 
3 #include <algorithm>
4 
5 #include <amdis/common/Math.hpp>
6 #include <amdis/common/Concepts.hpp>
7 #include <amdis/operations/Basic.hpp>
8 #include <amdis/operations/Composer.hpp>
9 
10 namespace AMDiS
11 {
12  namespace Operation
13  {
18  struct Plus
20  {
21  template <class... Ts>
22  constexpr auto operator()(Ts const&... ts) const
23  {
24  return Math::sum(ts...);
25  }
26  };
27 
28 #ifndef DOXYGEN
29  // [0] + g => g
30  template <class G>
32  : ComposerBuilder<Id, G> {};
33 
34  // g + [0] => g
35  template <class G>
37  : ComposerBuilder<Id, G> {};
38 
39  // [0] + [0] => [0]
40  template <>
41  struct ComposerBuilder<Plus, Zero, Zero>
42  : ComposerBuilder<Id, Zero> {};
43 #endif
44 
45  template <class... Int>
46  constexpr int order(Plus const&, Int... orders)
47  {
48  return Math::max(int(orders)...);
49  }
50 
51  template <std::size_t I>
52  constexpr auto partial(Plus const&, index_t<I>)
53  {
54  static_assert((I < 2), "Derivatives of `Plus` only defined for the binary case.");
55  return One{};
56  }
57 
58  // -------------------------------------------------------------------------
59 
61  struct Minus
62  {
63  template <class T, class S>
64  constexpr auto operator()(T const& lhs, S const& rhs) const
65  {
66  return lhs - rhs;
67  }
68 
69  friend constexpr int order(Minus const&, int lhs, int rhs)
70  {
71  return Math::max(lhs, rhs);
72  }
73 
74  friend constexpr auto partial(Minus const&, index_t<0>)
75  {
76  return One{};
77  }
78 
79  friend constexpr auto partial(Minus const&, index_t<1>)
80  {
81  return StaticConstant<int,-1>{};
82  }
83  };
84 
85 #ifndef DOXYGEN
86  // g - [0] => g
87  template <class G>
88  struct ComposerBuilder<Minus, G, Zero>
89  : ComposerBuilder<Id, G> {};
90 
91  // [0] - [0] => [0]
92  template <>
93  struct ComposerBuilder<Minus, Zero, Zero>
94  : ComposerBuilder<Id, Zero> {};
95 #endif
96 
97  // -------------------------------------------------------------------------
98 
100  struct Multiplies
101  {
102  template <class... Ts>
103  constexpr auto operator()(Ts const&... ts) const
104  {
105  return (ts * ...);
106  }
107  };
108 
109 
110 #ifndef DOXYGEN
111  // [0] * g => [0]
112  template <class G>
113  struct ComposerBuilder<Multiplies, Zero, G>
114  : ComposerBuilder<Id, Zero> {};
115 
116  // g * [0] => [0]
117  template <class G>
118  struct ComposerBuilder<Multiplies, G, Zero>
119  : ComposerBuilder<Id, Zero> {};
120 
121  // [0] * [0] => [0]
122  template <>
123  struct ComposerBuilder<Multiplies, Zero, Zero>
124  : ComposerBuilder<Id, Zero> {};
125 #endif
126 
127 
128  template <class... Int>
129  constexpr int order(Multiplies const&, Int... orders)
130  {
131  return Math::sum(int(orders)...);
132  }
133 
134  // only for binary *
135  // d_0 (x * y) = y, d_1 (x * y) = x
136  template <std::size_t I>
137  constexpr auto partial(Multiplies const&, index_t<I>)
138  {
139  static_assert((I < 2), "Derivatives of `Multiplies` only defined for the binary case.");
140  return Arg<1-I>{};
141  }
142 
143  // -------------------------------------------------------------------------
144 
146  struct Divides
147  {
148  template <class T, class S>
149  constexpr auto operator()(T const& lhs, S const& rhs) const
150  {
151  return lhs / rhs;
152  }
153 
154  // d_0 f(x,y) = 1 / y
155  friend constexpr auto partial(Divides const&, index_t<0>)
156  {
157  return compose(Divides{}, One{}, Arg<1>{});
158  }
159 
160  // d_1 f(x,y) = (y - x)/y^2
161  friend constexpr auto partial(Divides const&, index_t<1>);
162  };
163 
164  // -------------------------------------------------------------------------
165 
167  struct Negate
168  {
169  template <class T>
170  constexpr auto operator()(T const& x) const
171  {
172  return -x;
173  }
174 
175  friend constexpr int order(Negate const&, int d)
176  {
177  return d;
178  }
179 
180  friend constexpr auto partial(Negate const&, index_t<0>)
181  {
182  return StaticConstant<int,-1>{};
183  }
184  };
185 
186 #ifndef DOXYGEN
187  // g + -h => g - h
188  template <class G>
190  : ComposerBuilder<Minus, G, Id> {};
191 
192  // [0] - g => -g
193  template <class G>
194  struct ComposerBuilder<Minus, Zero, G>
195  : ComposerBuilder<Id, Negate> {};
196 
197  // -(g - h) => (h - g)
198  template <>
199  struct ComposerBuilder<Negate, Minus>
200  : ComposerBuilder<Minus, Arg<1>, Arg<0>> {};
201 #endif
202 
203  // -------------------------------------------------------------------------
204 
205  // forward declaration
206  template <int p, bool positive>
207  struct PowImpl;
208 
209  template <int p>
210  struct PowType
211  {
212  using type = PowImpl<p, (p>0)>;
213  };
214 
215  template <> struct PowType<1> { using type = Id; };
216  template <> struct PowType<0> { using type = One; };
217 
218  template <int p>
219  using Pow = typename PowType<p>::type;
220 
221  using Sqr = Pow<2>;
222 
224  template <int p>
225  struct PowImpl<p, true>
226  {
227  template <class T>
228  constexpr auto operator()(T const& x) const
229  {
230  return Math::pow<p>(x);
231  }
232 
233  friend constexpr int order(PowImpl const&, int d)
234  {
235  return p*d;
236  }
237 
238  friend constexpr auto partial(PowImpl const&, index_t<0>)
239  {
240  return compose(Multiplies{}, StaticConstant<int,p>{}, Pow<p-1>{});
241  }
242  };
243 
244  template <int p>
245  struct PowImpl<p, false>
246  : public Composer<Divides, One, Pow<-p>>
247  {
248  constexpr PowImpl()
249  : Composer<Divides, One, Pow<-p>>{}
250  {}
251 
252  template <class T>
253  constexpr auto operator()(T const& x) const
254  {
255  return T(1) / Math::pow<-p>(x);
256  }
257  };
258 
259 
260 #ifndef DOXYGEN
261  // (x^p1)^p2 => x^(p1*p2)
262  template <int p1, bool pos1, int p2, bool pos2>
263  struct ComposerBuilder<PowImpl<p1,pos1>, PowImpl<p2,pos2>>
264  : ComposerBuilder<Id, Pow<p1*p2>> {};
265 
266  // x^p * y^p => (x*y)^p
267  template <int p, bool pos>
268  struct ComposerBuilder<Multiplies, PowImpl<p,pos>, PowImpl<p,pos>>
269  : ComposerBuilder<Pow<p>, Multiplies> {};
270 #endif
271 
272  // d_1 f(x,y) = (y - x)/y^2
273  inline constexpr auto partial(Divides const&, index_t<1>)
274  {
275  return compose(Divides{}, compose(Minus{}, Arg<1>{}, Arg<0>{}),
276  compose(Pow<2>{}, Arg<1>{}));
277  }
278 
280  struct Pow_
281  {
282  constexpr Pow_(int p)
283  : p_(p)
284  {}
285 
286  template <class T>
287  auto operator()(T const& x) const
288  {
289  return std::pow(x, p_);
290  }
291 
292  friend constexpr int order(Pow_ const& P, int d)
293  {
294  return P.p_ * d;
295  }
296 
297  friend constexpr auto partial(Pow_ const& P, index_t<0>)
298  {
299  return compose(Multiplies{}, Constant<int>{P.p_}, Pow_{P.p_-1});
300  }
301 
302  int p_;
303  };
304 
307  } // end namespace Operation
308 } // end namespace AMDiS
Definition: Basic.hpp:132
Composition of Functors.
Definition: Composer.hpp:31
Functor that represents A-B.
Definition: Arithmetic.hpp:167
Contains all classes needed for solving linear and non linear equation systems.
Definition: AdaptBase.hpp:6
Functor that represents x^p,.
Definition: Arithmetic.hpp:280
Definition: Arithmetic.hpp:207
Functor that represents A*B.
Definition: Arithmetic.hpp:100
Functor that represents A+B.
Definition: Arithmetic.hpp:19
Functor representing a static constant value.
Definition: Basic.hpp:37
auto order(F const &f) -> decltype(&F::operator(), f.order())
polynomial order of functions
Definition: Order.hpp:11
Functor that represents A/B.
Definition: Arithmetic.hpp:146
std::integral_constant< std::size_t, I > index_t
A wrapper for std::size_t type.
Definition: Index.hpp:31
Definition: Composer.hpp:53
Functor that represents A-B.
Definition: Arithmetic.hpp:61
Functor representing a constant value.
Definition: Basic.hpp:87
Definition: Arithmetic.hpp:210
(Unary-)Functor representing the identity
Definition: Basic.hpp:64