quad_utils.txx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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 <iostream>
  10. #include <iomanip>
  11. #include <vector>
  12. QuadReal_t atoquad(const char* str){
  13. size_t i=0;
  14. QuadReal_t sign=1.0;
  15. for(;str[i]!='\0';i++){
  16. char c=str[i];
  17. if(c=='-') sign=-sign;
  18. if(c>='0' && c<='9') break;
  19. }
  20. QuadReal_t val=0.0;
  21. for(;str[i]!='\0';i++){
  22. char c=str[i];
  23. if(c>='0' && c<='9') val=val*10+(c-'0');
  24. else break;
  25. }
  26. if(str[i]=='.'){
  27. i++;
  28. QuadReal_t exp=1.0;exp/=10;
  29. for(;str[i]!='\0';i++){
  30. char c=str[i];
  31. if(c>='0' && c<='9') val=val+(c-'0')*exp;
  32. else break;
  33. exp/=10;
  34. }
  35. }
  36. return sign*val;
  37. }
  38. QuadReal_t fabs(const QuadReal_t& f){
  39. if(f>=0.0) return f;
  40. else return -f;
  41. }
  42. QuadReal_t sqrt(const QuadReal_t& a){
  43. QuadReal_t b=sqrt((double)a);
  44. b=b+(a/b-b)*0.5;
  45. b=b+(a/b-b)*0.5;
  46. return b;
  47. }
  48. QuadReal_t sin(const QuadReal_t& a){
  49. const size_t 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];
  66. for(int i=N-2;i>=0;i--){
  67. sinval[i]=2.0*sinval[i+1]*cosval[i+1];
  68. cosval[i]=sqrt(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. QuadReal_t cos(const QuadReal_t& a){
  87. const size_t N=200;
  88. static std::vector<QuadReal_t> theta;
  89. static std::vector<QuadReal_t> sinval;
  90. static std::vector<QuadReal_t> cosval;
  91. if(theta.size()==0){
  92. #pragma omp critical (QUAD_COS)
  93. if(theta.size()==0){
  94. theta.resize(N);
  95. sinval.resize(N);
  96. cosval.resize(N);
  97. QuadReal_t t=1.0;
  98. for(int i=0;i<N;i++){
  99. theta[i]=t;
  100. t=t*0.5;
  101. }
  102. sinval[N-1]=theta[N-1];
  103. cosval[N-1]=1.0-sinval[N-1]*sinval[N-1];
  104. for(int i=N-2;i>=0;i--){
  105. sinval[i]=2.0*sinval[i+1]*cosval[i+1];
  106. cosval[i]=sqrt(1.0-sinval[i]*sinval[i]);
  107. }
  108. }
  109. }
  110. QuadReal_t t=(a<0.0?-a:a);
  111. QuadReal_t sval=0.0;
  112. QuadReal_t cval=1.0;
  113. for(int i=0;i<N;i++){
  114. while(theta[i]<=t){
  115. QuadReal_t sval_=sval*cosval[i]+cval*sinval[i];
  116. QuadReal_t cval_=cval*cosval[i]-sval*sinval[i];
  117. sval=sval_;
  118. cval=cval_;
  119. t=t-theta[i];
  120. }
  121. }
  122. return cval;
  123. }
  124. QuadReal_t exp(const QuadReal_t& a){
  125. const size_t N=200;
  126. static std::vector<QuadReal_t> theta0;
  127. static std::vector<QuadReal_t> theta1;
  128. static std::vector<QuadReal_t> expval0;
  129. static std::vector<QuadReal_t> expval1;
  130. if(theta0.size()==0){
  131. #pragma omp critical (QUAD_EXP)
  132. if(theta0.size()==0){
  133. theta0.resize(N);
  134. theta1.resize(N);
  135. expval0.resize(N);
  136. expval1.resize(N);
  137. theta0[0]=1.0;
  138. theta1[0]=1.0;
  139. expval0[0]=const_e<QuadReal_t>();
  140. expval1[0]=const_e<QuadReal_t>();
  141. for(int i=1;i<N;i++){
  142. theta0[i]=theta0[i-1]*0.5;
  143. theta1[i]=theta1[i-1]*2.0;
  144. expval0[i]=sqrt(expval0[i-1]);
  145. expval1[i]=expval1[i-1]*expval1[i-1];
  146. }
  147. }
  148. }
  149. QuadReal_t t=(a<0.0?-a:a);
  150. QuadReal_t eval=1.0;
  151. for(int i=N-1;i>0;i--){
  152. while(theta1[i]<=t){
  153. eval=eval*expval1[i];
  154. t=t-theta1[i];
  155. }
  156. }
  157. for(int i=0;i<N;i++){
  158. while(theta0[i]<=t){
  159. eval=eval*expval0[i];
  160. t=t-theta0[i];
  161. }
  162. }
  163. eval=eval*(1.0+t);
  164. return (a<0.0?1.0/eval:eval);
  165. return eval;
  166. }
  167. std::ostream& operator<<(std::ostream& output, const QuadReal_t& q_){
  168. int width=output.width();
  169. output<<std::setw(1);
  170. QuadReal_t q=q_;
  171. if(q<0.0){
  172. output<<"-";
  173. q=-q;
  174. }else if(q>0){
  175. output<<" ";
  176. }else{
  177. output<<" ";
  178. output<<"0.0";
  179. return output;
  180. }
  181. int exp=0;
  182. static const QuadReal_t ONETENTH=(QuadReal_t)1/10;
  183. while(q<1.0 && abs(exp)<10000){
  184. q=q*10;
  185. exp--;
  186. }
  187. while(q>=10 && abs(exp)<10000){
  188. q=q*ONETENTH;
  189. exp++;
  190. }
  191. for(size_t i=0;i<34;i++){
  192. output<<(int)q;
  193. if(i==0) output<<".";
  194. q=(q-int(q))*10;
  195. if(q==0 && i>0) break;
  196. }
  197. if(exp>0){
  198. std::cout<<"e+"<<exp;
  199. }else if(exp<0){
  200. std::cout<<"e"<<exp;
  201. }
  202. return output;
  203. }