Advertisement
Guest User

sinhatanh2

a guest
Oct 20th, 2018
149
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.75 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <float.h>
  4. #include <fenv.h>
  5. #include <typeinfo>
  6. #include <mpreal.h>
  7. #include <iomanip>
  8. #include <immintrin.h>
  9.  
  10. #define PREC 50
  11. #define ULP_THRESH 1
  12.  
  13. #define debug(msg, x) std::cout << std::scientific << std::setprecision(PREC) << msg << " = " << x << std::endl;
  14.  
  15. template<class R>
  16. R sinhatanh(R x)
  17. {
  18.     if (typeid(R) == typeid(float))
  19.         return sinhf(atanhf(x));
  20.     else if (typeid(R) == typeid(double))
  21.         return sinh(atanh(x));
  22.     else if (typeid(R) == typeid(long double))
  23.         return sinhl(atanhl(x));
  24.  
  25.     __builtin_unreachable();
  26. }
  27.  
  28. template<class R>
  29. R sinhatanh2_dijkstra(R x)
  30. {
  31.     if (typeid(R) == typeid(float))
  32.     {    
  33.         float u = 1 - fabsf(x);
  34.         return x/sqrtf(2*u - u*u);
  35.     }
  36.     else if (typeid(R) == typeid(double))
  37.     {
  38.         double u = 1 - fabs(x);
  39.         return x/sqrt(2*u - u*u);
  40.     }
  41.     else if (typeid(R) == typeid(long double))
  42.     {  
  43.         long double u = 1 - fabsl(x);
  44.         return x/sqrtl(2*u - u*u);
  45.     }
  46.     __builtin_unreachable();
  47. }
  48.  
  49. template<class R>
  50. R sinhatanh2_fma(R x)
  51. {
  52.     if (typeid(R) == typeid(float))
  53.     {  
  54.         __m128 mx  = _mm_set_ps(x  , x  ,  x ,  x );
  55.         __m128 one = _mm_set_ps(1.f, 1.f, 1.f, 1.f);
  56.         __m128 sq  = _mm_fnmadd_ps(mx, mx, one);
  57.         float r = * (float*) &sq;
  58.         return x/sqrtf(r);
  59.     }
  60.     else if (typeid(R) == typeid(double))
  61.     {    
  62.         __m128d mx  = _mm_set_pd(x , x);
  63.         __m128d one = _mm_set_pd(1., 1.);
  64.         __m128d sq  = _mm_fnmadd_pd(mx, mx, one);
  65.         double r = * (double*) &sq;
  66.         return x/sqrt(r);
  67.     }
  68.     else if (typeid(R) == typeid(long double))
  69.         return x/sqrtl(1 - x*x);
  70.  
  71.     __builtin_unreachable();
  72. }
  73.  
  74. template<class R>
  75. R coshatanh(R x)
  76. {
  77.     if (typeid(R) == typeid(float))
  78.         return coshf(atanhf(x));
  79.     else if (typeid(R) == typeid(double))
  80.         return cosh(atanh(x));
  81.     else if (typeid(R) == typeid(long double))
  82.         return coshl(atanhl(x));
  83.  
  84.     __builtin_unreachable();
  85. }
  86.  
  87. template<class R>
  88. R coshatanh2_dijkstra(R x)
  89. {
  90.     R ret;
  91.     if (typeid(R) == typeid(float))
  92.     {
  93.         double u = 1 - fabs(x);
  94.         double sqrtr = sqrtf(2*u - u*u);
  95.         ret =  1/sqrtr;
  96.     }
  97.     else if (typeid(R) == typeid(double))
  98.     {
  99.         double u = 1 - fabs(x);
  100.         ret =  1/sqrt(2*u - u*u);
  101.     }
  102.     else if (typeid(R) == typeid(long double))
  103.     {  
  104.         long double u = 1 - fabsl(x);
  105.         ret = 1/sqrtl(2*u - u*u);
  106.     }
  107.     return ret;
  108. }
  109.  
  110. template<class R>
  111. R coshatanh2_fma(R x)
  112. {
  113.     if (typeid(R) == typeid(float))
  114.     {  
  115.         __m128 mx  = _mm_set_ps(x  , x  ,  x ,  x );
  116.         __m128 one = _mm_set_ps(1.f, 1.f, 1.f, 1.f);
  117.         __m128 sq  = _mm_fnmadd_ps(mx, mx, one);
  118.         float r = * (float*) &sq;
  119.         return 1/sqrtf(r);
  120.     }
  121.     else if (typeid(R) == typeid(double))
  122.     {    
  123.         __m128d mx  = _mm_set_pd(x , x);
  124.         __m128d one = _mm_set_pd(1., 1.);
  125.         __m128d sq  = _mm_fnmadd_pd(mx, mx, one);
  126.         double r = * (double*) &sq;
  127.         return 1/sqrt(r);
  128.     }
  129.     else if (typeid(R) == typeid(long double))
  130.         return 1/sqrtl(1 - x*x);
  131.  
  132.     __builtin_unreachable();
  133. }
  134.  
  135.  
  136. template<class R>
  137. R nextafter_(R x, R y)
  138. {
  139.     if (typeid(R) == typeid(float))
  140.         return nextafterf(x, y);
  141.     else if (typeid(R) == typeid(double))
  142.         return nextafter(x, y);
  143.     else if (typeid(R) == typeid(long double))
  144.         return nextafterl(x, y);
  145.  
  146.     __builtin_unreachable();
  147. }
  148.  
  149. //not efficient, but OK for our needs.
  150. template<class R>
  151. int ulp_diff(R x, R y)
  152. {
  153.     int ulp = 0;
  154.  
  155.     while (x != y)
  156.     {
  157.         x = nextafter_(x, y);
  158.         ulp++;
  159.     }
  160.     return ulp;
  161. }
  162.  
  163. template<class R>
  164. mpfr::mpreal mpfr_sinhatanh(R x)
  165. {
  166.     mpfr::mpreal mpfr_x = x;
  167.     return sinh(atanh(mpfr_x));
  168. }
  169.  
  170. template<class R>
  171. mpfr::mpreal mpfr_coshatanh(R x)
  172. {
  173.     mpfr::mpreal mpfr_x = x;
  174.     return cosh(atanh(mpfr_x));
  175. }
  176.  
  177. #define err(x) fabs(x - ms)
  178.  
  179. template<class R>
  180. void sinh_test()
  181. {
  182.     R xi = 1, s1, s2, sp, mone=-1;
  183.     mpfr::mpreal ms;
  184.  
  185.     do
  186.     {
  187.         xi = nextafter_(xi, mone);
  188.         s1 = sinhatanh(xi);
  189.         s2 = sinhatanh2_dijkstra(xi);
  190.         ms = mpfr_sinhatanh(xi);
  191.         sp = (R) ms;
  192.     } while(isnan(s1-s2) || isinf(s2-s1) || ulp_diff(s1, sp) + ULP_THRESH >= ulp_diff(s2, sp));
  193.    
  194.     debug("with input  : ", xi);
  195.     debug("sinh: before: ", s1);
  196.     debug("sinh: after : ", s2);
  197.     debug("sinh: mpfr  : ", ms);
  198.     debug("ulp err befr: ", ulp_diff(s1, sp));
  199.     debug("ulp err aftr: ", ulp_diff(s2, sp));
  200. }
  201. #undef err
  202.  
  203.  
  204. #define err(x) fabs(x - mc)
  205. template<class R>
  206. void cosh_test()
  207. {
  208.     R xi = 1, c1, c2, cp, mone=-1;
  209.     mpfr::mpreal mc;
  210.  
  211.     do
  212.     {
  213.         xi = nextafter_(xi, mone);
  214.         c1 = coshatanh(xi);
  215.         c2 = coshatanh2_dijkstra(xi);
  216.         mc = mpfr_coshatanh(xi);
  217.         cp = (R) mc;
  218.  
  219.     } while (isnan(c1-c2) || isinf(c2-c1) || ulp_diff(c1, cp) + ULP_THRESH >= ulp_diff(c2, cp));
  220.  
  221.     debug("with input  : ", xi);
  222.     debug("cosh: before: ", c1);
  223.     debug("cosh: after : ", c2);
  224.     debug("cosh: mpfr  : ", mc);
  225.     debug("ulp err befr: ", ulp_diff(c1, cp));
  226.     debug("ulp err aftr: ", ulp_diff(c2, cp));
  227. }
  228. #undef err
  229.  
  230. int main()
  231. {
  232.     mpfr_set_default_prec(512);
  233.  
  234.     std::cout << "With floats: " << std::endl;
  235.     sinh_test<float>();
  236. //    cosh_test<float>();
  237.     std::cout << std::endl;
  238.    
  239.     std::cout << "With doubles: " << std::endl;
  240.     sinh_test<double>();
  241. //    cosh_test<double>();
  242.     std::cout << std::endl;
  243.    
  244.     std::cout << "With long doubles: " << std::endl;
  245.     sinh_test<long double>();
  246. //    cosh_test<long double>();
  247.     std::cout << std::endl;
  248.    
  249.     return 0;
  250. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement