RFFGen
 All Classes Namespaces Files Functions Typedefs Enumerations Groups
pow.hh
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the C++-library RFFGen. */
4 /* Copyright 2015 Lars Lubkoll */
5 /* */
6 /* RFFGen is free software: you can redistribute it and/or modify */
7 /* it under the terms of the GNU General Public License as published by */
8 /* the Free Software Foundation, either version 3 of the License, or */
9 /* (at your option) any later version. */
10 /* */
11 /* RFFGen is distributed in the hope that it will be useful, */
12 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14 /* GNU General Public License for more details. */
15 /* */
16 /* You should have received a copy of the GNU General Public License */
17 /* along with RFFGen. If not, see <http://www.gnu.org/licenses/>. */
18 /* */
19 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
20 
21 #ifndef RFFGEN_CMATH_POW_HH
22 #define RFFGEN_CMATH_POW_HH
23 
24 #include <cmath>
25 #include "../Util/base.hh"
26 #include "../Util/chainer.hh"
27 #include "../Util/exceptions.hh"
28 
29 namespace RFFGen
30 {
31  namespace CMath
32  {
42  template <int dividend, int divisor=1>
43  struct Pow : Base , Chainer< Pow<dividend,divisor> >
44  {
45  using Chainer< Pow<dividend,divisor> >::operator ();
46 
51  explicit Pow(double x=1) { update(x); }
52 
54  void update(double x)
55  {
56 #ifdef RFFGEN_ENABLE_EXCEPTIONS
57  if( k < 3 && x == 0 ) throw OutOfDomainException("Pow<" + std::to_string(dividend) + "," + std::to_string(divisor) + ">" , "]-inf,inf[ \\ {0}",x,__FILE__,__LINE__);
58 #endif
59  xk = x * (xk1 = x * (xk2 = x * ( xk3 = ::pow(x,k-3)) ) );
60  }
61 
63  double d0() const noexcept
64  {
65  return xk;
66  }
67 
69  template < int = -1 >
70  double d1(double dx = 1.) const
71  {
72  return k * xk1 * dx;
73  }
74 
76  template < int = -1 , int = -1 >
77  double d2(double dx = 1., double dy = 1.) const
78  {
79  return k * (k-1) * xk2 * dx * dy;
80  }
81 
83  template < int = -1 , int = -1 , int = -1 >
84  double d3(double dx = 1., double dy = 1., double dz = 1.) const
85  {
86  return k * (k-1) * (k-2) * xk3 * dx * dy * dz;
87  }
88 
89  private:
90  const double k = static_cast<double>(dividend)/divisor;
91  double xk, xk1, xk2, xk3;
92  };
93 
98  template <int dividend, int divisor=1>
99  auto power()
100  {
101  return Pow<dividend,divisor>();
102  }
112  template <>
113  struct Pow<2,1> : Base, Chainer< Pow<2,1> >
114  {
115  using Chainer< Pow<2,1> >::operator ();
116 
117  explicit Pow(double x_=0) { update(x_); }
118 
119  void update(const double& x_)
120  {
121  x = 2*x_;
122  x2 = x_*x_;
123  }
124 
126  double d0() const noexcept
127  {
128  return x2;
129  }
130 
132  template < int = -1 >
133  double d1(double dx=1.) const
134  {
135  return x * dx;
136  }
137 
139  template < int = -1 , int = -1 >
140  double d2(double dx=1, double dy=1) const
141  {
142  return 2 * dx * dy;
143  }
144 
145  private:
146  double x = 0., x2 = 0.;
147  };
148 
149  template <>
150  struct Pow<3,1> : Base , Chainer< Pow<3,1> >
151  {
152  using Chainer< Pow<3,1> >::operator ();
153 
154  explicit Pow(double x_=0) { update(x_); }
155 
156  void update(double x_)
157  {
158  x = x_;
159  x2 = x*x;
160  x3 = x2*x;
161  }
162 
164  double d0() const noexcept
165  {
166  return x3;
167  }
168 
170  template < int = -1 >
171  double d1(double dx=1) const
172  {
173  return 3 * x2 * dx;
174  }
175 
177  template < int = -1 , int = -1 >
178  double d2(double dx=1, double dy=1) const
179  {
180  return 6 * x * dx * dy;
181  }
182 
183  template < int = -1 , int = -1 , int = -1 >
184  double d3(double dx=1,double dy=1,double dz=1) const
185  {
186  return 6*dx*dy*dz;
187  }
188 
189  private:
190  double x = 0., x2 = 0., x3 = 0.;
191  };
192 
198  template <>
199  struct Pow<-1,1> : Base , Chainer< Pow<-1,1> >
200  {
201  using Chainer< Pow<-1,1> >::operator ();
202 
203  explicit Pow(double x=1.) { update(x); }
204 
205  void update(double x)
206  {
207 #ifdef RFFGEN_ENABLE_EXCEPTIONS
208  if( x == 0 ) throw OutOfDomainException("Pow<-1,1>","]-inf,inf[ \\ {0}",x,__FILE__,__LINE__);
209 #endif
210  x_inv = 1. / x;
211  x_inv2 = x_inv*x_inv;
212  }
213 
215  double d0() const noexcept
216  {
217  return x_inv;
218  }
219 
221  template < int = -1 >
222  double d1(double dx = 1.) const
223  {
224  return -1 * x_inv2 * dx;
225  }
226 
228  template < int = -1 , int = -1 >
229  double d2(double dx = 1., double dy = 1.) const
230  {
231  return 2 * x_inv2 * x_inv * dx * dy;
232  }
233 
235  template < int = -1 , int = -1 , int = -1 >
236  double d3(double dx = 1., double dy = 1., double dz = 1.) const
237  {
238  return -6 * x_inv2 * x_inv2 * dx * dy * dz;
239  }
240 
241  private:
242  double x_inv = 1., x_inv2 = 1.;
243  };
244 
245  template <>
246  struct Pow<1,2> : Base, Chainer< Pow<1,2> >
247  {
248  using Chainer< Pow<1,2> >::operator ();
249 
254  explicit Pow(double x=0) { update(x); }
255 
257  void update(double x)
258  {
259 #ifdef RFFGEN_ENABLE_EXCEPTIONS
260  if( x < 0 ) throw OutOfDomainException("Pow<1,2>","[0,inf[",x,__FILE__,__LINE__);
261 #endif
262  x_ = x;
263  sqrt_x = ::sqrt(x);
264  }
265 
267  double d0() const noexcept
268  {
269  return sqrt_x;
270  }
271 
273  template < int = -1 >
274  double d1(double dx = 1.) const
275  {
276  return 0.5 / sqrt_x * dx;
277  }
278 
280  template < int = -1 , int = -1 >
281  double d2(double dx = 1., double dy = 1.) const
282  {
283  return -0.25 / (x_*sqrt_x) * dx * dy;
284  }
285 
287  template < int = -1 , int = -1 , int = -1 >
288  double d3(double dx = 1., double dy = 1., double dz = 1.) const
289  {
290  return 0.375 / (x_*x_*sqrt_x) * dx * dy * dz;
291  }
292 
293  private:
294  double x_ = 0., sqrt_x = 1.;
295  };
296 
301  template <>
302  struct Pow<-1,3> : Base , Chainer< Pow<-1,3> >
303  {
304  using Chainer< Pow<-1,3> >::operator ();
305 
310  explicit Pow(double t=1) { update(t); }
311 
313  void update(double x)
314  {
315 #ifdef RFFGEN_ENABLE_EXCEPTIONS
316  if( x < 0 ) throw OutOfDomainException("Pow<1,3>","[0,inf[",x,__FILE__,__LINE__);
317 #endif
318  auto p = cbrt(x);
319  d0val = 1/p;
320  p *= x;
321  d1val = -1/(3*p);
322  p *= x;
323  d2val = 4/(9*p);
324  p *= x;
325  d3val = -28/(27*p);
326  }
327 
329  double d0() const noexcept { return d0val; }
330 
332  template < int = -1 >
333  double d1(double dt=1) const { return d1val*dt; }
334 
336  template < int = -1 , int = -1 >
337  double d2(double dt0=1, double dt1=1) const { return d2val*dt0*dt1; }
338 
340  template < int = -1 , int = -1 , int = -1 >
341  double d3(double dt0=1, double dt1=1, double dt2=1) const { return d3val*dt0*dt1*dt2; }
342 
343  private:
344  double d0val = 0, d1val = 0, d2val = 0, d3val = 0;
345  };
346 
347 
352  template <>
353  struct Pow<-2,3> : Base , Chainer< Pow<-2,3> >
354  {
355  using Chainer< Pow<-2,3> >::operator ();
356 
361  explicit Pow(double t=1.) { update(t); }
362 
364  void update(double x)
365  {
366 #ifdef RFFGEN_ENABLE_EXCEPTIONS
367  if( x < 0 ) throw OutOfDomainException("Pow<2,3>","[0,inf[",x,__FILE__,__LINE__);
368 #endif
369  auto p0 = cbrt(x);
370  auto p = p0*p0;
371  d0val = 1/p;
372  p *= x;
373  d1val = -2/(3*p);
374  p *= x;
375  d2val = 10/(9*p);
376  p *= x;
377  d3val = -80/(27*p);
378  }
379 
381  double d0() const noexcept { return d0val; }
382 
384  template < int = -1 >
385  double d1(double dt=1) const { return d1val*dt; }
386 
388  template < int = -1 , int = -1 >
389  double d2(double dt0=1, double dt1=1) const { return d2val*dt0*dt1; }
390 
392  template < int = -1 , int = -1 , int = -1 >
393  double d3(double dt0=1, double dt1=1, double dt2=1) const { return d3val*dt0*dt1*dt2; }
394 
395  private:
396  double d0val = 0, d1val = 0, d2val = 0, d3val = 0;
397  };
406  using Sqrt = Pow<1,2>;
407 
412  using Cbrt = Pow<1,3>;
413 
418  using Cbrt2 = Pow<2,3>;
419 
424  template <class Function, class = std::enable_if_t<std::is_base_of<Base,Function>::value> >
425  auto sqrt(const Function& f)
426  {
427  return Sqrt()(f);
428  }
429 
434  template <class Function, class = std::enable_if_t<std::is_base_of<Base,Function>::value> >
435  auto cbrt(const Function& f)
436  {
437  return Cbrt()(f);
438  }
439 
444  template <class Function, class = std::enable_if_t<std::is_base_of<Base,Function>::value> >
445  auto cbrt2(const Function& f)
446  {
447  return Cbrt2()(f);
448  }
449 
454  template <int dividend, int divisor,
455  class Function,
456  class = std::enable_if_t<std::is_base_of<Base,Function>::value> >
457  auto pow(const Function& f)
458  {
459  return Pow<dividend,divisor>()(f);
460  }
461  }
462 }
463 
464 #endif // RFFGEN_CMATH_POW_HH
Pow< 2, 3 > Cbrt2
Third root squared including first three derivatives (based on sqrt(double) in <cmath>).
Definition: pow.hh:418
Base class for functions satisfying FunctionConcept. Required for enabling the operators in generate...
Definition: base.hh:27
double d2(double dx=1., double dy=1.) const
Second (directinal) derivative.
Definition: pow.hh:77
Power function with rational exponent including first three derivatives.
Definition: pow.hh:43
double d0() const noexcept
Function value.
Definition: pow.hh:63
auto power()
Definition: pow.hh:99
Exception for scalar function arguments that are outside the domain of the function.
Definition: exceptions.hh:40
Pow(double x=1)
Constructor.
Definition: pow.hh:51
Pow< 1, 3 > Cbrt
Third root including first three derivatives (based on sqrt(double) in <cmath>).
Definition: pow.hh:412
double d3(double dx=1., double dy=1., double dz=1.) const
Third (directional) derivative.
Definition: pow.hh:84
void update(double x)
Reset point of evaluation.
Definition: pow.hh:54
Pow< 1, 2 > Sqrt
Square root including first three derivatives (based on sqrt(double) in <cmath>). ...
Definition: pow.hh:406
double d1(double dx=1.) const
First (directional) derivative.
Definition: pow.hh:70