funcy  1.6.1
pow.h
1 #pragma once
2 
3 #include <funcy/concepts.h>
4 #include <funcy/util/chainer.h>
5 #include <funcy/util/exceptions.h>
6 #include <funcy/util/macros.h>
7 
8 #include <cmath>
9 
10 namespace funcy
11 {
25  template < int dividend, int divisor = 1 >
26  struct Pow : Chainer< Pow< dividend, divisor > >
27  {
29  explicit Pow( double x = 1 ) FUNCY_NOEXCEPT
30  {
31  update( x );
32  }
33 
35  void update( double x ) FUNCY_NOEXCEPT
36  {
37 #ifdef FUNCY_ENABLE_EXCEPTIONS
38  if ( k < 3 && x == 0 )
39  throw OutOfDomainException( "Pow<" + std::to_string( dividend ) + "," +
40  std::to_string( divisor ) + ">",
41  "]-inf,inf[ \\ {0}", x, __FILE__, __LINE__ );
42 #endif
43  xk = x * ( xk1 = x * ( xk2 = x * ( xk3 = ::pow( x, k - 3 ) ) ) );
44  }
45 
47  [[nodiscard]] double d0() const noexcept
48  {
49  return xk;
50  }
51 
53  [[nodiscard]] double d1( double dx = 1. ) const noexcept
54  {
55  return k * xk1 * dx;
56  }
57 
59  [[nodiscard]] double d2( double dx = 1., double dy = 1. ) const noexcept
60  {
61  return k * ( k - 1 ) * xk2 * dx * dy;
62  }
63 
65  [[nodiscard]] double d3( double dx = 1., double dy = 1., double dz = 1. ) const noexcept
66  {
67  return k * ( k - 1 ) * ( k - 2 ) * xk3 * dx * dy * dz;
68  }
69 
70  private:
71  const double k = static_cast< double >( dividend ) / divisor;
72  double xk = 0;
73  double xk1 = 0;
74  double xk2 = 0;
75  double xk3 = 0;
76  };
77 
79  template <>
80  struct Pow< 2, 1 > : Chainer< Pow< 2, 1 > >
81  {
83  explicit Pow( double x_ = 0 ) FUNCY_NOEXCEPT
84  {
85  update( x_ );
86  }
87 
89  void update( const double& x_ ) FUNCY_NOEXCEPT
90  {
91  x = 2 * x_;
92  x2 = x_ * x_;
93  }
94 
96  [[nodiscard]] double d0() const noexcept
97  {
98  return x2;
99  }
100 
102  [[nodiscard]] double d1( double dx = 1. ) const noexcept
103  {
104  return x * dx;
105  }
106 
108  [[nodiscard]] double d2( double dx = 1, double dy = 1 ) const noexcept
109  {
110  return 2 * dx * dy;
111  }
112 
113  private:
114  double x = 0., x2 = 0.;
115  };
116 
117  template <>
118  struct Pow< 3, 1 > : Chainer< Pow< 3, 1 > >
119  {
121  explicit Pow( double x_ = 0 ) FUNCY_NOEXCEPT
122  {
123  update( x_ );
124  }
125 
127  void update( double x_ ) FUNCY_NOEXCEPT
128  {
129  x = x_;
130  x2 = x * x;
131  x3 = x2 * x;
132  }
133 
135  [[nodiscard]] double d0() const noexcept
136  {
137  return x3;
138  }
139 
141  [[nodiscard]] double d1( double dx = 1 ) const noexcept
142  {
143  return 3 * x2 * dx;
144  }
145 
147  [[nodiscard]] double d2( double dx = 1, double dy = 1 ) const noexcept
148  {
149  return 6 * x * dx * dy;
150  }
151 
153  [[nodiscard]] double d3( double dx = 1, double dy = 1, double dz = 1 ) const noexcept
154  {
155  return 6 * dx * dy * dz;
156  }
157 
158  private:
159  double x = 0;
160  double x2 = 0;
161  double x3 = 0.;
162  };
163 
172  template <>
173  struct Pow< -1, 1 > : Chainer< Pow< -1, 1 > >
174  {
176  explicit Pow( double x = 1. ) FUNCY_NOEXCEPT
177  {
178  update( x );
179  }
180 
182  void update( double x ) FUNCY_NOEXCEPT
183  {
184 #ifdef FUNCY_ENABLE_EXCEPTIONS
185  if ( x == 0 )
186  throw OutOfDomainException( "Pow<-1,1>", "]-inf,inf[ \\ {0}", x, __FILE__,
187  __LINE__ );
188 #endif
189  x_inv = 1. / x;
190  x_inv2 = x_inv * x_inv;
191  }
192 
194  [[nodiscard]] double d0() const noexcept
195  {
196  return x_inv;
197  }
198 
200  [[nodiscard]] double d1( double dx = 1. ) const noexcept
201  {
202  return -1 * x_inv2 * dx;
203  }
204 
206  [[nodiscard]] double d2( double dx = 1., double dy = 1. ) const noexcept
207  {
208  return 2 * x_inv2 * x_inv * dx * dy;
209  }
210 
212  [[nodiscard]] double d3( double dx = 1., double dy = 1., double dz = 1. ) const noexcept
213  {
214  return -6 * x_inv2 * x_inv2 * dx * dy * dz;
215  }
216 
217  private:
218  double x_inv = 1;
219  double x_inv2 = 1;
220  };
221 
222  template <>
223  struct Pow< 1, 2 > : Chainer< Pow< 1, 2 > >
224  {
226  explicit Pow( double x = 0 ) FUNCY_NOEXCEPT
227  {
228  update( x );
229  }
230 
232  void update( double x )
233  {
234 #ifdef FUNCY_ENABLE_EXCEPTIONS
235  if ( x < 0 )
236  throw OutOfDomainException( "Pow<1,2>", "[0,inf[", x, __FILE__, __LINE__ );
237 #endif
238  x_ = x;
239  sqrt_x = ::sqrt( x );
240  }
241 
243  [[nodiscard]] double d0() const noexcept
244  {
245  return sqrt_x;
246  }
247 
249  [[nodiscard]] double d1( double dx = 1. ) const noexcept
250  {
251  return 0.5 / sqrt_x * dx;
252  }
253 
255  [[nodiscard]] double d2( double dx = 1., double dy = 1. ) const noexcept
256  {
257  return -0.25 / ( x_ * sqrt_x ) * dx * dy;
258  }
259 
261  [[nodiscard]] double d3( double dx = 1., double dy = 1., double dz = 1. ) const noexcept
262  {
263  return 0.375 / ( x_ * x_ * sqrt_x ) * dx * dy * dz;
264  }
265 
266  private:
267  double x_ = 0;
268  double sqrt_x = 1;
269  };
270 
272  template <>
273  struct Pow< -1, 3 > : Chainer< Pow< -1, 3 > >
274  {
276  explicit Pow( double t = 1 ) FUNCY_NOEXCEPT
277  {
278  update( t );
279  }
280 
282  void update( double x ) FUNCY_NOEXCEPT
283  {
284 #ifdef FUNCY_ENABLE_EXCEPTIONS
285  if ( x < 0 )
286  throw OutOfDomainException( "Pow<1,3>", "[0,inf[", x, __FILE__, __LINE__ );
287 #endif
288  auto p = cbrt( x );
289  d0val = 1 / p;
290  p *= x;
291  d1val = -1 / ( 3 * p );
292  p *= x;
293  d2val = 4 / ( 9 * p );
294  p *= x;
295  d3val = -28 / ( 27 * p );
296  }
297 
299  [[nodiscard]] double d0() const noexcept
300  {
301  return d0val;
302  }
303 
305  [[nodiscard]] double d1( double dt = 1 ) const noexcept
306  {
307  return d1val * dt;
308  }
309 
311  [[nodiscard]] double d2( double dt0 = 1, double dt1 = 1 ) const noexcept
312  {
313  return d2val * dt0 * dt1;
314  }
315 
317  [[nodiscard]] double d3( double dt0 = 1, double dt1 = 1, double dt2 = 1 ) const noexcept
318  {
319  return d3val * dt0 * dt1 * dt2;
320  }
321 
322  private:
323  double d0val = 0;
324  double d1val = 0;
325  double d2val = 0;
326  double d3val = 0;
327  };
328 
330  template <>
331  struct Pow< -2, 3 > : Chainer< Pow< -2, 3 > >
332  {
334  explicit Pow( double t = 1. ) FUNCY_NOEXCEPT
335  {
336  update( t );
337  }
338 
340  void update( double x ) FUNCY_NOEXCEPT
341  {
342 #ifdef FUNCY_ENABLE_EXCEPTIONS
343  if ( x < 0 )
344  throw OutOfDomainException( "Pow<2,3>", "[0,inf[", x, __FILE__, __LINE__ );
345 #endif
346  auto p0 = cbrt( x );
347  auto p = p0 * p0;
348  d0val = 1 / p;
349  p *= x;
350  d1val = -2 / ( 3 * p );
351  p *= x;
352  d2val = 10 / ( 9 * p );
353  p *= x;
354  d3val = -80 / ( 27 * p );
355  }
356 
358  [[nodiscard]] double d0() const noexcept
359  {
360  return d0val;
361  }
362 
364  [[nodiscard]] double d1( double dt = 1 ) const noexcept
365  {
366  return d1val * dt;
367  }
368 
370  [[nodiscard]] double d2( double dt0 = 1, double dt1 = 1 ) const noexcept
371  {
372  return d2val * dt0 * dt1;
373  }
374 
376  [[nodiscard]] double d3( double dt0 = 1, double dt1 = 1, double dt2 = 1 ) const noexcept
377  {
378  return d3val * dt0 * dt1 * dt2;
379  }
380 
381  private:
382  double d0val = 0;
383  double d1val = 0;
384  double d2val = 0;
385  double d3val = 0;
386  };
388 
390  using Sqrt = Pow< 1, 2 >;
391 
393  using Cbrt = Pow< 1, 3 >;
394 
397 
403  template < Function F >
404  [[nodiscard]] auto sqrt( const F& f )
405  {
406  return Sqrt()( f );
407  }
408 
414  template < Function F >
415  [[nodiscard]] auto cbrt( const F& f )
416  {
417  return Cbrt()( f );
418  }
419 
425  template < Function F >
426  [[nodiscard]] auto cbrt2( const F& f )
427  {
428  return Cbrt2()( f );
429  }
430 
438  template < int k, int l, Function F >
439  [[nodiscard]] auto pow( const F& f )
440  {
441  return Pow< k, l >()( f );
442  }
443 
450  template < int k, Function F >
451  [[nodiscard]] auto pow( const F& f )
452  {
453  return Pow< k >()( f );
454  }
456 } // namespace funcy
Pow< 1, 3 > Cbrt
Third root (based on sqrt(double) in <cmath>).
Definition: pow.h:393
double d1(double dx=1.) const noexcept
First (directional) derivative.
Definition: pow.h:53
double d0() const noexcept
Function value.
Definition: pow.h:47
auto cbrt(const F &f)
Generate .
Definition: pow.h:415
Pow(double x=1) FUNCY_NOEXCEPT
Constructor.
Definition: pow.h:29
Exception for scalar function arguments that are outside the domain of the function.
Definition: exceptions.h:21
auto sqrt(const F &f)
Generate .
Definition: pow.h:404
auto pow(const F &f)
Generate .
Definition: pow.h:439
Main namespace of the funcy library.
Power function with rational exponent including first three derivatives.
Definition: pow.h:26
double d3(double dx=1., double dy=1., double dz=1.) const noexcept
Third (directional) derivative.
Definition: pow.h:65
Pow< 1, 2 > Sqrt
Square root (based on sqrt(double) in <cmath>).
Definition: pow.h:390
double d2(double dx=1., double dy=1.) const noexcept
Second (directional) derivative.
Definition: pow.h:59
Pow< 2, 3 > Cbrt2
Third root squared (based on sqrt(double) in <cmath>).
Definition: pow.h:396
void update(double x) FUNCY_NOEXCEPT
Set point of evaluation.
Definition: pow.h:35
auto cbrt2(const F &f)
Generate .
Definition: pow.h:426