math_utils.cpp 5.7 KB

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