github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/common/math/internal/math_extension.h (about) 1 // Copyright (C) 2018 go-nebulas authors 2 // 3 // This file is part of the go-nebulas library. 4 // 5 // the go-nebulas library is free software: you can redistribute it and/or 6 // 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 // the go-nebulas library 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 the go-nebulas library. If not, see 18 // <http://www.gnu.org/licenses/>. 19 // 20 #pragma once 21 #include "common/math/internal/math_template.h" 22 23 namespace neb { 24 namespace math { 25 26 template <typename T> T min(const T &x, const T &y) { return x < y ? x : y; } 27 template <typename T> T max(const T &x, const T &y) { return x > y ? x : y; } 28 29 template <typename T> T abs(const T &x, const T &y) { 30 T delta = x - y; 31 return delta > 0 ? delta : 0 - delta; 32 } 33 34 template <typename T> std::string to_string(const T &val) { 35 std::stringstream ss; 36 ss << val; 37 return ss.str(); 38 } 39 template <typename T> T from_string(const std::string &str) { 40 std::stringstream ss(str); 41 T val; 42 ss >> val; 43 return val; 44 } 45 46 template <typename T> bool exit_cond(const T &x, const T &y) { 47 if (x - y < MATH_MIN && y - x < MATH_MIN) { 48 return true; 49 } 50 if (to_string(x) == std::string("inf") && 51 to_string(y) == std::string("inf")) { 52 return true; 53 } 54 if (to_string(x) == std::string("-nan") && 55 to_string(y) == std::string("-nan")) { 56 return true; 57 } 58 return false; 59 } 60 61 template <typename T> T exp(const T &x) { 62 T zero = softfloat_cast<uint32_t, typename T::value_type>(0); 63 T one = softfloat_cast<uint32_t, typename T::value_type>(1); 64 65 if (x < zero) { 66 return one / exp(-x); 67 } 68 69 T ret = one; 70 T i = one; 71 T tail = x; 72 73 while (true) { 74 T tmp; 75 76 tmp = ret + tail; 77 if (exit_cond(tmp, ret)) { 78 break; 79 } 80 81 ret = tmp; 82 i += one; 83 tail *= x / i; 84 } 85 86 return ret; 87 } 88 89 template <typename T> T arctan(const T &x) { 90 T zero = softfloat_cast<uint32_t, typename T::value_type>(0); 91 T one = softfloat_cast<uint32_t, typename T::value_type>(1); 92 T two = softfloat_cast<uint32_t, typename T::value_type>(2); 93 T half_pi = constants<T>::pi() / two; 94 95 if (x > one) { 96 return half_pi - arctan(one / x); 97 } else if (x < zero - one) { 98 return zero - half_pi - arctan(one / x); 99 } 100 101 T x2 = x * x; 102 T ret = zero; 103 T i = one; 104 T s = x; 105 bool odd = false; 106 107 while (true) { 108 T tmp; 109 if (odd) { 110 tmp = ret - s / i; 111 } else { 112 tmp = ret + s / i; 113 } 114 if (exit_cond(tmp, ret)) { 115 break; 116 } 117 ret = tmp; 118 odd = !odd; 119 i += two; 120 s = s * x2; 121 } 122 return ret; 123 } 124 125 template <typename T> T sin(const T &x) { 126 T zero = softfloat_cast<uint32_t, typename T::value_type>(0); 127 if (x < zero) { 128 return zero - sin(zero - x); 129 } 130 131 T one = softfloat_cast<uint32_t, typename T::value_type>(1); 132 T two = softfloat_cast<uint32_t, typename T::value_type>(2); 133 T double_pi = two * constants<T>::pi(); 134 if (x > double_pi) { 135 T tmp = (x / double_pi).integer_val(); 136 return sin(x - tmp * double_pi); 137 } 138 139 T x2 = x * x; 140 T ret = zero; 141 T i = one; 142 T tail = x; 143 bool odd = false; 144 145 while (true) { 146 T tmp; 147 if (odd) { 148 tmp = ret - tail; 149 } else { 150 tmp = ret + tail; 151 } 152 if (exit_cond(tmp, ret)) { 153 break; 154 } 155 ret = tmp; 156 odd = !odd; 157 tail *= (x2 / ((i + one) * (i + two))); 158 i += two; 159 } 160 return ret; 161 } 162 163 template <typename T> T ln(const T &x) { 164 T zero = softfloat_cast<uint32_t, typename T::value_type>(0); 165 T one = softfloat_cast<uint32_t, typename T::value_type>(1); 166 T two = softfloat_cast<uint32_t, typename T::value_type>(2); 167 168 auto func = [&](T x) { 169 T ret = zero; 170 bool odd = true; 171 172 T s = x; 173 T i = one; 174 175 while (true) { 176 T tmp; 177 178 if (odd) { 179 tmp = ret + s / i; 180 } else { 181 tmp = ret - s / i; 182 } 183 if (exit_cond(tmp, ret)) { 184 break; 185 } 186 187 ret = tmp; 188 odd = !odd; 189 i += one; 190 s = s * x; 191 } 192 return ret; 193 }; 194 195 if (x > two) { 196 return zero - func(one / x - one); 197 } 198 return func(x - one); 199 } 200 201 template <typename T> T fast_ln(const T &x) { 202 T zero = softfloat_cast<uint32_t, typename T::value_type>(0); 203 T one = softfloat_cast<uint32_t, typename T::value_type>(1); 204 T two = softfloat_cast<uint32_t, typename T::value_type>(2); 205 206 auto func = [&](T x) { 207 T ret = zero; 208 T s = two * x; 209 T i = one; 210 T x2 = x * x; 211 212 while (true) { 213 T tmp; 214 215 tmp = ret + s / i; 216 if (exit_cond(tmp, ret)) { 217 break; 218 } 219 220 ret = tmp; 221 i += two; 222 s = s * x2; 223 } 224 return ret; 225 }; 226 227 return func((x - one) / (x + one)); 228 } 229 230 namespace internal { 231 union float16_detail_t { 232 float16_t v; 233 struct { 234 uint64_t ey : 10; 235 uint16_t exponent : 5; 236 uint8_t sign : 1; 237 } detail; 238 }; 239 union float32_detail_t { 240 float32_t v; 241 struct { 242 uint64_t fraction : 23; 243 uint16_t exponent : 8; 244 uint8_t sign : 1; 245 } detail; 246 }; 247 union float64_detail_t { 248 float64_t v; 249 struct { 250 uint64_t fraction : 52; 251 uint16_t exponent : 11; 252 uint8_t sign : 1; 253 } detail; 254 }; 255 union float128_detail_t { 256 float128_t v; 257 struct { 258 uint64_t fraction0 : 48; 259 uint64_t fraction1 : 64; 260 uint16_t exponent : 15; 261 uint8_t sign : 1; 262 } detail; 263 }; 264 265 template <typename T> struct float_detail {}; 266 template <> struct float_detail<float16> { 267 typedef float16_detail_t value_type; 268 constexpr static uint16_t bias = 15; 269 }; 270 template <> struct float_detail<float32> { 271 typedef float32_detail_t value_type; 272 constexpr static uint16_t bias = 127; 273 }; 274 template <> struct float_detail<float64> { 275 typedef float64_detail_t value_type; 276 constexpr static uint16_t bias = 1023; 277 }; 278 template <> struct float_detail<float128> { 279 typedef float128_detail_t value_type; 280 constexpr static uint16_t bias = 16383; 281 }; 282 283 template <typename T> struct float_math_helper { 284 typedef typename T::value_type value_type; 285 typedef typename float_detail<T>::value_type detail_type; 286 287 static T get_exponent(const T &x) { 288 detail_type dt; 289 dt.v = (T)x; 290 detail_type ret; 291 ret.detail.sign = dt.detail.sign; 292 ret.detail.exponent = dt.detail.exponent; 293 return T(ret.v); 294 } 295 static T get_one_plus_fraction(const T &x) { 296 detail_type dt; 297 dt.v = (T)x; 298 detail_type ret; 299 ret.v = dt.v; 300 ret.detail.exponent = detail_type::bias; 301 return T(ret.v); 302 } 303 }; 304 } // namespace internal 305 306 template <typename T> T log2(const T &x) { return ln(x) / constants<T>::ln2(); } 307 308 //! return x^y 309 template <typename T> T pow(const T &x, const T &y) { 310 return exp(y * fast_ln(x)); 311 } 312 313 template <typename T> T pow(const T &x, const int64_t &y) { 314 T one = softfloat_cast<uint32_t, typename T::value_type>(1); 315 if (y == 0) { 316 return one; 317 } 318 319 T ret = one; 320 T tmp_x = x; 321 uint64_t tmp_y = y > 0 ? y : -y; 322 323 while (tmp_y) { 324 if ((tmp_y & 0x1) == 1) { 325 ret *= tmp_x; 326 } 327 tmp_x *= tmp_x; 328 tmp_y >>= 1; 329 } 330 return y > 0 ? ret : one / ret; 331 } 332 333 // only applicable for float16 and float32 334 template <typename T> T sqrt(const T &x) { 335 T one = softfloat_cast<uint32_t, typename T::value_type>(1); 336 T two = softfloat_cast<uint32_t, typename T::value_type>(2); 337 T one_and_half = one + one / two; 338 T half_x = x / two; 339 340 typename T::value_type tmp_x = typename T::value_type(x); 341 uint32_t i = *reinterpret_cast<uint32_t *>(&tmp_x); 342 i = 0x5f3759df - (i >> 1); 343 tmp_x = *reinterpret_cast<typename T::value_type *>(&i); 344 T sqrt_x(tmp_x); 345 sqrt_x = sqrt_x * (one_and_half - half_x * sqrt_x * sqrt_x); 346 sqrt_x = sqrt_x * (one_and_half - half_x * sqrt_x * sqrt_x); 347 sqrt_x = sqrt_x * (one_and_half - half_x * sqrt_x * sqrt_x); 348 return one / sqrt_x; 349 } 350 } // namespace math 351 352 } // namespace neb