github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/common/math/internal/math_template.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/common.h" 22 #include "common/math/softfloat.hpp" 23 #include <functional> 24 25 #define MATH_MIN 1e-5 26 27 namespace neb { 28 namespace math { 29 30 namespace internal { 31 32 template <typename T> T __get_pi() { 33 T zero = softfloat_cast<uint32_t, typename T::value_type>(0); 34 T one = softfloat_cast<uint32_t, typename T::value_type>(1); 35 T two = softfloat_cast<uint32_t, typename T::value_type>(2); 36 T four = softfloat_cast<uint32_t, typename T::value_type>(4); 37 38 T ret = zero; 39 T i = one; 40 bool odd = true; 41 42 while (true) { 43 T tmp; 44 auto x = four / i; 45 if (odd) { 46 tmp = ret + x; 47 } else { 48 tmp = ret - x; 49 } 50 if (tmp - ret < MATH_MIN && ret - tmp < MATH_MIN) { 51 break; 52 } 53 ret = tmp; 54 i += two; 55 odd = !odd; 56 } 57 return ret; 58 } 59 60 template <typename T> T __fast_get_pi() { 61 T one = softfloat_cast<uint32_t, typename T::value_type>(1); 62 T two = softfloat_cast<uint32_t, typename T::value_type>(2); 63 T four = softfloat_cast<uint32_t, typename T::value_type>(4); 64 65 T ret = one + two; 66 T i = two; 67 bool odd = true; 68 while (true) { 69 T tmp; 70 auto tail = four / (i * (i + one) * (i + two)); 71 if (odd) { 72 tmp = ret + tail; 73 } else { 74 tmp = ret - tail; 75 } 76 if (tmp - ret < MATH_MIN && ret - tmp < MATH_MIN) { 77 break; 78 } 79 ret = tmp; 80 i += two; 81 odd = !odd; 82 } 83 return ret; 84 } 85 86 template <typename T> T __get_e() { 87 T one = softfloat_cast<uint32_t, typename T::value_type>(1); 88 T ret = one; 89 90 T i = one; 91 T prev = one; 92 93 while (true) { 94 T tmp; 95 96 tmp = ret + one / prev; 97 if (tmp - ret < MATH_MIN && ret - tmp < MATH_MIN) { 98 break; 99 } 100 ret = tmp; 101 i += one; 102 prev = prev * i; 103 } 104 105 return ret; 106 } 107 108 template <typename T> T __get_ln2() { 109 T zero = softfloat_cast<uint32_t, typename T::value_type>(0); 110 T one = softfloat_cast<uint32_t, typename T::value_type>(1); 111 112 T ret = zero; 113 T i = one; 114 bool odd = true; 115 116 while (true) { 117 T tmp; 118 if (odd) { 119 tmp = ret + one / i; 120 } else { 121 tmp = ret - one / i; 122 } 123 124 if (tmp - ret < MATH_MIN && ret - tmp < MATH_MIN) { 125 break; 126 } 127 ret = tmp; 128 i += one; 129 odd = !odd; 130 } 131 return ret; 132 } 133 134 template <typename T> T __fast_get_ln2() { 135 T zero = softfloat_cast<uint32_t, typename T::value_type>(0); 136 T one = softfloat_cast<uint32_t, typename T::value_type>(1); 137 T two = softfloat_cast<uint32_t, typename T::value_type>(2); 138 139 auto func = [&](T x) { 140 T ret = zero; 141 T s = two * x; 142 T i = one; 143 T x2 = x * x; 144 145 while (true) { 146 T tmp; 147 148 tmp = ret + s / i; 149 if (tmp - ret < MATH_MIN && ret - tmp < MATH_MIN) { 150 break; 151 } 152 153 ret = tmp; 154 i += two; 155 s = s * x2; 156 } 157 return ret; 158 }; 159 160 return func((two - one) / (two + one)); 161 } 162 163 } // namespace internal 164 165 template <typename T> class constants { 166 public: 167 static T pi() { 168 std::call_once(s_init_once, std::bind(constants<T>::init)); 169 return s_pi; 170 } 171 static T ln2() { 172 std::call_once(s_init_once, std::bind(constants<T>::init)); 173 return s_ln2; 174 } 175 static T e() { 176 std::call_once(s_init_once, std::bind(constants<T>::init)); 177 return s_e; 178 } 179 180 protected: 181 static void init() { 182 s_pi = internal::__fast_get_pi<T>(); 183 s_ln2 = internal::__fast_get_ln2<T>(); 184 s_e = internal::__get_e<T>(); 185 } 186 static T s_pi; 187 static T s_ln2; 188 static T s_e; 189 static std::once_flag s_init_once; 190 }; 191 192 template <typename T> T constants<T>::s_pi; 193 template <typename T> T constants<T>::s_ln2; 194 template <typename T> T constants<T>::s_e; 195 template <typename T> std::once_flag constants<T>::s_init_once; 196 } // namespace math 197 } // namespace neb