math_utils.txx 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. #include <omp.h>
  2. #include <cmath>
  3. #include <cstdlib>
  4. #include <iostream>
  5. #include <iomanip>
  6. #include <vector>
  7. namespace SCTL_NAMESPACE {
  8. template <class Real> inline Real atoreal(const char* str) { // Warning: does not do correct rounding
  9. int i = 0;
  10. Real sign = 1.0;
  11. for (; str[i] != '\0'; i++) {
  12. char c = str[i];
  13. if (c == '-') sign = -sign;
  14. if (c >= '0' && c <= '9') break;
  15. }
  16. Real val = 0.0;
  17. for (; str[i] != '\0'; i++) {
  18. char c = str[i];
  19. if (c >= '0' && c <= '9')
  20. val = val * 10 + (c - '0');
  21. else
  22. break;
  23. }
  24. if (str[i] == '.') {
  25. i++;
  26. Real exp = 1.0;
  27. exp /= 10;
  28. for (; str[i] != '\0'; i++) {
  29. char c = str[i];
  30. if (c >= '0' && c <= '9')
  31. val = val + (c - '0') * exp;
  32. else
  33. break;
  34. exp /= 10;
  35. }
  36. }
  37. return sign * val;
  38. }
  39. template <class Real> inline Real const_pi_generic() {
  40. static Real pi = atoreal<Real>("3.1415926535897932384626433832795028841");
  41. return pi;
  42. }
  43. template <class Real> inline Real const_e_generic() {
  44. static Real e = atoreal<Real>("2.7182818284590452353602874713526624977");
  45. return e;
  46. }
  47. template <class Real> inline Real fabs_generic(const Real a) {
  48. if (a >= 0.0)
  49. return a;
  50. else
  51. return -a;
  52. }
  53. template <class Real> inline Real sqrt_generic(const Real a) {
  54. Real b = ::sqrt((double)a);
  55. if (a > 0) {
  56. b = (b + a / b) * 0.5;
  57. b = (b + a / b) * 0.5;
  58. }
  59. return b;
  60. }
  61. template <class Real> inline Real sin_generic(const Real a) {
  62. const int N = 200;
  63. static std::vector<Real> theta;
  64. static std::vector<Real> sinval;
  65. static std::vector<Real> cosval;
  66. if (theta.size() == 0) {
  67. #pragma omp critical(QUAD_SIN)
  68. if (theta.size() == 0) {
  69. sinval.resize(N);
  70. cosval.resize(N);
  71. Real t = 1.0;
  72. std::vector<Real> theta_(N);
  73. for (int i = 0; i < N; i++) {
  74. theta_[i] = t;
  75. t = t * 0.5;
  76. }
  77. sinval[N - 1] = theta_[N - 1];
  78. cosval[N - 1] = 1.0 - sinval[N - 1] * sinval[N - 1] / 2;
  79. for (int i = N - 2; i >= 0; i--) {
  80. sinval[i] = 2.0 * sinval[i + 1] * cosval[i + 1];
  81. cosval[i] = sqrt<Real>(1.0 - sinval[i] * sinval[i]);
  82. }
  83. theta_.swap(theta);
  84. }
  85. }
  86. Real t = (a < 0.0 ? -a : a);
  87. Real sval = 0.0;
  88. Real cval = 1.0;
  89. for (int i = 0; i < N; i++) {
  90. while (theta[i] <= t) {
  91. Real sval_ = sval * cosval[i] + cval * sinval[i];
  92. Real cval_ = cval * cosval[i] - sval * sinval[i];
  93. sval = sval_;
  94. cval = cval_;
  95. t = t - theta[i];
  96. }
  97. }
  98. return (a < 0.0 ? -sval : sval);
  99. }
  100. template <class Real> inline Real cos_generic(const Real a) {
  101. const int N = 200;
  102. static std::vector<Real> theta;
  103. static std::vector<Real> sinval;
  104. static std::vector<Real> cosval;
  105. if (theta.size() == 0) {
  106. #pragma omp critical(QUAD_COS)
  107. if (theta.size() == 0) {
  108. sinval.resize(N);
  109. cosval.resize(N);
  110. Real t = 1.0;
  111. std::vector<Real> theta_(N);
  112. for (int i = 0; i < N; i++) {
  113. theta_[i] = t;
  114. t = t * 0.5;
  115. }
  116. sinval[N - 1] = theta_[N - 1];
  117. cosval[N - 1] = 1.0 - sinval[N - 1] * sinval[N - 1] / 2;
  118. for (int i = N - 2; i >= 0; i--) {
  119. sinval[i] = 2.0 * sinval[i + 1] * cosval[i + 1];
  120. cosval[i] = sqrt<Real>(1.0 - sinval[i] * sinval[i]);
  121. }
  122. theta_.swap(theta);
  123. }
  124. }
  125. Real t = (a < 0.0 ? -a : a);
  126. Real sval = 0.0;
  127. Real cval = 1.0;
  128. for (int i = 0; i < N; i++) {
  129. while (theta[i] <= t) {
  130. Real sval_ = sval * cosval[i] + cval * sinval[i];
  131. Real cval_ = cval * cosval[i] - sval * sinval[i];
  132. sval = sval_;
  133. cval = cval_;
  134. t = t - theta[i];
  135. }
  136. }
  137. return cval;
  138. }
  139. template <class Real> inline Real exp_generic(const Real a) {
  140. const int N = 200;
  141. static std::vector<Real> theta0;
  142. static std::vector<Real> theta1;
  143. static std::vector<Real> expval0;
  144. static std::vector<Real> expval1;
  145. if (theta0.size() == 0) {
  146. #pragma omp critical(QUAD_EXP)
  147. if (theta0.size() == 0) {
  148. std::vector<Real> theta0_(N);
  149. theta1.resize(N);
  150. expval0.resize(N);
  151. expval1.resize(N);
  152. theta0_[0] = 1.0;
  153. theta1[0] = 1.0;
  154. expval0[0] = const_e<Real>();
  155. expval1[0] = const_e<Real>();
  156. for (int i = 1; i < N; i++) {
  157. theta0_[i] = theta0_[i - 1] * 0.5;
  158. theta1[i] = theta1[i - 1] * 2.0;
  159. expval0[i] = sqrt<Real>(expval0[i - 1]);
  160. expval1[i] = expval1[i - 1] * expval1[i - 1];
  161. }
  162. theta0.swap(theta0_);
  163. }
  164. }
  165. Real t = (a < 0.0 ? -a : a);
  166. Real eval = 1.0;
  167. for (int i = N - 1; i > 0; i--) {
  168. while (theta1[i] <= t) {
  169. eval = eval * expval1[i];
  170. t = t - theta1[i];
  171. }
  172. }
  173. for (int i = 0; i < N; i++) {
  174. while (theta0[i] <= t) {
  175. eval = eval * expval0[i];
  176. t = t - theta0[i];
  177. }
  178. }
  179. eval = eval * (1.0 + t);
  180. return (a < 0.0 ? 1.0 / eval : eval);
  181. }
  182. template <class Real> inline Real log_generic(const Real a) {
  183. Real y0 = ::log((double)a);
  184. y0 = y0 + (a / exp<Real>(y0) - 1.0);
  185. y0 = y0 + (a / exp<Real>(y0) - 1.0);
  186. return y0;
  187. }
  188. template <class Real> inline Real pow_generic(const Real b, const Real e) {
  189. if (e == 0) return 1;
  190. if (b == 0) return 0;
  191. if (b < 0) {
  192. Long e_ = (Long)e;
  193. SCTL_ASSERT(e == (Real)e_);
  194. return exp<Real>(log<Real>(-b) * e) * (e_ % 2 ? (Real)-1 : (Real)1.0);
  195. }
  196. return exp<Real>(log<Real>(b) * e);
  197. }
  198. template <class Real> inline std::ostream& ostream_insertion_generic(std::ostream& output, const Real q_) {
  199. // int width=output.width();
  200. output << std::setw(1);
  201. Real q = q_;
  202. if (q < 0.0) {
  203. output << "-";
  204. q = -q;
  205. } else if (q > 0) {
  206. output << " ";
  207. } else {
  208. output << " ";
  209. output << "0.0";
  210. return output;
  211. }
  212. int exp = 0;
  213. static const Real ONETENTH = (Real)1 / 10;
  214. while (q < 1.0 && abs(exp) < 10000) {
  215. q = q * 10;
  216. exp--;
  217. }
  218. while (q >= 10 && abs(exp) < 10000) {
  219. q = q * ONETENTH;
  220. exp++;
  221. }
  222. for (int i = 0; i < 34; i++) {
  223. output << (int)q;
  224. if (i == 0) output << ".";
  225. q = (q - int(q)) * 10;
  226. if (q == 0 && i > 0) break;
  227. }
  228. if (exp > 0) {
  229. std::cout << "e+" << exp;
  230. } else if (exp < 0) {
  231. std::cout << "e" << exp;
  232. }
  233. return output;
  234. }
  235. } // end namespace
  236. namespace SCTL_NAMESPACE {
  237. //template <> inline long double const_pi<long double>() { return const_pi_generic<long double>(); }
  238. //template <> inline long double const_e<long double>() { return const_e_generic<long double>(); }
  239. template <> inline long double fabs<long double>(const long double a) { return fabs_generic(a); }
  240. template <> inline long double sqrt<long double>(const long double a) { return sqrt_generic(a); }
  241. template <> inline long double sin<long double>(const long double a) { return sin_generic(a); }
  242. template <> inline long double cos<long double>(const long double a) { return cos_generic(a); }
  243. template <> inline long double exp<long double>(const long double a) { return exp_generic(a); }
  244. //template <> inline long double log<long double>(const long double a) { return log_generic(a); }
  245. //template <> inline long double pow<long double>(const long double b, const long double e) { return pow_generic(b, e); }
  246. } // end namespace
  247. #ifdef SCTL_QUAD_T
  248. namespace SCTL_NAMESPACE {
  249. template <> inline QuadReal const_pi<QuadReal>() { return const_pi_generic<QuadReal>(); }
  250. template <> inline QuadReal const_e<QuadReal>() { return const_e_generic<QuadReal>(); }
  251. template <> inline QuadReal fabs<QuadReal>(const QuadReal a) { return fabs_generic(a); }
  252. template <> inline QuadReal sqrt<QuadReal>(const QuadReal a) { return sqrt_generic(a); }
  253. template <> inline QuadReal sin<QuadReal>(const QuadReal a) { return sin_generic(a); }
  254. template <> inline QuadReal cos<QuadReal>(const QuadReal a) { return cos_generic(a); }
  255. template <> inline QuadReal exp<QuadReal>(const QuadReal a) { return exp_generic(a); }
  256. template <> inline QuadReal log<QuadReal>(const QuadReal a) { return log_generic(a); }
  257. template <> inline QuadReal pow<QuadReal>(const QuadReal b, const QuadReal e) { return pow_generic(b, e); }
  258. inline std::ostream& operator<<(std::ostream& output, const QuadReal q) { return ostream_insertion_generic(output, q); }
  259. } // end namespace
  260. inline std::ostream& operator<<(std::ostream& output, const SCTL_QUAD_T q) { return SCTL_NAMESPACE::ostream_insertion_generic(output, q); }
  261. #endif // SCTL_QUAD_T
  262. //namespace SCTL_NAMESPACE {
  263. //template <class Real> inline unsigned int pow(const unsigned int b, const unsigned int e) {
  264. // unsigned int r = 1;
  265. // for (unsigned int i = 0; i < e; i++) r *= b;
  266. // return r;
  267. //}
  268. //}