quad_utils.txx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /**
  2. * \file quad_utils.txx
  3. * \author Dhairya Malhotra, dhairya.malhotra@gmail.com
  4. * \date 7-16-2014
  5. * \brief This file contains quadruple-precision related functions.
  6. */
  7. #include <omp.h>
  8. #include <cmath>
  9. #include <cstdlib>
  10. #include <iostream>
  11. #include <iomanip>
  12. #include <vector>
  13. QuadReal_t atoquad(const char* str){
  14. size_t i=0;
  15. QuadReal_t sign=1.0;
  16. for(;str[i]!='\0';i++){
  17. char c=str[i];
  18. if(c=='-') sign=-sign;
  19. if(c>='0' && c<='9') break;
  20. }
  21. QuadReal_t val=0.0;
  22. for(;str[i]!='\0';i++){
  23. char c=str[i];
  24. if(c>='0' && c<='9') val=val*10+(c-'0');
  25. else break;
  26. }
  27. if(str[i]=='.'){
  28. i++;
  29. QuadReal_t exp=1.0;exp/=10;
  30. for(;str[i]!='\0';i++){
  31. char c=str[i];
  32. if(c>='0' && c<='9') val=val+(c-'0')*exp;
  33. else break;
  34. exp/=10;
  35. }
  36. }
  37. return sign*val;
  38. }
  39. QuadReal_t fabs(const QuadReal_t& f){
  40. if(f>=0.0) return f;
  41. else return -f;
  42. }
  43. QuadReal_t sqrt(const QuadReal_t& a){
  44. QuadReal_t b=sqrt((double)a);
  45. b=(b+a/b)*0.5;
  46. b=(b+a/b)*0.5;
  47. return b;
  48. }
  49. QuadReal_t sin(const QuadReal_t& a){
  50. const size_t N=200;
  51. static std::vector<QuadReal_t> theta;
  52. static std::vector<QuadReal_t> sinval;
  53. static std::vector<QuadReal_t> cosval;
  54. if(theta.size()==0){
  55. #pragma omp critical (QUAD_SIN)
  56. if(theta.size()==0){
  57. theta.resize(N);
  58. sinval.resize(N);
  59. cosval.resize(N);
  60. QuadReal_t t=1.0;
  61. for(int i=0;i<N;i++){
  62. theta[i]=t;
  63. t=t*0.5;
  64. }
  65. sinval[N-1]=theta[N-1];
  66. cosval[N-1]=1.0-sinval[N-1]*sinval[N-1];
  67. for(int i=N-2;i>=0;i--){
  68. sinval[i]=2.0*sinval[i+1]*cosval[i+1];
  69. cosval[i]=sqrt(1.0-sinval[i]*sinval[i]);
  70. }
  71. }
  72. }
  73. QuadReal_t t=(a<0.0?-a:a);
  74. QuadReal_t sval=0.0;
  75. QuadReal_t cval=1.0;
  76. for(int i=0;i<N;i++){
  77. while(theta[i]<=t){
  78. QuadReal_t sval_=sval*cosval[i]+cval*sinval[i];
  79. QuadReal_t cval_=cval*cosval[i]-sval*sinval[i];
  80. sval=sval_;
  81. cval=cval_;
  82. t=t-theta[i];
  83. }
  84. }
  85. return (a<0.0?-sval:sval);
  86. }
  87. QuadReal_t cos(const QuadReal_t& a){
  88. const size_t 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];
  105. for(int i=N-2;i>=0;i--){
  106. sinval[i]=2.0*sinval[i+1]*cosval[i+1];
  107. cosval[i]=sqrt(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. QuadReal_t exp(const QuadReal_t& a){
  126. const size_t N=200;
  127. static std::vector<QuadReal_t> theta0;
  128. static std::vector<QuadReal_t> theta1;
  129. static std::vector<QuadReal_t> expval0;
  130. static std::vector<QuadReal_t> expval1;
  131. if(theta0.size()==0){
  132. #pragma omp critical (QUAD_EXP)
  133. if(theta0.size()==0){
  134. theta0.resize(N);
  135. theta1.resize(N);
  136. expval0.resize(N);
  137. expval1.resize(N);
  138. theta0[0]=1.0;
  139. theta1[0]=1.0;
  140. expval0[0]=const_e<QuadReal_t>();
  141. expval1[0]=const_e<QuadReal_t>();
  142. for(int i=1;i<N;i++){
  143. theta0[i]=theta0[i-1]*0.5;
  144. theta1[i]=theta1[i-1]*2.0;
  145. expval0[i]=sqrt(expval0[i-1]);
  146. expval1[i]=expval1[i-1]*expval1[i-1];
  147. }
  148. }
  149. }
  150. QuadReal_t t=(a<0.0?-a:a);
  151. QuadReal_t eval=1.0;
  152. for(int i=N-1;i>0;i--){
  153. while(theta1[i]<=t){
  154. eval=eval*expval1[i];
  155. t=t-theta1[i];
  156. }
  157. }
  158. for(int i=0;i<N;i++){
  159. while(theta0[i]<=t){
  160. eval=eval*expval0[i];
  161. t=t-theta0[i];
  162. }
  163. }
  164. eval=eval*(1.0+t);
  165. return (a<0.0?1.0/eval:eval);
  166. }
  167. QuadReal_t log(const QuadReal_t& a){
  168. QuadReal_t y0=log((double)a);
  169. y0=y0+(a/exp(y0)-1.0);
  170. y0=y0+(a/exp(y0)-1.0);
  171. return y0;
  172. }
  173. std::ostream& operator<<(std::ostream& output, const QuadReal_t& q_){
  174. int width=output.width();
  175. output<<std::setw(1);
  176. QuadReal_t q=q_;
  177. if(q<0.0){
  178. output<<"-";
  179. q=-q;
  180. }else if(q>0){
  181. output<<" ";
  182. }else{
  183. output<<" ";
  184. output<<"0.0";
  185. return output;
  186. }
  187. int exp=0;
  188. static const QuadReal_t ONETENTH=(QuadReal_t)1/10;
  189. while(q<1.0 && abs(exp)<10000){
  190. q=q*10;
  191. exp--;
  192. }
  193. while(q>=10 && abs(exp)<10000){
  194. q=q*ONETENTH;
  195. exp++;
  196. }
  197. for(size_t i=0;i<34;i++){
  198. output<<(int)q;
  199. if(i==0) output<<".";
  200. q=(q-int(q))*10;
  201. if(q==0 && i>0) break;
  202. }
  203. if(exp>0){
  204. std::cout<<"e+"<<exp;
  205. }else if(exp<0){
  206. std::cout<<"e"<<exp;
  207. }
  208. return output;
  209. }