Advertisement
Guest User

Untitled

a guest
Feb 23rd, 2019
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.87 KB | None | 0 0
  1. #ifndef __FP_CONTROL_HH__
  2. #define __FP_CONTROL_HH__
  3.  
  4. #include "common.hh"
  5. #include <cfenv>
  6. #include <cmath>
  7. namespace numbers {
  8.  
  9.  
  10. struct FPControl {
  11.     typedef int rounding;
  12.  
  13.     static void
  14.     setup() {}
  15.    
  16.     static void
  17.     get_rounding(rounding &mode) {
  18.         mode = std::fegetround();
  19.     }
  20.    
  21.     static void
  22.     set_rounding(rounding mode) {
  23.         std::fesetround(mode);
  24.     }
  25.    
  26.     static void
  27.     fe_up() {
  28.         set_rounding(FE_UPWARD);
  29.     }
  30.    
  31.     static void
  32.     fe_down() {
  33.         set_rounding(FE_DOWNWARD);
  34.     }
  35.    
  36.     static void
  37.     fe_nearest() {
  38.         set_rounding(FE_TONEAREST);
  39.     }
  40.    
  41.     static void
  42.     fe_zero() {
  43.         set_rounding(FE_TOWARDZERO);
  44.     }
  45.  
  46.     static long double
  47.     do_round(long double d) {
  48.         volatile long double dd = d;
  49.         return dd;
  50.     }
  51.  
  52.     template <typename T>
  53.     static T
  54.     round_int(T const &x) {
  55.         return std::rint(x);
  56.     }
  57.  
  58.     template <typename T>
  59.     static bool
  60.     is_nan(const T &n) {
  61.         return std::numeric_limits<T>::has_quiet_NaN && (n != n);
  62.     }
  63.  
  64. };
  65.  
  66. struct ICExact : FPControl {
  67.     template <typename S>
  68.     long double
  69.     r_down(S const &n) {
  70.         return n;
  71.     }
  72.  
  73.     template <typename S>
  74.     long double
  75.     r_up(S const &n) {
  76.         return n;
  77.     }
  78.  
  79.     long double
  80.     add_u(long double a, long double b) {
  81.         return a+b;
  82.     }
  83.  
  84.     long double
  85.     add_d(long double a, long double b) {
  86.         return a+b;
  87.     }
  88.  
  89.     long double
  90.     sub_u(long double a, long double b) {
  91.         return a-b;
  92.     }
  93.  
  94.     long double
  95.     sub_d(long double a, long double b) {
  96.         return a-b;
  97.     }
  98.  
  99.     long double
  100.     mul_u(long double a, long double b) {
  101.         return a*b;
  102.     }
  103.  
  104.     long double
  105.     mul_d(long double a, long double b) {
  106.         return a*b;
  107.     }
  108.  
  109.     long double
  110.     div_u(long double a, long double b) {
  111.         return a/b;
  112.     }
  113.  
  114.     long double
  115.     div_d(long double a, long double b) {
  116.         return a/b;
  117.     }
  118.  
  119.     long double
  120.     avg(long double a, long double b) {
  121.         return (a+b)/2.0;
  122.     }
  123.  
  124. #define FN_U_AND_D(FN)       \
  125.     long double              \
  126.     FN##_u(long double a) {  \
  127.         return std :: FN(a); \
  128.     }                        \
  129.     long double              \
  130.     FN##_d(long double a) {  \
  131.         return std :: FN(a); \
  132.     }
  133.  
  134.     FN_U_AND_D(sqrt)
  135.     FN_U_AND_D(exp)
  136.     FN_U_AND_D(log)
  137.     FN_U_AND_D(sin)
  138.     FN_U_AND_D(cos)
  139.     FN_U_AND_D(tan)
  140.     FN_U_AND_D(asin)
  141.     FN_U_AND_D(acos)
  142.     FN_U_AND_D(atan)
  143.     FN_U_AND_D(sinh)
  144.     FN_U_AND_D(cosh)
  145.     FN_U_AND_D(tanh)
  146.     FN_U_AND_D(asinh)
  147.     FN_U_AND_D(acosh)
  148.     FN_U_AND_D(atanh)
  149.  
  150. #undef FN_U_AND_D
  151.  
  152.     long double
  153.     ceil(long double a) {
  154.         return std::ceil(a);
  155.     }
  156.  
  157.     long double
  158.     floor(long double a) {
  159.         return std::floor(a);
  160.     }
  161. };
  162.  
  163. struct ICStandard : FPControl {
  164.  
  165.  
  166.     template <typename S>
  167.     long double
  168.     r_down(S const &n) {
  169.         fe_down();
  170.         return do_round(n);
  171.     }
  172.  
  173.     template <typename S>
  174.     long double
  175.     r_up(S const &n) {
  176.         fe_up();
  177.         return do_round(n);
  178.     }
  179.  
  180.     long double
  181.     add_u(long double a, long double b) {
  182.         fe_up();
  183.         return do_round(a+b);
  184.     }
  185.  
  186.     long double
  187.     add_d(long double a, long double b) {
  188.         fe_down();
  189.         return do_round(a+b);
  190.     }
  191.  
  192.     long double
  193.     sub_u(long double a, long double b) {
  194.         fe_up();
  195.         return do_round(a-b);
  196.     }
  197.  
  198.     long double
  199.     sub_d(long double a, long double b) {
  200.         fe_down();
  201.         return do_round(a-b);
  202.     }
  203.  
  204.     long double
  205.     mul_u(long double a, long double b) {
  206.         fe_up();
  207.         return do_round(a*b);
  208.     }
  209.  
  210.     long double
  211.     mul_d(long double a, long double b) {
  212.         fe_down();
  213.         return do_round(a*b);
  214.     }
  215.  
  216.     long double
  217.     div_u(long double a, long double b) {
  218.         fe_up();
  219.         return do_round(a/b);
  220.     }
  221.  
  222.     long double
  223.     div_d(long double a, long double b) {
  224.         fe_down();
  225.         return do_round(a/b);
  226.     }
  227.  
  228.     long double
  229.     avg(long double a, long double b) {
  230.         fe_nearest();
  231.         return do_round((a+b)/2.0);
  232.     }
  233.  
  234. #define FN_U_AND_D(FN)                 \
  235.     long double                        \
  236.     FN##_u(long double a) {            \
  237.         fe_up();                       \
  238.         return do_round(std :: FN(a)); \
  239.     }                                  \
  240.     long double                        \
  241.     FN##_d(long double a) {            \
  242.         fe_down();                     \
  243.         return do_round(std :: FN(a)); \
  244.     }
  245.  
  246.     FN_U_AND_D(sqrt)
  247.     FN_U_AND_D(exp)
  248.     FN_U_AND_D(log)
  249.     FN_U_AND_D(sin)
  250.     FN_U_AND_D(cos)
  251.     FN_U_AND_D(tan)
  252.     FN_U_AND_D(asin)
  253.     FN_U_AND_D(acos)
  254.     FN_U_AND_D(atan)
  255.     FN_U_AND_D(sinh)
  256.     FN_U_AND_D(cosh)
  257.     FN_U_AND_D(tanh)
  258.     FN_U_AND_D(asinh)
  259.     FN_U_AND_D(acosh)
  260.     FN_U_AND_D(atanh)
  261.  
  262. #undef FN_U_AND_D
  263.  
  264.     long double
  265.     ceil(long double a) {
  266.         fe_up();
  267.         return round_int(a);
  268.     }
  269.  
  270.     long double
  271.     floor(long double a) {
  272.         fe_down();
  273.         return round_int(a);
  274.     }
  275. };
  276.  
  277.  
  278.  
  279. struct ICOpposite : FPControl {
  280.     static void
  281.     setup() {
  282.         fe_up();
  283.     }
  284.  
  285.     template <typename S>
  286.     long double
  287.     r_down(S const &n) {
  288.         return -do_round(-n);
  289.     }
  290.  
  291.     template <typename S>
  292.     long double
  293.     r_up(S const &n) {
  294.         return do_round(n);
  295.     }
  296.  
  297.     long double
  298.     add_u(long double a, long double b) {
  299.         return do_round(a+b);
  300.     }
  301.  
  302.     long double
  303.     add_d(long double a, long double b) {
  304.         return -do_round(-((-a) - b));
  305.     }
  306.  
  307.     long double
  308.     sub_u(long double a, long double b) {
  309.         return do_round(a - b);
  310.     }
  311.  
  312.     long double
  313.     sub_d(long double a, long double b) {
  314.         return -do_round(b - a);
  315.     }
  316.  
  317.     long double
  318.     mul_u(long double a, long double b) {
  319.         return do_round(a * b);
  320.     }
  321.  
  322.     long double
  323.     mul_d(long double a, long double b) {
  324.         return -do_round(a * (-b));
  325.     }
  326.  
  327.     long double
  328.     div_u(long double a, long double b) {
  329.         return do_round(a / b);
  330.     }
  331.  
  332.     long double
  333.     div_d(long double a, long double b) {
  334.         return -do_round(a / (-b));
  335.     }
  336.  
  337.     long double
  338.     avg(long double a, long double b) {
  339.         fe_nearest();
  340.         long double c = do_round((a+b)/2);
  341.         fe_up();
  342.         return c;
  343.     }
  344.  
  345. #define FN_U_AND_D(FN)                          \
  346.     long double                                 \
  347.     FN##_u(long double a) {                     \
  348.         return do_round(std :: FN(a));          \
  349.     }                                           \
  350.     long double                                 \
  351.     FN##_d(long double a) {                     \
  352.         fe_down();                              \
  353.         long double d = do_round(std :: FN(a)); \
  354.         fe_up();                                \
  355.         return d;                               \
  356.     }
  357.  
  358.     FN_U_AND_D(sqrt)
  359.     FN_U_AND_D(exp)
  360.     FN_U_AND_D(log)
  361.     FN_U_AND_D(cos)
  362.     FN_U_AND_D(acos)
  363.     FN_U_AND_D(cosh)
  364.     FN_U_AND_D(asinh)
  365.     FN_U_AND_D(atanh)
  366.  
  367. #undef FN_U_AND_D
  368. #define FN_U_AND_D(FN)                          \
  369.     long double                                 \
  370.     FN##_u(long double a) {                     \
  371.         return do_round(std :: FN(a));          \
  372.     }                                           \
  373.     long double                                 \
  374.     FN##_d(long double a) {                     \
  375.         return -do_round(-(std :: FN(a)));      \
  376.     }
  377.  
  378.     FN_U_AND_D(sin)
  379.     FN_U_AND_D(tan)
  380.     FN_U_AND_D(asin)
  381.     FN_U_AND_D(atan)
  382.     FN_U_AND_D(sinh)
  383.     FN_U_AND_D(tanh)
  384.     FN_U_AND_D(acosh)
  385.  
  386. #undef FN_U_AND_D
  387.  
  388.     long double
  389.     ceil(long double a) {
  390.         return -round_int(-a);
  391.     }
  392.  
  393.     long double
  394.     floor(long double a) {
  395.         return round_int(a);
  396.     }
  397. };
  398.  
  399.  
  400.  
  401.  
  402. }
  403.  
  404.  
  405.  
  406.  
  407.  
  408.  
  409.  
  410.  
  411.  
  412. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement