math_utils.txx 6.0 KB

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