| 1 | #ifndef MATHUTIL_HPP |
| 2 | #define MATHUTIL_HPP |
| 3 | |
| 4 | #ifdef HAVE_LIBQUADMATH |
| 5 | #include <boost/multiprecision/float128.hpp> |
| 6 | #endif |
| 7 | |
| 8 | #include "util/cuda_util.hpp" |
| 9 | |
| 10 | namespace openfpm |
| 11 | { |
| 12 | namespace math |
| 13 | { |
| 14 | /*! \brief return the sign of an integer |
| 15 | * |
| 16 | * \param val integer |
| 17 | * |
| 18 | * \return the sign of the function |
| 19 | * |
| 20 | */ |
| 21 | template <typename T> |
| 22 | int sgn(T val) |
| 23 | { |
| 24 | return (T(0) < val) - (val < T(0)); |
| 25 | } |
| 26 | |
| 27 | /*! \brief calculate the factorial |
| 28 | * |
| 29 | * calculate the factorial of a number |
| 30 | * |
| 31 | * # Example |
| 32 | * \snippet mathutil_unit_test.hpp factorial usage |
| 33 | * |
| 34 | * \param f number |
| 35 | * \return the factorial |
| 36 | * |
| 37 | */ |
| 38 | static inline size_t factorial(size_t f) |
| 39 | { |
| 40 | size_t fc = 1; |
| 41 | |
| 42 | for (size_t s = 2 ; s <= f ; s++) |
| 43 | { |
| 44 | fc *= s; |
| 45 | } |
| 46 | |
| 47 | return fc; |
| 48 | } |
| 49 | |
| 50 | /*! \brief C(n,k) Combination of n objects taken on group of k elements |
| 51 | * |
| 52 | * C(n,k) Combination of n objects taken on group of k elements, defined as |
| 53 | * |
| 54 | * n!/(k!(n-k)!) |
| 55 | * |
| 56 | * # Example |
| 57 | * \snippet mathutil_unit_test.hpp Combination usage |
| 58 | * |
| 59 | * \param n |
| 60 | * \param k |
| 61 | * |
| 62 | */ |
| 63 | static inline size_t C(size_t n, size_t k) |
| 64 | { |
| 65 | return factorial(n)/(factorial(k)*factorial(n-k)); |
| 66 | } |
| 67 | |
| 68 | /*! \brief Round to the nearest bigger power of 2 number |
| 69 | * |
| 70 | * \param n number |
| 71 | * \return nearest bigger power of 2 number |
| 72 | * |
| 73 | * # Example |
| 74 | * \snippet mathutil_unit_test.hpp round to big pow |
| 75 | * |
| 76 | * |
| 77 | */ |
| 78 | static inline size_t round_big_2(size_t n) |
| 79 | { |
| 80 | n--; |
| 81 | n |= n >> 1; // Divide by 2^k for consecutive doublings of k up to 32, |
| 82 | n |= n >> 2; // and then or the results. |
| 83 | n |= n >> 4; |
| 84 | n |= n >> 8; |
| 85 | n |= n >> 16; |
| 86 | n++; |
| 87 | |
| 88 | return n; |
| 89 | } |
| 90 | |
| 91 | |
| 92 | /*! \brief It calculate at compile-time and runtime the power with recursion |
| 93 | * |
| 94 | * # Example |
| 95 | * \snippet mathutil_unit_test.hpp pow |
| 96 | * |
| 97 | * \tparam type of the pow expression |
| 98 | * |
| 99 | * \param base |
| 100 | * \param exponent |
| 101 | * |
| 102 | */ |
| 103 | |
| 104 | template<class T> |
| 105 | inline constexpr size_t pow(const T base, unsigned const exponent) |
| 106 | { |
| 107 | // (parentheses not required in next line) |
| 108 | return (exponent == 0) ? 1 : (base * pow(base, exponent-1)); |
| 109 | } |
| 110 | |
| 111 | /* \brief Return the positive modulo of a number |
| 112 | * |
| 113 | * # Example |
| 114 | * \snippet mathutil_unit_test.hpp positive modulo |
| 115 | * |
| 116 | * \param i number |
| 117 | * \param n modulo |
| 118 | * |
| 119 | */ |
| 120 | static inline long int positive_modulo(long int i, long int n) |
| 121 | { |
| 122 | return (i % n + n) % n; |
| 123 | } |
| 124 | |
| 125 | /*! \brief Bound the position to be inside p2 and p1 |
| 126 | * |
| 127 | * Given pos = 10.9, p2 = 1.0 and p1 = 0.1 and l = p2 - p1 = 1.0, |
| 128 | * it return 10.9 - (integer)( (10.9 - 0.1) / 1.0) * 1.0 |
| 129 | * |
| 130 | * # Example |
| 131 | * \snippet mathutil_unit_test.hpp periodic |
| 132 | * |
| 133 | * \param pos |
| 134 | * \param l |
| 135 | * \param b |
| 136 | * |
| 137 | * \return the bound number |
| 138 | * |
| 139 | */ |
| 140 | template<typename T> static inline T periodic(const T & pos, const T & p2, const T & p1) |
| 141 | { |
| 142 | T pos_tmp; |
| 143 | |
| 144 | pos_tmp = pos - (p2 - p1) * (long int)( (pos -p1) / (p2 - p1)); |
| 145 | pos_tmp += (pos < p1)?(p2 - p1):0; |
| 146 | |
| 147 | return pos_tmp; |
| 148 | } |
| 149 | |
| 150 | /*! \brief Bound the position to be inside p2 and p1 |
| 151 | * |
| 152 | * It is like periodic but faster |
| 153 | * |
| 154 | * \warning pos should not overshoot the domain more than one time, for example |
| 155 | * if p2 = 1.1 and p1 = 0.1, pos can be between 2.1 and -0.9 |
| 156 | * |
| 157 | * # Example |
| 158 | * \snippet mathutil_unit_test.hpp periodic_l |
| 159 | * |
| 160 | * \param pos |
| 161 | * \param l |
| 162 | * \param b |
| 163 | * |
| 164 | * \return the bound number |
| 165 | * |
| 166 | */ |
| 167 | template<typename T> __device__ __host__ static inline T periodic_l(const T & pos, const T & p2, const T & p1) |
| 168 | { |
| 169 | T pos_tmp = pos; |
| 170 | |
| 171 | if (pos >= p2) |
| 172 | { |
| 173 | pos_tmp = p1 + (pos - p2); |
| 174 | } |
| 175 | else if (pos < p1) |
| 176 | { |
| 177 | pos_tmp = p2 - (p1 - pos); |
| 178 | |
| 179 | // This is a round off error fix |
| 180 | // if the shift bring exactly on p2 p2 we back the particle to p1 |
| 181 | if (pos_tmp == p2) |
| 182 | pos_tmp = p1; |
| 183 | } |
| 184 | |
| 185 | return pos_tmp; |
| 186 | } |
| 187 | |
| 188 | /*! \brief floor math function |
| 189 | * |
| 190 | * |
| 191 | */ |
| 192 | inline long int size_t_floor(double x) |
| 193 | { |
| 194 | size_t i = (long int)x; /* truncate */ |
| 195 | return i - ( i > x ); /* convert trunc to floor */ |
| 196 | } |
| 197 | |
| 198 | /*! \brief floor math function |
| 199 | * |
| 200 | * |
| 201 | */ |
| 202 | inline long int size_t_floor(float x) |
| 203 | { |
| 204 | size_t i = (long int)x; /* truncate */ |
| 205 | return i - ( i > x ); /* convert trunc to floor */ |
| 206 | } |
| 207 | |
| 208 | /*! \brief floor math function |
| 209 | * |
| 210 | * |
| 211 | */ |
| 212 | __device__ __host__ inline int uint_floor(double x) |
| 213 | { |
| 214 | unsigned int i = (int)x; /* truncate */ |
| 215 | return i - ( i > x ); /* convert trunc to floor */ |
| 216 | } |
| 217 | |
| 218 | /*! \brief floor math function |
| 219 | * |
| 220 | * |
| 221 | */ |
| 222 | __device__ __host__ inline int uint_floor(float x) |
| 223 | { |
| 224 | unsigned int i = (int)x; /* truncate */ |
| 225 | return i - ( i > x ); /* convert trunc to floor */ |
| 226 | } |
| 227 | |
| 228 | const int tab64[64] = { |
| 229 | 63, 0, 58, 1, 59, 47, 53, 2, |
| 230 | 60, 39, 48, 27, 54, 33, 42, 3, |
| 231 | 61, 51, 37, 40, 49, 18, 28, 20, |
| 232 | 55, 30, 34, 11, 43, 14, 22, 4, |
| 233 | 62, 57, 46, 52, 38, 26, 32, 41, |
| 234 | 50, 36, 17, 19, 29, 10, 13, 21, |
| 235 | 56, 45, 25, 31, 35, 16, 9, 12, |
| 236 | 44, 24, 15, 8, 23, 7, 6, 5}; |
| 237 | |
| 238 | /*! \brief Calculate the logarith 2 of a 64 bit integer |
| 239 | * |
| 240 | * \param value |
| 241 | * |
| 242 | */ |
| 243 | inline int log2_64 (uint64_t value) |
| 244 | { |
| 245 | value |= value >> 1; |
| 246 | value |= value >> 2; |
| 247 | value |= value >> 4; |
| 248 | value |= value >> 8; |
| 249 | value |= value >> 16; |
| 250 | value |= value >> 32; |
| 251 | return tab64[((uint64_t)((value - (value >> 1))*0x07EDD5E59A4E28C2)) >> 58]; |
| 252 | } |
| 253 | |
| 254 | |
| 255 | #ifdef HAVE_LIBQUADMATH |
| 256 | |
| 257 | /*! \brief floor math function |
| 258 | * |
| 259 | * |
| 260 | */ |
| 261 | inline long int size_t_floor(boost::multiprecision::float128 x) |
| 262 | { |
| 263 | size_t i = (long int)x; /* truncate */ |
| 264 | return i - ( i > x ); /* convert trunc to floor */ |
| 265 | } |
| 266 | |
| 267 | #endif |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | #endif |
| 272 | |