Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/numeric/interval/detail/msvc_rounding_control.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* Boost interval/detail/msvc_rounding_control.hpp file
0002  *
0003  * Copyright 2000 Maarten Keijzer
0004  * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
0005  *
0006  * Distributed under the Boost Software License, Version 1.0.
0007  * (See accompanying file LICENSE_1_0.txt or
0008  * copy at http://www.boost.org/LICENSE_1_0.txt)
0009  */
0010 
0011 #ifndef BOOST_NUMERIC_INTERVAL_DETAIL_MSVC_ROUNDING_CONTROL_HPP
0012 #define BOOST_NUMERIC_INTERVAL_DETAIL_MSVC_ROUNDING_CONTROL_HPP
0013 
0014 #ifndef _MSC_VER
0015 #  error This header is only intended for MSVC, but might work for Borland as well
0016 #endif
0017 
0018 #include <float.h>      // MSVC rounding control
0019 
0020 // Although the function is called _control87, it seems to work for
0021 // other FPUs too, so it does not have to be changed to _controlfp.
0022 
0023 namespace boost {
0024 namespace numeric {
0025 namespace interval_lib {
0026 namespace detail {
0027 
0028 #if BOOST_MSVC < 1400 || defined(_WIN64)
0029 extern "C" { double rint(double); }
0030 #else
0031 inline double rint(double x)
0032 {
0033 _asm FLD [x] ;
0034 _asm FRNDINT ;
0035 //_asm RET ;
0036 }
0037 #endif
0038 
0039 struct x86_rounding
0040 {
0041   static unsigned int hard2msvc(unsigned short m) {
0042     unsigned int n = 0;
0043     if (m & 0x01) n |= _EM_INVALID;
0044     if (m & 0x02) n |= _EM_DENORMAL;
0045     if (m & 0x04) n |= _EM_ZERODIVIDE;
0046     if (m & 0x08) n |= _EM_OVERFLOW;
0047     if (m & 0x10) n |= _EM_UNDERFLOW;
0048     if (m & 0x20) n |= _EM_INEXACT;
0049     switch (m & 0x300) {
0050     case 0x000: n |= _PC_24; break;
0051     case 0x200: n |= _PC_53; break;
0052     case 0x300: n |= _PC_64; break;
0053     }
0054     switch (m & 0xC00) {
0055     case 0x000: n |= _RC_NEAR; break;
0056     case 0x400: n |= _RC_DOWN; break;
0057     case 0x800: n |= _RC_UP;   break;
0058     case 0xC00: n |= _RC_CHOP; break;
0059     }
0060     if (m & 0x1000) n |= _IC_AFFINE; // only useful on 287
0061     return n;
0062   }
0063 
0064   static unsigned short msvc2hard(unsigned int n) {
0065     unsigned short m = 0;
0066     if (n & _EM_INVALID)    m |= 0x01;
0067     if (n & _EM_DENORMAL)   m |= 0x02;
0068     if (n & _EM_ZERODIVIDE) m |= 0x04;
0069     if (n & _EM_OVERFLOW)   m |= 0x08;
0070     if (n & _EM_UNDERFLOW)  m |= 0x10;
0071     if (n & _EM_INEXACT)    m |= 0x20;
0072     switch (n & _MCW_RC) {
0073     case _RC_NEAR: m |= 0x000; break;
0074     case _RC_DOWN: m |= 0x400; break;
0075     case _RC_UP:   m |= 0x800; break;
0076     case _RC_CHOP: m |= 0xC00; break;
0077     }
0078     switch (n & _MCW_PC) {
0079     case _PC_24: m |= 0x000; break;
0080     case _PC_53: m |= 0x200; break;
0081     case _PC_64: m |= 0x300; break;
0082     }
0083     if ((n & _MCW_IC) == _IC_AFFINE) m |= 0x1000;
0084     return m;
0085   }
0086 
0087   typedef unsigned short rounding_mode;
0088   static void get_rounding_mode(rounding_mode& mode)
0089   { mode = msvc2hard(_control87(0, 0)); }
0090   static void set_rounding_mode(const rounding_mode mode)
0091   {
0092     _control87(hard2msvc(mode),
0093       _MCW_EM | _MCW_RC
0094 #if !defined(_M_AMD64) && !defined(_M_ARM) && !defined(_M_ARM64)
0095       // x64 ignores _MCW_PC and _MCW_IC, and the Debug CRT library actually
0096       // asserts when these are passed to _control87.
0097       // MSDN says on '_control87' that changing precision (_MCW_PC) or
0098       // infinity (_MCW_IC) handling is not supported on the ARM and x64
0099       // architectures and that _control87 raises an assertion
0100       // and the invalid parameter handler is invoked.
0101       | _MCW_PC | _MCW_IC
0102 #endif
0103     );
0104   }
0105   static double to_int(const double& x) { return rint(x); }
0106 };
0107 
0108 } // namespace detail
0109 } // namespace interval_lib
0110 } // namespace numeric
0111 } // namespace boost
0112 
0113 #endif /* BOOST_NUMERIC_INTERVAL_DETAIL_MSVC_ROUNDING_CONTROL_HPP */