CMath.hpp 4.81 KB
Newer Older
1
2
3
4
#pragma once

#include <cmath>

5
#include <amdis/operations/Basic.hpp>
6
7
8
9
10
11
12
13

/// Macro that generates a unary functor with explicitly given function and derivative.
/**
 *  \p NAME    Name of the class.
 *  \p FCT     Name of a unary c++-function that represents the functor.
 *  \p DERIV   Name of a unary c++-function that represents the derivative of this functor.
 */
#ifndef AMDIS_MAKE_UNARY_FUNCTOR
14
#define AMDIS_MAKE_UNARY_FUNCTOR( NAME, FCT, DERIV )          \
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
    struct NAME                                               \
    {                                                         \
      template <class T>                                      \
      constexpr auto operator() (T const& x) const            \
      {                                                       \
        return FCT ;                                          \
      }                                                       \
      struct Derivative                                       \
      {                                                       \
        template <class T>                                    \
        constexpr auto operator() (T const& x) const          \
        {                                                     \
          return DERIV ;                                      \
        }                                                     \
      };                                                      \
      friend constexpr auto partial(NAME, index_t<0>)         \
      {                                                       \
        return Derivative{} ;                                 \
      }                                                       \
    };
#endif


namespace AMDiS
{
  namespace Operation
  {
    /** \addtogroup operations
     *  @{
     **/

    /// Functor that represents the signum function
    struct Signum
    {
      template <class T>
      constexpr auto operator()(T const& x) const
      {
        return (x > T{0} ? T{1} : T{-1});
      }

55
      friend constexpr auto partial(Signum, index_t<0>)
56
57
58
59
60
61
62
63
      {
        return Zero{};
      }
    };

    // generated unary functors using a macro...
    // approximate polynomial order

64
#ifndef DOXYGEN
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
    AMDIS_MAKE_UNARY_FUNCTOR( Ceil,  std::ceil(x),  0.0 )
    AMDIS_MAKE_UNARY_FUNCTOR( Floor, std::floor(x), 0.0 )
    AMDIS_MAKE_UNARY_FUNCTOR( Sqrt,  std::sqrt(x),  1.0/(2.0 * std::sqrt(x)) )
    AMDIS_MAKE_UNARY_FUNCTOR( Exp,   std::exp(x),   std::exp(x) )
    AMDIS_MAKE_UNARY_FUNCTOR( Log,   std::log(x),   1.0/x )
    AMDIS_MAKE_UNARY_FUNCTOR( Sin,   std::sin(x),   std::cos(x) )
    AMDIS_MAKE_UNARY_FUNCTOR( Cos,   std::cos(x),   -std::sin(x) )
    AMDIS_MAKE_UNARY_FUNCTOR( Tan,   std::tan(x),   1.0 + Math::sqr(std::tan(x)) )
    AMDIS_MAKE_UNARY_FUNCTOR( Asin,  std::asin(x),  1.0/std::sqrt(1.0 - Math::sqr(x)) )
    AMDIS_MAKE_UNARY_FUNCTOR( Acos,  std::acos(x), -1.0/std::sqrt(1.0 - Math::sqr(x)) )
    AMDIS_MAKE_UNARY_FUNCTOR( Atan,  std::atan(x),  1.0/(1.0 + Math::sqr(x)) )
    AMDIS_MAKE_UNARY_FUNCTOR( Sinh,  std::sinh(x),  std::cosh(x) )
    AMDIS_MAKE_UNARY_FUNCTOR( Cosh,  std::cosh(x),  std::sinh(x) )
    AMDIS_MAKE_UNARY_FUNCTOR( Tanh,  std::tanh(x),  1.0 - Math::sqr(std::tanh(x)) )
    AMDIS_MAKE_UNARY_FUNCTOR( Asinh, std::asinh(x), 1.0/std::sqrt(1.0 + Math::sqr(x)) )
    AMDIS_MAKE_UNARY_FUNCTOR( Acosh, std::acosh(x), 1.0/std::sqrt(-1.0 + Math::sqr(x)) )
    AMDIS_MAKE_UNARY_FUNCTOR( Atanh, std::atanh(x), 1.0/(1.0 - Math::sqr(x)) )
82
#endif
83
84
85
86
87
88
89
90
91
92

    /// Binary functor representing the cmath function std::atan2(v)
    struct Atan2
    {
      template <class T1, class T2>
      constexpr auto operator() (T1 const& x, T2 const& y) const
      {
        return std::atan2(x, y);
      }

93
      // -y/(Math::sqr(x) + Math::sqr(y))
94
95
      constexpr friend auto partial(Atan2, index_t<0>)
      {
96
97
        return compose(Divides{}, compose(Negate{}, Arg<1>{}),
          compose(Plus{}, compose(Pow<2>{}, Arg<0>{}), compose(Pow<2>{}, Arg<1>{})));
98
99
      }

100
      // x/(Math::sqr(x) + Math::sqr(y));
101
102
      constexpr friend auto partial(Atan2, index_t<1>)
      {
103
104
        return compose(Divides{}, Arg<0>{},
          compose(Plus{}, compose(Pow<2>{}, Arg<0>{}), compose(Pow<2>{}, Arg<1>{})));
105
106
107
      }
    };

Praetorius, Simon's avatar
Praetorius, Simon committed
108
109
110
111

    template <class T>
    struct Clamp
    {
112
      constexpr Clamp(T const& lo, T const& hi)
Praetorius, Simon's avatar
Praetorius, Simon committed
113
114
115
        : lo_(lo)
        , hi_(hi)
      {
116
        // assert(lo < hi);
Praetorius, Simon's avatar
Praetorius, Simon committed
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
      }

      constexpr auto operator() (T const& v) const
      {
        return v < lo_ ? lo_ : hi_ < v ? hi_ : v;
      }

      struct DClamp
      {
        constexpr auto operator() (T const& v) const
        {
          return v < lo_ ? T(0) : hi_ < v ? T(0) : T(1);
        }

        T lo_, hi_;
      };

      constexpr friend auto partial(Clamp c, index_t<0>)
      {
        return DClamp{c.lo_,c.hi_};
      }

      T lo_, hi_;
    };

142
143
144
145
    /** @} **/

  } // end namespace Operation
} // end namespace AMDiS