New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
lcast_precision.hpp in vendors/XIOS/current/extern/boost/include/boost/detail – NEMO

source: vendors/XIOS/current/extern/boost/include/boost/detail/lcast_precision.hpp @ 3408

Last change on this file since 3408 was 3408, checked in by rblod, 12 years ago

importing initial XIOS vendor drop

  • Property svn:keywords set to Id
File size: 5.9 KB
Line 
1// Copyright Alexander Nasonov & Paul A. Bristow 2006.
2
3// Use, modification and distribution are subject to the
4// Boost Software License, Version 1.0.
5// (See accompanying file LICENSE_1_0.txt
6// or copy at http://www.boost.org/LICENSE_1_0.txt)
7
8#ifndef BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED
9#define BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED
10
11#include <climits>
12#include <ios>
13#include <limits>
14
15#include <boost/config.hpp>
16#include <boost/integer_traits.hpp>
17
18#ifndef BOOST_NO_IS_ABSTRACT
19// Fix for SF:1358600 - lexical_cast & pure virtual functions & VC 8 STL
20#include <boost/mpl/if.hpp>
21#include <boost/type_traits/is_abstract.hpp>
22#endif
23
24#if defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || \
25  (defined(BOOST_MSVC) && (BOOST_MSVC<1310))
26
27#define BOOST_LCAST_NO_COMPILE_TIME_PRECISION
28#endif
29
30#ifdef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
31#include <boost/assert.hpp>
32#else
33#include <boost/static_assert.hpp>
34#endif
35
36namespace boost { namespace detail {
37
38class lcast_abstract_stub {};
39
40#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
41// Calculate an argument to pass to std::ios_base::precision from
42// lexical_cast. See alternative implementation for broken standard
43// libraries in lcast_get_precision below. Keep them in sync, please.
44template<class T>
45struct lcast_precision
46{
47#ifdef BOOST_NO_IS_ABSTRACT
48    typedef std::numeric_limits<T> limits; // No fix for SF:1358600.
49#else
50    typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
51        boost::is_abstract<T>
52      , std::numeric_limits<lcast_abstract_stub>
53      , std::numeric_limits<T>
54      >::type limits;
55#endif
56
57    BOOST_STATIC_CONSTANT(bool, use_default_precision =
58            !limits::is_specialized || limits::is_exact
59        );
60
61    BOOST_STATIC_CONSTANT(bool, is_specialized_bin =
62            !use_default_precision &&
63            limits::radix == 2 && limits::digits > 0
64        );
65
66    BOOST_STATIC_CONSTANT(bool, is_specialized_dec =
67            !use_default_precision &&
68            limits::radix == 10 && limits::digits10 > 0
69        );
70
71    BOOST_STATIC_CONSTANT(std::streamsize, streamsize_max =
72            boost::integer_traits<std::streamsize>::const_max
73        );
74
75    BOOST_STATIC_CONSTANT(unsigned int, precision_dec = limits::digits10 + 1U);
76
77    BOOST_STATIC_ASSERT(!is_specialized_dec ||
78            precision_dec <= streamsize_max + 0UL
79        );
80
81    BOOST_STATIC_CONSTANT(unsigned long, precision_bin =
82            2UL + limits::digits * 30103UL / 100000UL
83        );
84
85    BOOST_STATIC_ASSERT(!is_specialized_bin ||
86            (limits::digits + 0UL < ULONG_MAX / 30103UL &&
87            precision_bin > limits::digits10 + 0UL &&
88            precision_bin <= streamsize_max + 0UL)
89        );
90
91    BOOST_STATIC_CONSTANT(std::streamsize, value =
92            is_specialized_bin ? precision_bin
93                               : is_specialized_dec ? precision_dec : 6
94        );
95};
96#endif
97
98template<class T>
99inline std::streamsize lcast_get_precision(T* = 0)
100{
101#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
102    return lcast_precision<T>::value;
103#else // Follow lcast_precision algorithm at run-time:
104
105#ifdef BOOST_NO_IS_ABSTRACT
106    typedef std::numeric_limits<T> limits; // No fix for SF:1358600.
107#else
108    typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
109        boost::is_abstract<T>
110      , std::numeric_limits<lcast_abstract_stub>
111      , std::numeric_limits<T>
112      >::type limits;
113#endif
114
115    bool const use_default_precision =
116        !limits::is_specialized || limits::is_exact;
117
118    if(!use_default_precision)
119    { // Includes all built-in floating-point types, float, double ...
120      // and UDT types for which digits (significand bits) is defined (not zero)
121
122        bool const is_specialized_bin =
123            limits::radix == 2 && limits::digits > 0;
124        bool const is_specialized_dec =
125            limits::radix == 10 && limits::digits10 > 0;
126        std::streamsize const streamsize_max =
127            (boost::integer_traits<std::streamsize>::max)();
128
129        if(is_specialized_bin)
130        { // Floating-point types with
131          // limits::digits defined by the specialization.
132
133            unsigned long const digits = limits::digits;
134            unsigned long const precision = 2UL + digits * 30103UL / 100000UL;
135            // unsigned long is selected because it is at least 32-bits
136            // and thus ULONG_MAX / 30103UL is big enough for all types.
137            BOOST_ASSERT(
138                    digits < ULONG_MAX / 30103UL &&
139                    precision > limits::digits10 + 0UL &&
140                    precision <= streamsize_max + 0UL
141                );
142            return precision;
143        }
144        else if(is_specialized_dec)
145        {   // Decimal Floating-point type, most likely a User Defined Type
146            // rather than a real floating-point hardware type.
147            unsigned int const precision = limits::digits10 + 1U;
148            BOOST_ASSERT(precision <= streamsize_max + 0UL);
149            return precision;
150        }
151    }
152
153    // Integral type (for which precision has no effect)
154    // or type T for which limits is NOT specialized,
155    // so assume stream precision remains the default 6 decimal digits.
156    // Warning: if your User-defined Floating-point type T is NOT specialized,
157    // then you may lose accuracy by only using 6 decimal digits.
158    // To avoid this, you need to specialize T with either
159    // radix == 2 and digits == the number of significand bits,
160    // OR
161    // radix = 10 and digits10 == the number of decimal digits.
162
163    return 6;
164#endif
165}
166
167template<class T>
168inline void lcast_set_precision(std::ios_base& stream, T*)
169{
170    stream.precision(lcast_get_precision<T>());
171}
172
173template<class Source, class Target>
174inline void lcast_set_precision(std::ios_base& stream, Source*, Target*)
175{
176    std::streamsize const s = lcast_get_precision(static_cast<Source*>(0));
177    std::streamsize const t = lcast_get_precision(static_cast<Target*>(0));
178    stream.precision(s > t ? s : t);
179}
180
181}}
182
183#endif //  BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED
184
Note: See TracBrowser for help on using the repository browser.