源码提交

This commit is contained in:
yangzuhao
2022-12-15 23:45:23 +08:00
parent cb7ca21a2e
commit b199dd2a76
63375 changed files with 9928567 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
# Boost.NumericConversion
The Boost Numeric Conversion library is a collection of tools to describe and perform conversions between values of different [numeric types][1].
The documentation for the library can be found [here][2]
[1]: http://www.boost.org/doc/libs/release/libs/numeric/conversion/doc/html/boost_numericconversion/definitions.html#boost_numericconversion.definitions.numeric_types
[2]: http://www.boost.org/doc/libs/release/libs/numeric/conversion/doc/html/index.html#numeric_conversion.overview
+36
View File
@@ -0,0 +1,36 @@
# Boost.Numeric/Conversion
#
# Copyright (c) 2004-2007 Fernando Luis Cacciola Carballal
#
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
# Quickbook
# -----------------------------------------------------------------------------
import quickbook ;
path-constant images : html ;
xml conversion
:
conversion.qbk
;
boostbook standalone
:
conversion
:
<xsl:param>boost.root=../../../../..
<xsl:param>html.stylesheet=boostbook.css
<xsl:param>toc.max.depth=2
<xsl:param>toc.section.depth=2
<xsl:param>chunk.section.depth=1
<format>pdf:<xsl:param>img.src.path=$(images)/
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/numeric/conversion/doc/html
;
+100
View File
@@ -0,0 +1,100 @@
[/
Boost.Optional
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
]
[section bounds<> traits class]
[section Introduction]
To determine the ranges of numeric types with `std::numeric_limits` \[18.2.1\],
different syntax have to be used depending on numeric type. Specifically,
`numeric_limits<T>::min()` for integral types returns the minimum finite value,
whereas for floating point types it returns the minimum positive normalized
value. The difference in semantics makes client code unnecessarily complex
and error prone.
`boost::numeric::bounds<>` provides a consistent interface for retrieving the
maximum finite value, the minimum finite value and the minimum positive normalized
value (0 for integral types) for numeric types. The selection of implementation
is performed at compile time, so there is no runtime overhead.
[endsect]
[section traits class bounds<N>]
template<class N>
struct bounds
{
static N lowest () { return implementation_defined; }
static N highest () { return implementation_defined; }
static N smallest() { return implementation_defined; }
};
[heading Members]
[: `lowest()` ]
Returns the minimum finite value, equivalent to `numeric_limits<T>::min()` when `T`
is an integral type, and to `-numeric_limits<T>::max()` when `T` is a floating point type.
[: `highest()` ]
Returns the maximum finite value, equivalent to `numeric_limits<T>::max()`.
[: `smallest()` ]
Returns the smallest positive normalized value for floating point types with
denormalization, or returns 0 for integral types.
[endsect]
[section Examples]
The following example demonstrates the use of `numeric::bounds<>` and the
equivalent code using `numeric_limits`:
#include <iostream>
#include <boost/numeric/conversion/bounds.hpp>
#include <boost/limits.hpp>
int main() {
std::cout << "numeric::bounds versus numeric_limits example.\n";
std::cout << "The maximum value for float:\n";
std::cout << boost::numeric::bounds<float>::highest() << "\n";
std::cout << std::numeric_limits<float>::max() << "\n";
std::cout << "The minimum value for float:\n";
std::cout << boost::numeric::bounds<float>::lowest() << "\n";
std::cout << -std::numeric_limits<float>::max() << "\n";
std::cout << "The smallest positive value for float:\n";
std::cout << boost::numeric::bounds<float>::smallest() << "\n";
std::cout << std::numeric_limits<float>::min() << "\n";
return 0;
}
[endsect]
[endsect]
+161
View File
@@ -0,0 +1,161 @@
[library Boost.NumericConversion
[quickbook 1.4]
[authors [Cacciola Carballal, Fernando Luis]]
[copyright 2004-2007 Fernando Luis Cacciola Carballal]
[category numerics]
[id numeric_conversion]
[dirname numeric_conversion]
[purpose
Optimized Policy-based Numeric Conversions
]
[source-mode c++]
[license
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
[@http://www.boost.org/LICENSE_1_0.txt])
]
]
[/ Macros will be used for links so we have a central place to change them ]
[/ Cited Boost resources ]
[def __MPL_INTEGRAL_CONSTANT__ [@../../../../mpl/doc/refmanual/integral-constant.html MPL's Integral Constant] ]
[/ Other web resources ]
[def __SGI_UNARY_FUNCTION__ [@http://www.sgi.com/tech/stl/UnaryFunction.html Unary Function Object]]
[/ Icons ]
[def __NOTE__ [$images/note.png]]
[def __ALERT__ [$images/caution.png]]
[def __DETAIL__ [$images/note.png]]
[def __TIP__ [$images/tip.png]]
[def __QUESTION_MARK__ [$images/question.png]]
[def __SPACE__ [$images/space.png]]
[def __GO_TO__ [$images/callouts/R.png]]
[section Overview]
The Boost Numeric Conversion library is a collection of tools to describe and
perform conversions between values of different
[link boost_numericconversion.definitions.numeric_types numeric types].
The library includes a special alternative for a subset of `std::numeric_limits<>`,
the [link boost_numericconversion.bounds___traits_class bounds<>] traits class, which provides
a consistent way to obtain the [link boost_numericconversion.definitions.range_and_precision boundary]
values for the [link boost_numericconversion.definitions.range_and_precision range] of a numeric type.
It also includes a set of [link boost_numericconversion.conversion_traits___traits_class trait classes]
which describes the compile-time
properties of a conversion from a source to a target numeric type.
Both [link boost_numericconversion.definitions.c___arithmetic_types arithmetic] and
[link boost_numericconversion.definitions.numeric_types user-defined numeric types] can be used.
A policy-based [link boost_numericconversion.converter___function_object converter] object which
uses `conversion_traits` to select
an optimized implementation is supplied. Such implementation uses an optimal
range checking code suitable for the source/target combination.
* The converter's out-of-range behavior can be customized via an
[link boost_numericconversion.numeric_converter_policy_classes.policy_overflowhandler OverflowHandler] policy.
* For floating-point to integral conversions, the rounding mode can be selected via the
[link boost_numericconversion.numeric_converter_policy_classes.policy_float2introunder Float2IntRounder] policy.
* A custom low-level conversion routine (for UDTs for instance) can be passed via a
[link boost_numericconversion.numeric_converter_policy_classes.policy_rawconverter RawConverter] policy.
* The optimized automatic range-checking logic can be overridden via a
[link boost_numericconversion.numeric_converter_policy_classes.policy_userrangechecker UserRangeChecker] policy.
[endsect]
[include definitions.qbk]
[include converter.qbk]
[include requirements.qbk]
[include bounds.qbk]
[include conversion_traits.qbk]
[include converter_policies.qbk]
[include numeric_cast.qbk]
[section History and Acknowledgments]
[heading Pre-formal review]
* Kevlin Henney, with help from David Abrahams and Beman Dawes, originally contributed
the previous version of `numeric_cast<>` which already presented the idea of a runtime
range check.
* Later, Eric Ford, Kevin Lynch and the author spotted some genericity problems with
that `numeric_cast<>` which prevented it from being used in a generic layer of math
functions.
* An improved `numeric_cast<>` which properly handled all combinations of arithmetic
types was presented.
* David Abrahams and Beman Dawes acknowledged the need of an improved version of
`numeric_cast<>` and supported the submission as originally laid out. Daryl Walker and
Darin Adler made some important comments and proposed fixes to the original submission.
* Special thanks go to Björn Karlsoon who helped the author considerably. Having found the
problems with `numeric_cast<>` himself, he revised very carefully the original submission
and spot a subtle bug in the range checking implementation. He also wrote part of
this documentation and proof-read and corrected other parts. And most importantly:
the features now presented here in this library evolved from the original submission as
a result of the useful private communications between Björn and the author.
[heading Post-formal review]
* Guillaume Melquiond spoted some documentation and code issues, particularly about
rounding conversions.
* The following people contributed an important review of the design, documentation and c
ode: Kevin Lynch, Thorsten Ottosen, Paul Bristow, Daryle Walker, Jhon Torjo, Eric Ford,
Gennadiy Rozental.
[endsect]
[section Bibliography]
* Standard Documents:
# ISO/IEC 14882:98 (C++98 Standard)
# ISO/IEC 9899:1999 (C99 Standard)
# ISO/IEC 10967-1 (Language Independent Arithmetic (LIA), Part I, 1994)
# ISO/IEC 2382-1:1993 (Information Technology - Vocabulary - Part I: Fundamental Terms)
# ANSI/IEEE 754-1985 [and IEC 60559:1989] (Binary floating-point)
# ANSI/IEEE 854-1988 (Radix Independent floating-point)
# ANSI X3/TR-1-82 (Dictionary for Information Processing Systems)
# ISO/IEC JTC1/SC22/WG14/N753 C9X Revision Proposal: LIA-1 Binding: Rationale
* Papers:
# David Goldberg What Every Computer Scientist Should Know About Floating-Point Arithmetic
# Prof. William Kahan papers on floating-point.
[endsect]
@@ -0,0 +1,272 @@
[/
Boost.Optional
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
]
[section conversion_traits<> traits class]
[section Types]
[section enumeration int_float_mixture_enum]
namespace boost { namespace numeric {
enum int_float_mixture_enum
{
integral_to_integral
,integral_to_float
,float_to_integral
,float_to_float
} ;
} } // namespace boost::numeric
[endsect]
[section enumeration sign_mixture_enum]
namespace boost { namespace numeric {
enum sign_mixture_enum
{
unsigned_to_unsigned
,signed_to_signed
,signed_to_unsigned
,unsigned_to_signed
} ;
} } // namespace boost::numeric
[endsect]
[section enumeration udt_builtin_mixture_enum]
namespace boost { namespace numeric {
enum udt_builtin_mixture_enum
{
builtin_to_builtin
,builtin_to_udt
,udt_to_builtin
,udt_to_udt
} ;
} } // namespace boost::numeric
[endsect]
[section template class int_float_mixture<>]
namespace boost { namespace numeric {
template <class T, class S>
struct int_float_mixture : mpl::integral_c<int_float_mixture_enum, impl-def-value> {} ;
} } // namespace boost::numeric
Classifying `S` and `T` as either integral or float, this __MPL_INTEGRAL_CONSTANT__
indicates the combination of these attributes.
Its `::value` is of enumeration type
[link boost_numericconversion.conversion_traits___traits_class.types.enumeration_int_float_mixture_enum `boost::numeric::int_float_mixture_enum`]
[endsect]
[section template class sign_mixture<>]
namespace boost { namespace numeric {
template <class T, class S>
struct sign_mixture : mpl::integral_c<sign_mixture_enum, impl-def-value> {} ;
} } // namespace boost::numeric
Classifying `S` and `T` as either signed or unsigned, this __MPL_INTEGRAL_CONSTANT__
indicates the combination of these attributes.
Its `::value` is of enumeration type
[link boost_numericconversion.conversion_traits___traits_class.types.enumeration_sign_mixture_enum `boost::numeric::sign_mixture_enum`]
[endsect]
[section template class udt_builtin_mixture<>]
namespace boost { namespace numeric {
template <class T, class S>
struct udt_builtin_mixture : mpl::integral_c<udt_builtin__mixture_enum, impl-def-value> {} ;
} } // namespace boost::numeric
Classifying `S` and `T` as either user-defined or builtin, this __MPL_INTEGRAL_CONSTANT__
indicates the combination of these attributes.
Its `::value` is of enumeration type
[link boost_numericconversion.conversion_traits___traits_class.types.enumeration_udt_builtin_mixture_enum `boost::numeric::udt_builtin_mixture_enum`]
[endsect]
[section template class is_subranged<>]
namespace boost { namespace numeric {
template <class T, class S>
struct is_subranged : mpl::bool_<impl-def-value> {} ;
} } // namespace boost::numeric
Indicates if the range of the target type `T` is a subset of the range of the source
type `S`. That is: if there are some source values which fall out of the
Target type's range.
It is a boolean __MPL_INTEGRAL_CONSTANT__.
It does not indicate if a particular conversion is effectively out of range;
it indicates that some conversion might be out of range because not all the
source values are representable as Target type.
[endsect]
[section template class conversion_traits<>]
namespace boost { namespace numeric {
template <class T, class S>
struct conversion_traits
{
mpl::integral_c<int_float_mixture_enum , ...> int_float_mixture ;
mpl::integral_c<sign_mixture_enum , ...> sign_mixture;
mpl::integral_c<udt_builtin_mixture_enum, ...> udt_builtin_mixture ;
mpl::bool_<...> subranged ;
mpl::bool_<...> trivial ;
typedef T target_type ;
typedef S source_type ;
typedef ... argument_type ;
typedef ... result_type ;
typedef ... supertype ;
typedef ... subtype ;
} ;
} } // namespace numeric, namespace boost
This traits class indicates some properties of a ['numeric conversion] direction:
from a source type `S` to a target type `T`. It does not indicate the properties
of a ['specific] conversion, but of the conversion direction. See
[link boost_numericconversion.definitions.subranged_conversion_direction__subtype_and_supertype Definitions] for details.
The traits class provides the following __MPL_INTEGRAL_CONSTANT__\s of enumeration
type. They express the combination of certain attributes of the Source and
Target types (thus they are call mixture):
[table
[[ ][ ]]
[[[*int_float_mixture ]][
Same as given by the traits class
[link boost_numericconversion.conversion_traits___traits_class.types.template_class_int_float_mixture__ int_float_mixture]
]]
[[[*sign_mixture ]][
Same as given by the traits class
[link boost_numericconversion.conversion_traits___traits_class.types.template_class_sign_mixture__ sign_mixture]
]]
[[[*udt_builtin_mixture ]]
[Same as given by the traits class
[link boost_numericconversion.conversion_traits___traits_class.types.template_class_udt_builtin_mixture__ udt_builtin_mixture]
]]
]
The traits class provides the following __MPL_INTEGRAL_CONSTANT__\s of boolean type
which indicates indirectly the relation between the Source and Target ranges
(see [link boost_numericconversion.definitions.range_and_precision Definitions] for details).
[table
[[ ][ ]]
[[subranged ][
Same as given by [link boost_numericconversion.conversion_traits___traits_class.types.template_class_is_subranged__ is_subranged]
]]
[[trivial][
Indicates if both Source and Target, [_without cv-qualifications], are the same type.
Its `::value` is of boolean type.
]]
]
The traits class provides the following types. They are the Source and Target types classified
and qualified for different purposes.
[table
[[ ][ ]]
[[[*target_type]][
The template parameter `T` without cv-qualifications
]]
[[[*source_type]][
The template parameter `S` without cv-qualifications
]]
[[[*argument_type]][
This type is either source_type or `source_type const&`.
It represents the optimal argument type for the
[link boost_numericconversion.converter___function_object converter] member functions.
If S is a built-in type, this is `source_type`, otherwise, this is `source_type const&`.
]]
[[[*result_type]][
This type is either target_type or target_type const&
It represents the return type of the
[link boost_numericconversion.converter___function_object converter] member functions.
If `T==S`, it is `target_type const&`, otherwise, it is `target_type`.
]]
[[[*supertype]][
If the conversion is subranged, it is `source_type`, otherwise, it is `target_type`
]]
[[[*subtype]][
If the conversion is subranged, it is `target_type`, otherwise, it is `source_type`
]]
]
[endsect]
[endsect]
[section Examples]
#include <cassert>
#include <typeinfo>
#include <boost/numeric/conversion/conversion_traits.hpp>
int main()
{
// A trivial conversion.
typedef boost::numeric::conversion_traits<short,short> Short2Short_Traits ;
assert ( Short2Short_Traits::trivial::value ) ;
// A subranged conversion.
typedef boost::numeric::conversion_traits<double,unsigned int> UInt2Double_Traits ;
assert ( UInt2Double_Traits::int_float_mixture::value == boost::numeric::integral_to_float ) ;
assert ( UInt2Double_Traits::sign_mixture::value == boost::numeric::unsigned_to_signed ) ;
assert ( !UInt2Double_Traits::subranged::value ) ;
assert ( typeid(UInt2Double_Traits::supertype) == typeid(double) ) ;
assert ( typeid(UInt2Double_Traits::subtype) == typeid(unsigned int) ) ;
// A doubly subranged conversion.
assert ( (boost::numeric::conversion_traits<short, unsigned short>::subranged::value) );
assert ( (boost::numeric::conversion_traits<unsigned short, short>::subranged::value) );
return 0;
}
[endsect]
[endsect]
+293
View File
@@ -0,0 +1,293 @@
[/
Boost.Optional
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
]
[section converter<> function object]
[section Synopsis]
namespace boost { namespace numeric {
template<class T,
class S,
class Traits, = conversion_traits<T,S>
class OverflowHandler = def_overflow_handler,
class Float2IntRounder = Trunc< typename Traits::source_type >,
class RawConverter = raw_converter<Traits>,
class UserRangeChecker = UseInternalRangeChecker
>
struct converter
{
typedef Traits traits ;
typedef typename Traits::source_type source_type ;
typedef typename Traits::argument_type argument_type ;
typedef typename Traits::result_type result_type ;
static result_type convert ( argument_type s ) ;
result_type operator() ( argument_type s ) const ;
// Internal member functions:
static range_check_result out_of_range ( argument_type s ) ;
static void validate_range ( argument_type s ) ;
static result_type low_level_convert ( argument_type s ) ;
static source_type nearbyint ( argument_type s ) ;
} ;
} } // namespace numeric, boost
`boost::numeric::converter<>` is a __SGI_UNARY_FUNCTION__ encapsulating
the code to perform a numeric conversion with the direction and
properties specified by the Traits template parameter. It can optionally
take some [link boost_numericconversion.numeric_converter_policy_classes policies] which can be used to customize its behavior. The
`Traits` parameter is not a policy but the parameter that defines
the conversion.
[endsect]
[section Template parameters]
[table
[[ ][ ]]
[[`T`][
The [link boost_numericconversion.definitions.numeric_types Numeric Type]
which is the ['Target] of the conversion.
]]
[[`S`][
The [link boost_numericconversion.definitions.numeric_types Numeric Type]
which is the ['Source] of the conversion.
]]
[[`Traits`][
This must be a conversion traits class with the interface of
[link boost_numericconversion.conversion_traits___traits_class `boost::numeric::conversion_traits`]
]]
[[`OverflowHandler`][
[*Stateless Policy] called to administrate the result of the range checking.
It is a [*Function Object] which receives the result of `out_of_range()`
and is called inside the `validate_range()` static member function exposed
by the converter.
]]
[[`Float2IntRounder`][
[*Stateless Policy] which specifies the rounding mode used for float to
integral conversions.
It supplies the `nearbyint()` static member function exposed by the converter.
]]
[[`RawConverter`][
[*Stateless Policy] which is used to perform the actual conversion.
It supplies the `low_level_convert()` static member function exposed
by the converter.
]]
[[`UserRangeChecker`][
['Special and Optional] [*Stateless Policy] which can be used to override
the internal range checking logic.
If given, supplies alternative code for the `out_of_range()` and
`validate_range()` static member functions exposed by the converter.
]]
]
[endsect]
[section Member functions]
[: `static result_type converter<>::convert ( argument_type s ) ; // throw
`]
This static member function converts an rvalue of type `source_type` to
an rvalue of type `target_type`.
If the conversion requires it, it performs a range checking before the conversion
and passes the result of the check to the overflow handler policy (the default
policy throws an exception if out-of-range is detected)
The implementation of this function is actually built from the policies and is
basically as follows:
result_type converter<>::convert ( argument_type s )
{
validate_range(s); // Implemented by the internal range checking logic
// (which also calls the OverflowHandler policy)
// or externally supplied by the UserRangeChecker policy.
s = nearbyint(s); // Externally supplied by the Float2IntRounder policy.
// NOTE: This is actually called only for float to int conversions.
return low_level_convert(s); // Externally supplied by the RawConverter policy.
}
`converter<>::operator() const` just calls `convert()`
__SPACE__
[: `static range_check_result numeric_converter<>::out_of_range ( argument_type s ) ;`]
This [link numeric_conversion_converter_internal internal] static member function
determines if the value `s` can be
represented by the target type without overflow.
It does not determine if the conversion is ['exact]; that is, it does not detect
['inexact] conversions, only ['out-of-range] conversions (see the
[link boost_numericconversion.definitions.exact__correctly_rounded_and_out_of_range_representations Definitions] for further details).
The return value is of enum type
[link boost_numericconversion.numeric_converter_policy_classes.enum_range_check_result `boost::numeric::range_check_result`]
The actual code for the range checking logic is optimized for the combined
properties of the source and target types. For example, a non-subranged
conversion (i.e: `int`->`float`), requires no range checking, so `out_of_range()`
returns `cInRange` directly. See the following
[link boost_numericconversion.converter___function_object.range_checking_logic table] for more details.
If the user supplied a
[link boost_numericconversion.numeric_converter_policy_classes.policy_userrangechecker UserRangeChecker] policy,
is this policy which implements this function, so the implementation is user
defined, although it is expected to perform the same conceptual check and
return the appropriate result.
__SPACE__
[: `static void numeric_converter<>::validate_range ( argument_type s ) ; // no throw
`]
This [link numeric_conversion_converter_internal internal] static member function
calls out_of_range(s), and passes the
result to the [link boost_numericconversion.numeric_converter_policy_classes.policy_overflowhandler OverflowHandler]
policy class.
For those Target/Source combinations which don't require range checking, this
is an empty inline function.
If the user supplied a
[link boost_numericconversion.numeric_converter_policy_classes.policy_userrangechecker UserRangeChecker] policy,
is this policy which implements this function, so the implementation is user
defined, although it is expected to perform the same action as the default.
In particular, it is expected to pass the result of the check to the overflow handler.
__SPACE__
[: `static result_type numeric_converter<>::low_level_convert ( argument_type s ) ;` ]
This [link numeric_conversion_converter_internal internal] static member function
performs the actual conversion.
This function is externally supplied by the
[link boost_numericconversion.numeric_converter_policy_classes.policy_rawconverter RawConverter] policy class.
__SPACE__
[: `static source_type converter<>::nearbyint ( argument_type s ) ;`]
This [link numeric_conversion_converter_internal internal] static member function,
which is [_only used] for
`float` to `int` conversions, returns an ['integer] value of ['[_floating-point
type]] according to some rounding direction.
This function is externally supplied by the
[link boost_numericconversion.numeric_converter_policy_classes.policy_float2introunder Float2IntRounder] policy class
which encapsulates the specific rounding mode.
__SPACE__
[#numeric_conversion_converter_internal]
[heading Internal Member Functions]
These static member functions build the actual conversion code used by `convert()`.
The user does not have to call these if calling `convert()`, since `convert()` calls
them infernally, but they can be called separately for specific needs.
[endsect]
[section Range Checking Logic]
The following table summarizes the internal range checking logic performed for
each combination of the properties of Source and Target.
LowestT/HighestT denotes the highest and lowest values of the Target type, respectively.
`S(n)` is short for `static_cast<S>(n)` (`S` denotes the Source type).
`NONE` indicates that for this case there is no range checking.
[pre
[^
int_to_int |--> sig_to_sig |--> subranged |--> ( s >= S(LowestT) ) && ( s <= S(HighestT) )
| |--> not subranged |--> NONE
|
|--> unsig_to_unsig |--> subranged |--> ( s >= S(LowestT) ) && ( s <= S(HighestT) )
| |--> not subranged |--> NONE
|
|--> sig_to_unsig |--> pos subranged |--> ( s >= S(0) ) && ( s <= S(HighestT) )
| |--> not pos subranged |--> ( s >= S(0) )
|
|--> unsig_to_sig |--> subranged |--> ( s <= S(HighestT) )
| |--> not subranged |--> NONE
]
[^
int_to_float |--> NONE
]
[^
float_to_int |--> round_to_zero |--> ( s > S(LowestT)-S(1) ) && ( s < S(HighestT)+S(1) )
|--> round_to_even_nearest |--> ( s >= S(LowestT)-S(0.5) ) && ( s < S(HighestT)+S(0.5) )
|--> round_to_infinity |--> ( s > S(LowestT)-S(1) ) && ( s <= S(HighestT) )
|--> round_to_neg_infinity |--> ( s >= S(LowestT) ) && ( s < S(HighestT)+S(1) )
]
[^
float_to_float |--> subranged |--> ( s >= S(LowestT) ) && ( s <= S(HighestT) )
|--> not subranged |--> NONE
]
]
[endsect]
[section Examples]
#include <cassert>
#include <boost/numeric/conversion/converter.hpp>
int main() {
typedef boost::numeric::converter<int,double> Double2Int ;
int x = Double2Int::convert(2.0);
assert ( x == 2 );
int y = Double2Int()(3.14); // As a function object.
assert ( y == 3 ) ; // The default rounding is trunc.
try
{
double m = boost::numeric::bounds<double>::highest();
int z = Double2Int::convert(m); // By default throws positive_overflow()
}
catch ( boost::numeric::positive_overflow const& )
{
}
return 0;
}
[endsect]
[endsect]
@@ -0,0 +1,311 @@
[/
Boost.Optional
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
]
[section Numeric Converter Policy Classes]
[section enum range_check_result]
namespace boost { namespace numeric {
enum range_check_result
{
cInRange ,
cNegOverflow ,
cPosOverflow
} ;
} }
Defines the values returned by `boost::numeric::converter<>::out_of_range()`
[endsect]
[section Policy OverflowHandler]
This ['stateless] non-template policy class must be a ['function object] and is
called to administrate the result of the range checking. It can throw an exception
if overflow has been detected by the range checking as indicated by its argument.
If it throws, is is recommended that it be `std::bad_cast` or derived.
It must have the following interface (it does not has to be a template class):
struct YourOverflowHandlerPolicy
{
void operator() ( boost::range_check_result ) ; // throw bad_cast or derived
} ;
It is called with the result of the converter's `out_of_range()` inside `validate_range()`.
These are the two overflow handler classes provided by the library:
namespace boost { namespace numeric {
struct def_overflow_handler
{
void operator() ( range_check_result r ) // throw bad_numeric_conversion derived
{
if ( r == cNegOverflow )
throw negative_overflow() ;
else if ( r == cPosOverflow )
throw positive_overflow() ;
}
} ;
struct silent_overflow_handler
{
void operator() ( range_check_result ) // no-throw
{}
} ;
} }
And these are the Exception Classes thrown by the default overflow handler
[link numeric_conversion_policy_overflow_handler_important_note (see IMPORTANT note)]
namespace boost { namespace numeric {
``[#numeric_conversion_bad_numeric_cast]``
class bad_numeric_cast : public std::bad_cast
{
public:
virtual const char *what() const // throw()
{
return "bad numeric conversion: overflow";
}
};
``[#numeric_conversion_negative_overflow]``
class negative_overflow : public bad_numeric_cast
{
public:
virtual const char *what() const // throw()
{
return "bad numeric conversion: negative overflow";
}
};
``[#numeric_conversion_possitive_overflow]``
class positive_overflow : public bad_numeric_cast
{
public:
virtual const char *what() const // throw()
{
return "bad numeric conversion: positive overflow";
}
};
} }
[#numeric_conversion_policy_overflow_handler_important_note]
[important [*RELEASE NOTE for 1.33]
Previous to boost version 1.33, the exception class `bad_numeric_cast` was
named `bad_numeric_conversion`. However, in 1.33, the old function
`numeric_cast<>` from `boost/cast.hpp` was completly replaced by the
new `numeric_cast<>` in `boost/numeric/conversion/cast.hpp`
(and `boost/cast.hpp` is including `boost/numeric/conversion/cast.hpp` now).
That old function which existed in boost for quite some time used the
`bad_numeric_cast` as its exception type so I decided to avoid backward
compatibility problems by adopting it (guessing that the user base for
the old code is wider than for the new code).
]
[endsect]
[section Policy Float2IntRounder]
This ['stateless] template policy class specifies the rounding mode used
for [_float to integral] conversions. It supplies the `nearbyint()`
static member function exposed by the converter, which means that it
[_publicly inherits from this policy].
The policy must have the following interface:
template<class S>
struct YourFloat2IntRounderPolicy
{
typedef S source_type ;
typedef {S or S const&} argument_type ;
static source_type nearbyint ( argument_type s ) { ... }
typedef mpl::integral_c<std::float_round_style,std::round_...> round_style ;
} ;
These are the rounder classes provided by the library (only the specific parts are shown,
see the general policy form above)
[note
These classes are not intended to be general purpose rounding functions
but specific policies for `converter<>`. This is why they are not function objects.
]
namespace boost { namespace numeric {
template<class S>
struct Trunc
{
static source_type nearbyint ( argument_type s )
{
using std::floor ;
using std::ceil ;
return s >= static_cast<S>(0) ? floor(s) : ceil(s) ;
}
typedef mpl::integral_c<std::float_round_style,std::round_toward_zero> round_style ;
} ;
template<class S>
struct RoundEven
{
static source_type nearbyint ( argument_type s )
{
return impl-defined-value ;
}
typedef mpl::integral_c<std::float_round_style,std::round_to_nearest> round_style ;
} ;
template<class S>
struct Ceil
{
static source_type nearbyint ( argument_type s )
{
using std::ceil ;
return ceil(s) ;
}
typedef mpl::integral_c<std::float_round_style,std::round_toward_infinity> round_style ;
} ;
template<class S>
struct Floor
{
static source_type nearbyint ( argument_type s )
{
using std::floor ;
return floor(s) ;
}
typedef mpl::integral_c<std::float_round_style,std::round_toward_neg_infinity> round_style ;
} ;
} } // namespace numeric, namespace boost
[heading Math Functions used by the rounder policies]
The rounder policies supplied by this header use math functions `floor()` and `ceil()`.
The standard versions of these functions are introduced in context by a using directive,
so in normal conditions, the standard functions will be used.
However, if there are other visible corresponding overloads an ambiguity could arise.
In this case, the user can supply her own rounder policy which could, for instance,
use a fully qualified call.
This technique allows the default rounder policies to be used directly with
user defined types. The user only requires that suitable overloads of `floor()` and `ceil()`
be visible. See also [link boost_numericconversion.type_requirements_and_user_defined_types_support User Defined Numeric Types]
support.
[endsect]
[section Policy RawConverter]
This ['stateless] template policy class is used to perform the
actual conversion from Source to Target. It supplies the
`low_level_convert()` static member function exposed by the
converter, which means that it publicly inherits from this policy.
The policy must have the following interface:
template<class Traits>
struct YourRawConverterPolicy
{
typedef typename Traits::result_type result_type ;
typedef typename Traits::argument_type argument_type ;
static result_type low_level_convert ( argument_type s ) { return <impl defined> ; }
} ;
This policy is mostly provided as a hook for user defined types which don't support `static_cast<>` conversions to some types
This is the only raw converter policy class provided by the library:
namespace boost { namespace numeric {
template<class Traits>
struct raw_numeric_converter
{
typedef typename Traits::result_type result_type ;
typedef typename Traits::argument_type argument_type ;
static result_type low_level_convert ( argument_type s )
{
return static_cast<result_type>(s) ;
}
} ;
} }
[endsect]
[section Policy UserRangeChecker]
This ['stateless] template policy class is used [_only if supplied]
to [*override] the internal range checking logic.
It supplies the `validate_range()` static member function
exposed by the converter, which means that it publicly inherits
from this policy.
The policy must have the following interface:
template<class Traits>
struct YourRangeCheckerPolicy
{
typedef typename Traits::argument_type argument_type ;
// Determines if the value 's' fits in the range of the Target type.
static range_check_result out_of_range ( argument_type s ) ;
// Checks whether the value 's' is out_of_range()
// and passes the result of the check to the OverflowHandler policy.
static void validate_range ( argument_type s )
{
OverflowHandler()( out_of_range(s) ) ;
}
} ;
This policy is [*only] provided as a hook for user defined types which require
range checking (which is disabled by default when a UDT is involved).
The library provides a class: `UseInternalRangeChecker{}`; which is a ['fake]
`RangeChecker` policy used to signal the converter to use its internal
range checking implementation.
[endsect]
[endsect]
+550
View File
@@ -0,0 +1,550 @@
[/
Boost.Optional
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
]
[section Definitions]
[section Introduction]
This section provides definitions of terms used in the Numeric Conversion library.
[blurb [*Notation]
[_underlined text] denotes terms defined in the C++ standard.
[*bold face] denotes terms defined here but not in the standard.
]
[endsect]
[section Types and Values]
As defined by the [_C++ Object Model] (§1.7) the [_storage] or memory on which a
C++ program runs is a contiguous sequence of [_bytes] where each byte is a
contiguous sequence of bits.
An [_object] is a region of storage (§1.8) and has a type (§3.9).
A [_type] is a discrete set of values.
An object of type `T` has an [_object representation] which is the sequence of
bytes stored in the object (§3.9/4)
An object of type `T` has a [_value representation] which is the set of
bits that determine the ['value] of an object of that type (§3.9/4).
For [_POD] types (§3.9/10), this bitset is given by the object representation,
but not all the bits in the storage need to participate in the value
representation (except for character types): for example, some bits might
be used for padding or there may be trap-bits.
__SPACE__
The [*typed value] that is held by an object is the value which is determined
by its value representation.
An [*abstract value] (untyped) is the conceptual information that is
represented in a type (i.e. the number π).
The [*intrinsic value] of an object is the binary value of the sequence of
unsigned characters which form its object representation.
__SPACE__
['Abstract] values can be [*represented] in a given type.
To [*represent] an abstract value `V` in a type `T` is to obtain a typed value
`v` which corresponds to the abstract value `V`.
The operation is denoted using the `rep()` operator, as in: `v=rep(V)`.
`v` is the [*representation] of `V` in the type `T`.
For example, the abstract value π can be represented in the type
`double` as the `double value M_PI` and in the type `int` as the
`int value 3`
__SPACE__
Conversely, ['typed values] can be [*abstracted].
To [*abstract] a typed value `v` of type `T` is to obtain the abstract value `V`
whose representation in `T` is `v`.
The operation is denoted using the `abt()` operator, as in: `V=abt(v)`.
`V` is the [*abstraction] of `v` of type `T`.
Abstraction is just an abstract operation (you can't do it); but it is
defined nevertheless because it will be used to give the definitions in the
rest of this document.
[endsect]
[section C++ Arithmetic Types]
The C++ language defines [_fundamental types] (§3.9.1). The following subsets of
the fundamental types are intended to represent ['numbers]:
[variablelist
[[[_signed integer types] (§3.9.1/2):][
`{signed char, signed short int, signed int, signed long int}`
Can be used to represent general integer numbers (both negative and positive).
]]
[[[_unsigned integer types] (§3.9.1/3):][
`{unsigned char, unsigned short int, unsigned int, unsigned long int}`
Can be used to represent positive integer numbers with modulo-arithmetic.
]]
[[[_floating-point types] (§3.9.1/8):][
`{float,double,long double}`
Can be used to represent real numbers.
]]
[[[_integral or integer types] (§3.9.1/7):][
`{{signed integers},{unsigned integers}, bool, char and wchar_t}`
]]
[[[_arithmetic types] (§3.9.1/8):][
`{{integer types},{floating types}}`
]]
]
The integer types are required to have a ['binary] value representation.
Additionally, the signed/unsigned integer types of the same base type
(`short`, `int` or `long`) are required to have the same value representation,
that is:
int i = -3 ; // suppose value representation is: 10011 (sign bit + 4 magnitude bits)
unsigned int u = i ; // u is required to have the same 10011 as its value representation.
In other words, the integer types signed/unsigned X use the same value
representation but a different ['interpretation] of it; that is, their
['typed values] might differ.
Another consequence of this is that the range for signed X is always a smaller
subset of the range of unsigned X, as required by §3.9.1/3.
[note
Always remember that unsigned types, unlike signed types, have modulo-arithmetic;
that is, they do not overflow.
This means that:
[*-] Always be extra careful when mixing signed/unsigned types
[*-] Use unsigned types only when you need modulo arithmetic or very very large
numbers. Don't use unsigned types just because you intend to deal with
positive values only (you can do this with signed types as well).
]
[endsect]
[section Numeric Types]
This section introduces the following definitions intended to integrate
arithmetic types with user-defined types which behave like numbers.
Some definitions are purposely broad in order to include a vast variety of
user-defined number types.
Within this library, the term ['number] refers to an abstract numeric value.
A type is [*numeric] if:
* It is an arithmetic type, or,
* It is a user-defined type which
* Represents numeric abstract values (i.e. numbers).
* Can be converted (either implicitly or explicitly) to/from at least one arithmetic type.
* Has [link boost_numericconversion.definitions.range_and_precision range] (possibly unbounded)
and [link boost_numericconversion.definitions.range_and_precision precision] (possibly dynamic or
unlimited).
* Provides an specialization of `std::numeric_limits`.
A numeric type is [*signed] if the abstract values it represent include negative numbers.
A numeric type is [*unsigned] if the abstract values it represent exclude negative numbers.
A numeric type is [*modulo] if it has modulo-arithmetic (does not overflow).
A numeric type is [*integer] if the abstract values it represent are whole numbers.
A numeric type is [*floating] if the abstract values it represent are real numbers.
An [*arithmetic value] is the typed value of an arithmetic type
A [*numeric value] is the typed value of a numeric type
These definitions simply generalize the standard notions of arithmetic types and
values by introducing a superset called [_numeric]. All arithmetic types and values are
numeric types and values, but not vice versa, since user-defined numeric types are not
arithmetic types.
The following examples clarify the differences between arithmetic and numeric
types (and values):
// A numeric type which is not an arithmetic type (is user-defined)
// and which is intended to represent integer numbers (i.e., an 'integer' numeric type)
class MyInt
{
MyInt ( long long v ) ;
long long to_builtin();
} ;
namespace std {
template<> numeric_limits<MyInt> { ... } ;
}
// A 'floating' numeric type (double) which is also an arithmetic type (built-in),
// with a float numeric value.
double pi = M_PI ;
// A 'floating' numeric type with a whole numeric value.
// NOTE: numeric values are typed valued, hence, they are, for instance,
// integer or floating, despite the value itself being whole or including
// a fractional part.
double two = 2.0 ;
// An integer numeric type with an integer numeric value.
MyInt i(1234);
[endsect]
[section Range and Precision]
Given a number set `N`, some of its elements are representable in a numeric type `T`.
The set of representable values of type `T`, or numeric set of `T`, is a set of numeric
values whose elements are the representation of some subset of `N`.
For example, the interval of `int` values `[INT_MIN,INT_MAX]` is the set of representable
values of type `int`, i.e. the `int` numeric set, and corresponds to the representation
of the elements of the interval of abstract values `[abt(INT_MIN),abt(INT_MAX)]` from
the integer numbers.
Similarly, the interval of `double` values `[-DBL_MAX,DBL_MAX]` is the `double`
numeric set, which corresponds to the subset of the real numbers from `abt(-DBL_MAX)` to
`abt(DBL_MAX)`.
__SPACE__
Let [*`next(x)`] denote the lowest numeric value greater than x.
Let [*`prev(x)`] denote the highest numeric value lower then x.
Let [*`v=prev(next(V))`] and [*`v=next(prev(V))`] be identities that relate a numeric
typed value `v` with a number `V`.
An ordered pair of numeric values `x`,`y` s.t. `x<y` are [*consecutive] iff `next(x)==y`.
The abstract distance between consecutive numeric values is usually referred to as a
[_Unit in the Last Place], or [*ulp] for short. A ulp is a quantity whose abstract
magnitude is relative to the numeric values it corresponds to: If the numeric set
is not evenly distributed, that is, if the abstract distance between consecutive
numeric values varies along the set -as is the case with the floating-point types-,
the magnitude of 1ulp after the numeric value `x` might be (usually is) different
from the magnitude of a 1ulp after the numeric value y for `x!=y`.
Since numbers are inherently ordered, a [*numeric set] of type `T` is an ordered sequence
of numeric values (of type `T`) of the form:
REP(T)={l,next(l),next(next(l)),...,prev(prev(h)),prev(h),h}
where `l` and `h` are respectively the lowest and highest values of type `T`, called
the boundary values of type `T`.
__SPACE__
A numeric set is discrete. It has a [*size] which is the number of numeric values in the set,
a [*width] which is the abstract difference between the highest and lowest boundary values:
`[abt(h)-abt(l)]`, and a [*density] which is the relation between its size and width:
`density=size/width`.
The integer types have density 1, which means that there are no unrepresentable integer
numbers between `abt(l)` and `abt(h)` (i.e. there are no gaps). On the other hand,
floating types have density much smaller than 1, which means that there are real numbers
unrepresented between consecutive floating values (i.e. there are gaps).
__SPACE__
The interval of [_abstract values] `[abt(l),abt(h)]` is the range of the type `T`,
denoted `R(T)`.
A range is a set of abstract values and not a set of numeric values. In other
documents, such as the C++ standard, the word `range` is ['sometimes] used as synonym
for `numeric set`, that is, as the ordered sequence of numeric values from `l` to `h`.
In this document, however, a range is an abstract interval which subtends the
numeric set.
For example, the sequence `[-DBL_MAX,DBL_MAX]` is the numeric set of the type
`double`, and the real interval `[abt(-DBL_MAX),abt(DBL_MAX)]` is its range.
Notice, for instance, that the range of a floating-point type is ['continuous]
unlike its numeric set.
This definition was chosen because:
* [*(a)] The discrete set of numeric values is already given by the numeric set.
* [*(b)] Abstract intervals are easier to compare and overlap since only boundary
values need to be considered.
This definition allows for a concise definition of `subranged` as given in the last section.
The width of a numeric set, as defined, is exactly equivalent to the width of a range.
__SPACE__
The [*precision] of a type is given by the width or density of the numeric set.
For integer types, which have density 1, the precision is conceptually equivalent
to the range and is determined by the number of bits used in the value representation:
The higher the number of bits the bigger the size of the numeric set, the wider the
range, and the higher the precision.
For floating types, which have density <<1, the precision is given not by the width
of the range but by the density. In a typical implementation, the range is determined
by the number of bits used in the exponent, and the precision by the number of bits
used in the mantissa (giving the maximum number of significant digits that can be
exactly represented). The higher the number of exponent bits the wider the range,
while the higher the number of mantissa bits, the higher the precision.
[endsect]
[section Exact, Correctly Rounded and Out-Of-Range Representations]
Given an abstract value `V` and a type `T` with its corresponding range `[abt(l),abt(h)]`:
If `V < abt(l)` or `V > abt(h)`, `V` is [*not representable] (cannot be represented) in
the type `T`, or, equivalently, it's representation in the type `T` is [*out of range],
or [*overflows].
* If `V < abt(l)`, the [*overflow is negative].
* If `V > abt(h)`, the [*overflow is positive].
If `V >= abt(l)` and `V <= abt(h)`, `V` is [*representable] (can be represented) in the
type `T`, or, equivalently, its representation in the type `T` is [*in range], or
[*does not overflow].
Notice that a numeric type, such as a C++ unsigned type, can define that any `V` does
not overflow by always representing not `V` itself but the abstract value
`U = [ V % (abt(h)+1) ]`, which is always in range.
Given an abstract value `V` represented in the type `T` as `v`, the [*roundoff] error
of the representation is the abstract difference: `(abt(v)-V)`.
Notice that a representation is an ['operation], hence, the roundoff error corresponds
to the representation operation and not to the numeric value itself
(i.e. numeric values do not have any error themselves)
* If the roundoff is 0, the representation is [*exact], and `V` is exactly representable
in the type `T`.
* If the roundoff is not 0, the representation is [*inexact], and `V` is inexactly
representable in the type `T`.
If a representation `v` in a type `T` -either exact or inexact-, is any of the adjacents
of `V` in that type, that is, if `v==prev` or `v==next`, the representation is
faithfully rounded. If the choice between `prev` and `next` matches a given
[*rounding direction], it is [*correctly rounded].
All exact representations are correctly rounded, but not all inexact representations are.
In particular, C++ requires numeric conversions (described below) and the result of
arithmetic operations (not covered by this document) to be correctly rounded, but
batch operations propagate roundoff, thus final results are usually incorrectly
rounded, that is, the numeric value `r` which is the computed result is neither of
the adjacents of the abstract value `R` which is the theoretical result.
Because a correctly rounded representation is always one of adjacents of the abstract
value being represented, the roundoff is guaranteed to be at most 1ulp.
The following examples summarize the given definitions. Consider:
* A numeric type `Int` representing integer numbers with a
['numeric set]: `{-2,-1,0,1,2}` and
['range]: `[-2,2]`
* A numeric type `Cardinal` representing integer numbers with a
['numeric set]: `{0,1,2,3,4,5,6,7,8,9}` and
['range]: `[0,9]` (no modulo-arithmetic here)
* A numeric type `Real` representing real numbers with a
['numeric set]: `{-2.0,-1.5,-1.0,-0.5,-0.0,+0.0,+0.5,+1.0,+1.5,+2.0}` and
['range]: `[-2.0,+2.0]`
* A numeric type `Whole` representing real numbers with a
['numeric set]: `{-2.0,-1.0,0.0,+1.0,+2.0}` and
['range]: `[-2.0,+2.0]`
First, notice that the types `Real` and `Whole` both represent real numbers,
have the same range, but different precision.
* The integer number `1` (an abstract value) can be exactly represented
in any of these types.
* The integer number `-1` can be exactly represented in `Int`, `Real` and `Whole`,
but cannot be represented in `Cardinal`, yielding negative overflow.
* The real number `1.5` can be exactly represented in `Real`, and inexactly
represented in the other types.
* If `1.5` is represented as either `1` or `2` in any of the types (except `Real`),
the representation is correctly rounded.
* If `0.5` is represented as `+1.5` in the type `Real`, it is incorrectly rounded.
* `(-2.0,-1.5)` are the `Real` adjacents of any real number in the interval
`[-2.0,-1.5]`, yet there are no `Real` adjacents for `x < -2.0`, nor for `x > +2.0`.
[endsect]
[section Standard (numeric) Conversions]
The C++ language defines [_Standard Conversions] (§4) some of which are conversions
between arithmetic types.
These are [_Integral promotions] (§4.5), [_Integral conversions] (§4.7),
[_Floating point promotions] (§4.6), [_Floating point conversions] (§4.8) and
[_Floating-integral conversions] (§4.9).
In the sequel, integral and floating point promotions are called [*arithmetic promotions],
and these plus integral, floating-point and floating-integral conversions are called
[*arithmetic conversions] (i.e, promotions are conversions).
Promotions, both Integral and Floating point, are ['value-preserving], which means that
the typed value is not changed with the conversion.
In the sequel, consider a source typed value `s` of type `S`, the source abstract
value `N=abt(s)`, a destination type `T`; and whenever possible, a result typed value
`t` of type `T`.
Integer to integer conversions are always defined:
* If `T` is unsigned, the abstract value which is effectively represented is not
`N` but `M=[ N % ( abt(h) + 1 ) ]`, where `h` is the highest unsigned typed
value of type `T`.
* If `T` is signed and `N` is not directly representable, the result `t` is
[_implementation-defined], which means that the C++ implementation is required to
produce a value `t` even if it is totally unrelated to `s`.
Floating to Floating conversions are defined only if `N` is representable;
if it is not, the conversion has [_undefined behavior].
* If `N` is exactly representable, `t` is required to be the exact representation.
* If `N` is inexactly representable, `t` is required to be one of the two
adjacents, with an implementation-defined choice of rounding direction;
that is, the conversion is required to be correctly rounded.
Floating to Integer conversions represent not `N` but `M=trunc(N)`, were
`trunc()` is to truncate: i.e. to remove the fractional part, if any.
* If `M` is not representable in `T`, the conversion has [_undefined behavior]
(unless `T` is `bool`, see §4.12).
Integer to Floating conversions are always defined.
* If `N` is exactly representable, `t` is required to be the exact representation.
* If `N` is inexactly representable, `t` is required to be one of the
two adjacents, with an implementation-defined choice of rounding direction;
that is, the conversion is required to be correctly rounded.
[endsect]
[section Subranged Conversion Direction, Subtype and Supertype]
Given a source type `S` and a destination type `T`, there is a
[*conversion direction] denoted: `S->T`.
For any two ranges the following ['range relation] can be defined:
A range `X` can be ['entirely contained] in a range `Y`, in which case
it is said that `X` is enclosed by `Y`.
[: [*Formally:] `R(S)` is enclosed by `R(T)` iif `(R(S) intersection R(T)) == R(S)`.]
If the source type range, `R(S)`, is not enclosed in the target type range,
`R(T)`; that is, if `(R(S) & R(T)) != R(S)`, the conversion direction is said
to be [*subranged], which means that `R(S)` is not entirely contained in `R(T)`
and therefore there is some portion of the source range which falls outside
the target range. In other words, if a conversion direction `S->T` is subranged,
there are values in `S` which cannot be represented in `T` because they are
out of range.
Notice that for `S->T`, the adjective subranged applies to `T`.
Examples:
Given the following numeric types all representing real numbers:
* `X` with numeric set `{-2.0,-1.0,0.0,+1.0,+2.0}` and range `[-2.0,+2.0]`
* `Y` with numeric set `{-2.0,-1.5,-1.0,-0.5,0.0,+0.5,+1.0,+1.5,+2.0}` and range `[-2.0,+2.0]`
* `Z` with numeric set `{-1.0,0.0,+1.0}` and range `[-1.0,+1.0]`
For:
[variablelist
[[(a) X->Y:][
`R(X) & R(Y) == R(X)`, then `X->Y` is not subranged.
Thus, all values of type `X` are representable in the type `Y`.
]]
[[(b) Y->X:][
`R(Y) & R(X) == R(Y)`, then `Y->X` is not subranged.
Thus, all values of type `Y` are representable in the type `X`, but in this case,
some values are ['inexactly] representable (all the halves).
(note: it is to permit this case that a range is an interval of abstract values and
not an interval of typed values)
]]
[[(b) X->Z:][
`R(X) & R(Z) != R(X)`, then `X->Z` is subranged.
Thus, some values of type `X` are not representable in the type `Z`, they fall
out of range `(-2.0 and +2.0)`.
]]
]
It is possible that `R(S)` is not enclosed by `R(T)`, while neither is `R(T)` enclosed
by `R(S)`; for example, `UNSIG=[0,255]` is not enclosed by `SIG=[-128,127]`;
neither is `SIG` enclosed by `UNSIG`.
This implies that is possible that a conversion direction is subranged both ways.
This occurs when a mixture of signed/unsigned types are involved and indicates that
in both directions there are values which can fall out of range.
Given the range relation (subranged or not) of a conversion direction `S->T`, it
is possible to classify `S` and `T` as [*supertype] and [*subtype]:
If the conversion is subranged, which means that `T` cannot represent all possible
values of type `S`, `S` is the supertype and `T` the subtype; otherwise, `T` is the
supertype and `S` the subtype.
For example:
[: `R(float)=[-FLT_MAX,FLT_MAX]` and `R(double)=[-DBL_MAX,DBL_MAX]` ]
If `FLT_MAX < DBL_MAX`:
* `double->float` is subranged and `supertype=double`, `subtype=float`.
* `float->double` is not subranged and `supertype=double`, `subtype=float`.
Notice that while `double->float` is subranged, `float->double` is not,
which yields the same supertype,subtype for both directions.
Now consider:
[: `R(int)=[INT_MIN,INT_MAX]` and `R(unsigned int)=[0,UINT_MAX]` ]
A C++ implementation is required to have `UINT_MAX > INT_MAX` (§3.9/3), so:
* 'int->unsigned' is subranged (negative values fall out of range)
and `supertype=int`, `subtype=unsigned`.
* 'unsigned->int' is ['also] subranged (high positive values fall out of range)
and `supertype=unsigned`, `subtype=int`.
In this case, the conversion is subranged in both directions and the
supertype,subtype pairs are not invariant (under inversion of direction).
This indicates that none of the types can represent all the values of the other.
When the supertype is the same for both `S->T` and `T->S`, it is effectively
indicating a type which can represent all the values of the subtype.
Consequently, if a conversion `X->Y` is not subranged, but the opposite `(Y->X)` is,
so that the supertype is always `Y`, it is said that the direction `X->Y` is [*correctly
rounded value preserving], meaning that all such conversions are guaranteed to
produce results in range and correctly rounded (even if inexact).
For example, all integer to floating conversions are correctly rounded value preserving.
[endsect]
[endsect]
@@ -0,0 +1,10 @@
index.html
boost_numericconversion/definitions.html
boost_numericconversion/converter___function_object.html
boost_numericconversion/type_requirements_and_user_defined_types_support.html
boost_numericconversion/bounds___traits_class.html
boost_numericconversion/conversion_traits___traits_class.html
boost_numericconversion/numeric_converter_policy_classes.html
boost_numericconversion/improved_numeric_cast__.html
numeric_conversion/history_and_acknowledgments.html
numeric_conversion/bibliography.html
@@ -0,0 +1,143 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>bounds&lt;&gt; traits class</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="prev" href="type_requirements_and_user_defined_types_support.html" title="Type Requirements and User-defined-types support">
<link rel="next" href="conversion_traits___traits_class.html" title="conversion_traits&lt;&gt; traits class">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="type_requirements_and_user_defined_types_support.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="conversion_traits___traits_class.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="boost_numericconversion.bounds___traits_class"></a><a class="link" href="bounds___traits_class.html" title="bounds&lt;&gt; traits class">bounds&lt;&gt;
traits class</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="bounds___traits_class.html#boost_numericconversion.bounds___traits_class.introduction">Introduction</a></span></dt>
<dt><span class="section"><a href="bounds___traits_class.html#boost_numericconversion.bounds___traits_class.traits_class_bounds_n_">traits
class bounds&lt;N&gt;</a></span></dt>
<dt><span class="section"><a href="bounds___traits_class.html#boost_numericconversion.bounds___traits_class.examples">Examples</a></span></dt>
</dl></div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.bounds___traits_class.introduction"></a><a class="link" href="bounds___traits_class.html#boost_numericconversion.bounds___traits_class.introduction" title="Introduction">Introduction</a>
</h3></div></div></div>
<p>
To determine the ranges of numeric types with <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span></code>
[18.2.1], different syntax have to be used depending on numeric type. Specifically,
<code class="computeroutput"><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">min</span><span class="special">()</span></code> for
integral types returns the minimum finite value, whereas for floating point
types it returns the minimum positive normalized value. The difference in
semantics makes client code unnecessarily complex and error prone.
</p>
<p>
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">bounds</span><span class="special">&lt;&gt;</span></code>
provides a consistent interface for retrieving the maximum finite value,
the minimum finite value and the minimum positive normalized value (0 for
integral types) for numeric types. The selection of implementation is performed
at compile time, so there is no runtime overhead.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.bounds___traits_class.traits_class_bounds_n_"></a><a class="link" href="bounds___traits_class.html#boost_numericconversion.bounds___traits_class.traits_class_bounds_n_" title="traits class bounds&lt;N&gt;">traits
class bounds&lt;N&gt;</a>
</h3></div></div></div>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">N</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">bounds</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="identifier">N</span> <span class="identifier">lowest</span> <span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">implementation_defined</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">static</span> <span class="identifier">N</span> <span class="identifier">highest</span> <span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">implementation_defined</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">static</span> <span class="identifier">N</span> <span class="identifier">smallest</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">implementation_defined</span><span class="special">;</span> <span class="special">}</span>
<span class="special">};</span>
</pre>
<h5>
<a name="boost_numericconversion.bounds___traits_class.traits_class_bounds_n_.h0"></a>
<span class="phrase"><a name="boost_numericconversion.bounds___traits_class.traits_class_bounds_n_.members"></a></span><a class="link" href="bounds___traits_class.html#boost_numericconversion.bounds___traits_class.traits_class_bounds_n_.members">Members</a>
</h5>
<div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">lowest</span><span class="special">()</span></code>
</p></blockquote></div>
<p>
Returns the minimum finite value, equivalent to <code class="computeroutput"><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">min</span><span class="special">()</span></code> when
<code class="computeroutput"><span class="identifier">T</span></code> is an integral type, and
to <code class="computeroutput"><span class="special">-</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">max</span><span class="special">()</span></code> when
<code class="computeroutput"><span class="identifier">T</span></code> is a floating point type.
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">highest</span><span class="special">()</span></code>
</p></blockquote></div>
<p>
Returns the maximum finite value, equivalent to <code class="computeroutput"><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">max</span><span class="special">()</span></code>.
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">smallest</span><span class="special">()</span></code>
</p></blockquote></div>
<p>
Returns the smallest positive normalized value for floating point types with
denormalization, or returns 0 for integral types.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.bounds___traits_class.examples"></a><a class="link" href="bounds___traits_class.html#boost_numericconversion.bounds___traits_class.examples" title="Examples">Examples</a>
</h3></div></div></div>
<p>
The following example demonstrates the use of <code class="computeroutput"><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">bounds</span><span class="special">&lt;&gt;</span></code> and the equivalent code using <code class="computeroutput"><span class="identifier">numeric_limits</span></code>:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">numeric</span><span class="special">/</span><span class="identifier">conversion</span><span class="special">/</span><span class="identifier">bounds</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">limits</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"numeric::bounds versus numeric_limits example.\n"</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"The maximum value for float:\n"</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">bounds</span><span class="special">&lt;</span><span class="keyword">float</span><span class="special">&gt;::</span><span class="identifier">highest</span><span class="special">()</span> <span class="special">&lt;&lt;</span> <span class="string">"\n"</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="keyword">float</span><span class="special">&gt;::</span><span class="identifier">max</span><span class="special">()</span> <span class="special">&lt;&lt;</span> <span class="string">"\n"</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"The minimum value for float:\n"</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">bounds</span><span class="special">&lt;</span><span class="keyword">float</span><span class="special">&gt;::</span><span class="identifier">lowest</span><span class="special">()</span> <span class="special">&lt;&lt;</span> <span class="string">"\n"</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="special">-</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="keyword">float</span><span class="special">&gt;::</span><span class="identifier">max</span><span class="special">()</span> <span class="special">&lt;&lt;</span> <span class="string">"\n"</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"The smallest positive value for float:\n"</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">bounds</span><span class="special">&lt;</span><span class="keyword">float</span><span class="special">&gt;::</span><span class="identifier">smallest</span><span class="special">()</span> <span class="special">&lt;&lt;</span> <span class="string">"\n"</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="keyword">float</span><span class="special">&gt;::</span><span class="identifier">min</span><span class="special">()</span> <span class="special">&lt;&lt;</span> <span class="string">"\n"</span><span class="special">;</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2004-2007 Fernando
Luis Cacciola Carballal<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="type_requirements_and_user_defined_types_support.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="conversion_traits___traits_class.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
@@ -0,0 +1,505 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>conversion_traits&lt;&gt; traits class</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="prev" href="bounds___traits_class.html" title="bounds&lt;&gt; traits class">
<link rel="next" href="numeric_converter_policy_classes.html" title="Numeric Converter Policy Classes">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="bounds___traits_class.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="numeric_converter_policy_classes.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="boost_numericconversion.conversion_traits___traits_class"></a><a class="link" href="conversion_traits___traits_class.html" title="conversion_traits&lt;&gt; traits class">conversion_traits&lt;&gt;
traits class</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types">Types</a></span></dt>
<dt><span class="section"><a href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.examples">Examples</a></span></dt>
</dl></div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.conversion_traits___traits_class.types"></a><a class="link" href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types" title="Types">Types</a>
</h3></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.enumeration_int_float_mixture_enum">enumeration
int_float_mixture_enum</a></span></dt>
<dt><span class="section"><a href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.enumeration_sign_mixture_enum">enumeration
sign_mixture_enum</a></span></dt>
<dt><span class="section"><a href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.enumeration_udt_builtin_mixture_enum">enumeration
udt_builtin_mixture_enum</a></span></dt>
<dt><span class="section"><a href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.template_class_int_float_mixture__">template
class int_float_mixture&lt;&gt;</a></span></dt>
<dt><span class="section"><a href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.template_class_sign_mixture__">template
class sign_mixture&lt;&gt;</a></span></dt>
<dt><span class="section"><a href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.template_class_udt_builtin_mixture__">template
class udt_builtin_mixture&lt;&gt;</a></span></dt>
<dt><span class="section"><a href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.template_class_is_subranged__">template
class is_subranged&lt;&gt;</a></span></dt>
<dt><span class="section"><a href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.template_class_conversion_traits__">template
class conversion_traits&lt;&gt;</a></span></dt>
</dl></div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_numericconversion.conversion_traits___traits_class.types.enumeration_int_float_mixture_enum"></a><a class="link" href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.enumeration_int_float_mixture_enum" title="enumeration int_float_mixture_enum">enumeration
int_float_mixture_enum</a>
</h4></div></div></div>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">numeric</span> <span class="special">{</span>
<span class="keyword">enum</span> <span class="identifier">int_float_mixture_enum</span>
<span class="special">{</span>
<span class="identifier">integral_to_integral</span>
<span class="special">,</span><span class="identifier">integral_to_float</span>
<span class="special">,</span><span class="identifier">float_to_integral</span>
<span class="special">,</span><span class="identifier">float_to_float</span>
<span class="special">}</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">}</span> <span class="comment">// namespace boost::numeric</span>
</pre>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_numericconversion.conversion_traits___traits_class.types.enumeration_sign_mixture_enum"></a><a class="link" href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.enumeration_sign_mixture_enum" title="enumeration sign_mixture_enum">enumeration
sign_mixture_enum</a>
</h4></div></div></div>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">numeric</span> <span class="special">{</span>
<span class="keyword">enum</span> <span class="identifier">sign_mixture_enum</span>
<span class="special">{</span>
<span class="identifier">unsigned_to_unsigned</span>
<span class="special">,</span><span class="identifier">signed_to_signed</span>
<span class="special">,</span><span class="identifier">signed_to_unsigned</span>
<span class="special">,</span><span class="identifier">unsigned_to_signed</span>
<span class="special">}</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">}</span> <span class="comment">// namespace boost::numeric</span>
</pre>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_numericconversion.conversion_traits___traits_class.types.enumeration_udt_builtin_mixture_enum"></a><a class="link" href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.enumeration_udt_builtin_mixture_enum" title="enumeration udt_builtin_mixture_enum">enumeration
udt_builtin_mixture_enum</a>
</h4></div></div></div>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">numeric</span> <span class="special">{</span>
<span class="keyword">enum</span> <span class="identifier">udt_builtin_mixture_enum</span>
<span class="special">{</span>
<span class="identifier">builtin_to_builtin</span>
<span class="special">,</span><span class="identifier">builtin_to_udt</span>
<span class="special">,</span><span class="identifier">udt_to_builtin</span>
<span class="special">,</span><span class="identifier">udt_to_udt</span>
<span class="special">}</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">}</span> <span class="comment">// namespace boost::numeric</span>
</pre>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_numericconversion.conversion_traits___traits_class.types.template_class_int_float_mixture__"></a><a class="link" href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.template_class_int_float_mixture__" title="template class int_float_mixture&lt;&gt;">template
class int_float_mixture&lt;&gt;</a>
</h4></div></div></div>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">numeric</span> <span class="special">{</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">S</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">int_float_mixture</span> <span class="special">:</span> <span class="identifier">mpl</span><span class="special">::</span><span class="identifier">integral_c</span><span class="special">&lt;</span><span class="identifier">int_float_mixture_enum</span><span class="special">,</span> <span class="identifier">impl</span><span class="special">-</span><span class="identifier">def</span><span class="special">-</span><span class="identifier">value</span><span class="special">&gt;</span> <span class="special">{}</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">}</span> <span class="comment">// namespace boost::numeric</span>
</pre>
<p>
Classifying <code class="computeroutput"><span class="identifier">S</span></code> and <code class="computeroutput"><span class="identifier">T</span></code> as either integral or float, this
<a href="../../../../../mpl/doc/refmanual/integral-constant.html" target="_top">MPL's
Integral Constant</a> indicates the combination of these attributes.
</p>
<p>
Its <code class="computeroutput"><span class="special">::</span><span class="identifier">value</span></code>
is of enumeration type <a class="link" href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.enumeration_int_float_mixture_enum" title="enumeration int_float_mixture_enum"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">int_float_mixture_enum</span></code></a>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_numericconversion.conversion_traits___traits_class.types.template_class_sign_mixture__"></a><a class="link" href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.template_class_sign_mixture__" title="template class sign_mixture&lt;&gt;">template
class sign_mixture&lt;&gt;</a>
</h4></div></div></div>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">numeric</span> <span class="special">{</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">S</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">sign_mixture</span> <span class="special">:</span> <span class="identifier">mpl</span><span class="special">::</span><span class="identifier">integral_c</span><span class="special">&lt;</span><span class="identifier">sign_mixture_enum</span><span class="special">,</span> <span class="identifier">impl</span><span class="special">-</span><span class="identifier">def</span><span class="special">-</span><span class="identifier">value</span><span class="special">&gt;</span> <span class="special">{}</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">}</span> <span class="comment">// namespace boost::numeric</span>
</pre>
<p>
Classifying <code class="computeroutput"><span class="identifier">S</span></code> and <code class="computeroutput"><span class="identifier">T</span></code> as either signed or unsigned, this
<a href="../../../../../mpl/doc/refmanual/integral-constant.html" target="_top">MPL's
Integral Constant</a> indicates the combination of these attributes.
</p>
<p>
Its <code class="computeroutput"><span class="special">::</span><span class="identifier">value</span></code>
is of enumeration type <a class="link" href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.enumeration_sign_mixture_enum" title="enumeration sign_mixture_enum"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">sign_mixture_enum</span></code></a>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_numericconversion.conversion_traits___traits_class.types.template_class_udt_builtin_mixture__"></a><a class="link" href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.template_class_udt_builtin_mixture__" title="template class udt_builtin_mixture&lt;&gt;">template
class udt_builtin_mixture&lt;&gt;</a>
</h4></div></div></div>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">numeric</span> <span class="special">{</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">S</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">udt_builtin_mixture</span> <span class="special">:</span> <span class="identifier">mpl</span><span class="special">::</span><span class="identifier">integral_c</span><span class="special">&lt;</span><span class="identifier">udt_builtin__mixture_enum</span><span class="special">,</span> <span class="identifier">impl</span><span class="special">-</span><span class="identifier">def</span><span class="special">-</span><span class="identifier">value</span><span class="special">&gt;</span> <span class="special">{}</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">}</span> <span class="comment">// namespace boost::numeric</span>
</pre>
<p>
Classifying <code class="computeroutput"><span class="identifier">S</span></code> and <code class="computeroutput"><span class="identifier">T</span></code> as either user-defined or builtin,
this <a href="../../../../../mpl/doc/refmanual/integral-constant.html" target="_top">MPL's
Integral Constant</a> indicates the combination of these attributes.
</p>
<p>
Its <code class="computeroutput"><span class="special">::</span><span class="identifier">value</span></code>
is of enumeration type <a class="link" href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.enumeration_udt_builtin_mixture_enum" title="enumeration udt_builtin_mixture_enum"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">udt_builtin_mixture_enum</span></code></a>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_numericconversion.conversion_traits___traits_class.types.template_class_is_subranged__"></a><a class="link" href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.template_class_is_subranged__" title="template class is_subranged&lt;&gt;">template
class is_subranged&lt;&gt;</a>
</h4></div></div></div>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">numeric</span> <span class="special">{</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">S</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">is_subranged</span> <span class="special">:</span> <span class="identifier">mpl</span><span class="special">::</span><span class="identifier">bool_</span><span class="special">&lt;</span><span class="identifier">impl</span><span class="special">-</span><span class="identifier">def</span><span class="special">-</span><span class="identifier">value</span><span class="special">&gt;</span> <span class="special">{}</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">}</span> <span class="comment">// namespace boost::numeric</span>
</pre>
<p>
Indicates if the range of the target type <code class="computeroutput"><span class="identifier">T</span></code>
is a subset of the range of the source type <code class="computeroutput"><span class="identifier">S</span></code>.
That is: if there are some source values which fall out of the Target type's
range.
</p>
<p>
It is a boolean <a href="../../../../../mpl/doc/refmanual/integral-constant.html" target="_top">MPL's
Integral Constant</a> .
</p>
<p>
It does not indicate if a particular conversion is effectively out of range;
it indicates that some conversion might be out of range because not all
the source values are representable as Target type.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_numericconversion.conversion_traits___traits_class.types.template_class_conversion_traits__"></a><a class="link" href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.template_class_conversion_traits__" title="template class conversion_traits&lt;&gt;">template
class conversion_traits&lt;&gt;</a>
</h4></div></div></div>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">numeric</span> <span class="special">{</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">S</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">conversion_traits</span>
<span class="special">{</span>
<span class="identifier">mpl</span><span class="special">::</span><span class="identifier">integral_c</span><span class="special">&lt;</span><span class="identifier">int_float_mixture_enum</span> <span class="special">,</span> <span class="special">...&gt;</span> <span class="identifier">int_float_mixture</span> <span class="special">;</span>
<span class="identifier">mpl</span><span class="special">::</span><span class="identifier">integral_c</span><span class="special">&lt;</span><span class="identifier">sign_mixture_enum</span> <span class="special">,</span> <span class="special">...&gt;</span> <span class="identifier">sign_mixture</span><span class="special">;</span>
<span class="identifier">mpl</span><span class="special">::</span><span class="identifier">integral_c</span><span class="special">&lt;</span><span class="identifier">udt_builtin_mixture_enum</span><span class="special">,</span> <span class="special">...&gt;</span> <span class="identifier">udt_builtin_mixture</span> <span class="special">;</span>
<span class="identifier">mpl</span><span class="special">::</span><span class="identifier">bool_</span><span class="special">&lt;...&gt;</span> <span class="identifier">subranged</span> <span class="special">;</span>
<span class="identifier">mpl</span><span class="special">::</span><span class="identifier">bool_</span><span class="special">&lt;...&gt;</span> <span class="identifier">trivial</span> <span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">T</span> <span class="identifier">target_type</span> <span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">S</span> <span class="identifier">source_type</span> <span class="special">;</span>
<span class="keyword">typedef</span> <span class="special">...</span> <span class="identifier">argument_type</span> <span class="special">;</span>
<span class="keyword">typedef</span> <span class="special">...</span> <span class="identifier">result_type</span> <span class="special">;</span>
<span class="keyword">typedef</span> <span class="special">...</span> <span class="identifier">supertype</span> <span class="special">;</span>
<span class="keyword">typedef</span> <span class="special">...</span> <span class="identifier">subtype</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">}</span> <span class="comment">// namespace numeric, namespace boost</span>
</pre>
<p>
This traits class indicates some properties of a <span class="emphasis"><em>numeric conversion</em></span>
direction: from a source type <code class="computeroutput"><span class="identifier">S</span></code>
to a target type <code class="computeroutput"><span class="identifier">T</span></code>. It
does not indicate the properties of a <span class="emphasis"><em>specific</em></span> conversion,
but of the conversion direction. See <a class="link" href="definitions.html#boost_numericconversion.definitions.subranged_conversion_direction__subtype_and_supertype" title="Subranged Conversion Direction, Subtype and Supertype">Definitions</a>
for details.
</p>
<p>
The traits class provides the following <a href="../../../../../mpl/doc/refmanual/integral-constant.html" target="_top">MPL's
Integral Constant</a> \s of enumeration type. They express the combination
of certain attributes of the Source and Target types (thus they are call
mixture):
</p>
<div class="informaltable"><table class="table">
<colgroup>
<col>
<col>
</colgroup>
<thead><tr>
<th>
</th>
<th>
</th>
</tr></thead>
<tbody>
<tr>
<td>
<p>
<span class="bold"><strong>int_float_mixture </strong></span>
</p>
</td>
<td>
<p>
Same as given by the traits class <a class="link" href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.template_class_int_float_mixture__" title="template class int_float_mixture&lt;&gt;">int_float_mixture</a>
</p>
</td>
</tr>
<tr>
<td>
<p>
<span class="bold"><strong>sign_mixture </strong></span>
</p>
</td>
<td>
<p>
Same as given by the traits class <a class="link" href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.template_class_sign_mixture__" title="template class sign_mixture&lt;&gt;">sign_mixture</a>
</p>
</td>
</tr>
<tr>
<td>
<p>
<span class="bold"><strong>udt_builtin_mixture </strong></span>
</p>
</td>
<td>
<p>
Same as given by the traits class <a class="link" href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.template_class_udt_builtin_mixture__" title="template class udt_builtin_mixture&lt;&gt;">udt_builtin_mixture</a>
</p>
</td>
</tr>
</tbody>
</table></div>
<p>
The traits class provides the following <a href="../../../../../mpl/doc/refmanual/integral-constant.html" target="_top">MPL's
Integral Constant</a> \s of boolean type which indicates indirectly
the relation between the Source and Target ranges (see <a class="link" href="definitions.html#boost_numericconversion.definitions.range_and_precision" title="Range and Precision">Definitions</a>
for details).
</p>
<div class="informaltable"><table class="table">
<colgroup>
<col>
<col>
</colgroup>
<thead><tr>
<th>
</th>
<th>
</th>
</tr></thead>
<tbody>
<tr>
<td>
<p>
subranged
</p>
</td>
<td>
<p>
Same as given by <a class="link" href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types.template_class_is_subranged__" title="template class is_subranged&lt;&gt;">is_subranged</a>
</p>
</td>
</tr>
<tr>
<td>
<p>
trivial
</p>
</td>
<td>
<p>
Indicates if both Source and Target, <span class="underline">without
cv-qualifications</span>, are the same type.
</p>
<p>
Its <code class="computeroutput"><span class="special">::</span><span class="identifier">value</span></code>
is of boolean type.
</p>
</td>
</tr>
</tbody>
</table></div>
<p>
The traits class provides the following types. They are the Source and
Target types classified and qualified for different purposes.
</p>
<div class="informaltable"><table class="table">
<colgroup>
<col>
<col>
</colgroup>
<thead><tr>
<th>
</th>
<th>
</th>
</tr></thead>
<tbody>
<tr>
<td>
<p>
<span class="bold"><strong>target_type</strong></span>
</p>
</td>
<td>
<p>
The template parameter <code class="computeroutput"><span class="identifier">T</span></code>
without cv-qualifications
</p>
</td>
</tr>
<tr>
<td>
<p>
<span class="bold"><strong>source_type</strong></span>
</p>
</td>
<td>
<p>
The template parameter <code class="computeroutput"><span class="identifier">S</span></code>
without cv-qualifications
</p>
</td>
</tr>
<tr>
<td>
<p>
<span class="bold"><strong>argument_type</strong></span>
</p>
</td>
<td>
<p>
This type is either source_type or <code class="computeroutput"><span class="identifier">source_type</span>
<span class="keyword">const</span><span class="special">&amp;</span></code>.
</p>
<p>
It represents the optimal argument type for the <a class="link" href="converter___function_object.html" title="converter&lt;&gt; function object">converter</a>
member functions.
</p>
<p>
If S is a built-in type, this is <code class="computeroutput"><span class="identifier">source_type</span></code>,
otherwise, this is <code class="computeroutput"><span class="identifier">source_type</span>
<span class="keyword">const</span><span class="special">&amp;</span></code>.
</p>
</td>
</tr>
<tr>
<td>
<p>
<span class="bold"><strong>result_type</strong></span>
</p>
</td>
<td>
<p>
This type is either target_type or target_type const&amp;
</p>
<p>
It represents the return type of the <a class="link" href="converter___function_object.html" title="converter&lt;&gt; function object">converter</a>
member functions.
</p>
<p>
If <code class="computeroutput"><span class="identifier">T</span><span class="special">==</span><span class="identifier">S</span></code>, it is <code class="computeroutput"><span class="identifier">target_type</span>
<span class="keyword">const</span><span class="special">&amp;</span></code>,
otherwise, it is <code class="computeroutput"><span class="identifier">target_type</span></code>.
</p>
</td>
</tr>
<tr>
<td>
<p>
<span class="bold"><strong>supertype</strong></span>
</p>
</td>
<td>
<p>
If the conversion is subranged, it is <code class="computeroutput"><span class="identifier">source_type</span></code>,
otherwise, it is <code class="computeroutput"><span class="identifier">target_type</span></code>
</p>
</td>
</tr>
<tr>
<td>
<p>
<span class="bold"><strong>subtype</strong></span>
</p>
</td>
<td>
<p>
If the conversion is subranged, it is <code class="computeroutput"><span class="identifier">target_type</span></code>,
otherwise, it is <code class="computeroutput"><span class="identifier">source_type</span></code>
</p>
</td>
</tr>
</tbody>
</table></div>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.conversion_traits___traits_class.examples"></a><a class="link" href="conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.examples" title="Examples">Examples</a>
</h3></div></div></div>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cassert</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">typeinfo</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">numeric</span><span class="special">/</span><span class="identifier">conversion</span><span class="special">/</span><span class="identifier">conversion_traits</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
<span class="comment">// A trivial conversion.</span>
<span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">conversion_traits</span><span class="special">&lt;</span><span class="keyword">short</span><span class="special">,</span><span class="keyword">short</span><span class="special">&gt;</span> <span class="identifier">Short2Short_Traits</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="identifier">Short2Short_Traits</span><span class="special">::</span><span class="identifier">trivial</span><span class="special">::</span><span class="identifier">value</span> <span class="special">)</span> <span class="special">;</span>
<span class="comment">// A subranged conversion.</span>
<span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">conversion_traits</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">,</span><span class="keyword">unsigned</span> <span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">UInt2Double_Traits</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="identifier">UInt2Double_Traits</span><span class="special">::</span><span class="identifier">int_float_mixture</span><span class="special">::</span><span class="identifier">value</span> <span class="special">==</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">integral_to_float</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="identifier">UInt2Double_Traits</span><span class="special">::</span><span class="identifier">sign_mixture</span><span class="special">::</span><span class="identifier">value</span> <span class="special">==</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">unsigned_to_signed</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="special">!</span><span class="identifier">UInt2Double_Traits</span><span class="special">::</span><span class="identifier">subranged</span><span class="special">::</span><span class="identifier">value</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="keyword">typeid</span><span class="special">(</span><span class="identifier">UInt2Double_Traits</span><span class="special">::</span><span class="identifier">supertype</span><span class="special">)</span> <span class="special">==</span> <span class="keyword">typeid</span><span class="special">(</span><span class="keyword">double</span><span class="special">)</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="keyword">typeid</span><span class="special">(</span><span class="identifier">UInt2Double_Traits</span><span class="special">::</span><span class="identifier">subtype</span><span class="special">)</span> <span class="special">==</span> <span class="keyword">typeid</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="keyword">int</span><span class="special">)</span> <span class="special">)</span> <span class="special">;</span>
<span class="comment">// A doubly subranged conversion.</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">conversion_traits</span><span class="special">&lt;</span><span class="keyword">short</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="keyword">short</span><span class="special">&gt;::</span><span class="identifier">subranged</span><span class="special">::</span><span class="identifier">value</span><span class="special">)</span> <span class="special">);</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">conversion_traits</span><span class="special">&lt;</span><span class="keyword">unsigned</span> <span class="keyword">short</span><span class="special">,</span> <span class="keyword">short</span><span class="special">&gt;::</span><span class="identifier">subranged</span><span class="special">::</span><span class="identifier">value</span><span class="special">)</span> <span class="special">);</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2004-2007 Fernando
Luis Cacciola Carballal<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="bounds___traits_class.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="numeric_converter_policy_classes.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
@@ -0,0 +1,462 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>converter&lt;&gt; function object</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="prev" href="definitions.html" title="Definitions">
<link rel="next" href="type_requirements_and_user_defined_types_support.html" title="Type Requirements and User-defined-types support">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="definitions.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="type_requirements_and_user_defined_types_support.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="boost_numericconversion.converter___function_object"></a><a class="link" href="converter___function_object.html" title="converter&lt;&gt; function object">converter&lt;&gt;
function object</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="converter___function_object.html#boost_numericconversion.converter___function_object.synopsis">Synopsis</a></span></dt>
<dt><span class="section"><a href="converter___function_object.html#boost_numericconversion.converter___function_object.template_parameters">Template
parameters</a></span></dt>
<dt><span class="section"><a href="converter___function_object.html#boost_numericconversion.converter___function_object.member_functions">Member
functions</a></span></dt>
<dt><span class="section"><a href="converter___function_object.html#boost_numericconversion.converter___function_object.range_checking_logic">Range
Checking Logic</a></span></dt>
<dt><span class="section"><a href="converter___function_object.html#boost_numericconversion.converter___function_object.examples">Examples</a></span></dt>
</dl></div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.converter___function_object.synopsis"></a><a class="link" href="converter___function_object.html#boost_numericconversion.converter___function_object.synopsis" title="Synopsis">Synopsis</a>
</h3></div></div></div>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">numeric</span> <span class="special">{</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span>
<span class="keyword">class</span> <span class="identifier">S</span><span class="special">,</span>
<span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="special">=</span> <span class="identifier">conversion_traits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">S</span><span class="special">&gt;</span>
<span class="keyword">class</span> <span class="identifier">OverflowHandler</span> <span class="special">=</span> <span class="identifier">def_overflow_handler</span><span class="special">,</span>
<span class="keyword">class</span> <span class="identifier">Float2IntRounder</span> <span class="special">=</span> <span class="identifier">Trunc</span><span class="special">&lt;</span> <span class="keyword">typename</span> <span class="identifier">Traits</span><span class="special">::</span><span class="identifier">source_type</span> <span class="special">&gt;,</span>
<span class="keyword">class</span> <span class="identifier">RawConverter</span> <span class="special">=</span> <span class="identifier">raw_converter</span><span class="special">&lt;</span><span class="identifier">Traits</span><span class="special">&gt;,</span>
<span class="keyword">class</span> <span class="identifier">UserRangeChecker</span> <span class="special">=</span> <span class="identifier">UseInternalRangeChecker</span>
<span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">converter</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="identifier">Traits</span> <span class="identifier">traits</span> <span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">Traits</span><span class="special">::</span><span class="identifier">source_type</span> <span class="identifier">source_type</span> <span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">Traits</span><span class="special">::</span><span class="identifier">argument_type</span> <span class="identifier">argument_type</span> <span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">Traits</span><span class="special">::</span><span class="identifier">result_type</span> <span class="identifier">result_type</span> <span class="special">;</span>
<span class="keyword">static</span> <span class="identifier">result_type</span> <span class="identifier">convert</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">result_type</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="comment">// Internal member functions:</span>
<span class="keyword">static</span> <span class="identifier">range_check_result</span> <span class="identifier">out_of_range</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span> <span class="special">;</span>
<span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">validate_range</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span> <span class="special">;</span>
<span class="keyword">static</span> <span class="identifier">result_type</span> <span class="identifier">low_level_convert</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span> <span class="special">;</span>
<span class="keyword">static</span> <span class="identifier">source_type</span> <span class="identifier">nearbyint</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">}</span> <span class="comment">// namespace numeric, boost</span>
</pre>
<p>
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">converter</span><span class="special">&lt;&gt;</span></code>
is a <a href="http://www.sgi.com/tech/stl/UnaryFunction.html" target="_top">Unary Function
Object</a> encapsulating the code to perform a numeric conversion with
the direction and properties specified by the Traits template parameter.
It can optionally take some <a class="link" href="numeric_converter_policy_classes.html" title="Numeric Converter Policy Classes">policies</a>
which can be used to customize its behavior. The <code class="computeroutput"><span class="identifier">Traits</span></code>
parameter is not a policy but the parameter that defines the conversion.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.converter___function_object.template_parameters"></a><a class="link" href="converter___function_object.html#boost_numericconversion.converter___function_object.template_parameters" title="Template parameters">Template
parameters</a>
</h3></div></div></div>
<div class="informaltable"><table class="table">
<colgroup>
<col>
<col>
</colgroup>
<thead><tr>
<th>
</th>
<th>
</th>
</tr></thead>
<tbody>
<tr>
<td>
<p>
<code class="computeroutput"><span class="identifier">T</span></code>
</p>
</td>
<td>
<p>
The <a class="link" href="definitions.html#boost_numericconversion.definitions.numeric_types" title="Numeric Types">Numeric
Type</a> which is the <span class="emphasis"><em>Target</em></span> of the conversion.
</p>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><span class="identifier">S</span></code>
</p>
</td>
<td>
<p>
The <a class="link" href="definitions.html#boost_numericconversion.definitions.numeric_types" title="Numeric Types">Numeric
Type</a> which is the <span class="emphasis"><em>Source</em></span> of the conversion.
</p>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><span class="identifier">Traits</span></code>
</p>
</td>
<td>
<p>
This must be a conversion traits class with the interface of <a class="link" href="conversion_traits___traits_class.html" title="conversion_traits&lt;&gt; traits class"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">conversion_traits</span></code></a>
</p>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><span class="identifier">OverflowHandler</span></code>
</p>
</td>
<td>
<p>
<span class="bold"><strong>Stateless Policy</strong></span> called to administrate
the result of the range checking.
</p>
<p>
It is a <span class="bold"><strong>Function Object</strong></span> which
receives the result of <code class="computeroutput"><span class="identifier">out_of_range</span><span class="special">()</span></code> and is called inside the <code class="computeroutput"><span class="identifier">validate_range</span><span class="special">()</span></code>
static member function exposed by the converter.
</p>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><span class="identifier">Float2IntRounder</span></code>
</p>
</td>
<td>
<p>
<span class="bold"><strong>Stateless Policy</strong></span> which specifies
the rounding mode used for float to integral conversions.
</p>
<p>
It supplies the <code class="computeroutput"><span class="identifier">nearbyint</span><span class="special">()</span></code> static member function exposed
by the converter.
</p>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><span class="identifier">RawConverter</span></code>
</p>
</td>
<td>
<p>
<span class="bold"><strong>Stateless Policy</strong></span> which is used
to perform the actual conversion.
</p>
<p>
It supplies the <code class="computeroutput"><span class="identifier">low_level_convert</span><span class="special">()</span></code> static member function exposed
by the converter.
</p>
</td>
</tr>
<tr>
<td>
<p>
<code class="computeroutput"><span class="identifier">UserRangeChecker</span></code>
</p>
</td>
<td>
<p>
<span class="emphasis"><em>Special and Optional</em></span> <span class="bold"><strong>Stateless
Policy</strong></span> which can be used to override the internal range
checking logic.
</p>
<p>
If given, supplies alternative code for the <code class="computeroutput"><span class="identifier">out_of_range</span><span class="special">()</span></code> and <code class="computeroutput"><span class="identifier">validate_range</span><span class="special">()</span></code> static member functions exposed
by the converter.
</p>
</td>
</tr>
</tbody>
</table></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.converter___function_object.member_functions"></a><a class="link" href="converter___function_object.html#boost_numericconversion.converter___function_object.member_functions" title="Member functions">Member
functions</a>
</h3></div></div></div>
<div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="keyword">static</span> <span class="identifier">result_type</span>
<span class="identifier">converter</span><span class="special">&lt;&gt;::</span><span class="identifier">convert</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span>
<span class="special">)</span> <span class="special">;</span> <span class="comment">// throw</span> </code>
</p></blockquote></div>
<p>
This static member function converts an rvalue of type <code class="computeroutput"><span class="identifier">source_type</span></code>
to an rvalue of type <code class="computeroutput"><span class="identifier">target_type</span></code>.
</p>
<p>
If the conversion requires it, it performs a range checking before the conversion
and passes the result of the check to the overflow handler policy (the default
policy throws an exception if out-of-range is detected)
</p>
<p>
The implementation of this function is actually built from the policies and
is basically as follows:
</p>
<pre class="programlisting"><span class="identifier">result_type</span> <span class="identifier">converter</span><span class="special">&lt;&gt;::</span><span class="identifier">convert</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span>
<span class="special">{</span>
<span class="identifier">validate_range</span><span class="special">(</span><span class="identifier">s</span><span class="special">);</span> <span class="comment">// Implemented by the internal range checking logic</span>
<span class="comment">// (which also calls the OverflowHandler policy)</span>
<span class="comment">// or externally supplied by the UserRangeChecker policy.</span>
<span class="identifier">s</span> <span class="special">=</span> <span class="identifier">nearbyint</span><span class="special">(</span><span class="identifier">s</span><span class="special">);</span> <span class="comment">// Externally supplied by the Float2IntRounder policy.</span>
<span class="comment">// NOTE: This is actually called only for float to int conversions.</span>
<span class="keyword">return</span> <span class="identifier">low_level_convert</span><span class="special">(</span><span class="identifier">s</span><span class="special">);</span> <span class="comment">// Externally supplied by the RawConverter policy.</span>
<span class="special">}</span>
</pre>
<p>
<code class="computeroutput"><span class="identifier">converter</span><span class="special">&lt;&gt;::</span><span class="keyword">operator</span><span class="special">()</span> <span class="keyword">const</span></code> just calls <code class="computeroutput"><span class="identifier">convert</span><span class="special">()</span></code>
</p>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="keyword">static</span> <span class="identifier">range_check_result</span>
<span class="identifier">numeric_converter</span><span class="special">&lt;&gt;::</span><span class="identifier">out_of_range</span> <span class="special">(</span>
<span class="identifier">argument_type</span> <span class="identifier">s</span>
<span class="special">)</span> <span class="special">;</span></code>
</p></blockquote></div>
<p>
This <a class="link" href="converter___function_object.html#numeric_conversion_converter_internal">internal</a>
static member function determines if the value <code class="computeroutput"><span class="identifier">s</span></code>
can be represented by the target type without overflow.
</p>
<p>
It does not determine if the conversion is <span class="emphasis"><em>exact</em></span>; that
is, it does not detect <span class="emphasis"><em>inexact</em></span> conversions, only <span class="emphasis"><em>out-of-range</em></span>
conversions (see the <a class="link" href="definitions.html#boost_numericconversion.definitions.exact__correctly_rounded_and_out_of_range_representations" title="Exact, Correctly Rounded and Out-Of-Range Representations">Definitions</a>
for further details).
</p>
<p>
The return value is of enum type <a class="link" href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.enum_range_check_result" title="enum range_check_result"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">range_check_result</span></code></a>
</p>
<p>
The actual code for the range checking logic is optimized for the combined
properties of the source and target types. For example, a non-subranged conversion
(i.e: <code class="computeroutput"><span class="keyword">int</span></code>-&gt;<code class="computeroutput"><span class="keyword">float</span></code>), requires no range checking, so <code class="computeroutput"><span class="identifier">out_of_range</span><span class="special">()</span></code>
returns <code class="computeroutput"><span class="identifier">cInRange</span></code> directly.
See the following <a class="link" href="converter___function_object.html#boost_numericconversion.converter___function_object.range_checking_logic" title="Range Checking Logic">table</a>
for more details.
</p>
<p>
If the user supplied a <a class="link" href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_userrangechecker" title="Policy UserRangeChecker">UserRangeChecker</a>
policy, is this policy which implements this function, so the implementation
is user defined, although it is expected to perform the same conceptual check
and return the appropriate result.
</p>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="keyword">static</span> <span class="keyword">void</span>
<span class="identifier">numeric_converter</span><span class="special">&lt;&gt;::</span><span class="identifier">validate_range</span> <span class="special">(</span>
<span class="identifier">argument_type</span> <span class="identifier">s</span>
<span class="special">)</span> <span class="special">;</span> <span class="comment">// no throw</span> </code>
</p></blockquote></div>
<p>
This <a class="link" href="converter___function_object.html#numeric_conversion_converter_internal">internal</a>
static member function calls out_of_range(s), and passes the result to the
<a class="link" href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_overflowhandler" title="Policy OverflowHandler">OverflowHandler</a>
policy class.
</p>
<p>
For those Target/Source combinations which don't require range checking,
this is an empty inline function.
</p>
<p>
If the user supplied a <a class="link" href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_userrangechecker" title="Policy UserRangeChecker">UserRangeChecker</a>
policy, is this policy which implements this function, so the implementation
is user defined, although it is expected to perform the same action as the
default. In particular, it is expected to pass the result of the check to
the overflow handler.
</p>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="keyword">static</span> <span class="identifier">result_type</span>
<span class="identifier">numeric_converter</span><span class="special">&lt;&gt;::</span><span class="identifier">low_level_convert</span> <span class="special">(</span>
<span class="identifier">argument_type</span> <span class="identifier">s</span>
<span class="special">)</span> <span class="special">;</span></code>
</p></blockquote></div>
<p>
This <a class="link" href="converter___function_object.html#numeric_conversion_converter_internal">internal</a>
static member function performs the actual conversion.
</p>
<p>
This function is externally supplied by the <a class="link" href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_rawconverter" title="Policy RawConverter">RawConverter</a>
policy class.
</p>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="keyword">static</span> <span class="identifier">source_type</span>
<span class="identifier">converter</span><span class="special">&lt;&gt;::</span><span class="identifier">nearbyint</span> <span class="special">(</span>
<span class="identifier">argument_type</span> <span class="identifier">s</span>
<span class="special">)</span> <span class="special">;</span></code>
</p></blockquote></div>
<p>
This <a class="link" href="converter___function_object.html#numeric_conversion_converter_internal">internal</a>
static member function, which is <span class="underline">only used</span>
for <code class="computeroutput"><span class="keyword">float</span></code> to <code class="computeroutput"><span class="keyword">int</span></code>
conversions, returns an <span class="emphasis"><em>integer</em></span> value of <span class="emphasis"><em><span class="underline">floating-point type</span></em></span> according to some
rounding direction.
</p>
<p>
This function is externally supplied by the <a class="link" href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_float2introunder" title="Policy Float2IntRounder">Float2IntRounder</a>
policy class which encapsulates the specific rounding mode.
</p>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<a name="numeric_conversion_converter_internal"></a><h5>
<a name="boost_numericconversion.converter___function_object.member_functions.h0"></a>
<span class="phrase"><a name="boost_numericconversion.converter___function_object.member_functions.internal_member_functions"></a></span><a class="link" href="converter___function_object.html#boost_numericconversion.converter___function_object.member_functions.internal_member_functions">Internal
Member Functions</a>
</h5>
<p>
These static member functions build the actual conversion code used by <code class="computeroutput"><span class="identifier">convert</span><span class="special">()</span></code>.
The user does not have to call these if calling <code class="computeroutput"><span class="identifier">convert</span><span class="special">()</span></code>, since <code class="computeroutput"><span class="identifier">convert</span><span class="special">()</span></code> calls them infernally, but they can be
called separately for specific needs.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.converter___function_object.range_checking_logic"></a><a class="link" href="converter___function_object.html#boost_numericconversion.converter___function_object.range_checking_logic" title="Range Checking Logic">Range
Checking Logic</a>
</h3></div></div></div>
<p>
The following table summarizes the internal range checking logic performed
for each combination of the properties of Source and Target.
</p>
<p>
LowestT/HighestT denotes the highest and lowest values of the Target type,
respectively.
</p>
<p>
<code class="computeroutput"><span class="identifier">S</span><span class="special">(</span><span class="identifier">n</span><span class="special">)</span></code> is short
for <code class="computeroutput"><span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">S</span><span class="special">&gt;(</span><span class="identifier">n</span><span class="special">)</span></code> (<code class="computeroutput"><span class="identifier">S</span></code> denotes the Source type).
</p>
<p>
<code class="computeroutput"><span class="identifier">NONE</span></code> indicates that for this
case there is no range checking.
</p>
<pre class="programlisting"><code class="literal">
int_to_int |--&gt; sig_to_sig |--&gt; subranged |--&gt; ( s &gt;= S(LowestT) ) &amp;&amp; ( s &lt;= S(HighestT) )
| |--&gt; not subranged |--&gt; NONE
|
|--&gt; unsig_to_unsig |--&gt; subranged |--&gt; ( s &gt;= S(LowestT) ) &amp;&amp; ( s &lt;= S(HighestT) )
| |--&gt; not subranged |--&gt; NONE
|
|--&gt; sig_to_unsig |--&gt; pos subranged |--&gt; ( s &gt;= S(0) ) &amp;&amp; ( s &lt;= S(HighestT) )
| |--&gt; not pos subranged |--&gt; ( s &gt;= S(0) )
|
|--&gt; unsig_to_sig |--&gt; subranged |--&gt; ( s &lt;= S(HighestT) )
| |--&gt; not subranged |--&gt; NONE
</code>
<code class="literal">
int_to_float |--&gt; NONE
</code>
<code class="literal">
float_to_int |--&gt; round_to_zero |--&gt; ( s &gt; S(LowestT)-S(1) ) &amp;&amp; ( s &lt; S(HighestT)+S(1) )
|--&gt; round_to_even_nearest |--&gt; ( s &gt;= S(LowestT)-S(0.5) ) &amp;&amp; ( s &lt; S(HighestT)+S(0.5) )
|--&gt; round_to_infinity |--&gt; ( s &gt; S(LowestT)-S(1) ) &amp;&amp; ( s &lt;= S(HighestT) )
|--&gt; round_to_neg_infinity |--&gt; ( s &gt;= S(LowestT) ) &amp;&amp; ( s &lt; S(HighestT)+S(1) )
</code>
<code class="literal">
float_to_float |--&gt; subranged |--&gt; ( s &gt;= S(LowestT) ) &amp;&amp; ( s &lt;= S(HighestT) )
|--&gt; not subranged |--&gt; NONE
</code>
</pre>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.converter___function_object.examples"></a><a class="link" href="converter___function_object.html#boost_numericconversion.converter___function_object.examples" title="Examples">Examples</a>
</h3></div></div></div>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cassert</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">numeric</span><span class="special">/</span><span class="identifier">conversion</span><span class="special">/</span><span class="identifier">converter</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">converter</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">double</span><span class="special">&gt;</span> <span class="identifier">Double2Int</span> <span class="special">;</span>
<span class="keyword">int</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">Double2Int</span><span class="special">::</span><span class="identifier">convert</span><span class="special">(</span><span class="number">2.0</span><span class="special">);</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="identifier">x</span> <span class="special">==</span> <span class="number">2</span> <span class="special">);</span>
<span class="keyword">int</span> <span class="identifier">y</span> <span class="special">=</span> <span class="identifier">Double2Int</span><span class="special">()(</span><span class="number">3.14</span><span class="special">);</span> <span class="comment">// As a function object.</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="identifier">y</span> <span class="special">==</span> <span class="number">3</span> <span class="special">)</span> <span class="special">;</span> <span class="comment">// The default rounding is trunc.</span>
<span class="keyword">try</span>
<span class="special">{</span>
<span class="keyword">double</span> <span class="identifier">m</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">bounds</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;::</span><span class="identifier">highest</span><span class="special">();</span>
<span class="keyword">int</span> <span class="identifier">z</span> <span class="special">=</span> <span class="identifier">Double2Int</span><span class="special">::</span><span class="identifier">convert</span><span class="special">(</span><span class="identifier">m</span><span class="special">);</span> <span class="comment">// By default throws positive_overflow()</span>
<span class="special">}</span>
<span class="keyword">catch</span> <span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">positive_overflow</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="special">)</span>
<span class="special">{</span>
<span class="special">}</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2004-2007 Fernando
Luis Cacciola Carballal<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="definitions.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="type_requirements_and_user_defined_types_support.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
@@ -0,0 +1,974 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Definitions</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="prev" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="next" href="converter___function_object.html" title="converter&lt;&gt; function object">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../index.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="converter___function_object.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="boost_numericconversion.definitions"></a><a class="link" href="definitions.html" title="Definitions">Definitions</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="definitions.html#boost_numericconversion.definitions.introduction">Introduction</a></span></dt>
<dt><span class="section"><a href="definitions.html#boost_numericconversion.definitions.types_and_values">Types
and Values</a></span></dt>
<dt><span class="section"><a href="definitions.html#boost_numericconversion.definitions.c___arithmetic_types">C++
Arithmetic Types</a></span></dt>
<dt><span class="section"><a href="definitions.html#boost_numericconversion.definitions.numeric_types">Numeric
Types</a></span></dt>
<dt><span class="section"><a href="definitions.html#boost_numericconversion.definitions.range_and_precision">Range
and Precision</a></span></dt>
<dt><span class="section"><a href="definitions.html#boost_numericconversion.definitions.exact__correctly_rounded_and_out_of_range_representations">Exact,
Correctly Rounded and Out-Of-Range Representations</a></span></dt>
<dt><span class="section"><a href="definitions.html#boost_numericconversion.definitions.standard__numeric__conversions">Standard
(numeric) Conversions</a></span></dt>
<dt><span class="section"><a href="definitions.html#boost_numericconversion.definitions.subranged_conversion_direction__subtype_and_supertype">Subranged
Conversion Direction, Subtype and Supertype</a></span></dt>
</dl></div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.definitions.introduction"></a><a class="link" href="definitions.html#boost_numericconversion.definitions.introduction" title="Introduction">Introduction</a>
</h3></div></div></div>
<p>
This section provides definitions of terms used in the Numeric Conversion
library.
</p>
<div class="blurb">
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
<p>
<span class="bold"><strong>Notation</strong></span> <span class="underline">underlined
text</span> denotes terms defined in the C++ standard.
</p>
<p>
<span class="bold"><strong>bold face</strong></span> denotes terms defined here but
not in the standard.
</p>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.definitions.types_and_values"></a><a class="link" href="definitions.html#boost_numericconversion.definitions.types_and_values" title="Types and Values">Types
and Values</a>
</h3></div></div></div>
<p>
As defined by the <span class="underline">C++ Object Model</span>
(&#167;1.7) the <span class="underline">storage</span> or memory on which
a C++ program runs is a contiguous sequence of <span class="underline">bytes</span>
where each byte is a contiguous sequence of bits.
</p>
<p>
An <span class="underline">object</span> is a region of storage (&#167;1.8)
and has a type (&#167;3.9).
</p>
<p>
A <span class="underline">type</span> is a discrete set of values.
</p>
<p>
An object of type <code class="computeroutput"><span class="identifier">T</span></code> has an
<span class="underline">object representation</span> which is the
sequence of bytes stored in the object (&#167;3.9/4)
</p>
<p>
An object of type <code class="computeroutput"><span class="identifier">T</span></code> has a
<span class="underline">value representation</span> which is the set
of bits that determine the <span class="emphasis"><em>value</em></span> of an object of that
type (&#167;3.9/4). For <span class="underline">POD</span> types (&#167;3.9/10),
this bitset is given by the object representation, but not all the bits in
the storage need to participate in the value representation (except for character
types): for example, some bits might be used for padding or there may be
trap-bits.
</p>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<p>
The <span class="bold"><strong>typed value</strong></span> that is held by an object
is the value which is determined by its value representation.
</p>
<p>
An <span class="bold"><strong>abstract value</strong></span> (untyped) is the conceptual
information that is represented in a type (i.e. the number &#960;).
</p>
<p>
The <span class="bold"><strong>intrinsic value</strong></span> of an object is the
binary value of the sequence of unsigned characters which form its object
representation.
</p>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<p>
<span class="emphasis"><em>Abstract</em></span> values can be <span class="bold"><strong>represented</strong></span>
in a given type.
</p>
<p>
To <span class="bold"><strong>represent</strong></span> an abstract value <code class="computeroutput"><span class="identifier">V</span></code> in a type <code class="computeroutput"><span class="identifier">T</span></code>
is to obtain a typed value <code class="computeroutput"><span class="identifier">v</span></code>
which corresponds to the abstract value <code class="computeroutput"><span class="identifier">V</span></code>.
</p>
<p>
The operation is denoted using the <code class="computeroutput"><span class="identifier">rep</span><span class="special">()</span></code> operator, as in: <code class="computeroutput"><span class="identifier">v</span><span class="special">=</span><span class="identifier">rep</span><span class="special">(</span><span class="identifier">V</span><span class="special">)</span></code>. <code class="computeroutput"><span class="identifier">v</span></code> is the <span class="bold"><strong>representation</strong></span>
of <code class="computeroutput"><span class="identifier">V</span></code> in the type <code class="computeroutput"><span class="identifier">T</span></code>.
</p>
<p>
For example, the abstract value &#960; can be represented in the type <code class="computeroutput"><span class="keyword">double</span></code> as the <code class="computeroutput"><span class="keyword">double</span>
<span class="identifier">value</span> <span class="identifier">M_PI</span></code>
and in the type <code class="computeroutput"><span class="keyword">int</span></code> as the
<code class="computeroutput"><span class="keyword">int</span> <span class="identifier">value</span>
<span class="number">3</span></code>
</p>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<p>
Conversely, <span class="emphasis"><em>typed values</em></span> can be <span class="bold"><strong>abstracted</strong></span>.
</p>
<p>
To <span class="bold"><strong>abstract</strong></span> a typed value <code class="computeroutput"><span class="identifier">v</span></code> of type <code class="computeroutput"><span class="identifier">T</span></code>
is to obtain the abstract value <code class="computeroutput"><span class="identifier">V</span></code>
whose representation in <code class="computeroutput"><span class="identifier">T</span></code>
is <code class="computeroutput"><span class="identifier">v</span></code>.
</p>
<p>
The operation is denoted using the <code class="computeroutput"><span class="identifier">abt</span><span class="special">()</span></code> operator, as in: <code class="computeroutput"><span class="identifier">V</span><span class="special">=</span><span class="identifier">abt</span><span class="special">(</span><span class="identifier">v</span><span class="special">)</span></code>.
</p>
<p>
<code class="computeroutput"><span class="identifier">V</span></code> is the <span class="bold"><strong>abstraction</strong></span>
of <code class="computeroutput"><span class="identifier">v</span></code> of type <code class="computeroutput"><span class="identifier">T</span></code>.
</p>
<p>
Abstraction is just an abstract operation (you can't do it); but it is defined
nevertheless because it will be used to give the definitions in the rest
of this document.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.definitions.c___arithmetic_types"></a><a class="link" href="definitions.html#boost_numericconversion.definitions.c___arithmetic_types" title="C++ Arithmetic Types">C++
Arithmetic Types</a>
</h3></div></div></div>
<p>
The C++ language defines <span class="underline">fundamental types</span>
(&#167;3.9.1). The following subsets of the fundamental types are intended to
represent <span class="emphasis"><em>numbers</em></span>:
</p>
<div class="variablelist">
<p class="title"><b></b></p>
<dl class="variablelist">
<dt><span class="term"><span class="underline">signed integer types</span> (&#167;3.9.1/2):</span></dt>
<dd><p>
<code class="computeroutput"><span class="special">{</span><span class="keyword">signed</span>
<span class="keyword">char</span><span class="special">,</span>
<span class="keyword">signed</span> <span class="keyword">short</span>
<span class="keyword">int</span><span class="special">,</span>
<span class="keyword">signed</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">signed</span> <span class="keyword">long</span> <span class="keyword">int</span><span class="special">}</span></code> Can be used to represent general integer
numbers (both negative and positive).
</p></dd>
<dt><span class="term"><span class="underline">unsigned integer types</span> (&#167;3.9.1/3):</span></dt>
<dd><p>
<code class="computeroutput"><span class="special">{</span><span class="keyword">unsigned</span>
<span class="keyword">char</span><span class="special">,</span>
<span class="keyword">unsigned</span> <span class="keyword">short</span>
<span class="keyword">int</span><span class="special">,</span>
<span class="keyword">unsigned</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">unsigned</span>
<span class="keyword">long</span> <span class="keyword">int</span><span class="special">}</span></code> Can be used to represent positive
integer numbers with modulo-arithmetic.
</p></dd>
<dt><span class="term"><span class="underline">floating-point types</span> (&#167;3.9.1/8):</span></dt>
<dd><p>
<code class="computeroutput"><span class="special">{</span><span class="keyword">float</span><span class="special">,</span><span class="keyword">double</span><span class="special">,</span><span class="keyword">long</span> <span class="keyword">double</span><span class="special">}</span></code>
Can be used to represent real numbers.
</p></dd>
<dt><span class="term"><span class="underline">integral or integer types</span> (&#167;3.9.1/7):</span></dt>
<dd><p>
<code class="computeroutput"><span class="special">{{</span><span class="keyword">signed</span>
<span class="identifier">integers</span><span class="special">},{</span><span class="keyword">unsigned</span> <span class="identifier">integers</span><span class="special">},</span> <span class="keyword">bool</span><span class="special">,</span> <span class="keyword">char</span> <span class="keyword">and</span> <span class="keyword">wchar_t</span><span class="special">}</span></code>
</p></dd>
<dt><span class="term"><span class="underline">arithmetic types</span> (&#167;3.9.1/8):</span></dt>
<dd><p>
<code class="computeroutput"><span class="special">{{</span><span class="identifier">integer</span>
<span class="identifier">types</span><span class="special">},{</span><span class="identifier">floating</span> <span class="identifier">types</span><span class="special">}}</span></code>
</p></dd>
</dl>
</div>
<p>
The integer types are required to have a <span class="emphasis"><em>binary</em></span> value
representation.
</p>
<p>
Additionally, the signed/unsigned integer types of the same base type (<code class="computeroutput"><span class="keyword">short</span></code>, <code class="computeroutput"><span class="keyword">int</span></code>
or <code class="computeroutput"><span class="keyword">long</span></code>) are required to have
the same value representation, that is:
</p>
<pre class="programlisting"> <span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="special">-</span><span class="number">3</span> <span class="special">;</span> <span class="comment">// suppose value representation is: 10011 (sign bit + 4 magnitude bits)</span>
<span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">u</span> <span class="special">=</span> <span class="identifier">i</span> <span class="special">;</span> <span class="comment">// u is required to have the same 10011 as its value representation.</span>
</pre>
<p>
In other words, the integer types signed/unsigned X use the same value representation
but a different <span class="emphasis"><em>interpretation</em></span> of it; that is, their
<span class="emphasis"><em>typed values</em></span> might differ.
</p>
<p>
Another consequence of this is that the range for signed X is always a smaller
subset of the range of unsigned X, as required by &#167;3.9.1/3.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top">
<p>
Always remember that unsigned types, unlike signed types, have modulo-arithmetic;
that is, they do not overflow. This means that:
</p>
<p>
<span class="bold"><strong>-</strong></span> Always be extra careful when mixing
signed/unsigned types
</p>
<p>
<span class="bold"><strong>-</strong></span> Use unsigned types only when you need
modulo arithmetic or very very large numbers. Don't use unsigned types
just because you intend to deal with positive values only (you can do this
with signed types as well).
</p>
</td></tr>
</table></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.definitions.numeric_types"></a><a class="link" href="definitions.html#boost_numericconversion.definitions.numeric_types" title="Numeric Types">Numeric
Types</a>
</h3></div></div></div>
<p>
This section introduces the following definitions intended to integrate arithmetic
types with user-defined types which behave like numbers. Some definitions
are purposely broad in order to include a vast variety of user-defined number
types.
</p>
<p>
Within this library, the term <span class="emphasis"><em>number</em></span> refers to an abstract
numeric value.
</p>
<p>
A type is <span class="bold"><strong>numeric</strong></span> if:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
It is an arithmetic type, or,
</li>
<li class="listitem">
It is a user-defined type which
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; ">
<li class="listitem">
Represents numeric abstract values (i.e. numbers).
</li>
<li class="listitem">
Can be converted (either implicitly or explicitly) to/from at least
one arithmetic type.
</li>
<li class="listitem">
Has <a class="link" href="definitions.html#boost_numericconversion.definitions.range_and_precision" title="Range and Precision">range</a>
(possibly unbounded) and <a class="link" href="definitions.html#boost_numericconversion.definitions.range_and_precision" title="Range and Precision">precision</a>
(possibly dynamic or unlimited).
</li>
<li class="listitem">
Provides an specialization of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span></code>.
</li>
</ul></div>
</li>
</ul></div>
<p>
A numeric type is <span class="bold"><strong>signed</strong></span> if the abstract
values it represent include negative numbers.
</p>
<p>
A numeric type is <span class="bold"><strong>unsigned</strong></span> if the abstract
values it represent exclude negative numbers.
</p>
<p>
A numeric type is <span class="bold"><strong>modulo</strong></span> if it has modulo-arithmetic
(does not overflow).
</p>
<p>
A numeric type is <span class="bold"><strong>integer</strong></span> if the abstract
values it represent are whole numbers.
</p>
<p>
A numeric type is <span class="bold"><strong>floating</strong></span> if the abstract
values it represent are real numbers.
</p>
<p>
An <span class="bold"><strong>arithmetic value</strong></span> is the typed value of
an arithmetic type
</p>
<p>
A <span class="bold"><strong>numeric value</strong></span> is the typed value of a
numeric type
</p>
<p>
These definitions simply generalize the standard notions of arithmetic types
and values by introducing a superset called <span class="underline">numeric</span>.
All arithmetic types and values are numeric types and values, but not vice
versa, since user-defined numeric types are not arithmetic types.
</p>
<p>
The following examples clarify the differences between arithmetic and numeric
types (and values):
</p>
<pre class="programlisting"><span class="comment">// A numeric type which is not an arithmetic type (is user-defined)</span>
<span class="comment">// and which is intended to represent integer numbers (i.e., an 'integer' numeric type)</span>
<span class="keyword">class</span> <span class="identifier">MyInt</span>
<span class="special">{</span>
<span class="identifier">MyInt</span> <span class="special">(</span> <span class="keyword">long</span> <span class="keyword">long</span> <span class="identifier">v</span> <span class="special">)</span> <span class="special">;</span>
<span class="keyword">long</span> <span class="keyword">long</span> <span class="identifier">to_builtin</span><span class="special">();</span>
<span class="special">}</span> <span class="special">;</span>
<span class="keyword">namespace</span> <span class="identifier">std</span> <span class="special">{</span>
<span class="keyword">template</span><span class="special">&lt;&gt;</span> <span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">MyInt</span><span class="special">&gt;</span> <span class="special">{</span> <span class="special">...</span> <span class="special">}</span> <span class="special">;</span>
<span class="special">}</span>
<span class="comment">// A 'floating' numeric type (double) which is also an arithmetic type (built-in),</span>
<span class="comment">// with a float numeric value.</span>
<span class="keyword">double</span> <span class="identifier">pi</span> <span class="special">=</span> <span class="identifier">M_PI</span> <span class="special">;</span>
<span class="comment">// A 'floating' numeric type with a whole numeric value.</span>
<span class="comment">// NOTE: numeric values are typed valued, hence, they are, for instance,</span>
<span class="comment">// integer or floating, despite the value itself being whole or including</span>
<span class="comment">// a fractional part.</span>
<span class="keyword">double</span> <span class="identifier">two</span> <span class="special">=</span> <span class="number">2.0</span> <span class="special">;</span>
<span class="comment">// An integer numeric type with an integer numeric value.</span>
<span class="identifier">MyInt</span> <span class="identifier">i</span><span class="special">(</span><span class="number">1234</span><span class="special">);</span>
</pre>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.definitions.range_and_precision"></a><a class="link" href="definitions.html#boost_numericconversion.definitions.range_and_precision" title="Range and Precision">Range
and Precision</a>
</h3></div></div></div>
<p>
Given a number set <code class="computeroutput"><span class="identifier">N</span></code>, some
of its elements are representable in a numeric type <code class="computeroutput"><span class="identifier">T</span></code>.
</p>
<p>
The set of representable values of type <code class="computeroutput"><span class="identifier">T</span></code>,
or numeric set of <code class="computeroutput"><span class="identifier">T</span></code>, is a
set of numeric values whose elements are the representation of some subset
of <code class="computeroutput"><span class="identifier">N</span></code>.
</p>
<p>
For example, the interval of <code class="computeroutput"><span class="keyword">int</span></code>
values <code class="computeroutput"><span class="special">[</span><span class="identifier">INT_MIN</span><span class="special">,</span><span class="identifier">INT_MAX</span><span class="special">]</span></code> is the set of representable values of type
<code class="computeroutput"><span class="keyword">int</span></code>, i.e. the <code class="computeroutput"><span class="keyword">int</span></code> numeric set, and corresponds to the representation
of the elements of the interval of abstract values <code class="computeroutput"><span class="special">[</span><span class="identifier">abt</span><span class="special">(</span><span class="identifier">INT_MIN</span><span class="special">),</span><span class="identifier">abt</span><span class="special">(</span><span class="identifier">INT_MAX</span><span class="special">)]</span></code>
from the integer numbers.
</p>
<p>
Similarly, the interval of <code class="computeroutput"><span class="keyword">double</span></code>
values <code class="computeroutput"><span class="special">[-</span><span class="identifier">DBL_MAX</span><span class="special">,</span><span class="identifier">DBL_MAX</span><span class="special">]</span></code> is the <code class="computeroutput"><span class="keyword">double</span></code>
numeric set, which corresponds to the subset of the real numbers from <code class="computeroutput"><span class="identifier">abt</span><span class="special">(-</span><span class="identifier">DBL_MAX</span><span class="special">)</span></code> to <code class="computeroutput"><span class="identifier">abt</span><span class="special">(</span><span class="identifier">DBL_MAX</span><span class="special">)</span></code>.
</p>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<p>
Let <span class="bold"><strong><code class="computeroutput"><span class="identifier">next</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span></code></strong></span>
denote the lowest numeric value greater than x.
</p>
<p>
Let <span class="bold"><strong><code class="computeroutput"><span class="identifier">prev</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span></code></strong></span>
denote the highest numeric value lower then x.
</p>
<p>
Let <span class="bold"><strong><code class="computeroutput"><span class="identifier">v</span><span class="special">=</span><span class="identifier">prev</span><span class="special">(</span><span class="identifier">next</span><span class="special">(</span><span class="identifier">V</span><span class="special">))</span></code></strong></span> and <span class="bold"><strong><code class="computeroutput"><span class="identifier">v</span><span class="special">=</span><span class="identifier">next</span><span class="special">(</span><span class="identifier">prev</span><span class="special">(</span><span class="identifier">V</span><span class="special">))</span></code></strong></span>
be identities that relate a numeric typed value <code class="computeroutput"><span class="identifier">v</span></code>
with a number <code class="computeroutput"><span class="identifier">V</span></code>.
</p>
<p>
An ordered pair of numeric values <code class="computeroutput"><span class="identifier">x</span></code>,<code class="computeroutput"><span class="identifier">y</span></code> s.t. <code class="computeroutput"><span class="identifier">x</span><span class="special">&lt;</span><span class="identifier">y</span></code> are
<span class="bold"><strong>consecutive</strong></span> iff <code class="computeroutput"><span class="identifier">next</span><span class="special">(</span><span class="identifier">x</span><span class="special">)==</span><span class="identifier">y</span></code>.
</p>
<p>
The abstract distance between consecutive numeric values is usually referred
to as a <span class="underline">Unit in the Last Place</span>, or
<span class="bold"><strong>ulp</strong></span> for short. A ulp is a quantity whose
abstract magnitude is relative to the numeric values it corresponds to: If
the numeric set is not evenly distributed, that is, if the abstract distance
between consecutive numeric values varies along the set -as is the case with
the floating-point types-, the magnitude of 1ulp after the numeric value
<code class="computeroutput"><span class="identifier">x</span></code> might be (usually is) different
from the magnitude of a 1ulp after the numeric value y for <code class="computeroutput"><span class="identifier">x</span><span class="special">!=</span><span class="identifier">y</span></code>.
</p>
<p>
Since numbers are inherently ordered, a <span class="bold"><strong>numeric set</strong></span>
of type <code class="computeroutput"><span class="identifier">T</span></code> is an ordered sequence
of numeric values (of type <code class="computeroutput"><span class="identifier">T</span></code>)
of the form:
</p>
<pre class="programlisting"><span class="identifier">REP</span><span class="special">(</span><span class="identifier">T</span><span class="special">)={</span><span class="identifier">l</span><span class="special">,</span><span class="identifier">next</span><span class="special">(</span><span class="identifier">l</span><span class="special">),</span><span class="identifier">next</span><span class="special">(</span><span class="identifier">next</span><span class="special">(</span><span class="identifier">l</span><span class="special">)),...,</span><span class="identifier">prev</span><span class="special">(</span><span class="identifier">prev</span><span class="special">(</span><span class="identifier">h</span><span class="special">)),</span><span class="identifier">prev</span><span class="special">(</span><span class="identifier">h</span><span class="special">),</span><span class="identifier">h</span><span class="special">}</span>
</pre>
<p>
where <code class="computeroutput"><span class="identifier">l</span></code> and <code class="computeroutput"><span class="identifier">h</span></code> are respectively the lowest and highest
values of type <code class="computeroutput"><span class="identifier">T</span></code>, called
the boundary values of type <code class="computeroutput"><span class="identifier">T</span></code>.
</p>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<p>
A numeric set is discrete. It has a <span class="bold"><strong>size</strong></span>
which is the number of numeric values in the set, a <span class="bold"><strong>width</strong></span>
which is the abstract difference between the highest and lowest boundary
values: <code class="computeroutput"><span class="special">[</span><span class="identifier">abt</span><span class="special">(</span><span class="identifier">h</span><span class="special">)-</span><span class="identifier">abt</span><span class="special">(</span><span class="identifier">l</span><span class="special">)]</span></code>, and a <span class="bold"><strong>density</strong></span>
which is the relation between its size and width: <code class="computeroutput"><span class="identifier">density</span><span class="special">=</span><span class="identifier">size</span><span class="special">/</span><span class="identifier">width</span></code>.
</p>
<p>
The integer types have density 1, which means that there are no unrepresentable
integer numbers between <code class="computeroutput"><span class="identifier">abt</span><span class="special">(</span><span class="identifier">l</span><span class="special">)</span></code>
and <code class="computeroutput"><span class="identifier">abt</span><span class="special">(</span><span class="identifier">h</span><span class="special">)</span></code> (i.e.
there are no gaps). On the other hand, floating types have density much smaller
than 1, which means that there are real numbers unrepresented between consecutive
floating values (i.e. there are gaps).
</p>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<p>
The interval of <span class="underline">abstract values</span> <code class="computeroutput"><span class="special">[</span><span class="identifier">abt</span><span class="special">(</span><span class="identifier">l</span><span class="special">),</span><span class="identifier">abt</span><span class="special">(</span><span class="identifier">h</span><span class="special">)]</span></code>
is the range of the type <code class="computeroutput"><span class="identifier">T</span></code>,
denoted <code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="identifier">T</span><span class="special">)</span></code>.
</p>
<p>
A range is a set of abstract values and not a set of numeric values. In other
documents, such as the C++ standard, the word <code class="computeroutput"><span class="identifier">range</span></code>
is <span class="emphasis"><em>sometimes</em></span> used as synonym for <code class="computeroutput"><span class="identifier">numeric</span>
<span class="identifier">set</span></code>, that is, as the ordered sequence
of numeric values from <code class="computeroutput"><span class="identifier">l</span></code>
to <code class="computeroutput"><span class="identifier">h</span></code>. In this document, however,
a range is an abstract interval which subtends the numeric set.
</p>
<p>
For example, the sequence <code class="computeroutput"><span class="special">[-</span><span class="identifier">DBL_MAX</span><span class="special">,</span><span class="identifier">DBL_MAX</span><span class="special">]</span></code>
is the numeric set of the type <code class="computeroutput"><span class="keyword">double</span></code>,
and the real interval <code class="computeroutput"><span class="special">[</span><span class="identifier">abt</span><span class="special">(-</span><span class="identifier">DBL_MAX</span><span class="special">),</span><span class="identifier">abt</span><span class="special">(</span><span class="identifier">DBL_MAX</span><span class="special">)]</span></code>
is its range.
</p>
<p>
Notice, for instance, that the range of a floating-point type is <span class="emphasis"><em>continuous</em></span>
unlike its numeric set.
</p>
<p>
This definition was chosen because:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>(a)</strong></span> The discrete set of numeric values
is already given by the numeric set.
</li>
<li class="listitem">
<span class="bold"><strong>(b)</strong></span> Abstract intervals are easier to
compare and overlap since only boundary values need to be considered.
</li>
</ul></div>
<p>
This definition allows for a concise definition of <code class="computeroutput"><span class="identifier">subranged</span></code>
as given in the last section.
</p>
<p>
The width of a numeric set, as defined, is exactly equivalent to the width
of a range.
</p>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<p>
The <span class="bold"><strong>precision</strong></span> of a type is given by the
width or density of the numeric set.
</p>
<p>
For integer types, which have density 1, the precision is conceptually equivalent
to the range and is determined by the number of bits used in the value representation:
The higher the number of bits the bigger the size of the numeric set, the
wider the range, and the higher the precision.
</p>
<p>
For floating types, which have density &lt;&lt;1, the precision is given
not by the width of the range but by the density. In a typical implementation,
the range is determined by the number of bits used in the exponent, and the
precision by the number of bits used in the mantissa (giving the maximum
number of significant digits that can be exactly represented). The higher
the number of exponent bits the wider the range, while the higher the number
of mantissa bits, the higher the precision.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.definitions.exact__correctly_rounded_and_out_of_range_representations"></a><a class="link" href="definitions.html#boost_numericconversion.definitions.exact__correctly_rounded_and_out_of_range_representations" title="Exact, Correctly Rounded and Out-Of-Range Representations">Exact,
Correctly Rounded and Out-Of-Range Representations</a>
</h3></div></div></div>
<p>
Given an abstract value <code class="computeroutput"><span class="identifier">V</span></code>
and a type <code class="computeroutput"><span class="identifier">T</span></code> with its corresponding
range <code class="computeroutput"><span class="special">[</span><span class="identifier">abt</span><span class="special">(</span><span class="identifier">l</span><span class="special">),</span><span class="identifier">abt</span><span class="special">(</span><span class="identifier">h</span><span class="special">)]</span></code>:
</p>
<p>
If <code class="computeroutput"><span class="identifier">V</span> <span class="special">&lt;</span>
<span class="identifier">abt</span><span class="special">(</span><span class="identifier">l</span><span class="special">)</span></code> or
<code class="computeroutput"><span class="identifier">V</span> <span class="special">&gt;</span>
<span class="identifier">abt</span><span class="special">(</span><span class="identifier">h</span><span class="special">)</span></code>, <code class="computeroutput"><span class="identifier">V</span></code> is <span class="bold"><strong>not representable</strong></span>
(cannot be represented) in the type <code class="computeroutput"><span class="identifier">T</span></code>,
or, equivalently, it's representation in the type <code class="computeroutput"><span class="identifier">T</span></code>
is <span class="bold"><strong>out of range</strong></span>, or <span class="bold"><strong>overflows</strong></span>.
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
If <code class="computeroutput"><span class="identifier">V</span> <span class="special">&lt;</span>
<span class="identifier">abt</span><span class="special">(</span><span class="identifier">l</span><span class="special">)</span></code>,
the <span class="bold"><strong>overflow is negative</strong></span>.
</li>
<li class="listitem">
If <code class="computeroutput"><span class="identifier">V</span> <span class="special">&gt;</span>
<span class="identifier">abt</span><span class="special">(</span><span class="identifier">h</span><span class="special">)</span></code>,
the <span class="bold"><strong>overflow is positive</strong></span>.
</li>
</ul></div>
<p>
If <code class="computeroutput"><span class="identifier">V</span> <span class="special">&gt;=</span>
<span class="identifier">abt</span><span class="special">(</span><span class="identifier">l</span><span class="special">)</span></code> and
<code class="computeroutput"><span class="identifier">V</span> <span class="special">&lt;=</span>
<span class="identifier">abt</span><span class="special">(</span><span class="identifier">h</span><span class="special">)</span></code>, <code class="computeroutput"><span class="identifier">V</span></code> is <span class="bold"><strong>representable</strong></span>
(can be represented) in the type <code class="computeroutput"><span class="identifier">T</span></code>,
or, equivalently, its representation in the type <code class="computeroutput"><span class="identifier">T</span></code>
is <span class="bold"><strong>in range</strong></span>, or <span class="bold"><strong>does
not overflow</strong></span>.
</p>
<p>
Notice that a numeric type, such as a C++ unsigned type, can define that
any <code class="computeroutput"><span class="identifier">V</span></code> does not overflow by
always representing not <code class="computeroutput"><span class="identifier">V</span></code>
itself but the abstract value <code class="computeroutput"><span class="identifier">U</span>
<span class="special">=</span> <span class="special">[</span> <span class="identifier">V</span> <span class="special">%</span> <span class="special">(</span><span class="identifier">abt</span><span class="special">(</span><span class="identifier">h</span><span class="special">)+</span><span class="number">1</span><span class="special">)</span>
<span class="special">]</span></code>, which is always in range.
</p>
<p>
Given an abstract value <code class="computeroutput"><span class="identifier">V</span></code>
represented in the type <code class="computeroutput"><span class="identifier">T</span></code>
as <code class="computeroutput"><span class="identifier">v</span></code>, the <span class="bold"><strong>roundoff</strong></span>
error of the representation is the abstract difference: <code class="computeroutput"><span class="special">(</span><span class="identifier">abt</span><span class="special">(</span><span class="identifier">v</span><span class="special">)-</span><span class="identifier">V</span><span class="special">)</span></code>.
</p>
<p>
Notice that a representation is an <span class="emphasis"><em>operation</em></span>, hence,
the roundoff error corresponds to the representation operation and not to
the numeric value itself (i.e. numeric values do not have any error themselves)
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
If the roundoff is 0, the representation is <span class="bold"><strong>exact</strong></span>,
and <code class="computeroutput"><span class="identifier">V</span></code> is exactly representable
in the type <code class="computeroutput"><span class="identifier">T</span></code>.
</li>
<li class="listitem">
If the roundoff is not 0, the representation is <span class="bold"><strong>inexact</strong></span>,
and <code class="computeroutput"><span class="identifier">V</span></code> is inexactly representable
in the type <code class="computeroutput"><span class="identifier">T</span></code>.
</li>
</ul></div>
<p>
If a representation <code class="computeroutput"><span class="identifier">v</span></code> in
a type <code class="computeroutput"><span class="identifier">T</span></code> -either exact or
inexact-, is any of the adjacents of <code class="computeroutput"><span class="identifier">V</span></code>
in that type, that is, if <code class="computeroutput"><span class="identifier">v</span><span class="special">==</span><span class="identifier">prev</span></code>
or <code class="computeroutput"><span class="identifier">v</span><span class="special">==</span><span class="identifier">next</span></code>, the representation is faithfully
rounded. If the choice between <code class="computeroutput"><span class="identifier">prev</span></code>
and <code class="computeroutput"><span class="identifier">next</span></code> matches a given
<span class="bold"><strong>rounding direction</strong></span>, it is <span class="bold"><strong>correctly
rounded</strong></span>.
</p>
<p>
All exact representations are correctly rounded, but not all inexact representations
are. In particular, C++ requires numeric conversions (described below) and
the result of arithmetic operations (not covered by this document) to be
correctly rounded, but batch operations propagate roundoff, thus final results
are usually incorrectly rounded, that is, the numeric value <code class="computeroutput"><span class="identifier">r</span></code> which is the computed result is neither
of the adjacents of the abstract value <code class="computeroutput"><span class="identifier">R</span></code>
which is the theoretical result.
</p>
<p>
Because a correctly rounded representation is always one of adjacents of
the abstract value being represented, the roundoff is guaranteed to be at
most 1ulp.
</p>
<p>
The following examples summarize the given definitions. Consider:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
A numeric type <code class="computeroutput"><span class="identifier">Int</span></code> representing
integer numbers with a <span class="emphasis"><em>numeric set</em></span>: <code class="computeroutput"><span class="special">{-</span><span class="number">2</span><span class="special">,-</span><span class="number">1</span><span class="special">,</span><span class="number">0</span><span class="special">,</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">}</span></code> and
<span class="emphasis"><em>range</em></span>: <code class="computeroutput"><span class="special">[-</span><span class="number">2</span><span class="special">,</span><span class="number">2</span><span class="special">]</span></code>
</li>
<li class="listitem">
A numeric type <code class="computeroutput"><span class="identifier">Cardinal</span></code>
representing integer numbers with a <span class="emphasis"><em>numeric set</em></span>:
<code class="computeroutput"><span class="special">{</span><span class="number">0</span><span class="special">,</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">,</span><span class="number">5</span><span class="special">,</span><span class="number">6</span><span class="special">,</span><span class="number">7</span><span class="special">,</span><span class="number">8</span><span class="special">,</span><span class="number">9</span><span class="special">}</span></code> and <span class="emphasis"><em>range</em></span>: <code class="computeroutput"><span class="special">[</span><span class="number">0</span><span class="special">,</span><span class="number">9</span><span class="special">]</span></code> (no
modulo-arithmetic here)
</li>
<li class="listitem">
A numeric type <code class="computeroutput"><span class="identifier">Real</span></code> representing
real numbers with a <span class="emphasis"><em>numeric set</em></span>: <code class="computeroutput"><span class="special">{-</span><span class="number">2.0</span><span class="special">,-</span><span class="number">1.5</span><span class="special">,-</span><span class="number">1.0</span><span class="special">,-</span><span class="number">0.5</span><span class="special">,-</span><span class="number">0.0</span><span class="special">,+</span><span class="number">0.0</span><span class="special">,+</span><span class="number">0.5</span><span class="special">,+</span><span class="number">1.0</span><span class="special">,+</span><span class="number">1.5</span><span class="special">,+</span><span class="number">2.0</span><span class="special">}</span></code> and
<span class="emphasis"><em>range</em></span>: <code class="computeroutput"><span class="special">[-</span><span class="number">2.0</span><span class="special">,+</span><span class="number">2.0</span><span class="special">]</span></code>
</li>
<li class="listitem">
A numeric type <code class="computeroutput"><span class="identifier">Whole</span></code>
representing real numbers with a <span class="emphasis"><em>numeric set</em></span>: <code class="computeroutput"><span class="special">{-</span><span class="number">2.0</span><span class="special">,-</span><span class="number">1.0</span><span class="special">,</span><span class="number">0.0</span><span class="special">,+</span><span class="number">1.0</span><span class="special">,+</span><span class="number">2.0</span><span class="special">}</span></code> and
<span class="emphasis"><em>range</em></span>: <code class="computeroutput"><span class="special">[-</span><span class="number">2.0</span><span class="special">,+</span><span class="number">2.0</span><span class="special">]</span></code>
</li>
</ul></div>
<p>
First, notice that the types <code class="computeroutput"><span class="identifier">Real</span></code>
and <code class="computeroutput"><span class="identifier">Whole</span></code> both represent
real numbers, have the same range, but different precision.
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
The integer number <code class="computeroutput"><span class="number">1</span></code> (an
abstract value) can be exactly represented in any of these types.
</li>
<li class="listitem">
The integer number <code class="computeroutput"><span class="special">-</span><span class="number">1</span></code>
can be exactly represented in <code class="computeroutput"><span class="identifier">Int</span></code>,
<code class="computeroutput"><span class="identifier">Real</span></code> and <code class="computeroutput"><span class="identifier">Whole</span></code>, but cannot be represented in
<code class="computeroutput"><span class="identifier">Cardinal</span></code>, yielding negative
overflow.
</li>
<li class="listitem">
The real number <code class="computeroutput"><span class="number">1.5</span></code> can be
exactly represented in <code class="computeroutput"><span class="identifier">Real</span></code>,
and inexactly represented in the other types.
</li>
<li class="listitem">
If <code class="computeroutput"><span class="number">1.5</span></code> is represented as
either <code class="computeroutput"><span class="number">1</span></code> or <code class="computeroutput"><span class="number">2</span></code> in any of the types (except <code class="computeroutput"><span class="identifier">Real</span></code>), the representation is correctly
rounded.
</li>
<li class="listitem">
If <code class="computeroutput"><span class="number">0.5</span></code> is represented as
<code class="computeroutput"><span class="special">+</span><span class="number">1.5</span></code>
in the type <code class="computeroutput"><span class="identifier">Real</span></code>, it
is incorrectly rounded.
</li>
<li class="listitem">
<code class="computeroutput"><span class="special">(-</span><span class="number">2.0</span><span class="special">,-</span><span class="number">1.5</span><span class="special">)</span></code>
are the <code class="computeroutput"><span class="identifier">Real</span></code> adjacents
of any real number in the interval <code class="computeroutput"><span class="special">[-</span><span class="number">2.0</span><span class="special">,-</span><span class="number">1.5</span><span class="special">]</span></code>, yet there are no <code class="computeroutput"><span class="identifier">Real</span></code>
adjacents for <code class="computeroutput"><span class="identifier">x</span> <span class="special">&lt;</span>
<span class="special">-</span><span class="number">2.0</span></code>,
nor for <code class="computeroutput"><span class="identifier">x</span> <span class="special">&gt;</span>
<span class="special">+</span><span class="number">2.0</span></code>.
</li>
</ul></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.definitions.standard__numeric__conversions"></a><a class="link" href="definitions.html#boost_numericconversion.definitions.standard__numeric__conversions" title="Standard (numeric) Conversions">Standard
(numeric) Conversions</a>
</h3></div></div></div>
<p>
The C++ language defines <span class="underline">Standard Conversions</span>
(&#167;4) some of which are conversions between arithmetic types.
</p>
<p>
These are <span class="underline">Integral promotions</span> (&#167;4.5),
<span class="underline">Integral conversions</span> (&#167;4.7), <span class="underline">Floating point promotions</span> (&#167;4.6), <span class="underline">Floating point conversions</span> (&#167;4.8) and <span class="underline">Floating-integral conversions</span> (&#167;4.9).
</p>
<p>
In the sequel, integral and floating point promotions are called <span class="bold"><strong>arithmetic promotions</strong></span>, and these plus integral, floating-point
and floating-integral conversions are called <span class="bold"><strong>arithmetic
conversions</strong></span> (i.e, promotions are conversions).
</p>
<p>
Promotions, both Integral and Floating point, are <span class="emphasis"><em>value-preserving</em></span>,
which means that the typed value is not changed with the conversion.
</p>
<p>
In the sequel, consider a source typed value <code class="computeroutput"><span class="identifier">s</span></code>
of type <code class="computeroutput"><span class="identifier">S</span></code>, the source abstract
value <code class="computeroutput"><span class="identifier">N</span><span class="special">=</span><span class="identifier">abt</span><span class="special">(</span><span class="identifier">s</span><span class="special">)</span></code>, a destination type <code class="computeroutput"><span class="identifier">T</span></code>;
and whenever possible, a result typed value <code class="computeroutput"><span class="identifier">t</span></code>
of type <code class="computeroutput"><span class="identifier">T</span></code>.
</p>
<p>
Integer to integer conversions are always defined:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
If <code class="computeroutput"><span class="identifier">T</span></code> is unsigned, the
abstract value which is effectively represented is not <code class="computeroutput"><span class="identifier">N</span></code> but <code class="computeroutput"><span class="identifier">M</span><span class="special">=[</span> <span class="identifier">N</span> <span class="special">%</span> <span class="special">(</span> <span class="identifier">abt</span><span class="special">(</span><span class="identifier">h</span><span class="special">)</span> <span class="special">+</span> <span class="number">1</span>
<span class="special">)</span> <span class="special">]</span></code>,
where <code class="computeroutput"><span class="identifier">h</span></code> is the highest
unsigned typed value of type <code class="computeroutput"><span class="identifier">T</span></code>.
</li>
<li class="listitem">
If <code class="computeroutput"><span class="identifier">T</span></code> is signed and <code class="computeroutput"><span class="identifier">N</span></code> is not directly representable, the
result <code class="computeroutput"><span class="identifier">t</span></code> is <span class="underline">implementation-defined</span>, which means that
the C++ implementation is required to produce a value <code class="computeroutput"><span class="identifier">t</span></code>
even if it is totally unrelated to <code class="computeroutput"><span class="identifier">s</span></code>.
</li>
</ul></div>
<p>
Floating to Floating conversions are defined only if <code class="computeroutput"><span class="identifier">N</span></code>
is representable; if it is not, the conversion has <span class="underline">undefined
behavior</span>.
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
If <code class="computeroutput"><span class="identifier">N</span></code> is exactly representable,
<code class="computeroutput"><span class="identifier">t</span></code> is required to be the
exact representation.
</li>
<li class="listitem">
If <code class="computeroutput"><span class="identifier">N</span></code> is inexactly representable,
<code class="computeroutput"><span class="identifier">t</span></code> is required to be one
of the two adjacents, with an implementation-defined choice of rounding
direction; that is, the conversion is required to be correctly rounded.
</li>
</ul></div>
<p>
Floating to Integer conversions represent not <code class="computeroutput"><span class="identifier">N</span></code>
but <code class="computeroutput"><span class="identifier">M</span><span class="special">=</span><span class="identifier">trunc</span><span class="special">(</span><span class="identifier">N</span><span class="special">)</span></code>, were
<code class="computeroutput"><span class="identifier">trunc</span><span class="special">()</span></code>
is to truncate: i.e. to remove the fractional part, if any.
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
If <code class="computeroutput"><span class="identifier">M</span></code> is not representable
in <code class="computeroutput"><span class="identifier">T</span></code>, the conversion
has <span class="underline">undefined behavior</span> (unless
<code class="computeroutput"><span class="identifier">T</span></code> is <code class="computeroutput"><span class="keyword">bool</span></code>,
see &#167;4.12).
</li></ul></div>
<p>
Integer to Floating conversions are always defined.
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
If <code class="computeroutput"><span class="identifier">N</span></code> is exactly representable,
<code class="computeroutput"><span class="identifier">t</span></code> is required to be the
exact representation.
</li>
<li class="listitem">
If <code class="computeroutput"><span class="identifier">N</span></code> is inexactly representable,
<code class="computeroutput"><span class="identifier">t</span></code> is required to be one
of the two adjacents, with an implementation-defined choice of rounding
direction; that is, the conversion is required to be correctly rounded.
</li>
</ul></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.definitions.subranged_conversion_direction__subtype_and_supertype"></a><a class="link" href="definitions.html#boost_numericconversion.definitions.subranged_conversion_direction__subtype_and_supertype" title="Subranged Conversion Direction, Subtype and Supertype">Subranged
Conversion Direction, Subtype and Supertype</a>
</h3></div></div></div>
<p>
Given a source type <code class="computeroutput"><span class="identifier">S</span></code> and
a destination type <code class="computeroutput"><span class="identifier">T</span></code>, there
is a <span class="bold"><strong>conversion direction</strong></span> denoted: <code class="computeroutput"><span class="identifier">S</span><span class="special">-&gt;</span><span class="identifier">T</span></code>.
</p>
<p>
For any two ranges the following <span class="emphasis"><em>range relation</em></span> can
be defined: A range <code class="computeroutput"><span class="identifier">X</span></code> can
be <span class="emphasis"><em>entirely contained</em></span> in a range <code class="computeroutput"><span class="identifier">Y</span></code>,
in which case it is said that <code class="computeroutput"><span class="identifier">X</span></code>
is enclosed by <code class="computeroutput"><span class="identifier">Y</span></code>.
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<span class="bold"><strong>Formally:</strong></span> <code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="identifier">S</span><span class="special">)</span></code>
is enclosed by <code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="identifier">T</span><span class="special">)</span></code> iif
<code class="computeroutput"><span class="special">(</span><span class="identifier">R</span><span class="special">(</span><span class="identifier">S</span><span class="special">)</span>
<span class="identifier">intersection</span> <span class="identifier">R</span><span class="special">(</span><span class="identifier">T</span><span class="special">))</span>
<span class="special">==</span> <span class="identifier">R</span><span class="special">(</span><span class="identifier">S</span><span class="special">)</span></code>.
</p></blockquote></div>
<p>
If the source type range, <code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="identifier">S</span><span class="special">)</span></code>,
is not enclosed in the target type range, <code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="identifier">T</span><span class="special">)</span></code>;
that is, if <code class="computeroutput"><span class="special">(</span><span class="identifier">R</span><span class="special">(</span><span class="identifier">S</span><span class="special">)</span>
<span class="special">&amp;</span> <span class="identifier">R</span><span class="special">(</span><span class="identifier">T</span><span class="special">))</span>
<span class="special">!=</span> <span class="identifier">R</span><span class="special">(</span><span class="identifier">S</span><span class="special">)</span></code>,
the conversion direction is said to be <span class="bold"><strong>subranged</strong></span>,
which means that <code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="identifier">S</span><span class="special">)</span></code> is not
entirely contained in <code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="identifier">T</span><span class="special">)</span></code> and
therefore there is some portion of the source range which falls outside the
target range. In other words, if a conversion direction <code class="computeroutput"><span class="identifier">S</span><span class="special">-&gt;</span><span class="identifier">T</span></code>
is subranged, there are values in <code class="computeroutput"><span class="identifier">S</span></code>
which cannot be represented in <code class="computeroutput"><span class="identifier">T</span></code>
because they are out of range. Notice that for <code class="computeroutput"><span class="identifier">S</span><span class="special">-&gt;</span><span class="identifier">T</span></code>,
the adjective subranged applies to <code class="computeroutput"><span class="identifier">T</span></code>.
</p>
<p>
Examples:
</p>
<p>
Given the following numeric types all representing real numbers:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<code class="computeroutput"><span class="identifier">X</span></code> with numeric set <code class="computeroutput"><span class="special">{-</span><span class="number">2.0</span><span class="special">,-</span><span class="number">1.0</span><span class="special">,</span><span class="number">0.0</span><span class="special">,+</span><span class="number">1.0</span><span class="special">,+</span><span class="number">2.0</span><span class="special">}</span></code> and
range <code class="computeroutput"><span class="special">[-</span><span class="number">2.0</span><span class="special">,+</span><span class="number">2.0</span><span class="special">]</span></code>
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">Y</span></code> with numeric set <code class="computeroutput"><span class="special">{-</span><span class="number">2.0</span><span class="special">,-</span><span class="number">1.5</span><span class="special">,-</span><span class="number">1.0</span><span class="special">,-</span><span class="number">0.5</span><span class="special">,</span><span class="number">0.0</span><span class="special">,+</span><span class="number">0.5</span><span class="special">,+</span><span class="number">1.0</span><span class="special">,+</span><span class="number">1.5</span><span class="special">,+</span><span class="number">2.0</span><span class="special">}</span></code> and range <code class="computeroutput"><span class="special">[-</span><span class="number">2.0</span><span class="special">,+</span><span class="number">2.0</span><span class="special">]</span></code>
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">Z</span></code> with numeric set <code class="computeroutput"><span class="special">{-</span><span class="number">1.0</span><span class="special">,</span><span class="number">0.0</span><span class="special">,+</span><span class="number">1.0</span><span class="special">}</span></code> and range <code class="computeroutput"><span class="special">[-</span><span class="number">1.0</span><span class="special">,+</span><span class="number">1.0</span><span class="special">]</span></code>
</li>
</ul></div>
<p>
For:
</p>
<div class="variablelist">
<p class="title"><b></b></p>
<dl class="variablelist">
<dt><span class="term">(a) X-&gt;Y:</span></dt>
<dd><p>
<code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="identifier">X</span><span class="special">)</span> <span class="special">&amp;</span> <span class="identifier">R</span><span class="special">(</span><span class="identifier">Y</span><span class="special">)</span> <span class="special">==</span> <span class="identifier">R</span><span class="special">(</span><span class="identifier">X</span><span class="special">)</span></code>,
then <code class="computeroutput"><span class="identifier">X</span><span class="special">-&gt;</span><span class="identifier">Y</span></code> is not subranged. Thus, all values
of type <code class="computeroutput"><span class="identifier">X</span></code> are representable
in the type <code class="computeroutput"><span class="identifier">Y</span></code>.
</p></dd>
<dt><span class="term">(b) Y-&gt;X:</span></dt>
<dd><p>
<code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="identifier">Y</span><span class="special">)</span> <span class="special">&amp;</span> <span class="identifier">R</span><span class="special">(</span><span class="identifier">X</span><span class="special">)</span> <span class="special">==</span> <span class="identifier">R</span><span class="special">(</span><span class="identifier">Y</span><span class="special">)</span></code>,
then <code class="computeroutput"><span class="identifier">Y</span><span class="special">-&gt;</span><span class="identifier">X</span></code> is not subranged. Thus, all values
of type <code class="computeroutput"><span class="identifier">Y</span></code> are representable
in the type <code class="computeroutput"><span class="identifier">X</span></code>, but
in this case, some values are <span class="emphasis"><em>inexactly</em></span> representable
(all the halves). (note: it is to permit this case that a range is
an interval of abstract values and not an interval of typed values)
</p></dd>
<dt><span class="term">(b) X-&gt;Z:</span></dt>
<dd><p>
<code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="identifier">X</span><span class="special">)</span> <span class="special">&amp;</span> <span class="identifier">R</span><span class="special">(</span><span class="identifier">Z</span><span class="special">)</span> <span class="special">!=</span> <span class="identifier">R</span><span class="special">(</span><span class="identifier">X</span><span class="special">)</span></code>,
then <code class="computeroutput"><span class="identifier">X</span><span class="special">-&gt;</span><span class="identifier">Z</span></code> is subranged. Thus, some values
of type <code class="computeroutput"><span class="identifier">X</span></code> are not representable
in the type <code class="computeroutput"><span class="identifier">Z</span></code>, they
fall out of range <code class="computeroutput"><span class="special">(-</span><span class="number">2.0</span>
<span class="keyword">and</span> <span class="special">+</span><span class="number">2.0</span><span class="special">)</span></code>.
</p></dd>
</dl>
</div>
<p>
It is possible that <code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="identifier">S</span><span class="special">)</span></code> is not
enclosed by <code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="identifier">T</span><span class="special">)</span></code>, while
neither is <code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="identifier">T</span><span class="special">)</span></code> enclosed
by <code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="identifier">S</span><span class="special">)</span></code>; for
example, <code class="computeroutput"><span class="identifier">UNSIG</span><span class="special">=[</span><span class="number">0</span><span class="special">,</span><span class="number">255</span><span class="special">]</span></code> is not enclosed by <code class="computeroutput"><span class="identifier">SIG</span><span class="special">=[-</span><span class="number">128</span><span class="special">,</span><span class="number">127</span><span class="special">]</span></code>; neither
is <code class="computeroutput"><span class="identifier">SIG</span></code> enclosed by <code class="computeroutput"><span class="identifier">UNSIG</span></code>. This implies that is possible that
a conversion direction is subranged both ways. This occurs when a mixture
of signed/unsigned types are involved and indicates that in both directions
there are values which can fall out of range.
</p>
<p>
Given the range relation (subranged or not) of a conversion direction <code class="computeroutput"><span class="identifier">S</span><span class="special">-&gt;</span><span class="identifier">T</span></code>, it is possible to classify <code class="computeroutput"><span class="identifier">S</span></code> and <code class="computeroutput"><span class="identifier">T</span></code>
as <span class="bold"><strong>supertype</strong></span> and <span class="bold"><strong>subtype</strong></span>:
If the conversion is subranged, which means that <code class="computeroutput"><span class="identifier">T</span></code>
cannot represent all possible values of type <code class="computeroutput"><span class="identifier">S</span></code>,
<code class="computeroutput"><span class="identifier">S</span></code> is the supertype and <code class="computeroutput"><span class="identifier">T</span></code> the subtype; otherwise, <code class="computeroutput"><span class="identifier">T</span></code> is the supertype and <code class="computeroutput"><span class="identifier">S</span></code>
the subtype.
</p>
<p>
For example:
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="keyword">float</span><span class="special">)=[-</span><span class="identifier">FLT_MAX</span><span class="special">,</span><span class="identifier">FLT_MAX</span><span class="special">]</span></code>
and <code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="keyword">double</span><span class="special">)=[-</span><span class="identifier">DBL_MAX</span><span class="special">,</span><span class="identifier">DBL_MAX</span><span class="special">]</span></code>
</p></blockquote></div>
<p>
If <code class="computeroutput"><span class="identifier">FLT_MAX</span> <span class="special">&lt;</span>
<span class="identifier">DBL_MAX</span></code>:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<code class="computeroutput"><span class="keyword">double</span><span class="special">-&gt;</span><span class="keyword">float</span></code> is subranged and <code class="computeroutput"><span class="identifier">supertype</span><span class="special">=</span><span class="keyword">double</span></code>,
<code class="computeroutput"><span class="identifier">subtype</span><span class="special">=</span><span class="keyword">float</span></code>.
</li>
<li class="listitem">
<code class="computeroutput"><span class="keyword">float</span><span class="special">-&gt;</span><span class="keyword">double</span></code> is not subranged and <code class="computeroutput"><span class="identifier">supertype</span><span class="special">=</span><span class="keyword">double</span></code>, <code class="computeroutput"><span class="identifier">subtype</span><span class="special">=</span><span class="keyword">float</span></code>.
</li>
</ul></div>
<p>
Notice that while <code class="computeroutput"><span class="keyword">double</span><span class="special">-&gt;</span><span class="keyword">float</span></code> is subranged, <code class="computeroutput"><span class="keyword">float</span><span class="special">-&gt;</span><span class="keyword">double</span></code>
is not, which yields the same supertype,subtype for both directions.
</p>
<p>
Now consider:
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="keyword">int</span><span class="special">)=[</span><span class="identifier">INT_MIN</span><span class="special">,</span><span class="identifier">INT_MAX</span><span class="special">]</span></code> and <code class="computeroutput"><span class="identifier">R</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="keyword">int</span><span class="special">)=[</span><span class="number">0</span><span class="special">,</span><span class="identifier">UINT_MAX</span><span class="special">]</span></code>
</p></blockquote></div>
<p>
A C++ implementation is required to have <code class="computeroutput"><span class="identifier">UINT_MAX</span>
<span class="special">&gt;</span> <span class="identifier">INT_MAX</span></code>
(&#167;3.9/3), so:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
'int-&gt;unsigned' is subranged (negative values fall out of range) and
<code class="computeroutput"><span class="identifier">supertype</span><span class="special">=</span><span class="keyword">int</span></code>, <code class="computeroutput"><span class="identifier">subtype</span><span class="special">=</span><span class="keyword">unsigned</span></code>.
</li>
<li class="listitem">
'unsigned-&gt;int' is <span class="emphasis"><em>also</em></span> subranged (high positive
values fall out of range) and <code class="computeroutput"><span class="identifier">supertype</span><span class="special">=</span><span class="keyword">unsigned</span></code>,
<code class="computeroutput"><span class="identifier">subtype</span><span class="special">=</span><span class="keyword">int</span></code>.
</li>
</ul></div>
<p>
In this case, the conversion is subranged in both directions and the supertype,subtype
pairs are not invariant (under inversion of direction). This indicates that
none of the types can represent all the values of the other.
</p>
<p>
When the supertype is the same for both <code class="computeroutput"><span class="identifier">S</span><span class="special">-&gt;</span><span class="identifier">T</span></code>
and <code class="computeroutput"><span class="identifier">T</span><span class="special">-&gt;</span><span class="identifier">S</span></code>, it is effectively indicating a type
which can represent all the values of the subtype. Consequently, if a conversion
<code class="computeroutput"><span class="identifier">X</span><span class="special">-&gt;</span><span class="identifier">Y</span></code> is not subranged, but the opposite <code class="computeroutput"><span class="special">(</span><span class="identifier">Y</span><span class="special">-&gt;</span><span class="identifier">X</span><span class="special">)</span></code> is,
so that the supertype is always <code class="computeroutput"><span class="identifier">Y</span></code>,
it is said that the direction <code class="computeroutput"><span class="identifier">X</span><span class="special">-&gt;</span><span class="identifier">Y</span></code>
is <span class="bold"><strong>correctly rounded value preserving</strong></span>, meaning
that all such conversions are guaranteed to produce results in range and
correctly rounded (even if inexact). For example, all integer to floating
conversions are correctly rounded value preserving.
</p>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2004-2007 Fernando
Luis Cacciola Carballal<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../index.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="converter___function_object.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
@@ -0,0 +1,212 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Improved numeric_cast&lt;&gt;</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="prev" href="numeric_converter_policy_classes.html" title="Numeric Converter Policy Classes">
<link rel="next" href="../numeric_conversion/history_and_acknowledgments.html" title="History and Acknowledgments">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="numeric_converter_policy_classes.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../numeric_conversion/history_and_acknowledgments.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="boost_numericconversion.improved_numeric_cast__"></a><a class="link" href="improved_numeric_cast__.html" title="Improved numeric_cast&lt;&gt;">Improved
numeric_cast&lt;&gt;</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="improved_numeric_cast__.html#boost_numericconversion.improved_numeric_cast__.introduction">Introduction</a></span></dt>
<dt><span class="section"><a href="improved_numeric_cast__.html#boost_numericconversion.improved_numeric_cast__.numeric_cast">numeric_cast</a></span></dt>
<dt><span class="section"><a href="improved_numeric_cast__.html#boost_numericconversion.improved_numeric_cast__.numeric_cast_traits">numeric_cast_traits</a></span></dt>
<dt><span class="section"><a href="improved_numeric_cast__.html#boost_numericconversion.improved_numeric_cast__.examples">Examples</a></span></dt>
</dl></div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.improved_numeric_cast__.introduction"></a><a class="link" href="improved_numeric_cast__.html#boost_numericconversion.improved_numeric_cast__.introduction" title="Introduction">Introduction</a>
</h3></div></div></div>
<p>
The lack of preservation of range makes conversions between numeric types
error prone. This is true for both implicit conversions and explicit conversions
(through <code class="computeroutput"><span class="keyword">static_cast</span></code>). <a class="link" href="improved_numeric_cast__.html#boost_numericconversion.improved_numeric_cast__.numeric_cast" title="numeric_cast"><code class="computeroutput"><span class="identifier">numeric_cast</span></code></a> detects loss of range
when a numeric type is converted, and throws an exception if the range cannot
be preserved.
</p>
<p>
There are several situations where conversions are unsafe:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
Conversions from an integral type with a wider range than the target
integral type.
</li>
<li class="listitem">
Conversions from unsigned to signed (and vice versa) integral types.
</li>
<li class="listitem">
Conversions from floating point types to integral types.
</li>
</ul></div>
<p>
The C++ Standard does not specify the behavior when a numeric type is assigned
a value that cannot be represented by the type, except for unsigned integral
types [3.9.1.4], which must obey the laws of arithmetic modulo 2n (this implies
that the result will be reduced modulo the number that is one greater than
the largest value that can be represented). The fact that the behavior for
overflow is undefined for all conversions (except the aforementioned unsigned
to unsigned) makes any code that may produce positive or negative overflows
exposed to portability issues.
</p>
<p>
By default <code class="computeroutput"><span class="identifier">numeric_cast</span></code> adheres
to the rules for implicit conversions mandated by the C++ Standard, such
as truncating floating point types when converting to integral types. The
implementation must guarantee that for a conversion to a type that can hold
all possible values of the source type, there will be no runtime overhead.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.improved_numeric_cast__.numeric_cast"></a><a class="link" href="improved_numeric_cast__.html#boost_numericconversion.improved_numeric_cast__.numeric_cast" title="numeric_cast">numeric_cast</a>
</h3></div></div></div>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Target</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Source</span><span class="special">&gt;</span> <span class="keyword">inline</span>
<span class="identifier">Target</span> <span class="identifier">numeric_cast</span><span class="special">(</span> <span class="identifier">Source</span> <span class="identifier">arg</span> <span class="special">)</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="identifier">conversion_traits</span><span class="special">&lt;</span><span class="identifier">Target</span><span class="special">,</span> <span class="identifier">Source</span><span class="special">&gt;</span> <span class="identifier">conv_traits</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">numeric_cast_traits</span><span class="special">&lt;</span><span class="identifier">Target</span><span class="special">,</span> <span class="identifier">Source</span><span class="special">&gt;</span> <span class="identifier">cast_traits</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">converter</span>
<span class="special">&lt;</span>
<span class="identifier">Target</span><span class="special">,</span>
<span class="identifier">Source</span><span class="special">,</span>
<span class="identifier">conv_traits</span><span class="special">,</span>
<span class="keyword">typename</span> <span class="identifier">cast_traits</span><span class="special">::</span><span class="identifier">overflow_policy</span><span class="special">,</span>
<span class="keyword">typename</span> <span class="identifier">cast_traits</span><span class="special">::</span><span class="identifier">rounding_policy</span><span class="special">,</span>
<span class="identifier">raw_converter</span><span class="special">&lt;</span><span class="identifier">conv_traits</span><span class="special">&gt;,</span>
<span class="keyword">typename</span> <span class="identifier">cast_traits</span><span class="special">::</span><span class="identifier">range_checking_policy</span>
<span class="special">&gt;</span> <span class="identifier">converter</span><span class="special">;</span>
<span class="keyword">return</span> <span class="identifier">converter</span><span class="special">::</span><span class="identifier">convert</span><span class="special">(</span><span class="identifier">arg</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
<code class="computeroutput"><span class="identifier">numeric_cast</span></code> returns the
result of converting a value of type Source to a value of type Target. If
out-of-range is detected, an overflow policy is executed whose default behavior
is to throw an an exception (see <a class="link" href="numeric_converter_policy_classes.html#numeric_conversion_bad_numeric_cast">bad_numeric_cast</a>,
<a class="link" href="numeric_converter_policy_classes.html#numeric_conversion_negative_overflow">negative_overflow</a>
and <a class="link" href="numeric_converter_policy_classes.html#numeric_conversion_possitive_overflow">positive_overflow</a>
).
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.improved_numeric_cast__.numeric_cast_traits"></a><a class="link" href="improved_numeric_cast__.html#boost_numericconversion.improved_numeric_cast__.numeric_cast_traits" title="numeric_cast_traits">numeric_cast_traits</a>
</h3></div></div></div>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Target</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Source</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">EnableIf</span> <span class="special">=</span> <span class="keyword">void</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">numeric_cast_traits</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="identifier">def_overflow_handler</span> <span class="identifier">overflow_policy</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">UseInternalRangeChecker</span> <span class="identifier">range_checking_policy</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">Trunc</span><span class="special">&lt;</span><span class="identifier">Source</span><span class="special">&gt;</span> <span class="identifier">rounding_policy</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
The behavior of <code class="computeroutput"><span class="identifier">numeric_cast</span></code>
may be tailored for custom numeric types through the specialization of <code class="computeroutput"><span class="identifier">numeric_cast_traits</span></code>. (see <a class="link" href="type_requirements_and_user_defined_types_support.html" title="Type Requirements and User-defined-types support">User
Defined Types</a> for details. )
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.improved_numeric_cast__.examples"></a><a class="link" href="improved_numeric_cast__.html#boost_numericconversion.improved_numeric_cast__.examples" title="Examples">Examples</a>
</h3></div></div></div>
<p>
The following example performs some typical conversions between numeric types:
</p>
<div class="orderedlist"><ol class="orderedlist" type="1">
<li class="listitem">
include &lt;boost/numeric/conversion/cast.hpp&gt;
</li>
<li class="listitem">
include &lt;iostream&gt;
</li>
</ol></div>
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric_cast</span><span class="special">;</span>
<span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">bad_numeric_cast</span><span class="special">;</span>
<span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">positive_overflow</span><span class="special">;</span>
<span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">negative_overflow</span><span class="special">;</span>
<span class="keyword">try</span>
<span class="special">{</span>
<span class="keyword">int</span> <span class="identifier">i</span><span class="special">=</span><span class="number">42</span><span class="special">;</span>
<span class="keyword">short</span> <span class="identifier">s</span><span class="special">=</span><span class="identifier">numeric_cast</span><span class="special">&lt;</span><span class="keyword">short</span><span class="special">&gt;(</span><span class="identifier">i</span><span class="special">);</span> <span class="comment">// This conversion succeeds (is in range)</span>
<span class="special">}</span>
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">negative_overflow</span><span class="special">&amp;</span> <span class="identifier">e</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">e</span><span class="special">.</span><span class="identifier">what</span><span class="special">();</span>
<span class="special">}</span>
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">positive_overflow</span><span class="special">&amp;</span> <span class="identifier">e</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">e</span><span class="special">.</span><span class="identifier">what</span><span class="special">();</span>
<span class="special">}</span>
<span class="keyword">try</span>
<span class="special">{</span>
<span class="keyword">float</span> <span class="identifier">f</span><span class="special">=-</span><span class="number">42.1234</span><span class="special">;</span>
<span class="comment">// This will cause a boost::numeric::negative_overflow exception to be thrown</span>
<span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">i</span><span class="special">=</span><span class="identifier">numeric_cast</span><span class="special">&lt;</span><span class="keyword">unsigned</span> <span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">f</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">bad_numeric_cast</span><span class="special">&amp;</span> <span class="identifier">e</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">e</span><span class="special">.</span><span class="identifier">what</span><span class="special">();</span>
<span class="special">}</span>
<span class="keyword">double</span> <span class="identifier">d</span><span class="special">=</span> <span class="identifier">f</span> <span class="special">+</span> <span class="identifier">numeric_cast</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="number">123</span><span class="special">);</span> <span class="comment">// int -&gt; double</span>
<span class="keyword">unsigned</span> <span class="keyword">long</span> <span class="identifier">l</span><span class="special">=</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="keyword">unsigned</span> <span class="keyword">long</span><span class="special">&gt;::</span><span class="identifier">max</span><span class="special">();</span>
<span class="keyword">try</span>
<span class="special">{</span>
<span class="comment">// This will cause a boost::numeric::positive_overflow exception to be thrown</span>
<span class="comment">// NOTE: *operations* on unsigned integral types cannot cause overflow</span>
<span class="comment">// but *conversions* to a signed type ARE range checked by numeric_cast.</span>
<span class="keyword">unsigned</span> <span class="keyword">char</span> <span class="identifier">c</span><span class="special">=</span><span class="identifier">numeric_cast</span><span class="special">&lt;</span><span class="keyword">unsigned</span> <span class="keyword">char</span><span class="special">&gt;(</span><span class="identifier">l</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">positive_overflow</span><span class="special">&amp;</span> <span class="identifier">e</span><span class="special">)</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">e</span><span class="special">.</span><span class="identifier">what</span><span class="special">();</span>
<span class="special">}</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2004-2007 Fernando
Luis Cacciola Carballal<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="numeric_converter_policy_classes.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../numeric_conversion/history_and_acknowledgments.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
@@ -0,0 +1,395 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Numeric Converter Policy Classes</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="prev" href="conversion_traits___traits_class.html" title="conversion_traits&lt;&gt; traits class">
<link rel="next" href="improved_numeric_cast__.html" title="Improved numeric_cast&lt;&gt;">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="conversion_traits___traits_class.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="improved_numeric_cast__.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="boost_numericconversion.numeric_converter_policy_classes"></a><a class="link" href="numeric_converter_policy_classes.html" title="Numeric Converter Policy Classes">Numeric
Converter Policy Classes</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.enum_range_check_result">enum
range_check_result</a></span></dt>
<dt><span class="section"><a href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_overflowhandler">Policy
OverflowHandler</a></span></dt>
<dt><span class="section"><a href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_float2introunder">Policy
Float2IntRounder</a></span></dt>
<dt><span class="section"><a href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_rawconverter">Policy
RawConverter</a></span></dt>
<dt><span class="section"><a href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_userrangechecker">Policy
UserRangeChecker</a></span></dt>
</dl></div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.numeric_converter_policy_classes.enum_range_check_result"></a><a class="link" href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.enum_range_check_result" title="enum range_check_result">enum
range_check_result</a>
</h3></div></div></div>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">numeric</span> <span class="special">{</span>
<span class="keyword">enum</span> <span class="identifier">range_check_result</span>
<span class="special">{</span>
<span class="identifier">cInRange</span> <span class="special">,</span>
<span class="identifier">cNegOverflow</span> <span class="special">,</span>
<span class="identifier">cPosOverflow</span>
<span class="special">}</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">}</span>
</pre>
<p>
Defines the values returned by <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">converter</span><span class="special">&lt;&gt;::</span><span class="identifier">out_of_range</span><span class="special">()</span></code>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.numeric_converter_policy_classes.policy_overflowhandler"></a><a class="link" href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_overflowhandler" title="Policy OverflowHandler">Policy
OverflowHandler</a>
</h3></div></div></div>
<p>
This <span class="emphasis"><em>stateless</em></span> non-template policy class must be a
<span class="emphasis"><em>function object</em></span> and is called to administrate the result
of the range checking. It can throw an exception if overflow has been detected
by the range checking as indicated by its argument. If it throws, is is recommended
that it be <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_cast</span></code> or derived.
</p>
<p>
It must have the following interface (it does not has to be a template class):
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">YourOverflowHandlerPolicy</span>
<span class="special">{</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">range_check_result</span> <span class="special">)</span> <span class="special">;</span> <span class="comment">// throw bad_cast or derived</span>
<span class="special">}</span> <span class="special">;</span>
</pre>
<p>
It is called with the result of the converter's <code class="computeroutput"><span class="identifier">out_of_range</span><span class="special">()</span></code> inside <code class="computeroutput"><span class="identifier">validate_range</span><span class="special">()</span></code>.
</p>
<p>
These are the two overflow handler classes provided by the library:
</p>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">numeric</span> <span class="special">{</span>
<span class="keyword">struct</span> <span class="identifier">def_overflow_handler</span>
<span class="special">{</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span> <span class="identifier">range_check_result</span> <span class="identifier">r</span> <span class="special">)</span> <span class="comment">// throw bad_numeric_conversion derived</span>
<span class="special">{</span>
<span class="keyword">if</span> <span class="special">(</span> <span class="identifier">r</span> <span class="special">==</span> <span class="identifier">cNegOverflow</span> <span class="special">)</span>
<span class="keyword">throw</span> <span class="identifier">negative_overflow</span><span class="special">()</span> <span class="special">;</span>
<span class="keyword">else</span> <span class="keyword">if</span> <span class="special">(</span> <span class="identifier">r</span> <span class="special">==</span> <span class="identifier">cPosOverflow</span> <span class="special">)</span>
<span class="keyword">throw</span> <span class="identifier">positive_overflow</span><span class="special">()</span> <span class="special">;</span>
<span class="special">}</span>
<span class="special">}</span> <span class="special">;</span>
<span class="keyword">struct</span> <span class="identifier">silent_overflow_handler</span>
<span class="special">{</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span> <span class="identifier">range_check_result</span> <span class="special">)</span> <span class="comment">// no-throw</span>
<span class="special">{}</span>
<span class="special">}</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">}</span>
</pre>
<p>
And these are the Exception Classes thrown by the default overflow handler
<a class="link" href="numeric_converter_policy_classes.html#numeric_conversion_policy_overflow_handler_important_note">(see
IMPORTANT note)</a>
</p>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">numeric</span> <span class="special">{</span>
<a name="numeric_conversion_bad_numeric_cast"></a>
<span class="keyword">class</span> <span class="identifier">bad_numeric_cast</span> <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_cast</span>
<span class="special">{</span>
<span class="keyword">public</span><span class="special">:</span>
<span class="keyword">virtual</span> <span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">what</span><span class="special">()</span> <span class="keyword">const</span> <span class="comment">// throw()</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="string">"bad numeric conversion: overflow"</span><span class="special">;</span>
<span class="special">}</span>
<span class="special">};</span>
<a name="numeric_conversion_negative_overflow"></a>
<span class="keyword">class</span> <span class="identifier">negative_overflow</span> <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">bad_numeric_cast</span>
<span class="special">{</span>
<span class="keyword">public</span><span class="special">:</span>
<span class="keyword">virtual</span> <span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">what</span><span class="special">()</span> <span class="keyword">const</span> <span class="comment">// throw()</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="string">"bad numeric conversion: negative overflow"</span><span class="special">;</span>
<span class="special">}</span>
<span class="special">};</span>
<a name="numeric_conversion_possitive_overflow"></a>
<span class="keyword">class</span> <span class="identifier">positive_overflow</span> <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">bad_numeric_cast</span>
<span class="special">{</span>
<span class="keyword">public</span><span class="special">:</span>
<span class="keyword">virtual</span> <span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">what</span><span class="special">()</span> <span class="keyword">const</span> <span class="comment">// throw()</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="string">"bad numeric conversion: positive overflow"</span><span class="special">;</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="special">}</span> <span class="special">}</span>
</pre>
<a name="numeric_conversion_policy_overflow_handler_important_note"></a><div class="important"><table border="0" summary="Important">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../../../../../doc/src/images/important.png"></td>
<th align="left">Important</th>
</tr>
<tr><td align="left" valign="top"><p>
<span class="bold"><strong>RELEASE NOTE for 1.33</strong></span> Previous to boost
version 1.33, the exception class <code class="computeroutput"><span class="identifier">bad_numeric_cast</span></code>
was named <code class="computeroutput"><span class="identifier">bad_numeric_conversion</span></code>.
However, in 1.33, the old function <code class="computeroutput"><span class="identifier">numeric_cast</span><span class="special">&lt;&gt;</span></code> from <code class="computeroutput"><span class="identifier">boost</span><span class="special">/</span><span class="identifier">cast</span><span class="special">.</span><span class="identifier">hpp</span></code>
was completly replaced by the new <code class="computeroutput"><span class="identifier">numeric_cast</span><span class="special">&lt;&gt;</span></code> in <code class="computeroutput"><span class="identifier">boost</span><span class="special">/</span><span class="identifier">numeric</span><span class="special">/</span><span class="identifier">conversion</span><span class="special">/</span><span class="identifier">cast</span><span class="special">.</span><span class="identifier">hpp</span></code>
(and <code class="computeroutput"><span class="identifier">boost</span><span class="special">/</span><span class="identifier">cast</span><span class="special">.</span><span class="identifier">hpp</span></code> is including <code class="computeroutput"><span class="identifier">boost</span><span class="special">/</span><span class="identifier">numeric</span><span class="special">/</span><span class="identifier">conversion</span><span class="special">/</span><span class="identifier">cast</span><span class="special">.</span><span class="identifier">hpp</span></code>
now). That old function which existed in boost for quite some time used
the <code class="computeroutput"><span class="identifier">bad_numeric_cast</span></code> as
its exception type so I decided to avoid backward compatibility problems
by adopting it (guessing that the user base for the old code is wider than
for the new code).
</p></td></tr>
</table></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.numeric_converter_policy_classes.policy_float2introunder"></a><a class="link" href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_float2introunder" title="Policy Float2IntRounder">Policy
Float2IntRounder</a>
</h3></div></div></div>
<p>
This <span class="emphasis"><em>stateless</em></span> template policy class specifies the rounding
mode used for <span class="underline">float to integral</span> conversions.
It supplies the <code class="computeroutput"><span class="identifier">nearbyint</span><span class="special">()</span></code> static member function exposed by the converter,
which means that it <span class="underline">publicly inherits from this
policy</span>.
</p>
<p>
The policy must have the following interface:
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">S</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">YourFloat2IntRounderPolicy</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="identifier">S</span> <span class="identifier">source_type</span> <span class="special">;</span>
<span class="keyword">typedef</span> <span class="special">{</span><span class="identifier">S</span> <span class="keyword">or</span> <span class="identifier">S</span> <span class="keyword">const</span><span class="special">&amp;}</span> <span class="identifier">argument_type</span> <span class="special">;</span>
<span class="keyword">static</span> <span class="identifier">source_type</span> <span class="identifier">nearbyint</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span> <span class="special">{</span> <span class="special">...</span> <span class="special">}</span>
<span class="keyword">typedef</span> <span class="identifier">mpl</span><span class="special">::</span><span class="identifier">integral_c</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">float_round_style</span><span class="special">,</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">round_</span><span class="special">...&gt;</span> <span class="identifier">round_style</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">;</span>
</pre>
<p>
These are the rounder classes provided by the library (only the specific
parts are shown, see the general policy form above)
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
These classes are not intended to be general purpose rounding functions
but specific policies for <code class="computeroutput"><span class="identifier">converter</span><span class="special">&lt;&gt;</span></code>. This is why they are not function
objects.
</p></td></tr>
</table></div>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">numeric</span> <span class="special">{</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">S</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">Trunc</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="identifier">source_type</span> <span class="identifier">nearbyint</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">floor</span> <span class="special">;</span>
<span class="keyword">using</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ceil</span> <span class="special">;</span>
<span class="keyword">return</span> <span class="identifier">s</span> <span class="special">&gt;=</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">S</span><span class="special">&gt;(</span><span class="number">0</span><span class="special">)</span> <span class="special">?</span> <span class="identifier">floor</span><span class="special">(</span><span class="identifier">s</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">ceil</span><span class="special">(</span><span class="identifier">s</span><span class="special">)</span> <span class="special">;</span>
<span class="special">}</span>
<span class="keyword">typedef</span> <span class="identifier">mpl</span><span class="special">::</span><span class="identifier">integral_c</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">float_round_style</span><span class="special">,</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">round_toward_zero</span><span class="special">&gt;</span> <span class="identifier">round_style</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">;</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">S</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">RoundEven</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="identifier">source_type</span> <span class="identifier">nearbyint</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">impl</span><span class="special">-</span><span class="identifier">defined</span><span class="special">-</span><span class="identifier">value</span> <span class="special">;</span>
<span class="special">}</span>
<span class="keyword">typedef</span> <span class="identifier">mpl</span><span class="special">::</span><span class="identifier">integral_c</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">float_round_style</span><span class="special">,</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">round_to_nearest</span><span class="special">&gt;</span> <span class="identifier">round_style</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">;</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">S</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">Ceil</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="identifier">source_type</span> <span class="identifier">nearbyint</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ceil</span> <span class="special">;</span>
<span class="keyword">return</span> <span class="identifier">ceil</span><span class="special">(</span><span class="identifier">s</span><span class="special">)</span> <span class="special">;</span>
<span class="special">}</span>
<span class="keyword">typedef</span> <span class="identifier">mpl</span><span class="special">::</span><span class="identifier">integral_c</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">float_round_style</span><span class="special">,</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">round_toward_infinity</span><span class="special">&gt;</span> <span class="identifier">round_style</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">;</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">S</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">Floor</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="identifier">source_type</span> <span class="identifier">nearbyint</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">floor</span> <span class="special">;</span>
<span class="keyword">return</span> <span class="identifier">floor</span><span class="special">(</span><span class="identifier">s</span><span class="special">)</span> <span class="special">;</span>
<span class="special">}</span>
<span class="keyword">typedef</span> <span class="identifier">mpl</span><span class="special">::</span><span class="identifier">integral_c</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">float_round_style</span><span class="special">,</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">round_toward_neg_infinity</span><span class="special">&gt;</span> <span class="identifier">round_style</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">}</span> <span class="comment">// namespace numeric, namespace boost</span>
</pre>
<h5>
<a name="boost_numericconversion.numeric_converter_policy_classes.policy_float2introunder.h0"></a>
<span class="phrase"><a name="boost_numericconversion.numeric_converter_policy_classes.policy_float2introunder.math_functions_used_by_the_rounder_policies"></a></span><a class="link" href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_float2introunder.math_functions_used_by_the_rounder_policies">Math
Functions used by the rounder policies</a>
</h5>
<p>
The rounder policies supplied by this header use math functions <code class="computeroutput"><span class="identifier">floor</span><span class="special">()</span></code>
and <code class="computeroutput"><span class="identifier">ceil</span><span class="special">()</span></code>.
The standard versions of these functions are introduced in context by a using
directive, so in normal conditions, the standard functions will be used.
</p>
<p>
However, if there are other visible corresponding overloads an ambiguity
could arise. In this case, the user can supply her own rounder policy which
could, for instance, use a fully qualified call.
</p>
<p>
This technique allows the default rounder policies to be used directly with
user defined types. The user only requires that suitable overloads of <code class="computeroutput"><span class="identifier">floor</span><span class="special">()</span></code>
and <code class="computeroutput"><span class="identifier">ceil</span><span class="special">()</span></code>
be visible. See also <a class="link" href="type_requirements_and_user_defined_types_support.html" title="Type Requirements and User-defined-types support">User
Defined Numeric Types</a> support.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.numeric_converter_policy_classes.policy_rawconverter"></a><a class="link" href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_rawconverter" title="Policy RawConverter">Policy
RawConverter</a>
</h3></div></div></div>
<p>
This <span class="emphasis"><em>stateless</em></span> template policy class is used to perform
the actual conversion from Source to Target. It supplies the <code class="computeroutput"><span class="identifier">low_level_convert</span><span class="special">()</span></code>
static member function exposed by the converter, which means that it publicly
inherits from this policy.
</p>
<p>
The policy must have the following interface:
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">YourRawConverterPolicy</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">Traits</span><span class="special">::</span><span class="identifier">result_type</span> <span class="identifier">result_type</span> <span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">Traits</span><span class="special">::</span><span class="identifier">argument_type</span> <span class="identifier">argument_type</span> <span class="special">;</span>
<span class="keyword">static</span> <span class="identifier">result_type</span> <span class="identifier">low_level_convert</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="special">&lt;</span><span class="identifier">impl</span> <span class="identifier">defined</span><span class="special">&gt;</span> <span class="special">;</span> <span class="special">}</span>
<span class="special">}</span> <span class="special">;</span>
</pre>
<p>
This policy is mostly provided as a hook for user defined types which don't
support <code class="computeroutput"><span class="keyword">static_cast</span><span class="special">&lt;&gt;</span></code>
conversions to some types
</p>
<p>
This is the only raw converter policy class provided by the library:
</p>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">numeric</span> <span class="special">{</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">raw_numeric_converter</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">Traits</span><span class="special">::</span><span class="identifier">result_type</span> <span class="identifier">result_type</span> <span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">Traits</span><span class="special">::</span><span class="identifier">argument_type</span> <span class="identifier">argument_type</span> <span class="special">;</span>
<span class="keyword">static</span> <span class="identifier">result_type</span> <span class="identifier">low_level_convert</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">result_type</span><span class="special">&gt;(</span><span class="identifier">s</span><span class="special">)</span> <span class="special">;</span>
<span class="special">}</span>
<span class="special">}</span> <span class="special">;</span>
<span class="special">}</span> <span class="special">}</span>
</pre>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.numeric_converter_policy_classes.policy_userrangechecker"></a><a class="link" href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_userrangechecker" title="Policy UserRangeChecker">Policy
UserRangeChecker</a>
</h3></div></div></div>
<p>
This <span class="emphasis"><em>stateless</em></span> template policy class is used <span class="underline">only if supplied</span> to <span class="bold"><strong>override</strong></span>
the internal range checking logic.
</p>
<p>
It supplies the <code class="computeroutput"><span class="identifier">validate_range</span><span class="special">()</span></code> static member function exposed by the converter,
which means that it publicly inherits from this policy.
</p>
<p>
The policy must have the following interface:
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">YourRangeCheckerPolicy</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">Traits</span><span class="special">::</span><span class="identifier">argument_type</span> <span class="identifier">argument_type</span> <span class="special">;</span>
<span class="comment">// Determines if the value 's' fits in the range of the Target type.</span>
<span class="keyword">static</span> <span class="identifier">range_check_result</span> <span class="identifier">out_of_range</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span> <span class="special">;</span>
<span class="comment">// Checks whether the value 's' is out_of_range()</span>
<span class="comment">// and passes the result of the check to the OverflowHandler policy.</span>
<span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">validate_range</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span>
<span class="special">{</span>
<span class="identifier">OverflowHandler</span><span class="special">()(</span> <span class="identifier">out_of_range</span><span class="special">(</span><span class="identifier">s</span><span class="special">)</span> <span class="special">)</span> <span class="special">;</span>
<span class="special">}</span>
<span class="special">}</span> <span class="special">;</span>
</pre>
<p>
This policy is <span class="bold"><strong>only</strong></span> provided as a hook for
user defined types which require range checking (which is disabled by default
when a UDT is involved). The library provides a class: <code class="computeroutput"><span class="identifier">UseInternalRangeChecker</span><span class="special">{}</span></code>; which is a <span class="emphasis"><em>fake</em></span>
<code class="computeroutput"><span class="identifier">RangeChecker</span></code> policy used
to signal the converter to use its internal range checking implementation.
</p>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2004-2007 Fernando
Luis Cacciola Carballal<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="conversion_traits___traits_class.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="improved_numeric_cast__.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
@@ -0,0 +1,554 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Type Requirements and User-defined-types support</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="prev" href="converter___function_object.html" title="converter&lt;&gt; function object">
<link rel="next" href="bounds___traits_class.html" title="bounds&lt;&gt; traits class">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="converter___function_object.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="bounds___traits_class.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="boost_numericconversion.type_requirements_and_user_defined_types_support"></a><a class="link" href="type_requirements_and_user_defined_types_support.html" title="Type Requirements and User-defined-types support">Type
Requirements and User-defined-types support</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="type_requirements_and_user_defined_types_support.html#boost_numericconversion.type_requirements_and_user_defined_types_support.type_requirements">Type
Requirements</a></span></dt>
<dt><span class="section"><a href="type_requirements_and_user_defined_types_support.html#boost_numericconversion.type_requirements_and_user_defined_types_support.udt_s_special_semantics">UDT's
special semantics</a></span></dt>
<dt><span class="section"><a href="type_requirements_and_user_defined_types_support.html#boost_numericconversion.type_requirements_and_user_defined_types_support.special_policies">Special
Policies</a></span></dt>
<dt><span class="section"><a href="type_requirements_and_user_defined_types_support.html#boost_numericconversion.type_requirements_and_user_defined_types_support.udts_with_numeric_cast">UDTs
with numeric_cast</a></span></dt>
</dl></div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.type_requirements_and_user_defined_types_support.type_requirements"></a><a class="link" href="type_requirements_and_user_defined_types_support.html#boost_numericconversion.type_requirements_and_user_defined_types_support.type_requirements" title="Type Requirements">Type
Requirements</a>
</h3></div></div></div>
<p>
Both arithmetic (built-in) and user-defined numeric types require proper
specialization of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;&gt;</span></code>
(that is, with (in-class) integral constants).
</p>
<p>
The library uses <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">is_specialized</span></code> to detect whether the type
is builtin or user defined, and <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">is_integer</span></code>, <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">is_signed</span></code> to detect whether the type is
integer or floating point; and whether it is signed/unsigned.
</p>
<p>
The default <code class="computeroutput"><span class="identifier">Float2IntRounder</span></code>
policies uses unqualified calls to functions <code class="computeroutput"><span class="identifier">floor</span><span class="special">()</span></code> and <code class="computeroutput"><span class="identifier">ceil</span><span class="special">()</span></code>; but the standard functions are introduced
in scope by a using directive:
</p>
<pre class="programlisting"><span class="keyword">using</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">floor</span> <span class="special">;</span> <span class="keyword">return</span> <span class="identifier">floor</span><span class="special">(</span><span class="identifier">s</span><span class="special">);</span>
</pre>
<p>
Therefore, for builtin arithmetic types, the std functions will be used.
User defined types should provide overloaded versions of these functions
in order to use the default rounder policies. If these overloads are defined
within a user namespace argument dependent lookup (ADL) should find them,
but if your compiler has a weak ADL you might need to put these functions
some place else or write your own rounder policy.
</p>
<p>
The default <code class="computeroutput"><span class="identifier">Trunc</span><span class="special">&lt;&gt;</span></code>
rounder policy needs to determine if the source value is positive or not,
and for this it evaluates the expression <code class="computeroutput"><span class="identifier">s</span>
<span class="special">&lt;</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">S</span><span class="special">&gt;(</span><span class="number">0</span><span class="special">)</span></code>. Therefore,
user defined types require a visible <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;</span></code> in order to use the <code class="computeroutput"><span class="identifier">Trunc</span><span class="special">&lt;&gt;</span></code> policy (the default).
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.type_requirements_and_user_defined_types_support.udt_s_special_semantics"></a><a class="link" href="type_requirements_and_user_defined_types_support.html#boost_numericconversion.type_requirements_and_user_defined_types_support.udt_s_special_semantics" title="UDT's special semantics">UDT's
special semantics</a>
</h3></div></div></div>
<h5>
<a name="boost_numericconversion.type_requirements_and_user_defined_types_support.udt_s_special_semantics.h0"></a>
<span class="phrase"><a name="boost_numericconversion.type_requirements_and_user_defined_types_support.udt_s_special_semantics.conversion_traits"></a></span><a class="link" href="type_requirements_and_user_defined_types_support.html#boost_numericconversion.type_requirements_and_user_defined_types_support.udt_s_special_semantics.conversion_traits">Conversion
Traits</a>
</h5>
<p>
If a User Defined Type is involved in a conversion, it is <span class="emphasis"><em>assumed</em></span>
that the UDT has <a class="link" href="definitions.html#boost_numericconversion.definitions.range_and_precision" title="Range and Precision">wider
range</a> than any built-in type, and consequently the values of some
<code class="computeroutput"><span class="identifier">converter_traits</span><span class="special">&lt;&gt;</span></code>
members are hardwired regardless of the reality. The following table summarizes
this:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<code class="computeroutput"><span class="identifier">Target</span><span class="special">=</span></code><span class="emphasis"><em>UDT</em></span>
and <code class="computeroutput"><span class="identifier">Source</span><span class="special">=</span></code><span class="emphasis"><em>built-in</em></span>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; ">
<li class="listitem">
<code class="computeroutput"><span class="identifier">subranged</span><span class="special">=</span><span class="keyword">false</span></code>
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">supertype</span><span class="special">=</span><span class="identifier">Target</span></code>
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">subtype</span><span class="special">=</span><span class="identifier">Source</span></code>
</li>
</ul></div>
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">Target</span><span class="special">=</span></code><span class="emphasis"><em>built-in</em></span>
and <code class="computeroutput"><span class="identifier">Source</span><span class="special">=</span></code><span class="emphasis"><em>UDT</em></span>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; ">
<li class="listitem">
<code class="computeroutput"><span class="identifier">subranged</span><span class="special">=</span><span class="keyword">true</span></code>
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">supertype</span><span class="special">=</span><span class="identifier">Source</span></code>
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">subtype</span><span class="special">=</span><span class="identifier">Target</span></code>
</li>
</ul></div>
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">Target</span><span class="special">=</span></code><span class="emphasis"><em>UDT</em></span>
and <code class="computeroutput"><span class="identifier">Source</span><span class="special">=</span></code><span class="emphasis"><em>UDT</em></span>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; ">
<li class="listitem">
<code class="computeroutput"><span class="identifier">subranged</span><span class="special">=</span><span class="keyword">false</span></code>
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">supertype</span><span class="special">=</span><span class="identifier">Target</span></code>
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">subtype</span><span class="special">=</span><span class="identifier">Source</span></code>
</li>
</ul></div>
</li>
</ul></div>
<p>
The <code class="computeroutput"><span class="identifier">Traits</span></code> member <code class="computeroutput"><span class="identifier">udt_mixture</span></code> can be used to detect whether
a UDT is involved and to infer the validity of the other members as shown
above.
</p>
<h5>
<a name="boost_numericconversion.type_requirements_and_user_defined_types_support.udt_s_special_semantics.h1"></a>
<span class="phrase"><a name="boost_numericconversion.type_requirements_and_user_defined_types_support.udt_s_special_semantics.range_checking"></a></span><a class="link" href="type_requirements_and_user_defined_types_support.html#boost_numericconversion.type_requirements_and_user_defined_types_support.udt_s_special_semantics.range_checking">Range
Checking</a>
</h5>
<p>
Because User Defined Numeric Types might have peculiar ranges (such as an
unbounded range), this library does not attempt to supply a meaningful range
checking logic when UDTs are involved in a conversion. Therefore, if either
Target or Source are not built-in types, the bundled range checking of the
<code class="computeroutput"><span class="identifier">converter</span><span class="special">&lt;&gt;</span></code>
function object is automatically disabled. However, it is possible to supply
a user-defined range-checker. See <a class="link" href="type_requirements_and_user_defined_types_support.html#boost_numericconversion.type_requirements_and_user_defined_types_support.special_policies" title="Special Policies">Special
Policies</a>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.type_requirements_and_user_defined_types_support.special_policies"></a><a class="link" href="type_requirements_and_user_defined_types_support.html#boost_numericconversion.type_requirements_and_user_defined_types_support.special_policies" title="Special Policies">Special
Policies</a>
</h3></div></div></div>
<p>
There are two components of the <code class="computeroutput"><span class="identifier">converter</span><span class="special">&lt;&gt;</span></code> class that might require special
behavior if User Defined Numeric Types are involved: the Range Checking and
the Raw Conversion.
</p>
<p>
When both Target and Source are built-in types, the converter class uses
an internal range checking logic which is optimized and customized for the
combined properties of the types.
</p>
<p>
However, this internal logic is disabled when either type is User Defined.
In this case, the user can specify an <span class="emphasis"><em>external</em></span> range
checking policy which will be used in place of the internal code. See <a class="link" href="type_requirements_and_user_defined_types_support.html#boost_numericconversion.type_requirements_and_user_defined_types_support.udts_with_numeric_cast" title="UDTs with numeric_cast">numeric_cast_traits</a>
for details on using UDTs with <code class="computeroutput"><span class="identifier">numeric_cast</span></code>.
</p>
<p>
The converter class performs the actual conversion using a Raw Converter
policy. The default raw converter simply performs a <code class="computeroutput"><span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">Target</span><span class="special">&gt;(</span><span class="identifier">source</span><span class="special">)</span></code>.
</p>
<p>
However, if the a UDT is involved, the <code class="computeroutput"><span class="keyword">static_cast</span></code>
might not work. In this case, the user can implement and pass a different
raw converter policy. See <a class="link" href="numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_rawconverter" title="Policy RawConverter">RawConverter</a>
policy for details.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_numericconversion.type_requirements_and_user_defined_types_support.udts_with_numeric_cast"></a><a class="link" href="type_requirements_and_user_defined_types_support.html#boost_numericconversion.type_requirements_and_user_defined_types_support.udts_with_numeric_cast" title="UDTs with numeric_cast">UDTs
with numeric_cast</a>
</h3></div></div></div>
<p>
In order to employ UDTs with <code class="computeroutput"><span class="identifier">numeric_cast</span></code>,
the user should define a <code class="computeroutput"><span class="identifier">numeric_cast_traits</span></code>
specialization on the UDT for each conversion. Here is an example of specializations
for converting between the UDT and any other type:
</p>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">numeric</span> <span class="special">{</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Source</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">numeric_cast_traits</span><span class="special">&lt;</span><span class="identifier">UDT</span><span class="special">,</span> <span class="identifier">Source</span><span class="special">&gt;</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="identifier">conversion_traits</span><span class="special">&lt;</span><span class="identifier">UDT</span><span class="special">,</span> <span class="identifier">Source</span><span class="special">&gt;</span> <span class="identifier">conv_traits</span><span class="special">;</span>
<span class="comment">//! The following are required:</span>
<span class="keyword">typedef</span> <span class="identifier">YourOverflowHandlerPolicy</span> <span class="identifier">overflow_policy</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">YourRangeCheckerPolicy</span><span class="special">&lt;</span><span class="identifier">conv_traits</span><span class="special">&gt;</span> <span class="identifier">range_checking_policy</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">YourFloat2IntRounderPolicy</span><span class="special">&lt;</span><span class="identifier">Source</span><span class="special">&gt;</span> <span class="identifier">rounding_policy</span><span class="special">;</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Target</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">numeric_cast_traits</span><span class="special">&lt;</span><span class="identifier">Target</span><span class="special">,</span> <span class="identifier">UDT</span><span class="special">&gt;</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="identifier">conversion_traits</span><span class="special">&lt;</span><span class="identifier">Target</span><span class="special">,</span> <span class="identifier">UDT</span><span class="special">&gt;</span> <span class="identifier">conv_traits</span><span class="special">;</span>
<span class="comment">//! The following are required:</span>
<span class="keyword">typedef</span> <span class="identifier">YourOverflowHandlerPolicy</span> <span class="identifier">overflow_policy</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">YourRangeCheckerPolicy</span><span class="special">&lt;</span><span class="identifier">conv_traits</span><span class="special">&gt;</span> <span class="identifier">range_checking_policy</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">YourFloat2IntRounderPolicy</span><span class="special">&lt;</span><span class="identifier">UDT</span><span class="special">&gt;</span> <span class="identifier">rounding_policy</span><span class="special">;</span>
<span class="special">};</span>
<span class="special">}}//</span><span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">;</span>
</pre>
<p>
These specializations are already defined with default values for the built-in
numeric types. It is possible to disable the generation of specializations
for built-in types by defining <code class="computeroutput"><span class="identifier">BOOST_NUMERIC_CONVERSION_RELAX_BUILT_IN_CAST_TRAITS</span></code>.
For details on defining custom policies see <a class="link" href="numeric_converter_policy_classes.html" title="Numeric Converter Policy Classes">Converter
Policies</a>.
</p>
<p>
Here is a full example of how to define a custom UDT for use with <code class="computeroutput"><span class="identifier">numeric_cast</span></code>:
</p>
<pre class="programlisting"><span class="comment">//! Define a simple custom number</span>
<span class="keyword">struct</span> <span class="identifier">Double</span>
<span class="special">:</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ordered_field_operators</span>
<span class="special">&lt;</span>
<span class="identifier">Double</span>
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ordered_field_operators2</span><span class="special">&lt;</span> <span class="identifier">Double</span><span class="special">,</span> <span class="keyword">long</span> <span class="keyword">double</span>
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ordered_field_operators2</span><span class="special">&lt;</span> <span class="identifier">Double</span><span class="special">,</span> <span class="keyword">double</span>
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ordered_field_operators2</span><span class="special">&lt;</span> <span class="identifier">Double</span><span class="special">,</span> <span class="keyword">float</span>
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ordered_field_operators2</span><span class="special">&lt;</span> <span class="identifier">Double</span><span class="special">,</span> <span class="keyword">int</span>
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ordered_field_operators2</span><span class="special">&lt;</span> <span class="identifier">Double</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="keyword">int</span>
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ordered_field_operators2</span><span class="special">&lt;</span> <span class="identifier">Double</span><span class="special">,</span> <span class="keyword">long</span>
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ordered_field_operators2</span><span class="special">&lt;</span> <span class="identifier">Double</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="keyword">long</span>
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ordered_field_operators2</span><span class="special">&lt;</span> <span class="identifier">Double</span><span class="special">,</span> <span class="keyword">long</span> <span class="keyword">long</span>
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ordered_field_operators2</span><span class="special">&lt;</span> <span class="identifier">Double</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="keyword">long</span> <span class="keyword">long</span>
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ordered_field_operators2</span><span class="special">&lt;</span> <span class="identifier">Double</span><span class="special">,</span> <span class="keyword">char</span>
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ordered_field_operators2</span><span class="special">&lt;</span> <span class="identifier">Double</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="keyword">char</span>
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ordered_field_operators2</span><span class="special">&lt;</span> <span class="identifier">Double</span><span class="special">,</span> <span class="keyword">short</span>
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ordered_field_operators2</span><span class="special">&lt;</span> <span class="identifier">Double</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="keyword">short</span>
<span class="special">&gt;</span> <span class="special">&gt;</span> <span class="special">&gt;</span> <span class="special">&gt;</span> <span class="special">&gt;</span> <span class="special">&gt;</span> <span class="special">&gt;</span> <span class="special">&gt;</span> <span class="special">&gt;</span> <span class="special">&gt;</span> <span class="special">&gt;</span> <span class="special">&gt;</span> <span class="special">&gt;</span> <span class="special">&gt;</span>
<span class="special">{</span>
<span class="identifier">Double</span><span class="special">()</span>
<span class="special">:</span> <span class="identifier">v</span><span class="special">(</span><span class="number">0</span><span class="special">)</span>
<span class="special">{}</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">explicit</span> <span class="identifier">Double</span><span class="special">(</span> <span class="identifier">T</span> <span class="identifier">v</span> <span class="special">)</span>
<span class="special">:</span> <span class="identifier">v</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="identifier">v</span><span class="special">))</span>
<span class="special">{}</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="identifier">Double</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">T</span> <span class="identifier">t</span> <span class="special">)</span>
<span class="special">{</span>
<span class="identifier">v</span> <span class="special">=</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="identifier">t</span><span class="special">);</span>
<span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">&lt;</span> <span class="special">(</span> <span class="keyword">const</span> <span class="identifier">Double</span><span class="special">&amp;</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="keyword">const</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">v</span> <span class="special">&lt;</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">v</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">&lt;</span> <span class="special">(</span> <span class="identifier">T</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="keyword">const</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">v</span> <span class="special">&lt;</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="identifier">rhs</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">&gt;</span> <span class="special">(</span> <span class="keyword">const</span> <span class="identifier">Double</span><span class="special">&amp;</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="keyword">const</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">v</span> <span class="special">&gt;</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">v</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">&gt;</span> <span class="special">(</span> <span class="identifier">T</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="keyword">const</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">v</span> <span class="special">&gt;</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="identifier">rhs</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==(</span> <span class="keyword">const</span> <span class="identifier">Double</span><span class="special">&amp;</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="keyword">const</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">v</span> <span class="special">==</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">v</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span> <span class="identifier">T</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="keyword">const</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">v</span> <span class="special">==</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="identifier">rhs</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!()</span> <span class="keyword">const</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">v</span> <span class="special">==</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
<span class="identifier">Double</span> <span class="keyword">operator</span> <span class="special">-()</span> <span class="keyword">const</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">Double</span><span class="special">(-</span><span class="identifier">v</span><span class="special">);</span>
<span class="special">}</span>
<span class="identifier">Double</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">+=(</span> <span class="keyword">const</span> <span class="identifier">Double</span><span class="special">&amp;</span> <span class="identifier">t</span> <span class="special">)</span>
<span class="special">{</span>
<span class="identifier">v</span> <span class="special">+=</span> <span class="identifier">t</span><span class="special">.</span><span class="identifier">v</span><span class="special">;</span>
<span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="identifier">Double</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">+=(</span> <span class="identifier">T</span> <span class="identifier">t</span> <span class="special">)</span>
<span class="special">{</span>
<span class="identifier">v</span> <span class="special">+=</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="identifier">t</span><span class="special">);</span>
<span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span>
<span class="special">}</span>
<span class="identifier">Double</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">-=(</span> <span class="keyword">const</span> <span class="identifier">Double</span><span class="special">&amp;</span> <span class="identifier">t</span> <span class="special">)</span>
<span class="special">{</span>
<span class="identifier">v</span> <span class="special">-=</span> <span class="identifier">t</span><span class="special">.</span><span class="identifier">v</span><span class="special">;</span>
<span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="identifier">Double</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">-=(</span> <span class="identifier">T</span> <span class="identifier">t</span> <span class="special">)</span>
<span class="special">{</span>
<span class="identifier">v</span> <span class="special">-=</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="identifier">t</span><span class="special">);</span>
<span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span>
<span class="special">}</span>
<span class="identifier">Double</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">*=</span> <span class="special">(</span> <span class="keyword">const</span> <span class="identifier">Double</span><span class="special">&amp;</span> <span class="identifier">factor</span> <span class="special">)</span>
<span class="special">{</span>
<span class="identifier">v</span> <span class="special">*=</span> <span class="identifier">factor</span><span class="special">.</span><span class="identifier">v</span><span class="special">;</span>
<span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="identifier">Double</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">*=(</span> <span class="identifier">T</span> <span class="identifier">t</span> <span class="special">)</span>
<span class="special">{</span>
<span class="identifier">v</span> <span class="special">*=</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="identifier">t</span><span class="special">);</span>
<span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span>
<span class="special">}</span>
<span class="identifier">Double</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">/=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">Double</span><span class="special">&amp;</span> <span class="identifier">divisor</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">v</span> <span class="special">/=</span> <span class="identifier">divisor</span><span class="special">.</span><span class="identifier">v</span><span class="special">;</span>
<span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="identifier">Double</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">/=(</span> <span class="identifier">T</span> <span class="identifier">t</span> <span class="special">)</span>
<span class="special">{</span>
<span class="identifier">v</span> <span class="special">/=</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="identifier">t</span><span class="special">);</span>
<span class="keyword">return</span> <span class="special">(*</span><span class="keyword">this</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">double</span> <span class="identifier">v</span><span class="special">;</span>
<span class="special">};</span>
<span class="comment">//! Define numeric_limits for the custom type.</span>
<span class="keyword">namespace</span> <span class="identifier">std</span>
<span class="special">{</span>
<span class="keyword">template</span><span class="special">&lt;&gt;</span>
<span class="keyword">class</span> <span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">Double</span><span class="special">&gt;</span> <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;</span>
<span class="special">{</span>
<span class="keyword">public</span><span class="special">:</span>
<span class="comment">//! Limit our Double to a range of +/- 100.0</span>
<span class="keyword">static</span> <span class="identifier">Double</span> <span class="special">(</span><span class="identifier">min</span><span class="special">)()</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">Double</span><span class="special">(</span><span class="number">1.e-2</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">static</span> <span class="identifier">Double</span> <span class="special">(</span><span class="identifier">max</span><span class="special">)()</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">Double</span><span class="special">(</span><span class="number">1.e2</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">static</span> <span class="identifier">Double</span> <span class="identifier">epsilon</span><span class="special">()</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">Double</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;::</span><span class="identifier">epsilon</span><span class="special">()</span> <span class="special">);</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="special">}</span>
<span class="comment">//! Define range checking and overflow policies.</span>
<span class="keyword">namespace</span> <span class="identifier">custom</span>
<span class="special">{</span>
<span class="comment">//! Define a custom range checker</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">OverFlowHandler</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">range_checker</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">Traits</span><span class="special">::</span><span class="identifier">argument_type</span> <span class="identifier">argument_type</span> <span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">Traits</span><span class="special">::</span><span class="identifier">source_type</span> <span class="identifier">S</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">Traits</span><span class="special">::</span><span class="identifier">target_type</span> <span class="identifier">T</span><span class="special">;</span>
<span class="comment">//! Check range of integral types.</span>
<span class="keyword">static</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">range_check_result</span> <span class="identifier">out_of_range</span><span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">;</span>
<span class="keyword">if</span><span class="special">(</span> <span class="identifier">s</span> <span class="special">&gt;</span> <span class="identifier">bounds</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">highest</span><span class="special">()</span> <span class="special">)</span>
<span class="keyword">return</span> <span class="identifier">cPosOverflow</span><span class="special">;</span>
<span class="keyword">else</span> <span class="keyword">if</span><span class="special">(</span> <span class="identifier">s</span> <span class="special">&lt;</span> <span class="identifier">bounds</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">lowest</span><span class="special">()</span> <span class="special">)</span>
<span class="keyword">return</span> <span class="identifier">cNegOverflow</span><span class="special">;</span>
<span class="keyword">else</span>
<span class="keyword">return</span> <span class="identifier">cInRange</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">validate_range</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span>
<span class="special">{</span>
<span class="identifier">BOOST_STATIC_ASSERT</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">is_bounded</span> <span class="special">);</span>
<span class="identifier">OverFlowHandler</span><span class="special">()(</span> <span class="identifier">out_of_range</span><span class="special">(</span><span class="identifier">s</span><span class="special">)</span> <span class="special">);</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="comment">//! Overflow handler</span>
<span class="keyword">struct</span> <span class="identifier">positive_overflow</span><span class="special">{};</span>
<span class="keyword">struct</span> <span class="identifier">negative_overflow</span><span class="special">{};</span>
<span class="keyword">struct</span> <span class="identifier">overflow_handler</span>
<span class="special">{</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">range_check_result</span> <span class="identifier">r</span> <span class="special">)</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">;</span>
<span class="keyword">if</span><span class="special">(</span> <span class="identifier">r</span> <span class="special">==</span> <span class="identifier">cNegOverflow</span> <span class="special">)</span>
<span class="keyword">throw</span> <span class="identifier">negative_overflow</span><span class="special">()</span> <span class="special">;</span>
<span class="keyword">else</span> <span class="keyword">if</span><span class="special">(</span> <span class="identifier">r</span> <span class="special">==</span> <span class="identifier">cPosOverflow</span> <span class="special">)</span>
<span class="keyword">throw</span> <span class="identifier">positive_overflow</span><span class="special">()</span> <span class="special">;</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="comment">//! Define a rounding policy and specialize on the custom type.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">S</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">Ceil</span> <span class="special">:</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">Ceil</span><span class="special">&lt;</span><span class="identifier">S</span><span class="special">&gt;{};</span>
<span class="keyword">template</span><span class="special">&lt;&gt;</span>
<span class="keyword">struct</span> <span class="identifier">Ceil</span><span class="special">&lt;</span><span class="identifier">Double</span><span class="special">&gt;</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="identifier">Double</span> <span class="identifier">source_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">Double</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">argument_type</span><span class="special">;</span>
<span class="keyword">static</span> <span class="identifier">source_type</span> <span class="identifier">nearbyint</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span>
<span class="special">{</span>
<span class="preprocessor">#if</span> <span class="special">!</span><span class="identifier">defined</span><span class="special">(</span><span class="identifier">BOOST_NO_STDC_NAMESPACE</span><span class="special">)</span>
<span class="keyword">using</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ceil</span> <span class="special">;</span>
<span class="preprocessor">#endif</span>
<span class="keyword">return</span> <span class="identifier">Double</span><span class="special">(</span> <span class="identifier">ceil</span><span class="special">(</span><span class="identifier">s</span><span class="special">.</span><span class="identifier">v</span><span class="special">)</span> <span class="special">);</span>
<span class="special">}</span>
<span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">mpl</span><span class="special">::</span><span class="identifier">integral_c</span><span class="special">&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">float_round_style</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">round_toward_infinity</span><span class="special">&gt;</span> <span class="identifier">round_style</span><span class="special">;</span>
<span class="special">};</span>
<span class="comment">//! Define a rounding policy and specialize on the custom type.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">S</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">Trunc</span><span class="special">:</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">Trunc</span><span class="special">&lt;</span><span class="identifier">S</span><span class="special">&gt;{};</span>
<span class="keyword">template</span><span class="special">&lt;&gt;</span>
<span class="keyword">struct</span> <span class="identifier">Trunc</span><span class="special">&lt;</span><span class="identifier">Double</span><span class="special">&gt;</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="identifier">Double</span> <span class="identifier">source_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">Double</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">argument_type</span><span class="special">;</span>
<span class="keyword">static</span> <span class="identifier">source_type</span> <span class="identifier">nearbyint</span> <span class="special">(</span> <span class="identifier">argument_type</span> <span class="identifier">s</span> <span class="special">)</span>
<span class="special">{</span>
<span class="preprocessor">#if</span> <span class="special">!</span><span class="identifier">defined</span><span class="special">(</span><span class="identifier">BOOST_NO_STDC_NAMESPACE</span><span class="special">)</span>
<span class="keyword">using</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">floor</span><span class="special">;</span>
<span class="preprocessor">#endif</span>
<span class="keyword">return</span> <span class="identifier">Double</span><span class="special">(</span> <span class="identifier">floor</span><span class="special">(</span><span class="identifier">s</span><span class="special">.</span><span class="identifier">v</span><span class="special">)</span> <span class="special">);</span>
<span class="special">}</span>
<span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">mpl</span><span class="special">::</span><span class="identifier">integral_c</span><span class="special">&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">float_round_style</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">round_toward_zero</span><span class="special">&gt;</span> <span class="identifier">round_style</span><span class="special">;</span>
<span class="special">};</span>
<span class="special">}//</span><span class="keyword">namespace</span> <span class="identifier">custom</span><span class="special">;</span>
<span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">numeric</span> <span class="special">{</span>
<span class="comment">//! Define the numeric_cast_traits specializations on the custom type.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">S</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">numeric_cast_traits</span><span class="special">&lt;</span><span class="identifier">Double</span><span class="special">,</span> <span class="identifier">S</span><span class="special">&gt;</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="identifier">custom</span><span class="special">::</span><span class="identifier">overflow_handler</span> <span class="identifier">overflow_policy</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">custom</span><span class="special">::</span><span class="identifier">range_checker</span>
<span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">conversion_traits</span><span class="special">&lt;</span><span class="identifier">Double</span><span class="special">,</span> <span class="identifier">S</span><span class="special">&gt;</span>
<span class="special">,</span> <span class="identifier">overflow_policy</span>
<span class="special">&gt;</span> <span class="identifier">range_checking_policy</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">Trunc</span><span class="special">&lt;</span><span class="identifier">S</span><span class="special">&gt;</span> <span class="identifier">rounding_policy</span><span class="special">;</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">numeric_cast_traits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">Double</span><span class="special">&gt;</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="identifier">custom</span><span class="special">::</span><span class="identifier">overflow_handler</span> <span class="identifier">overflow_policy</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">custom</span><span class="special">::</span><span class="identifier">range_checker</span>
<span class="special">&lt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">conversion_traits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">Double</span><span class="special">&gt;</span>
<span class="special">,</span> <span class="identifier">overflow_policy</span>
<span class="special">&gt;</span> <span class="identifier">range_checking_policy</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">custom</span><span class="special">::</span><span class="identifier">Trunc</span><span class="special">&lt;</span><span class="identifier">Double</span><span class="special">&gt;</span> <span class="identifier">rounding_policy</span><span class="special">;</span>
<span class="special">};</span>
<span class="comment">//! Define the conversion from the custom type to built-in types and vice-versa.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">raw_converter</span><span class="special">&lt;</span> <span class="identifier">conversion_traits</span><span class="special">&lt;</span> <span class="identifier">T</span><span class="special">,</span> <span class="identifier">Double</span> <span class="special">&gt;</span> <span class="special">&gt;</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="identifier">T</span> <span class="identifier">low_level_convert</span> <span class="special">(</span> <span class="keyword">const</span> <span class="identifier">Double</span><span class="special">&amp;</span> <span class="identifier">n</span> <span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;(</span> <span class="identifier">n</span><span class="special">.</span><span class="identifier">v</span> <span class="special">);</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">S</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">raw_converter</span><span class="special">&lt;</span> <span class="identifier">conversion_traits</span><span class="special">&lt;</span> <span class="identifier">Double</span><span class="special">,</span> <span class="identifier">S</span> <span class="special">&gt;</span> <span class="special">&gt;</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="identifier">Double</span> <span class="identifier">low_level_convert</span> <span class="special">(</span> <span class="keyword">const</span> <span class="identifier">S</span><span class="special">&amp;</span> <span class="identifier">n</span> <span class="special">)</span>
<span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">Double</span><span class="special">(</span><span class="identifier">n</span><span class="special">);</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="special">}}//</span><span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">;</span>
</pre>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2004-2007 Fernando
Luis Cacciola Carballal<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="converter___function_object.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="bounds___traits_class.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
@@ -0,0 +1,582 @@
/*=============================================================================
Copyright (c) 2004 Joel de Guzman
http://spirit.sourceforge.net/
Use, modification and distribution is subject to the Boost Software
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
/*=============================================================================
Body defaults
=============================================================================*/
body
{
margin: 1em;
font-family: sans-serif;
}
/*=============================================================================
Paragraphs
=============================================================================*/
p
{
text-align: left;
font-size: 10pt;
line-height: 1.15;
}
/*=============================================================================
Program listings
=============================================================================*/
/* Code on paragraphs */
p tt.computeroutput
{
font-size: 10pt;
}
pre.synopsis
{
font-size: 10pt;
margin: 1pc 4% 0pc 4%;
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
}
.programlisting,
.screen
{
font-size: 10pt;
display: block;
margin: 1pc 4% 0pc 4%;
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
}
/* Program listings in tables don't get borders */
td .programlisting,
td .screen
{
margin: 0pc 0pc 0pc 0pc;
padding: 0pc 0pc 0pc 0pc;
}
/*=============================================================================
Headings
=============================================================================*/
h1, h2, h3, h4, h5, h6
{
text-align: left;
margin: 1em 0em 0.5em 0em;
font-weight: bold;
}
h1 { font: 140% }
h2 { font: bold 140% }
h3 { font: bold 130% }
h4 { font: bold 120% }
h5 { font: italic 110% }
h6 { font: italic 100% }
/* Top page titles */
title,
h1.title,
h2.title
h3.title,
h4.title,
h5.title,
h6.title,
.refentrytitle
{
font-weight: bold;
margin-bottom: 1pc;
}
h1.title { font-size: 140% }
h2.title { font-size: 140% }
h3.title { font-size: 130% }
h4.title { font-size: 120% }
h5.title { font-size: 110% }
h6.title { font-size: 100% }
.section h1
{
margin: 0em 0em 0.5em 0em;
font-size: 140%;
}
.section h2 { font-size: 140% }
.section h3 { font-size: 130% }
.section h4 { font-size: 120% }
.section h5 { font-size: 110% }
.section h6 { font-size: 100% }
/* Code on titles */
h1 tt.computeroutput { font-size: 140% }
h2 tt.computeroutput { font-size: 140% }
h3 tt.computeroutput { font-size: 130% }
h4 tt.computeroutput { font-size: 120% }
h5 tt.computeroutput { font-size: 110% }
h6 tt.computeroutput { font-size: 100% }
/*=============================================================================
Author
=============================================================================*/
h3.author
{
font-size: 100%
}
/*=============================================================================
Lists
=============================================================================*/
li
{
font-size: 10pt;
line-height: 1.3;
}
/* Unordered lists */
ul
{
text-align: left;
}
/* Ordered lists */
ol
{
text-align: left;
}
/*=============================================================================
Links
=============================================================================*/
a
{
text-decoration: none; /* no underline */
}
a:hover
{
text-decoration: underline;
}
/*=============================================================================
Spirit style navigation
=============================================================================*/
.spirit-nav
{
text-align: right;
}
.spirit-nav a
{
color: white;
padding-left: 0.5em;
}
.spirit-nav img
{
border-width: 0px;
}
/*=============================================================================
Table of contents
=============================================================================*/
.toc
{
margin: 1pc 4% 0pc 4%;
padding: 0.1pc 1pc 0.1pc 1pc;
font-size: 10pt;
line-height: 1.15;
}
.toc-main
{
text-align: center;
margin: 3pc 16% 3pc 16%;
padding: 3pc 1pc 3pc 1pc;
line-height: 0.1;
}
.boost-toc
{
float: right;
padding: 0.5pc;
}
/*=============================================================================
Tables
=============================================================================*/
.table-title,
div.table p.title
{
margin-left: 4%;
padding-right: 0.5em;
padding-left: 0.5em;
}
.informaltable table,
.table table
{
width: 92%;
margin-left: 4%;
margin-right: 4%;
}
div.informaltable table,
div.table table
{
padding: 4px;
}
/* Table Cells */
div.informaltable table tr td,
div.table table tr td
{
padding: 0.5em;
text-align: left;
}
div.informaltable table tr th,
div.table table tr th
{
padding: 0.5em 0.5em 0.5em 0.5em;
border: 1pt solid white;
font-size: 120%;
}
/*=============================================================================
Blurbs
=============================================================================*/
div.note,
div.tip,
div.important,
div.caution,
div.warning,
div.sidebar
{
font-size: 10pt;
line-height: 1.2;
display: block;
margin: 1pc 4% 0pc 4%;
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
}
div.sidebar img
{
padding: 1pt;
}
/*=============================================================================
Callouts
=============================================================================*/
.line_callout_bug img
{
float: left;
position:relative;
left: 4px;
top: -12px;
clear: left;
margin-left:-22px;
}
.callout_bug img
{
}
/*=============================================================================
Variable Lists
=============================================================================*/
/* Make the terms in definition lists bold */
div.variablelist dl dt,
span.term
{
font-weight: bold;
font-size: 10pt;
}
div.variablelist table tbody tr td
{
text-align: left;
vertical-align: top;
padding: 0em 2em 0em 0em;
font-size: 10pt;
margin: 0em 0em 0.5em 0em;
line-height: 1;
}
/* Make the terms in definition lists bold */
div.variablelist dl dt
{
margin-bottom: 0.2em;
}
div.variablelist dl dd
{
margin: 0em 0em 0.5em 2em;
font-size: 10pt;
}
div.variablelist table tbody tr td p
div.variablelist dl dd p
{
margin: 0em 0em 0.5em 0em;
line-height: 1;
}
/*=============================================================================
Misc
=============================================================================*/
/* Title of books and articles in bibliographies */
span.title
{
font-style: italic;
}
span.underline
{
text-decoration: underline;
}
span.strikethrough
{
text-decoration: line-through;
}
/* Copyright, Legal Notice */
div div.legalnotice p
{
text-align: left
}
/*=============================================================================
Colors
=============================================================================*/
@media screen
{
/* Links */
a
{
color: #0C7445;
}
a:visited
{
color: #663974;
}
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a,
h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover,
h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited
{
text-decoration: none; /* no underline */
color: #000000;
}
/* Syntax Highlighting */
.keyword { color: #0000AA; }
.identifier { color: #000000; }
.special { color: #707070; }
.preprocessor { color: #402080; }
.char { color: teal; }
.comment { color: #800000; }
.string { color: teal; }
.number { color: teal; }
.white_bkd { background-color: #E8FBE9; }
.dk_grey_bkd { background-color: #A0DAAC; }
/* Copyright, Legal Notice */
.copyright
{
color: #666666;
font-size: small;
}
div div.legalnotice p
{
color: #666666;
}
/* Program listing */
pre.synopsis
{
border: 1px solid #DCDCDC;
border-bottom: 3px solid #9D9D9D;
border-right: 3px solid #9D9D9D;
background-color: #FAFFFB;
}
.programlisting,
.screen
{
border: 1px solid #DCDCDC;
border-bottom: 3px solid #9D9D9D;
border-right: 3px solid #9D9D9D;
background-color: #FAFFFB;
}
td .programlisting,
td .screen
{
border: 0px solid #DCDCDC;
}
/* Blurbs */
div.note,
div.tip,
div.important,
div.caution,
div.warning,
div.sidebar
{
border: 1px solid #DCDCDC;
border-bottom: 3px solid #9D9D9D;
border-right: 3px solid #9D9D9D;
background-color: #FAFFFB;
}
/* Table of contents */
.toc
{
border: 1px solid #DCDCDC;
border-bottom: 3px solid #9D9D9D;
border-right: 3px solid #9D9D9D;
background-color: #FAFFFB;
}
/* Table of contents */
.toc-main
{
border: 1px solid #DCDCDC;
border-bottom: 3px solid #9D9D9D;
border-right: 3px solid #9D9D9D;
background-color: #FAFFFB;
}
/* Tables */
div.informaltable table tr td,
div.table table tr td
{
border: 1px solid #DCDCDC;
background-color: #FAFFFB;
}
div.informaltable table tr th,
div.table table tr th
{
background-color: #E3F9E4;
border: 1px solid #DCDCDC;
}
/* Misc */
span.highlight
{
color: #00A000;
}
}
@media print
{
/* Links */
a
{
color: black;
}
a:visited
{
color: black;
}
.spirit-nav
{
display: none;
}
/* Program listing */
pre.synopsis
{
border: 1px solid gray;
background-color: #FAFFFB;
}
.programlisting,
.screen
{
border: 1px solid gray;
background-color: #FAFFFB;
}
td .programlisting,
td .screen
{
border: 0px solid #DCDCDC;
}
/* Table of contents */
.toc
{
border: 1px solid #DCDCDC;
border-bottom: 3px solid #9D9D9D;
border-right: 3px solid #9D9D9D;
background-color: #FAFFFB;
}
/* Table of contents */
.toc-main
{
border: 1px solid #DCDCDC;
border-bottom: 3px solid #9D9D9D;
border-right: 3px solid #9D9D9D;
background-color: #FAFFFB;
}
.informaltable table,
.table table
{
border: 1px solid #DCDCDC;
border-bottom: 3px solid #9D9D9D;
border-right: 3px solid #9D9D9D;
border-collapse: collapse;
background-color: #FAFFFB;
}
/* Tables */
div.informaltable table tr td,
div.table table tr td
{
border: 1px solid #DCDCDC;
background-color: #FAFFFB;
}
div.informaltable table tr th,
div.table table tr th
{
border: 1px solid #DCDCDC;
background-color: #FAFFFB;
}
/* Misc */
span.highlight
{
font-weight: bold;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 293 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 B

+181
View File
@@ -0,0 +1,181 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Chapter&#160;1.&#160;Boost.NumericConversion</title>
<link rel="stylesheet" href="boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="next" href="boost_numericconversion/definitions.html" title="Definitions">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav"><a accesskey="n" href="boost_numericconversion/definitions.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a></div>
<div class="chapter">
<div class="titlepage"><div>
<div><h2 class="title">
<a name="numeric_conversion"></a>Chapter&#160;1.&#160;Boost.NumericConversion</h2></div>
<div><div class="author"><h3 class="author">
<span class="firstname">Fernando Luis</span> <span class="surname">Cacciola Carballal</span>
</h3></div></div>
<div><p class="copyright">Copyright &#169; 2004-2007 Fernando
Luis Cacciola Carballal</p></div>
<div><div class="legalnotice">
<a name="numeric_conversion.legal"></a><p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></div>
</div></div>
<div class="toc">
<p><b>Table of Contents</b></p>
<dl class="toc">
<dt><span class="section"><a href="index.html#numeric_conversion.overview">Overview</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/definitions.html">Definitions</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="boost_numericconversion/definitions.html#boost_numericconversion.definitions.introduction">Introduction</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/definitions.html#boost_numericconversion.definitions.types_and_values">Types
and Values</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/definitions.html#boost_numericconversion.definitions.c___arithmetic_types">C++
Arithmetic Types</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/definitions.html#boost_numericconversion.definitions.numeric_types">Numeric
Types</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/definitions.html#boost_numericconversion.definitions.range_and_precision">Range
and Precision</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/definitions.html#boost_numericconversion.definitions.exact__correctly_rounded_and_out_of_range_representations">Exact,
Correctly Rounded and Out-Of-Range Representations</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/definitions.html#boost_numericconversion.definitions.standard__numeric__conversions">Standard
(numeric) Conversions</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/definitions.html#boost_numericconversion.definitions.subranged_conversion_direction__subtype_and_supertype">Subranged
Conversion Direction, Subtype and Supertype</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="boost_numericconversion/converter___function_object.html">converter&lt;&gt;
function object</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="boost_numericconversion/converter___function_object.html#boost_numericconversion.converter___function_object.synopsis">Synopsis</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/converter___function_object.html#boost_numericconversion.converter___function_object.template_parameters">Template
parameters</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/converter___function_object.html#boost_numericconversion.converter___function_object.member_functions">Member
functions</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/converter___function_object.html#boost_numericconversion.converter___function_object.range_checking_logic">Range
Checking Logic</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/converter___function_object.html#boost_numericconversion.converter___function_object.examples">Examples</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="boost_numericconversion/type_requirements_and_user_defined_types_support.html">Type
Requirements and User-defined-types support</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="boost_numericconversion/type_requirements_and_user_defined_types_support.html#boost_numericconversion.type_requirements_and_user_defined_types_support.type_requirements">Type
Requirements</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/type_requirements_and_user_defined_types_support.html#boost_numericconversion.type_requirements_and_user_defined_types_support.udt_s_special_semantics">UDT's
special semantics</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/type_requirements_and_user_defined_types_support.html#boost_numericconversion.type_requirements_and_user_defined_types_support.special_policies">Special
Policies</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/type_requirements_and_user_defined_types_support.html#boost_numericconversion.type_requirements_and_user_defined_types_support.udts_with_numeric_cast">UDTs
with numeric_cast</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="boost_numericconversion/bounds___traits_class.html">bounds&lt;&gt;
traits class</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="boost_numericconversion/bounds___traits_class.html#boost_numericconversion.bounds___traits_class.introduction">Introduction</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/bounds___traits_class.html#boost_numericconversion.bounds___traits_class.traits_class_bounds_n_">traits
class bounds&lt;N&gt;</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/bounds___traits_class.html#boost_numericconversion.bounds___traits_class.examples">Examples</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="boost_numericconversion/conversion_traits___traits_class.html">conversion_traits&lt;&gt;
traits class</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="boost_numericconversion/conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.types">Types</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/conversion_traits___traits_class.html#boost_numericconversion.conversion_traits___traits_class.examples">Examples</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="boost_numericconversion/numeric_converter_policy_classes.html">Numeric
Converter Policy Classes</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="boost_numericconversion/numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.enum_range_check_result">enum
range_check_result</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_overflowhandler">Policy
OverflowHandler</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_float2introunder">Policy
Float2IntRounder</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_rawconverter">Policy
RawConverter</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_userrangechecker">Policy
UserRangeChecker</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="boost_numericconversion/improved_numeric_cast__.html">Improved
numeric_cast&lt;&gt;</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="boost_numericconversion/improved_numeric_cast__.html#boost_numericconversion.improved_numeric_cast__.introduction">Introduction</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/improved_numeric_cast__.html#boost_numericconversion.improved_numeric_cast__.numeric_cast">numeric_cast</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/improved_numeric_cast__.html#boost_numericconversion.improved_numeric_cast__.numeric_cast_traits">numeric_cast_traits</a></span></dt>
<dt><span class="section"><a href="boost_numericconversion/improved_numeric_cast__.html#boost_numericconversion.improved_numeric_cast__.examples">Examples</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="numeric_conversion/history_and_acknowledgments.html">History
and Acknowledgments</a></span></dt>
<dt><span class="section"><a href="numeric_conversion/bibliography.html">Bibliography</a></span></dt>
</dl>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="numeric_conversion.overview"></a><a class="link" href="index.html#numeric_conversion.overview" title="Overview">Overview</a>
</h2></div></div></div>
<p>
The Boost Numeric Conversion library is a collection of tools to describe and
perform conversions between values of different <a class="link" href="boost_numericconversion/definitions.html#boost_numericconversion.definitions.numeric_types" title="Numeric Types">numeric
types</a>.
</p>
<p>
The library includes a special alternative for a subset of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;&gt;</span></code>, the <a class="link" href="boost_numericconversion/bounds___traits_class.html" title="bounds&lt;&gt; traits class">bounds&lt;&gt;</a>
traits class, which provides a consistent way to obtain the <a class="link" href="boost_numericconversion/definitions.html#boost_numericconversion.definitions.range_and_precision" title="Range and Precision">boundary</a>
values for the <a class="link" href="boost_numericconversion/definitions.html#boost_numericconversion.definitions.range_and_precision" title="Range and Precision">range</a>
of a numeric type.
</p>
<p>
It also includes a set of <a class="link" href="boost_numericconversion/conversion_traits___traits_class.html" title="conversion_traits&lt;&gt; traits class">trait
classes</a> which describes the compile-time properties of a conversion
from a source to a target numeric type. Both <a class="link" href="boost_numericconversion/definitions.html#boost_numericconversion.definitions.c___arithmetic_types" title="C++ Arithmetic Types">arithmetic</a>
and <a class="link" href="boost_numericconversion/definitions.html#boost_numericconversion.definitions.numeric_types" title="Numeric Types">user-defined
numeric types</a> can be used.
</p>
<p>
A policy-based <a class="link" href="boost_numericconversion/converter___function_object.html" title="converter&lt;&gt; function object">converter</a>
object which uses <code class="computeroutput"><span class="identifier">conversion_traits</span></code>
to select an optimized implementation is supplied. Such implementation uses
an optimal range checking code suitable for the source/target combination.
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
The converter's out-of-range behavior can be customized via an <a class="link" href="boost_numericconversion/numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_overflowhandler" title="Policy OverflowHandler">OverflowHandler</a>
policy.
</li>
<li class="listitem">
For floating-point to integral conversions, the rounding mode can be selected
via the <a class="link" href="boost_numericconversion/numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_float2introunder" title="Policy Float2IntRounder">Float2IntRounder</a>
policy.
</li>
<li class="listitem">
A custom low-level conversion routine (for UDTs for instance) can be passed
via a <a class="link" href="boost_numericconversion/numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_rawconverter" title="Policy RawConverter">RawConverter</a>
policy.
</li>
<li class="listitem">
The optimized automatic range-checking logic can be overridden via a <a class="link" href="boost_numericconversion/numeric_converter_policy_classes.html#boost_numericconversion.numeric_converter_policy_classes.policy_userrangechecker" title="Policy UserRangeChecker">UserRangeChecker</a>
policy.
</li>
</ul></div>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"><p><small>Last revised: August 14, 2019 at 12:05:59 GMT</small></p></td>
<td align="right"><div class="copyright-footer"></div></td>
</tr></table>
<hr>
<div class="spirit-nav"><a accesskey="n" href="boost_numericconversion/definitions.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a></div>
</body>
</html>
@@ -0,0 +1,88 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Bibliography</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="prev" href="history_and_acknowledgments.html" title="History and Acknowledgments">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="history_and_acknowledgments.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="numeric_conversion.bibliography"></a><a class="link" href="bibliography.html" title="Bibliography">Bibliography</a>
</h2></div></div></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
Standard Documents:
<div class="orderedlist"><ol class="orderedlist" type="1">
<li class="listitem">
ISO/IEC 14882:98 (C++98 Standard)
</li>
<li class="listitem">
ISO/IEC 9899:1999 (C99 Standard)
</li>
<li class="listitem">
ISO/IEC 10967-1 (Language Independent Arithmetic (LIA), Part I, 1994)
</li>
<li class="listitem">
ISO/IEC 2382-1:1993 (Information Technology - Vocabulary - Part I:
Fundamental Terms)
</li>
<li class="listitem">
ANSI/IEEE 754-1985 [and IEC 60559:1989] (Binary floating-point)
</li>
<li class="listitem">
ANSI/IEEE 854-1988 (Radix Independent floating-point)
</li>
<li class="listitem">
ANSI X3/TR-1-82 (Dictionary for Information Processing Systems)
</li>
<li class="listitem">
ISO/IEC JTC1/SC22/WG14/N753 C9X Revision Proposal: LIA-1 Binding:
Rationale
</li>
</ol></div>
</li>
<li class="listitem">
Papers:
<div class="orderedlist"><ol class="orderedlist" type="1">
<li class="listitem">
David Goldberg What Every Computer Scientist Should Know About Floating-Point
Arithmetic
</li>
<li class="listitem">
Prof. William Kahan papers on floating-point.
</li>
</ol></div>
</li>
</ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2004-2007 Fernando
Luis Cacciola Carballal<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="history_and_acknowledgments.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a>
</div>
</body>
</html>
@@ -0,0 +1,97 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>History and Acknowledgments</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.NumericConversion">
<link rel="prev" href="../boost_numericconversion/improved_numeric_cast__.html" title="Improved numeric_cast&lt;&gt;">
<link rel="next" href="bibliography.html" title="Bibliography">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../boost_numericconversion/improved_numeric_cast__.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="bibliography.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="numeric_conversion.history_and_acknowledgments"></a><a class="link" href="history_and_acknowledgments.html" title="History and Acknowledgments">History
and Acknowledgments</a>
</h2></div></div></div>
<h4>
<a name="numeric_conversion.history_and_acknowledgments.h0"></a>
<span class="phrase"><a name="numeric_conversion.history_and_acknowledgments.pre_formal_review"></a></span><a class="link" href="history_and_acknowledgments.html#numeric_conversion.history_and_acknowledgments.pre_formal_review">Pre-formal
review</a>
</h4>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
Kevlin Henney, with help from David Abrahams and Beman Dawes, originally
contributed the previous version of <code class="computeroutput"><span class="identifier">numeric_cast</span><span class="special">&lt;&gt;</span></code> which already presented the idea
of a runtime range check.
</li>
<li class="listitem">
Later, Eric Ford, Kevin Lynch and the author spotted some genericity problems
with that <code class="computeroutput"><span class="identifier">numeric_cast</span><span class="special">&lt;&gt;</span></code> which prevented it from being used
in a generic layer of math functions.
</li>
<li class="listitem">
An improved <code class="computeroutput"><span class="identifier">numeric_cast</span><span class="special">&lt;&gt;</span></code> which properly handled all combinations
of arithmetic types was presented.
</li>
<li class="listitem">
David Abrahams and Beman Dawes acknowledged the need of an improved version
of <code class="computeroutput"><span class="identifier">numeric_cast</span><span class="special">&lt;&gt;</span></code>
and supported the submission as originally laid out. Daryl Walker and Darin
Adler made some important comments and proposed fixes to the original submission.
</li>
<li class="listitem">
Special thanks go to Bj&#246;rn Karlsoon who helped the author considerably.
Having found the problems with <code class="computeroutput"><span class="identifier">numeric_cast</span><span class="special">&lt;&gt;</span></code> himself, he revised very carefully
the original submission and spot a subtle bug in the range checking implementation.
He also wrote part of this documentation and proof-read and corrected other
parts. And most importantly: the features now presented here in this library
evolved from the original submission as a result of the useful private
communications between Bj&#246;rn and the author.
</li>
</ul></div>
<h4>
<a name="numeric_conversion.history_and_acknowledgments.h1"></a>
<span class="phrase"><a name="numeric_conversion.history_and_acknowledgments.post_formal_review"></a></span><a class="link" href="history_and_acknowledgments.html#numeric_conversion.history_and_acknowledgments.post_formal_review">Post-formal
review</a>
</h4>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
Guillaume Melquiond spoted some documentation and code issues, particularly
about rounding conversions.
</li>
<li class="listitem">
The following people contributed an important review of the design, documentation
and c ode: Kevin Lynch, Thorsten Ottosen, Paul Bristow, Daryle Walker,
Jhon Torjo, Eric Ford, Gennadiy Rozental.
</li>
</ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2004-2007 Fernando
Luis Cacciola Carballal<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../boost_numericconversion/improved_numeric_cast__.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="bibliography.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
@@ -0,0 +1,10 @@
index.html
boost_numericconversion/definitions.html
boost_numericconversion/converter___function_object.html
boost_numericconversion/type_requirements_and_user_defined_types_support.html
boost_numericconversion/bounds___traits_class.html
boost_numericconversion/conversion_traits___traits_class.html
boost_numericconversion/numeric_converter_policy_classes.html
boost_numericconversion/improved_numeric_cast__.html
numeric_conversion/history_and_acknowledgments.html
numeric_conversion/bibliography.html
@@ -0,0 +1,153 @@
[/
Boost.Optional
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
]
[section Improved numeric_cast<>]
[section Introduction]
The lack of preservation of range makes conversions between numeric types
error prone. This is true for both implicit conversions and explicit
conversions (through `static_cast`).
[link boost_numericconversion.improved_numeric_cast__.numeric_cast `numeric_cast`]
detects loss of range when a numeric type is converted, and throws an
exception if the range cannot be preserved.
There are several situations where conversions are unsafe:
* Conversions from an integral type with a wider range than the target integral type.
* Conversions from unsigned to signed (and vice versa) integral types.
* Conversions from floating point types to integral types.
The C++ Standard does not specify the behavior when a numeric type is
assigned a value that cannot be represented by the type, except for unsigned
integral types \[3.9.1.4\], which must obey the laws of arithmetic modulo 2n
(this implies that the result will be reduced modulo the number that is one
greater than the largest value that can be represented). The fact that the
behavior for overflow is undefined for all conversions (except the
aforementioned unsigned to unsigned) makes any code that may produce
positive or negative overflows exposed to portability issues.
By default `numeric_cast` adheres to the rules for implicit conversions mandated by
the C++ Standard, such as truncating floating point types when converting
to integral types. The implementation must guarantee that for a conversion
to a type that can hold all possible values of the source type, there will
be no runtime overhead.
[endsect]
[section numeric_cast]
template <typename Target, typename Source> inline
Target numeric_cast( Source arg )
{
typedef conversion_traits<Target, Source> conv_traits;
typedef numeric_cast_traits<Target, Source> cast_traits;
typedef converter
<
Target,
Source,
conv_traits,
typename cast_traits::overflow_policy,
typename cast_traits::rounding_policy,
raw_converter<conv_traits>,
typename cast_traits::range_checking_policy
> converter;
return converter::convert(arg);
}
`numeric_cast` returns the result of converting a value of type Source
to a value of type Target. If out-of-range is detected, an overflow policy
is executed whose default behavior is to throw an an exception (see
[link numeric_conversion_bad_numeric_cast bad_numeric_cast],
[link numeric_conversion_negative_overflow negative_overflow] and
[link numeric_conversion_possitive_overflow positive_overflow]
).
[endsect]
[section numeric_cast_traits]
template <typename Target, typename Source, typename EnableIf = void>
struct numeric_cast_traits
{
typedef def_overflow_handler overflow_policy;
typedef UseInternalRangeChecker range_checking_policy;
typedef Trunc<Source> rounding_policy;
};
The behavior of `numeric_cast` may be tailored for custom numeric types through
the specialization of `numeric_cast_traits`. (see
[link boost_numericconversion.type_requirements_and_user_defined_types_support User Defined Types]
for details.
)
[endsect]
[section Examples]
The following example performs some typical conversions between numeric types:
#include <boost/numeric/conversion/cast.hpp>
#include <iostream>
int main()
{
using boost::numeric_cast;
using boost::numeric::bad_numeric_cast;
using boost::numeric::positive_overflow;
using boost::numeric::negative_overflow;
try
{
int i=42;
short s=numeric_cast<short>(i); // This conversion succeeds (is in range)
}
catch(negative_overflow& e) {
std::cout << e.what();
}
catch(positive_overflow& e) {
std::cout << e.what();
}
try
{
float f=-42.1234;
// This will cause a boost::numeric::negative_overflow exception to be thrown
unsigned int i=numeric_cast<unsigned int>(f);
}
catch(bad_numeric_cast& e) {
std::cout << e.what();
}
double d= f + numeric_cast<double>(123); // int -> double
unsigned long l=std::numeric_limits<unsigned long>::max();
try
{
// This will cause a boost::numeric::positive_overflow exception to be thrown
// NOTE: *operations* on unsigned integral types cannot cause overflow
// but *conversions* to a signed type ARE range checked by numeric_cast.
unsigned char c=numeric_cast<unsigned char>(l);
}
catch(positive_overflow& e) {
std::cout << e.what();
}
return 0;
}
[endsect]
[endsect]
@@ -0,0 +1,448 @@
[/
Boost.Optional
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
]
[section Type Requirements and User-defined-types support]
[section Type Requirements]
Both arithmetic (built-in) and user-defined numeric types require proper
specialization of `std::numeric_limits<>` (that is, with (in-class) integral
constants).
The library uses `std::numeric_limits<T>::is_specialized` to detect whether
the type is builtin or user defined, and `std::numeric_limits<T>::is_integer`,
`std::numeric_limits<T>::is_signed` to detect whether the type is integer
or floating point; and whether it is signed/unsigned.
The default `Float2IntRounder` policies uses unqualified calls to functions
`floor()` and `ceil()`; but the standard functions are introduced in scope
by a using directive:
using std::floor ; return floor(s);
Therefore, for builtin arithmetic types, the std functions will be used.
User defined types should provide overloaded versions of these functions in
order to use the default rounder policies. If these overloads are defined
within a user namespace argument dependent lookup (ADL) should find them,
but if your compiler has a weak ADL you might need to put these functions
some place else or write your own rounder policy.
The default `Trunc<>` rounder policy needs to determine if the source value
is positive or not, and for this it evaluates the expression
`s < static_cast<S>(0)`. Therefore, user defined types require a visible
`operator<` in order to use the `Trunc<>` policy (the default).
[endsect]
[section UDT's special semantics]
[heading Conversion Traits]
If a User Defined Type is involved in a conversion, it is ['assumed] that
the UDT has [link boost_numericconversion.definitions.range_and_precision wider range]
than any built-in type, and consequently the values
of some `converter_traits<>` members are hardwired regardless of the reality.
The following table summarizes this:
* `Target=`['UDT] and `Source=`['built-in]
* `subranged=false`
* `supertype=Target`
* `subtype=Source`
* `Target=`['built-in] and `Source=`['UDT]
* `subranged=true`
* `supertype=Source`
* `subtype=Target`
* `Target=`['UDT] and `Source=`['UDT]
* `subranged=false`
* `supertype=Target`
* `subtype=Source`
The `Traits` member `udt_mixture` can be used to detect whether a UDT is involved
and to infer the validity of the other members as shown above.
[heading Range Checking]
Because User Defined Numeric Types might have peculiar ranges (such as an
unbounded range), this library does not attempt to supply a meaningful range
checking logic when UDTs are involved in a conversion. Therefore, if either
Target or Source are not built-in types, the bundled range checking of the
`converter<>` function object is automatically disabled. However, it is possible
to supply a user-defined range-checker. See
[link boost_numericconversion.type_requirements_and_user_defined_types_support.special_policies Special Policies]
[endsect]
[section Special Policies]
There are two components of the `converter<>` class that might require special
behavior if User Defined Numeric Types are involved: the Range Checking and the
Raw Conversion.
When both Target and Source are built-in types, the converter class uses an internal
range checking logic which is optimized and customized for the combined properties
of the types.
However, this internal logic is disabled when either type is User Defined.
In this case, the user can specify an ['external] range checking policy which will be
used in place of the internal code. See
[link boost_numericconversion.type_requirements_and_user_defined_types_support.udts_with_numeric_cast numeric_cast_traits]
for details on using UDTs with `numeric_cast`.
The converter class performs the actual conversion using a Raw Converter policy.
The default raw converter simply performs a `static_cast<Target>(source)`.
However, if the a UDT is involved, the `static_cast` might not work. In this case,
the user can implement and pass a different raw converter policy.
See [link boost_numericconversion.numeric_converter_policy_classes.policy_rawconverter RawConverter] policy for details.
[endsect]
[section UDTs with numeric_cast]
In order to employ UDTs with `numeric_cast`, the user should define
a `numeric_cast_traits` specialization on the UDT for each conversion.
Here is an example of specializations for converting between the UDT
and any other type:
namespace boost { namespace numeric {
template <typename Source>
struct numeric_cast_traits<UDT, Source>
{
typedef conversion_traits<UDT, Source> conv_traits;
//! The following are required:
typedef YourOverflowHandlerPolicy overflow_policy;
typedef YourRangeCheckerPolicy<conv_traits> range_checking_policy;
typedef YourFloat2IntRounderPolicy<Source> rounding_policy;
};
template <typename Target>
struct numeric_cast_traits<Target, UDT>
{
typedef conversion_traits<Target, UDT> conv_traits;
//! The following are required:
typedef YourOverflowHandlerPolicy overflow_policy;
typedef YourRangeCheckerPolicy<conv_traits> range_checking_policy;
typedef YourFloat2IntRounderPolicy<UDT> rounding_policy;
};
}}//namespace boost::numeric;
These specializations are already defined with default values for the built-in
numeric types. It is possible to disable the generation of specializations for
built-in types by defining `BOOST_NUMERIC_CONVERSION_RELAX_BUILT_IN_CAST_TRAITS`.
For details on defining custom policies see [link boost_numericconversion.numeric_converter_policy_classes Converter Policies].
Here is a full example of how to define a custom UDT for use with `numeric_cast`:
//! Define a simple custom number
struct Double
: boost::ordered_field_operators
<
Double
, boost::ordered_field_operators2< Double, long double
, boost::ordered_field_operators2< Double, double
, boost::ordered_field_operators2< Double, float
, boost::ordered_field_operators2< Double, int
, boost::ordered_field_operators2< Double, unsigned int
, boost::ordered_field_operators2< Double, long
, boost::ordered_field_operators2< Double, unsigned long
, boost::ordered_field_operators2< Double, long long
, boost::ordered_field_operators2< Double, unsigned long long
, boost::ordered_field_operators2< Double, char
, boost::ordered_field_operators2< Double, unsigned char
, boost::ordered_field_operators2< Double, short
, boost::ordered_field_operators2< Double, unsigned short
> > > > > > > > > > > > > >
{
Double()
: v(0)
{}
template <typename T>
explicit Double( T v )
: v(static_cast<double>(v))
{}
template <typename T>
Double& operator= ( T t )
{
v = static_cast<double>(t);
return *this;
}
bool operator < ( const Double& rhs ) const
{
return v < rhs.v;
}
template <typename T>
bool operator < ( T rhs ) const
{
return v < static_cast<double>(rhs);
}
bool operator > ( const Double& rhs ) const
{
return v > rhs.v;
}
template <typename T>
bool operator > ( T rhs ) const
{
return v > static_cast<double>(rhs);
}
bool operator ==( const Double& rhs ) const
{
return v == rhs.v;
}
template <typename T>
bool operator == ( T rhs ) const
{
return v == static_cast<double>(rhs);
}
bool operator !() const
{
return v == 0;
}
Double operator -() const
{
return Double(-v);
}
Double& operator +=( const Double& t )
{
v += t.v;
return *this;
}
template <typename T>
Double& operator +=( T t )
{
v += static_cast<double>(t);
return *this;
}
Double& operator -=( const Double& t )
{
v -= t.v;
return *this;
}
template <typename T>
Double& operator -=( T t )
{
v -= static_cast<double>(t);
return *this;
}
Double& operator *= ( const Double& factor )
{
v *= factor.v;
return *this;
}
template <typename T>
Double& operator *=( T t )
{
v *= static_cast<double>(t);
return *this;
}
Double& operator /= (const Double& divisor)
{
v /= divisor.v;
return *this;
}
template <typename T>
Double& operator /=( T t )
{
v /= static_cast<double>(t);
return (*this);
}
double v;
};
//! Define numeric_limits for the custom type.
namespace std
{
template<>
class numeric_limits<Double> : public numeric_limits<double>
{
public:
//! Limit our Double to a range of +/- 100.0
static Double (min)()
{
return Double(1.e-2);
}
static Double (max)()
{
return Double(1.e2);
}
static Double epsilon()
{
return Double( std::numeric_limits<double>::epsilon() );
}
};
}
//! Define range checking and overflow policies.
namespace custom
{
//! Define a custom range checker
template<typename Traits, typename OverFlowHandler>
struct range_checker
{
typedef typename Traits::argument_type argument_type ;
typedef typename Traits::source_type S;
typedef typename Traits::target_type T;
//! Check range of integral types.
static boost::numeric::range_check_result out_of_range( argument_type s )
{
using namespace boost::numeric;
if( s > bounds<T>::highest() )
return cPosOverflow;
else if( s < bounds<T>::lowest() )
return cNegOverflow;
else
return cInRange;
}
static void validate_range ( argument_type s )
{
BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_bounded );
OverFlowHandler()( out_of_range(s) );
}
};
//! Overflow handler
struct positive_overflow{};
struct negative_overflow{};
struct overflow_handler
{
void operator() ( boost::numeric::range_check_result r )
{
using namespace boost::numeric;
if( r == cNegOverflow )
throw negative_overflow() ;
else if( r == cPosOverflow )
throw positive_overflow() ;
}
};
//! Define a rounding policy and specialize on the custom type.
template<class S>
struct Ceil : boost::numeric::Ceil<S>{};
template<>
struct Ceil<Double>
{
typedef Double source_type;
typedef Double const& argument_type;
static source_type nearbyint ( argument_type s )
{
#if !defined(BOOST_NO_STDC_NAMESPACE)
using std::ceil ;
#endif
return Double( ceil(s.v) );
}
typedef boost::mpl::integral_c< std::float_round_style, std::round_toward_infinity> round_style;
};
//! Define a rounding policy and specialize on the custom type.
template<class S>
struct Trunc: boost::numeric::Trunc<S>{};
template<>
struct Trunc<Double>
{
typedef Double source_type;
typedef Double const& argument_type;
static source_type nearbyint ( argument_type s )
{
#if !defined(BOOST_NO_STDC_NAMESPACE)
using std::floor;
#endif
return Double( floor(s.v) );
}
typedef boost::mpl::integral_c< std::float_round_style, std::round_toward_zero> round_style;
};
}//namespace custom;
namespace boost { namespace numeric {
//! Define the numeric_cast_traits specializations on the custom type.
template <typename S>
struct numeric_cast_traits<Double, S>
{
typedef custom::overflow_handler overflow_policy;
typedef custom::range_checker
<
boost::numeric::conversion_traits<Double, S>
, overflow_policy
> range_checking_policy;
typedef boost::numeric::Trunc<S> rounding_policy;
};
template <typename T>
struct numeric_cast_traits<T, Double>
{
typedef custom::overflow_handler overflow_policy;
typedef custom::range_checker
<
boost::numeric::conversion_traits<T, Double>
, overflow_policy
> range_checking_policy;
typedef custom::Trunc<Double> rounding_policy;
};
//! Define the conversion from the custom type to built-in types and vice-versa.
template<typename T>
struct raw_converter< conversion_traits< T, Double > >
{
static T low_level_convert ( const Double& n )
{
return static_cast<T>( n.v );
}
};
template<typename S>
struct raw_converter< conversion_traits< Double, S > >
{
static Double low_level_convert ( const S& n )
{
return Double(n);
}
};
}}//namespace boost::numeric;
[endsect]
[endsect]
+13
View File
@@ -0,0 +1,13 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=doc/html/index.html">
</head>
<body>
Automatic redirection failed, please go to
<a href="doc/html/index.html">doc/index.html</a>.&nbsp;<hr>
<p> Copyright Beman Dawes, 2001</p>
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
</body>
</html>
@@ -0,0 +1,16 @@
{
"key": "numeric/conversion",
"name": "Numeric Conversion",
"authors": [
"Fernando Cacciola"
],
"description": "Optimized Policy-based Numeric Conversions.",
"category": [
"Math",
"Miscellaneous"
],
"maintainers": [
"Fernando Cacciola <fernando_cacciola -at- ciudad.com.ar>",
"Brandon Kohn <blkohn -at- hotmail.com>"
]
}
+42
View File
@@ -0,0 +1,42 @@
# Boost Numeric Conversion Library test Jamfile
#
# Copyright (C) 2003, Fernando Luis Cacciola Carballal.
#
# Distributed under the Boost Software License, Version 1.0. (See
# accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# import testing ;
project numeric_conversion_unit_tests
:
requirements
<include>.
<toolset>gcc:<cxxflags>"-ftemplate-depth-300 -g0"
<toolset>darwin:<cxxflags>"-ftemplate-depth-300 -g0"
;
test-suite minimal
:
[ run bounds_test.cpp ]
[ run traits_test.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run converter_test.cpp ]
[ run udt_support_test.cpp ]
[ run numeric_cast_test.cpp ]
[ run udt_example_0.cpp ]
[ run numeric_cast_traits_test.cpp ]
;
test-suite full
:
minimal
[ compile-fail compile_fail/built_in_numeric_cast_traits.cpp ]
;
test-suite extra ;
explicit minimal ;
explicit extra ;
# support the old test target
test-suite numeric/conversion : full ;
@@ -0,0 +1,101 @@
// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See library home page at http://www.boost.org/libs/numeric/conversion
//
// Contact the author at: fernando_cacciola@hotmail.com
//
#include<typeinfo>
#include<iostream>
#include<iomanip>
#include "boost/numeric/conversion/bounds.hpp"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "test_helpers.cpp"
using namespace std ;
using namespace boost ;
using namespace numeric ;
// Test the fields of boost::numeric::bounds<> against the expected values.
//
template<class T>
void test_bounds( T expected_lowest, T expected_highest, T expected_smallest )
{
T lowest = bounds<T>::lowest () ;
T highest = bounds<T>::highest () ;
T smallest = bounds<T>::smallest() ;
BOOST_CHECK_MESSAGE ( lowest == expected_lowest,
"bounds<" << typeid(T).name() << ">::lowest() = " << printable(lowest) << ". Expected " << printable(expected_lowest)
) ;
BOOST_CHECK_MESSAGE ( highest == expected_highest,
"bounds<" << typeid(T).name() << ">::highest() = " << printable(highest) << ". Expected " << printable(expected_highest)
) ;
BOOST_CHECK_MESSAGE ( smallest == expected_smallest,
"bounds<" << typeid(T).name() << ">::smallest() = " << printable(smallest) << ". Expected " << printable(expected_smallest)
) ;
}
template<class T>
void test_bounds_integer( MATCH_FNTPL_ARG(T) )
{
test_bounds( numeric_limits<T>::min BOOST_PREVENT_MACRO_SUBSTITUTION()
, numeric_limits<T>::max BOOST_PREVENT_MACRO_SUBSTITUTION()
, static_cast<T>(1)
) ;
}
template<class T>
void test_bounds_float( MATCH_FNTPL_ARG(T))
{
test_bounds( -numeric_limits<T>::max BOOST_PREVENT_MACRO_SUBSTITUTION ()
, numeric_limits<T>::max BOOST_PREVENT_MACRO_SUBSTITUTION ()
, numeric_limits<T>::min BOOST_PREVENT_MACRO_SUBSTITUTION ()
) ;
}
void test_bounds_integers()
{
test_bounds_integer( SET_FNTPL_ARG(unsigned char) ) ;
test_bounds_integer( SET_FNTPL_ARG(signed char) ) ;
test_bounds_integer( SET_FNTPL_ARG(char) ) ;
test_bounds_integer( SET_FNTPL_ARG(unsigned short) ) ;
test_bounds_integer( SET_FNTPL_ARG(short) ) ;
test_bounds_integer( SET_FNTPL_ARG(unsigned int) ) ;
test_bounds_integer( SET_FNTPL_ARG(int) ) ;
test_bounds_integer( SET_FNTPL_ARG(unsigned long) ) ;
test_bounds_integer( SET_FNTPL_ARG(long) ) ;
}
void test_bounds_floats()
{
test_bounds_float( SET_FNTPL_ARG(float) );
test_bounds_float( SET_FNTPL_ARG(double) );
test_bounds_float( SET_FNTPL_ARG(long double) );
}
void test_bounds()
{
test_bounds_integers() ;
test_bounds_floats () ;
}
int test_main( int, char * [] )
{
cout << setprecision( std::numeric_limits<long double>::digits10 ) ;
test_bounds();
return 0;
}
@@ -0,0 +1,122 @@
//
//! Copyright (c) 2011
//! Brandon Kohn
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/operators.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/preprocessor/control/iif.hpp>
#include <boost/preprocessor/comparison/less.hpp>
#include <boost/preprocessor/comparison/not_equal.hpp>
#include <boost/preprocessor/repetition/for.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/test/minimal.hpp>
//! Generate default traits for the specified source and target.
#define BOOST_NUMERIC_CONVERSION_GENERATE_CAST_TRAITS(r, state) \
template <> \
struct numeric_cast_traits< \
BOOST_PP_SEQ_ELEM( BOOST_PP_TUPLE_ELEM(4,0,state) \
, BOOST_PP_TUPLE_ELEM(4,3,state) ) \
, BOOST_PP_TUPLE_ELEM(4,2,state)> \
{ \
typedef def_overflow_handler overflow_policy; \
typedef UseInternalRangeChecker range_checking_policy; \
typedef Trunc<BOOST_PP_TUPLE_ELEM(4,2,state)> rounding_policy; \
}; \
/***/
#define BOOST_NUMERIC_CONVERSION_TUPLE_SENTINAL(r, state) \
BOOST_PP_LESS \
( \
BOOST_PP_TUPLE_ELEM(4,0,state) \
, BOOST_PP_TUPLE_ELEM(4,1,state) \
) \
/***/
#define BOOST_NUMERIC_CONVERSION_INC_OP(r, state) \
( \
BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(4,0,state)) \
, BOOST_PP_TUPLE_ELEM(4,1,state) \
, BOOST_PP_TUPLE_ELEM(4,2,state) \
, BOOST_PP_TUPLE_ELEM(4,3,state) \
) \
/***/
#define BOOST_NUMERIC_CONVERSION_GENERATE_CAST_TARGET_STEP(r, state) \
BOOST_PP_FOR \
( \
( \
0 \
, BOOST_PP_TUPLE_ELEM(4,1,state) \
, BOOST_PP_SEQ_ELEM(BOOST_PP_TUPLE_ELEM(4,0,state),BOOST_PP_TUPLE_ELEM(4,2,state)) \
, BOOST_PP_TUPLE_ELEM(4,2,state) \
) \
, BOOST_NUMERIC_CONVERSION_TUPLE_SENTINAL \
, BOOST_NUMERIC_CONVERSION_INC_OP \
, BOOST_NUMERIC_CONVERSION_GENERATE_CAST_TRAITS \
) \
/***/
#define BOOST_NUMERIC_CONVERSION_GENERATE_BUILTIN_CAST_TRAITS(types) \
BOOST_PP_FOR \
( \
(0,BOOST_PP_SEQ_SIZE(types),types,_) \
, BOOST_NUMERIC_CONVERSION_TUPLE_SENTINAL \
, BOOST_NUMERIC_CONVERSION_INC_OP \
, BOOST_NUMERIC_CONVERSION_GENERATE_CAST_TARGET_STEP \
) \
/***/
namespace boost { namespace numeric {
#if !defined( BOOST_NO_INT64_T )
//! Generate the specializations for the built-in types.
BOOST_NUMERIC_CONVERSION_GENERATE_BUILTIN_CAST_TRAITS
(
(char)
(boost::int8_t)
(boost::uint8_t)
(boost::int16_t)
(boost::uint16_t)
(boost::int32_t)
(boost::uint32_t)
(boost::int64_t)
(boost::uint64_t)
(float)
(double)
(long double)
)
#else
BOOST_NUMERIC_CONVERSION_GENERATE_BUILTIN_CAST_TRAITS
(
(char)
(boost::int8_t)
(boost::uint8_t)
(boost::int16_t)
(boost::uint16_t)
(boost::int32_t)
(boost::uint32_t)
(float)
(double)
(long double)
)
#endif
}}//namespace boost::numeric;
int test_main( int argc, char * argv[] )
{
//! This test should not compile.
return 1;
}
#undef BOOST_NUMERIC_CONVERSION_GENERATE_BUILTIN_CAST_TRAITS
#undef BOOST_NUMERIC_CONVERSION_GENERATE_CAST_TARGET_STEP
#undef BOOST_NUMERIC_CONVERSION_INC_OP
#undef BOOST_NUMERIC_CONVERSION_TUPLE_SENTINAL
#undef BOOST_NUMERIC_CONVERSION_GENERATE_CAST_TRAITS
@@ -0,0 +1,562 @@
// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See library home page at http://www.boost.org/libs/numeric/conversion
//
// Contact the author at: fernando_cacciola@hotmail.com
//
#include<cstdlib>
#include<iostream>
#include<iomanip>
#include<string>
#include<typeinfo>
#include<vector>
#include<algorithm>
#include "boost/config.hpp"
#include "boost/cstdint.hpp"
#include "boost/utility.hpp"
//
// Borland 5.5 lacks the following math overloads
//
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x551)
namespace std
{
inline float ceil (float x) { return std::ceil ( static_cast<double>(x)); }
inline float floor (float x) { return std::floor ( static_cast<double>(x)); }
inline long double ceil (long double x) { return std::ceill (x); }
inline long double floor (long double x) { return std::floorl(x); }
} // namespace std
#endif
#include "boost/numeric/conversion/converter.hpp"
#include "boost/numeric/conversion/cast.hpp"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "test_helpers.cpp"
#include "test_helpers2.cpp"
#include "test_helpers3.cpp"
#include "boost/mpl/alias.hpp"
using std::cout ;
// A generic 'abs' function.
template<class N> inline N absG ( N v )
{
return v < static_cast<N>(0) ? static_cast<N>(-v) : v ;
}
template<> inline unsigned char absG<unsigned char> ( unsigned char v ) { return v ; }
template<> inline unsigned short absG<unsigned short> ( unsigned short v ) { return v ; }
template<> inline unsigned int absG<unsigned int> ( unsigned int v ) { return v ; }
template<> inline unsigned long absG<unsigned long> ( unsigned long v ) { return v ; }
template<class T> inline void unused_variable ( T const& ) {}
//
// The following function excersizes specific conversions that cover
// usual and boundary cases for each relevant combination.
//
void test_conversions()
{
using namespace boost ;
using namespace numeric ;
// To help the test found possible bugs a random numbers are used.
#if !defined(BOOST_NO_STDC_NAMESPACE)
using std::rand ;
#endif
boost::int16_t v16 ;
boost::uint16_t uv16 ;
boost::int32_t v32 ;
boost::uint32_t uv32 ;
volatile float fv ; // avoid this to be cached internally in some fpu register
volatile double dv ; // avoid this to be cached internally in some fpu register
//
// sample (representative) conversions:
//
cout << "Testing representative conversions\n";
// integral to integral
// signed to signed
// not subranged
v16 = static_cast<boost::int16_t>(rand());
TEST_SUCCEEDING_CONVERSION_DEF(boost::int32_t,boost::int16_t,v16,v16);
// subranged
v16 = static_cast<boost::int16_t>(rand());
TEST_SUCCEEDING_CONVERSION_DEF(boost::int16_t,boost::int32_t,v16,v16);
TEST_POS_OVERFLOW_CONVERSION_DEF(boost::int16_t,boost::int32_t,bounds<boost::int16_t>::highest() + boost::int32_t(1) ) ;
TEST_NEG_OVERFLOW_CONVERSION_DEF(boost::int16_t,boost::int32_t,bounds<boost::int16_t>::lowest() - boost::int32_t(1) ) ;
// signed to unsigned
// subranged
v32 = absG(static_cast<boost::int32_t>(rand()));
v16 = absG(static_cast<boost::int16_t>(rand()));
TEST_SUCCEEDING_CONVERSION_DEF(boost::uint32_t,boost::int32_t,v32,v32);
TEST_SUCCEEDING_CONVERSION_DEF(boost::uint16_t,boost::int32_t,v16,v16);
TEST_POS_OVERFLOW_CONVERSION_DEF(boost::uint16_t,boost::int32_t,bounds<boost::uint16_t>::highest() + boost::int32_t(1) ) ;
TEST_NEG_OVERFLOW_CONVERSION_DEF(boost::uint32_t,boost::int32_t,boost::int32_t(-1) ) ;
// unsigned to signed
// not subranged
v32 = absG(static_cast<boost::int32_t>(rand()));
TEST_SUCCEEDING_CONVERSION_DEF(boost::int32_t,boost::uint32_t,v32,v32);
// subranged
v16 = absG(static_cast<boost::int16_t>(rand()));
TEST_SUCCEEDING_CONVERSION_DEF(boost::int16_t,boost::uint32_t,v16,v16);
TEST_POS_OVERFLOW_CONVERSION_DEF(boost::int32_t,boost::uint32_t,bounds<boost::uint32_t>::highest() ) ;
TEST_POS_OVERFLOW_CONVERSION_DEF(boost::int16_t,boost::uint32_t,bounds<boost::uint32_t>::highest() ) ;
// unsigned to unsigned
// not subranged
uv16 = static_cast<boost::uint16_t>(rand());
TEST_SUCCEEDING_CONVERSION_DEF(boost::uint32_t,boost::uint16_t,uv16,uv16);
// subranged
uv16 = static_cast<boost::uint16_t>(rand());
TEST_SUCCEEDING_CONVERSION_DEF(boost::uint16_t,boost::uint32_t,uv16,uv16);
TEST_POS_OVERFLOW_CONVERSION_DEF(boost::uint16_t,boost::uint32_t,bounds<boost::uint32_t>::highest() ) ;
// integral to float
// from signed integral
v32 = static_cast<boost::int32_t>(rand());
TEST_SUCCEEDING_CONVERSION_DEF(double,boost::int32_t,v32,v32);
// from uint32_tegral
uv32 = static_cast<boost::uint32_t>(rand());
TEST_SUCCEEDING_CONVERSION_DEF(double,boost::uint32_t,uv32,uv32);
// float to integral
// to signed integral
v32 = static_cast<boost::int32_t>(rand());
TEST_SUCCEEDING_CONVERSION_DEF(boost::int32_t,double,v32,v32);
dv = static_cast<double>(bounds<boost::uint32_t>::highest()) + 1.0 ;
TEST_POS_OVERFLOW_CONVERSION_DEF(boost::int32_t,double,dv) ;
TEST_NEG_OVERFLOW_CONVERSION_DEF(boost::int32_t,double,-dv) ;
// float to float
// not subranged
fv = static_cast<float>(rand()) / static_cast<float>(3) ;
TEST_SUCCEEDING_CONVERSION_DEF(double,float,fv,fv);
// subranged
fv = static_cast<float>(rand()) / static_cast<float>(3) ;
TEST_SUCCEEDING_CONVERSION_DEF(float,double,fv,fv);
TEST_POS_OVERFLOW_CONVERSION_DEF(float,double,bounds<double>::highest()) ;
TEST_NEG_OVERFLOW_CONVERSION_DEF(float,double,bounds<double>::lowest ()) ;
}
// Custom OverflowHandler
struct custom_overflow_handler
{
void operator() ( boost::numeric::range_check_result r )
{
if ( r == boost::numeric::cNegOverflow )
cout << "negative_overflow detected!\n" ;
else if ( r == boost::numeric::cPosOverflow )
cout << "positive_overflow detected!\n" ;
}
} ;
template<class T, class S,class OverflowHandler>
void test_overflow_handler( MATCH_FNTPL_ARG(T), MATCH_FNTPL_ARG(S), MATCH_FNTPL_ARG(OverflowHandler),
PostCondition pos,
PostCondition neg
)
{
typedef boost::numeric::conversion_traits<T,S> traits ;
typedef boost::numeric::converter<T,S,traits,OverflowHandler> converter ;
static const S psrc = boost::numeric::bounds<S>::highest();
static const S nsrc = boost::numeric::bounds<S>::lowest ();
static const T pres = static_cast<T>(psrc);
static const T nres = static_cast<T>(nsrc);
test_conv_base ( ConversionInstance<converter>(pres,psrc,pos) ) ;
test_conv_base ( ConversionInstance<converter>(nres,nsrc,neg) ) ;
}
template<class T, class S>
void test_overflow_handlers( MATCH_FNTPL_ARG(T), MATCH_FNTPL_ARG(S) )
{
cout << "Testing Silent Overflow Handler policy\n";
test_overflow_handler( SET_FNTPL_ARG(T),
SET_FNTPL_ARG(S),
SET_FNTPL_ARG(boost::numeric::silent_overflow_handler),
c_converted,
c_converted
) ;
cout << "Testing Default Overflow Handler policy\n";
test_overflow_handler( SET_FNTPL_ARG(T),
SET_FNTPL_ARG(S),
SET_FNTPL_ARG(boost::numeric::def_overflow_handler),
c_pos_overflow,
c_neg_overflow
) ;
cout << "Testing Custom (User-Defined) Overflow Handler policy\n";
test_overflow_handler( SET_FNTPL_ARG(T),
SET_FNTPL_ARG(S),
SET_FNTPL_ARG(custom_overflow_handler),
c_converted,
c_converted
) ;
}
// For a given float-type number 'n' of integer value (n.0), check the conversions
// within the range [n-1,n+1] taking values at: (n-1,n-0.5,n,n+0.5,n+1).
// For each sampled value there is an expected result and a PostCondition according to the
// specified round_style.
//
template<class T, class S, class Float2IntRounder>
void test_rounding_conversion ( MATCH_FNTPL_ARG(T), MATCH_FNTPL_ARG(Float2IntRounder),
S s,
PostCondition resl1,
PostCondition resl0,
PostCondition res,
PostCondition resr0,
PostCondition resr1
)
{
typedef boost::numeric::conversion_traits<T,S> Traits ;
typedef boost::numeric::converter<T,S, Traits, boost::numeric::def_overflow_handler,Float2IntRounder>
Converter ;
S sl1 = s - static_cast<S>(1);
S sl0 = s - static_cast<S>(0.5);
S sr0 = s + static_cast<S>(0.5);
S sr1 = s + static_cast<S>(1);
T tl1 = static_cast<T>( Converter::nearbyint(sl1) );
T tl0 = static_cast<T>( Converter::nearbyint(sl0) );
T t = static_cast<T>( Converter::nearbyint(s) );
T tr0 = static_cast<T>( Converter::nearbyint(sr0) );
T tr1 = static_cast<T>( Converter::nearbyint(sr1) );
test_conv_base ( ConversionInstance<Converter>(tl1,sl1,resl1) ) ;
test_conv_base ( ConversionInstance<Converter>(tl0,sl0,resl0) ) ;
test_conv_base ( ConversionInstance<Converter>(t,s,res) ) ;
test_conv_base ( ConversionInstance<Converter>(tr0,sr0,resr0) ) ;
test_conv_base ( ConversionInstance<Converter>(tr1,sr1,resr1) ) ;
}
template<class T,class S>
void test_round_style( MATCH_FNTPL_ARG(T), MATCH_FNTPL_ARG(S) )
{
S min = boost::numeric::bounds<T>::lowest();
S max = boost::numeric::bounds<T>::highest();
cout << "Testing 'Trunc' Float2IntRounder policy\n";
test_rounding_conversion(SET_FNTPL_ARG(T),
SET_FNTPL_ARG(boost::numeric::Trunc<S>),
min,
c_neg_overflow,
c_converted,
c_converted,
c_converted,
c_converted
) ;
test_rounding_conversion(SET_FNTPL_ARG(T),
SET_FNTPL_ARG(boost::numeric::Trunc<S>),
max,
c_converted,
c_converted,
c_converted,
c_converted,
c_pos_overflow
) ;
cout << "Testing 'RoundEven' Float2IntRounder policy\n";
test_rounding_conversion(SET_FNTPL_ARG(T),
SET_FNTPL_ARG(boost::numeric::RoundEven<S>),
min,
c_neg_overflow,
c_converted,
c_converted,
c_converted,
c_converted
) ;
test_rounding_conversion(SET_FNTPL_ARG(T),
SET_FNTPL_ARG(boost::numeric::RoundEven<S>),
max,
c_converted,
c_converted,
c_converted,
c_pos_overflow,
c_pos_overflow
) ;
cout << "Testing 'Ceil' Float2IntRounder policy\n";
test_rounding_conversion(SET_FNTPL_ARG(T),
SET_FNTPL_ARG(boost::numeric::Ceil<S>),
min,
c_neg_overflow,
c_converted,
c_converted,
c_converted,
c_converted
) ;
test_rounding_conversion(SET_FNTPL_ARG(T),
SET_FNTPL_ARG(boost::numeric::Ceil<S>),
max,
c_converted,
c_converted,
c_converted,
c_pos_overflow,
c_pos_overflow
) ;
cout << "Testing 'Floor' Float2IntRounder policy\n" ;
test_rounding_conversion(SET_FNTPL_ARG(T),
SET_FNTPL_ARG(boost::numeric::Floor<S>),
min,
c_neg_overflow,
c_neg_overflow,
c_converted,
c_converted,
c_converted
) ;
test_rounding_conversion(SET_FNTPL_ARG(T),
SET_FNTPL_ARG(boost::numeric::Floor<S>),
max,
c_converted,
c_converted,
c_converted,
c_converted,
c_pos_overflow
) ;
}
void test_round_even( double n, double x )
{
double r = boost::numeric::RoundEven<double>::nearbyint(n);
BOOST_CHECK( r == x ) ;
}
void test_round_even()
{
cout << "Testing 'RoundEven' tie-breaking\n";
double min = boost::numeric::bounds<double>::lowest();
double max = boost::numeric::bounds<double>::highest();
#if !defined(BOOST_NO_STDC_NAMESPACE)
using std::floor ;
using std::ceil ;
#endif
test_round_even(min, floor(min));
test_round_even(max, ceil (max));
test_round_even(2.0, 2.0);
test_round_even(2.3, 2.0);
test_round_even(2.5, 2.0);
test_round_even(2.7, 3.0);
test_round_even(3.0, 3.0);
test_round_even(3.3, 3.0);
test_round_even(3.5, 4.0);
test_round_even(3.7, 4.0);
}
int double_to_int ( double n ) { return static_cast<int>(n) ; }
void test_converter_as_function_object()
{
cout << "Testing converter as function object.\n";
// Create a sample sequence of double values.
std::vector<double> S ;
for ( int i = 0 ; i < 10 ; ++ i )
S.push_back( i * ( 18.0 / 19.0 ) );
// Create a sequence of int values from 's' using the standard conversion.
std::vector<int> W ;
std::transform(S.begin(),S.end(),std::back_inserter(W),double_to_int);
// Create a sequence of int values from s using a default numeric::converter
std::vector<int> I ;
std::transform(S.begin(),
S.end(),
std::back_inserter(I),
boost::numeric::converter<int,double>()
) ;
// Match 'w' and 'i' which should be equal.
bool double_to_int_OK = std::equal(W.begin(),W.end(),I.begin()) ;
BOOST_CHECK_MESSAGE(double_to_int_OK, "converter (int,double) as function object");
// Create a sequence of double values from s using a default numeric::converter (which should be the trivial conv).
std::vector<double> D ;
std::transform(S.begin(),
S.end(),
std::back_inserter(D),
boost::numeric::converter<double,double>()
) ;
// Match 's' and 'd' which should be equal.
bool double_to_double_OK = std::equal(S.begin(),S.end(),D.begin()) ;
BOOST_CHECK_MESSAGE(double_to_double_OK, "converter (double,double) as function object");
}
#if BOOST_WORKAROUND(__IBMCPP__, <= 600 ) // VCAPP6
# define UNOPTIMIZED
#else
# define UNOPTIMIZED volatile
#endif
void test_optimizations()
{
using namespace boost;
using namespace numeric;
float fv0 = 18.0f / 19.0f ;
// This code deosn't produce any output.
// It is intended to show the optimization of numeric::converter<> by manual inspection
// of the generated code.
// Each test shows first the equivalent hand-coded version.
// The numeric_cast<> code should be the same if full compiler optimization/inlining is used.
//---------------------------------
// trivial conversion.
//
// equivalent code:
UNOPTIMIZED float fv1a = fv0 ;
float fv1b = numeric_cast<float>(fv0);
unused_variable(fv1a);
unused_variable(fv1b);
//
//---------------------------------
//---------------------------------
// nonsubranged conversion.
//
// equivalent code:
UNOPTIMIZED double dv1a = static_cast<double>(fv0);
double dv1b = numeric_cast<double>(fv0);
unused_variable(dv1a);
unused_variable(dv1b);
//
//---------------------------------
//------------------------------------------------------
// subranged conversion with both-sided range checking.
//
// equivalent code:
{
double const& s = dv1b ;
// range checking
range_check_result r = s < static_cast<double>(bounds<float>::lowest())
? cNegOverflow : cInRange ;
if ( r == cInRange )
{
r = s > static_cast<double>(bounds<float>::highest()) ? cPosOverflow : cInRange ;
}
if ( r == cNegOverflow )
throw negative_overflow() ;
else if ( r == cPosOverflow )
throw positive_overflow() ;
// conversion
UNOPTIMIZED float fv2a = static_cast<float>(s);
unused_variable(fv2a);
}
float fv2b = numeric_cast<float>(dv1b);
unused_variable(fv2b);
//
//---------------------------------
//---------------------------------
// subranged rounding conversion
//
// equivalent code:
{
double const& s = dv1b ;
// range checking
range_check_result r = s <= static_cast<double>(bounds<int>::lowest()) - static_cast<double>(1.0)
? cNegOverflow : cInRange ;
if ( r == cInRange )
{
r = s >= static_cast<double>(bounds<int>::highest()) + static_cast<double>(1.0)
? cPosOverflow : cInRange ;
}
if ( r == cNegOverflow )
throw negative_overflow() ;
else if ( r == cPosOverflow )
throw positive_overflow() ;
// rounding
#if !defined(BOOST_NO_STDC_NAMESPACE)
using std::floor ;
#endif
double s1 = floor(dv1b + 0.5);
// conversion
UNOPTIMIZED int iv1a = static_cast<int>(s1);
unused_variable(iv1a);
}
int iv1b = numeric_cast<int>(dv1b);
unused_variable(iv1b);
//
//---------------------------------
}
int test_main( int, char* argv[] )
{
std::cout << std::setprecision( std::numeric_limits<long double>::digits10 ) ;
test_conversions();
test_overflow_handlers( SET_FNTPL_ARG(boost::int16_t), SET_FNTPL_ARG(boost::int32_t));
test_round_style(SET_FNTPL_ARG(boost::int32_t), SET_FNTPL_ARG(double) ) ;
test_round_even() ;
test_converter_as_function_object();
test_optimizations() ;
return 0;
}
//---------------------------------------------------------------------------
@@ -0,0 +1,97 @@
// boost utility cast test program -----------------------------------------//
// (C) Copyright Beman Dawes, Dave Abrahams 1999. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 28 Set 04 taken from the old cast library (Fernando Cacciola)
#include <iostream>
#include <climits>
#include <cfloat> // for DBL_MAX (Peter Schmid)
#include <boost/numeric/conversion/cast.hpp>
#include "boost/test/minimal.hpp"
# if SCHAR_MAX == LONG_MAX
# error "This test program doesn't work if SCHAR_MAX == LONG_MAX"
# endif
using namespace boost;
using std::cout;
int test_main( int argc, char * argv[] )
{
# ifdef NDEBUG
cout << "NDEBUG is defined\n";
# else
cout << "NDEBUG is not defined\n";
# endif
cout << "\nBeginning tests...\n";
// test implicit_cast and numeric_cast -------------------------------------//
// tests which should succeed
long small_value = 1;
long small_negative_value = -1;
long large_value = LONG_MAX;
long large_negative_value = LONG_MIN;
signed char c = 0;
c = large_value; // see if compiler generates warning
c = numeric_cast<signed char>( small_value );
BOOST_CHECK( c == 1 );
c = 0;
c = numeric_cast<signed char>( small_value );
BOOST_CHECK( c == 1 );
c = 0;
c = numeric_cast<signed char>( small_negative_value );
BOOST_CHECK( c == -1 );
// These tests courtesy of Joe R NWP Swatosh<joe.r.swatosh@usace.army.mil>
BOOST_CHECK( 0.0f == numeric_cast<float>( 0.0 ) );
BOOST_CHECK( 0.0 == numeric_cast<double>( 0.0 ) );
// tests which should result in errors being detected
bool caught_exception = false;
try { c = numeric_cast<signed char>( large_value ); }
catch ( numeric::bad_numeric_cast )
{ cout<<"caught bad_numeric_cast #1\n"; caught_exception = true; }
BOOST_CHECK ( caught_exception );
caught_exception = false;
try { c = numeric_cast<signed char>( large_negative_value ); }
catch ( numeric::bad_numeric_cast )
{ cout<<"caught bad_numeric_cast #2\n"; caught_exception = true; }
BOOST_CHECK ( caught_exception );
unsigned long ul;
caught_exception = false;
try { ul = numeric_cast<unsigned long>( large_negative_value ); }
catch ( numeric::bad_numeric_cast )
{ cout<<"caught bad_numeric_cast #3\n"; caught_exception = true; }
BOOST_CHECK ( caught_exception );
caught_exception = false;
try { ul = numeric_cast<unsigned long>( small_negative_value ); }
catch ( numeric::bad_numeric_cast )
{ cout<<"caught bad_numeric_cast #4\n"; caught_exception = true; }
BOOST_CHECK ( caught_exception );
caught_exception = false;
try { numeric_cast<int>( DBL_MAX ); }
catch ( numeric::bad_numeric_cast )
{ cout<<"caught bad_numeric_cast #5\n"; caught_exception = true; }
BOOST_CHECK ( caught_exception );
return 0 ;
} // main
@@ -0,0 +1,380 @@
//
//! Copyright (c) 2011
//! Brandon Kohn
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/operators.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/cstdint.hpp>
#include <boost/test/minimal.hpp>
//! Define a simple custom number
struct Double
{
Double()
: v(0)
{}
template <typename T>
explicit Double( T v )
: v(static_cast<double>(v))
{}
template <typename T>
Double& operator= ( T t )
{
v = static_cast<double>(t);
return *this;
}
bool operator < ( const Double& rhs ) const
{
return v < rhs.v;
}
template <typename T>
bool operator < ( T rhs ) const
{
return v < static_cast<double>(rhs);
}
template <typename LHS>
friend bool operator < ( const LHS& lhs, const Double& rhs )
{
return lhs < rhs.v;
}
bool operator > ( const Double& rhs ) const
{
return v > rhs.v;
}
template <typename LHS>
friend bool operator > ( const LHS& lhs, const Double& rhs )
{
return lhs > rhs.v;
}
template <typename T>
bool operator > ( T rhs ) const
{
return v > static_cast<double>(rhs);
}
bool operator == ( const Double& rhs ) const
{
return v == rhs.v;
}
template <typename T>
bool operator == ( T rhs ) const
{
return v == static_cast<double>(rhs);
}
template <typename LHS>
friend bool operator == ( const LHS& lhs, const Double& rhs )
{
return lhs == rhs.v;
}
bool operator !() const
{
return v == 0;
}
Double operator -() const
{
return Double(-v);
}
Double& operator +=( const Double& t )
{
v += t.v;
return *this;
}
template <typename T>
Double& operator +=( T t )
{
v += static_cast<double>(t);
return *this;
}
Double& operator -=( const Double& t )
{
v -= t.v;
return *this;
}
template <typename T>
Double& operator -=( T t )
{
v -= static_cast<double>(t);
return *this;
}
Double& operator *= ( const Double& factor )
{
v *= factor.v;
return *this;
}
template <typename T>
Double& operator *=( T t )
{
v *= static_cast<double>(t);
return *this;
}
Double& operator /= (const Double& divisor)
{
v /= divisor.v;
return *this;
}
template <typename T>
Double& operator /=( T t )
{
v /= static_cast<double>(t);
return (*this);
}
double v;
};
//! Define numeric_limits for the custom type.
namespace std
{
template<>
class numeric_limits< Double > : public numeric_limits<double>
{
public:
//! Limit our Double to a range of +/- 100.0
static Double (min)()
{
return Double(1.e-2);
}
static Double (max)()
{
return Double(1.e2);
}
static Double epsilon()
{
return Double( std::numeric_limits<double>::epsilon() );
}
};
}
//! Define range checking and overflow policies.
namespace custom
{
//! Define a custom range checker
template<typename Traits, typename OverFlowHandler>
struct range_checker
{
typedef typename Traits::argument_type argument_type ;
typedef typename Traits::source_type S;
typedef typename Traits::target_type T;
//! Check range of integral types.
static boost::numeric::range_check_result out_of_range( argument_type s )
{
using namespace boost::numeric;
if( s > bounds<T>::highest() )
return cPosOverflow;
else if( s < bounds<T>::lowest() )
return cNegOverflow;
else
return cInRange;
}
static void validate_range ( argument_type s )
{
BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_bounded );
OverFlowHandler()( out_of_range(s) );
}
};
//! Overflow handler
struct positive_overflow{};
struct negative_overflow{};
struct overflow_handler
{
void operator() ( boost::numeric::range_check_result r )
{
using namespace boost::numeric;
if( r == cNegOverflow )
throw negative_overflow() ;
else if( r == cPosOverflow )
throw positive_overflow() ;
}
};
//! Define a rounding policy and specialize on the custom type.
template<class S>
struct Ceil : boost::numeric::Ceil<S>{};
template<>
struct Ceil<Double>
{
typedef Double source_type;
typedef Double const& argument_type;
static source_type nearbyint ( argument_type s )
{
#if !defined(BOOST_NO_STDC_NAMESPACE)
using std::ceil ;
#endif
return Double( ceil(s.v) );
}
typedef boost::mpl::integral_c< std::float_round_style, std::round_toward_infinity> round_style;
};
//! Define a rounding policy and specialize on the custom type.
template<class S>
struct Trunc: boost::numeric::Trunc<S>{};
template<>
struct Trunc<Double>
{
typedef Double source_type;
typedef Double const& argument_type;
static source_type nearbyint ( argument_type s )
{
#if !defined(BOOST_NO_STDC_NAMESPACE)
using std::floor;
#endif
return Double( floor(s.v) );
}
typedef boost::mpl::integral_c< std::float_round_style, std::round_toward_zero> round_style;
};
}//namespace custom;
namespace boost { namespace numeric {
//! Define the numeric_cast_traits specializations on the custom type.
template <typename S>
struct numeric_cast_traits<Double, S>
{
typedef custom::overflow_handler overflow_policy;
typedef custom::range_checker
<
boost::numeric::conversion_traits<Double, S>
, overflow_policy
> range_checking_policy;
typedef boost::numeric::Trunc<S> rounding_policy;
};
template <typename T>
struct numeric_cast_traits<T, Double>
{
typedef custom::overflow_handler overflow_policy;
typedef custom::range_checker
<
boost::numeric::conversion_traits<T, Double>
, overflow_policy
> range_checking_policy;
typedef custom::Trunc<Double> rounding_policy;
};
//! Define the conversion from the custom type to built-in types and vice-versa.
template<typename T>
struct raw_converter< conversion_traits< T, Double > >
{
static T low_level_convert ( const Double& n )
{
return static_cast<T>( n.v );
}
};
template<typename S>
struct raw_converter< conversion_traits< Double, S > >
{
static Double low_level_convert ( const S& n )
{
return Double(n);
}
};
}}//namespace boost::numeric;
#define BOOST_TEST_CATCH_CUSTOM_POSITIVE_OVERFLOW( CastCode ) \
try { CastCode; BOOST_CHECK( false ); } \
catch( custom::positive_overflow& ){} \
catch(...){ BOOST_CHECK( false ); } \
/***/
#define BOOST_TEST_CATCH_CUSTOM_NEGATIVE_OVERFLOW( CastCode ) \
try { CastCode; BOOST_CHECK( false ); } \
catch( custom::negative_overflow& ){} \
catch(...){ BOOST_CHECK( false ); } \
/***/
struct test_cast_traits
{
template <typename T>
void operator()(T) const
{
Double d = boost::numeric_cast<Double>( static_cast<T>(50) );
BOOST_CHECK( d.v == 50. );
T v = boost::numeric_cast<T>( d );
BOOST_CHECK( v == 50 );
}
};
void test_numeric_cast_traits()
{
typedef boost::mpl::vector
<
boost::int8_t
, boost::uint8_t
, boost::int16_t
, boost::uint16_t
, boost::int32_t
, boost::uint32_t
#if !defined( BOOST_NO_INT64_T )
, boost::int64_t
, boost::uint64_t
#endif
, float
, double
, long double
> types;
boost::mpl::for_each<types>( test_cast_traits() );
//! Check overflow handler.
Double d( 56.0 );
BOOST_TEST_CATCH_CUSTOM_POSITIVE_OVERFLOW( d = boost::numeric_cast<Double>( 101 ) );
BOOST_CHECK( d.v == 56. );
BOOST_TEST_CATCH_CUSTOM_NEGATIVE_OVERFLOW( d = boost::numeric_cast<Double>( -101 ) );
BOOST_CHECK( d.v == 56.);
//! Check custom round policy.
d = 5.9;
int five = boost::numeric_cast<int>( d );
BOOST_CHECK( five == 5 );
}
int test_main( int argc, char * argv[] )
{
test_numeric_cast_traits();
return 0;
}
#undef BOOST_TEST_CATCH_CUSTOM_POSITIVE_OVERFLOW
#undef BOOST_TEST_CATCH_CUSTOM_NEGATIVE_OVERFLOW
@@ -0,0 +1,152 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// NOTE: This file is intended to be used ONLY by the test files
// from the Numeric Conversions Library
//
//
#include <cmath>
#include "boost/limits.hpp"
#include "boost/utility.hpp"
#include "boost/test/included/test_exec_monitor.hpp"
// Convenience macros to help with compilers which don't parse
// explicit template function instantiations (MSVC6)
#define MATCH_FNTPL_ARG(t) t const*
#define SET_FNTPL_ARG(t) (static_cast< t const* >(0))
//
// *Minimal* example of a User Defined Numeric Type
//
//
namespace MyUDT
{
template<class T>
struct UDT
{
typedef T builtin_type ;
UDT ( T v_ ) : v (v_) {}
T to_builtin() const { return v ; }
friend bool operator == ( UDT const& lhs, UDT const& rhs )
{ return lhs.to_builtin() == rhs.to_builtin() ; }
// NOTE: This operator is *required* by the Numeric Conversion Library
// if Turnc<> is used as the Float2IntRounder policy.
friend bool operator < ( UDT const& lhs, UDT const& rhs )
{ return lhs.to_builtin() < rhs.to_builtin() ; }
friend std::ostream& operator << ( std::ostream& os, UDT const& n )
{ return os << n.to_builtin() ; }
T v ;
} ;
typedef UDT<int> MyInt ;
typedef UDT<double> MyFloat ;
//
// The Float2IntRounder policies *require* a visible 'ceil' or 'floor' math function
// with standard semantics.
// In a conformant compiler, ADL can pick these functions even if they are defined
// within a user namespace, as below.
//
inline MyInt ceil ( MyInt const& x ) { return x ; }
inline MyInt floor ( MyInt const& x ) { return x ; }
inline MyFloat floor ( MyFloat const& x )
{
#if !defined(BOOST_NO_STDC_NAMESPACE)
return MyFloat ( std::floor(x.to_builtin()) ) ;
#else
return MyFloat ( ::floor(x.to_builtin()) ) ;
#endif
}
inline MyFloat ceil ( MyFloat const& x )
{
#if !defined(BOOST_NO_STDC_NAMESPACE)
return MyFloat ( std::ceil(x.to_builtin()) ) ;
#else
return MyFloat ( ::ceil(x.to_builtin()) ) ;
#endif
}
} // namespace MyUDT
//
// The Numeric Conversion Library *requires* User Defined Numeric Types
// to properly specialize std::numeric_limits<>
//
namespace std
{
template<>
class numeric_limits<MyUDT::MyInt> : public numeric_limits<int>
{
public :
BOOST_STATIC_CONSTANT(bool, is_specialized = false);
} ;
template<>
class numeric_limits<MyUDT::MyFloat> : public numeric_limits<double>
{
public :
BOOST_STATIC_CONSTANT(bool, is_specialized = false);
} ;
} // namespace std
//
// The functions floor and ceil defined within namespace MyUDT
// should be found by koenig loopkup, but some compilers don't do it right
// so we inyect them into namespace std so ordinary overload resolution
// can found them.
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) || defined(__BORLANDC__) || defined(__GNUC__)
namespace std {
using MyUDT::floor ;
using MyUDT::ceil ;
} // namespace std
#endif
std::string to_string( bool arg )
{
return arg ? "true" : "false" ;
}
std::string to_string( ... ) { throw std::runtime_error("to_string() called with wrong type!") ; }
//
// This is used to print 'char' values as numbers instead of characters.
//
template<class T> struct printable_number_type { typedef T type ; } ;
template<> struct printable_number_type<signed char> { typedef int type ; } ;
template<> struct printable_number_type<unsigned char> { typedef unsigned type ; } ;
template<> struct printable_number_type<char> { typedef int type ; } ;
template<class T>
inline
typename printable_number_type<T>::type
printable( T n ) { return n ; }
//
///////////////////////////////////////////////////////////////////////////////////////////////
@@ -0,0 +1,60 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// NOTE: This file is intended to be used ONLY by the test files
// from the Numeric Conversions Library
//
//
// The following 'to_string' helpers are provided to give readable names
// to the various enums used by the library.
// NOTE: specializations of boost::lexical_cast<> were not used since some compilers had
// trouble dealing with such specializations for different enumerations.
//
std::string to_string ( boost::numeric::int_float_mixture_enum arg )
{
switch ( arg )
{
case boost::numeric::integral_to_integral : return "integral_to_integral" ;
case boost::numeric::integral_to_float : return "integral_to_float" ;
case boost::numeric::float_to_integral : return "float_to_integral" ;
case boost::numeric::float_to_float : return "float_to_float" ;
}
return "(Unknown result!)" ;
}
std::string to_string ( boost::numeric::sign_mixture_enum arg )
{
switch ( arg )
{
case boost::numeric::unsigned_to_unsigned : return "unsigned_to_unsigned" ;
case boost::numeric::signed_to_signed : return "signed_to_signed" ;
case boost::numeric::signed_to_unsigned : return "signed_to_unsigned" ;
case boost::numeric::unsigned_to_signed : return "unsigned_to_signed" ;
}
return "(Unknown result!)" ;
}
std::string to_string ( boost::numeric::udt_builtin_mixture_enum arg )
{
switch ( arg )
{
case boost::numeric::builtin_to_builtin : return "builtin_to_builtin" ;
case boost::numeric::builtin_to_udt : return "builtin_to_udt" ;
case boost::numeric::udt_to_builtin : return "udt_to_builtin" ;
case boost::numeric::udt_to_udt : return "udt_to_udt" ;
}
return "(Unknown result!)" ;
}
//
///////////////////////////////////////////////////////////////////////////////////////////////
@@ -0,0 +1,144 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// NOTE: This file is intended to be used ONLY by the test files
// from the Numeric Conversions Library
//
// The conversion test is performed using a class whose instances encapsulate
// a particular specific conversion defnied explicitely.
// A ConversionInstance object includes the source type, the target type,
// the source value and the expected result, including possible exceptions.
//
enum PostCondition { c_converted, c_overflow, c_neg_overflow, c_pos_overflow } ;
template<class Converter>
struct ConversionInstance
{
typedef Converter converter ;
typedef typename Converter::argument_type argument_type ;
typedef typename Converter::result_type result_type ;
typedef typename Converter::traits traits ;
typedef typename traits::target_type target_type ;
typedef typename traits::source_type source_type ;
ConversionInstance ( result_type a_result, argument_type a_source, PostCondition a_post)
:
source(a_source),
result(a_result),
post(a_post)
{}
std::string to_string() const
{
return std::string("converter<")
+ typeid(target_type).name()
+ std::string(",")
+ typeid(source_type).name()
+ std::string(">::convert(") ;
}
argument_type source ;
result_type result ;
PostCondition post ;
} ;
//
// Main conversion test point.
// Exercises a specific conversion described by 'conv'.
//
template<class Instance>
void test_conv_base( Instance const& conv )
{
typedef typename Instance::argument_type argument_type ;
typedef typename Instance::result_type result_type ;
typedef typename Instance::converter converter ;
argument_type source = conv.source ;
try
{
result_type result = converter::convert(source);
if ( conv.post == c_converted )
{
BOOST_CHECK_MESSAGE( result == conv.result,
conv.to_string() << printable(source) << ")= " << printable(result) << ". Expected:" << printable(conv.result)
) ;
}
else
{
BOOST_ERROR( conv.to_string() << printable(source) << ") = " << printable(result)
<< ". Expected:" << ( conv.post == c_neg_overflow ? " negative_overflow" : "positive_overflow" )
) ;
}
}
catch ( boost::numeric::negative_overflow const& )
{
if ( conv.post == c_neg_overflow )
{
BOOST_CHECK_MESSAGE( true, conv.to_string() << printable(source) << ") = negative_overflow, as expected" ) ;
}
else
{
BOOST_ERROR( conv.to_string() << printable(source) << ") = negative_overflow. Expected:" << printable(conv.result) ) ;
}
}
catch ( boost::numeric::positive_overflow const& )
{
if ( conv.post == c_pos_overflow )
{
BOOST_CHECK_MESSAGE( true, conv.to_string() << printable(source) << ") = positive_overflow, as expected" ) ;
}
else
{
BOOST_ERROR( conv.to_string() << printable(source) << ") = positive_overflow. Expected:" << printable(conv.result) ) ;
}
}
catch ( boost::numeric::bad_numeric_cast const& )
{
if ( conv.post == c_overflow )
{
BOOST_CHECK_MESSAGE( true, conv.to_string() << printable(source) << ") = bad_numeric_cast, as expected" ) ;
}
else
{
BOOST_ERROR( conv.to_string() << printable(source) << ") = bad_numeric_cast. Expected:" << printable(conv.result) ) ;
}
}
}
#define TEST_SUCCEEDING_CONVERSION(Conv,typeT,typeS,valueT,valueS) \
test_conv_base( ConversionInstance< Conv >(valueT, valueS, c_converted ) )
#define TEST_POS_OVERFLOW_CONVERSION(Conv,typeT,typeS,valueS) \
test_conv_base( ConversionInstance< Conv >( static_cast< typeT >(0), valueS, c_pos_overflow ) )
#define TEST_NEG_OVERFLOW_CONVERSION(Conv,typeT,typeS,valueS) \
test_conv_base( ConversionInstance< Conv >( static_cast< typeT >(0), valueS, c_neg_overflow ) )
#define DEF_CONVERTER(T,S) boost::numeric::converter< T , S >
#define TEST_SUCCEEDING_CONVERSION_DEF(typeT,typeS,valueT,valueS) \
TEST_SUCCEEDING_CONVERSION( DEF_CONVERTER(typeT,typeS), typeT, typeS, valueT, valueS )
#define TEST_POS_OVERFLOW_CONVERSION_DEF(typeT,typeS,valueS) \
TEST_POS_OVERFLOW_CONVERSION( DEF_CONVERTER(typeT,typeS), typeT, typeS, valueS )
#define TEST_NEG_OVERFLOW_CONVERSION_DEF(typeT,typeS,valueS) \
TEST_NEG_OVERFLOW_CONVERSION( DEF_CONVERTER(typeT,typeS), typeT, typeS, valueS )
//
///////////////////////////////////////////////////////////////////////////////////////////////
@@ -0,0 +1,341 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
#include<iostream>
#include<iomanip>
#include<string>
#include<typeinfo>
#include<vector>
#include<algorithm>
#include <boost/cstdint.hpp>
#include <boost/utility.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/numeric/conversion/conversion_traits.hpp>
#include <boost/numeric/conversion/int_float_mixture.hpp>
#include <boost/numeric/conversion/sign_mixture.hpp>
#include <boost/numeric/conversion/udt_builtin_mixture.hpp>
#include <boost/numeric/conversion/is_subranged.hpp>
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "test_helpers.cpp"
#include "test_helpers2.cpp"
using namespace std ;
using namespace boost ;
using namespace numeric;
using namespace MyUDT ;
// These helpers are used by generate_expected_traits<T,S>.
// Unlike the similar helpers in the implementation, they are specialized by extension.
//
template<class T, class S> struct my_is_subranged ;
template<class T, class S> struct my_is_trivial ;
template<class T, class S> struct my_int_float_mixture ;
template<class T, class S> struct my_sign_mixture ;
template<class T, class S> struct my_udt_builtin_mixture ;
// This macro is used to define the properties of each conversion between
// the builtin arithmetric types
//
// It defines the specialization of the helper traits used by 'generate_expected_traits'
//
#define DEFINE_CONVERSION(Target,Source,Trivial,Mixture,SignMixture,UdtMixture,SubRanged) \
\
template<> struct my_is_subranged<Target,Source> \
{ typedef mpl::bool_< (SubRanged) > type ; } ; \
\
template<> struct my_is_trivial<Target,Source> \
{ typedef mpl::bool_< (Trivial) > type ; } ; \
\
template<> struct my_int_float_mixture<Target,Source> \
{ typedef mpl::integral_c<boost::numeric::int_float_mixture_enum, (Mixture) > type ; } ; \
\
template<> struct my_sign_mixture<Target,Source> \
{ typedef mpl::integral_c<boost::numeric::sign_mixture_enum, (SignMixture) > type ; } ; \
\
template<> struct my_udt_builtin_mixture<Target,Source> \
{ typedef mpl::integral_c<boost::numeric::udt_builtin_mixture_enum, (UdtMixture) > type ; }
#define cSubRanged true
#define cTrivial true
// The following test assumes a specific relation between the sizes of the types being used;
// therefore, use specific fixed-width types instead built-in types directly.
// NOTE --> TARGET,SOURCE
//
DEFINE_CONVERSION(boost::uint8_t , boost::uint8_t, cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(boost::int8_t , boost::uint8_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::uint16_t , boost::uint8_t, !cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(boost::int16_t , boost::uint8_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(boost::uint32_t , boost::uint8_t, !cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(boost::int32_t , boost::uint8_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(float , boost::uint8_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(double , boost::uint8_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(long double , boost::uint8_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(MyInt , boost::uint8_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(MyFloat , boost::uint8_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(boost::uint8_t , boost::int8_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int8_t , boost::int8_t, cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(boost::uint16_t , boost::int8_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int16_t , boost::int8_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(boost::uint32_t , boost::int8_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int32_t , boost::int8_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(float , boost::int8_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(double , boost::int8_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(long double , boost::int8_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(MyInt , boost::int8_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(MyFloat , boost::int8_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(boost::uint8_t , boost::uint16_t, !cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int8_t , boost::uint16_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::uint16_t , boost::uint16_t, cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(boost::int16_t , boost::uint16_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::uint32_t , boost::uint16_t, !cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(boost::int32_t , boost::uint16_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(float , boost::uint16_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(double , boost::uint16_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(long double , boost::uint16_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(MyInt , boost::uint16_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(MyFloat , boost::uint16_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(boost::uint8_t , boost::int16_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int8_t , boost::int16_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::uint16_t , boost::int16_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int16_t , boost::int16_t, cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(boost::uint32_t , boost::int16_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int32_t , boost::int16_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(float , boost::int16_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(double , boost::int16_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(long double , boost::int16_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(MyInt , boost::int16_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(MyFloat , boost::int16_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(boost::uint8_t , boost::uint32_t, !cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int8_t , boost::uint32_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::uint16_t , boost::uint32_t, !cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int16_t , boost::uint32_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::uint32_t , boost::uint32_t, cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(boost::int32_t , boost::uint32_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(float , boost::uint32_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(double , boost::uint32_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(long double , boost::uint32_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(MyInt , boost::uint32_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(MyFloat , boost::uint32_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(boost::uint8_t , boost::int32_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int8_t , boost::int32_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::uint16_t , boost::int32_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int16_t , boost::int32_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::uint32_t , boost::int32_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int32_t , boost::int32_t, cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(float , boost::int32_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(double , boost::int32_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(long double , boost::int32_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(MyInt , boost::int32_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(MyFloat , boost::int32_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(boost::uint8_t , float, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int8_t , float, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::uint16_t , float, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int16_t , float, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::uint32_t , float, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int32_t , float, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(float , float, cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(double , float, !cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, ( sizeof(float) > sizeof(double) ) );
DEFINE_CONVERSION(long double , float, !cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, ( sizeof(float) > sizeof(long double) ) );
DEFINE_CONVERSION(MyInt , float, !cTrivial, float_to_integral, signed_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(MyFloat , float, !cTrivial, float_to_float , signed_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(boost::uint8_t , double, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int8_t , double, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::uint16_t , double, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int16_t , double, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::uint32_t , double, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int32_t , double, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(float , double, !cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, ( sizeof(double) > sizeof(float) ) );
DEFINE_CONVERSION(double , double, cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(long double , double, !cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, ( sizeof(double) > sizeof(long double) ) );
DEFINE_CONVERSION(MyInt , double, !cTrivial, float_to_integral, signed_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(MyFloat , double, !cTrivial, float_to_float , signed_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(boost::uint8_t , long double, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int8_t , long double, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::uint16_t , long double, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int16_t , long double, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::uint32_t , long double, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(boost::int32_t , long double, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
DEFINE_CONVERSION(float , long double, !cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, ( sizeof(long double) > sizeof(float) ) );
DEFINE_CONVERSION(double , long double, !cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, ( sizeof(long double) > sizeof(double) ) );
DEFINE_CONVERSION(long double , long double, cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
DEFINE_CONVERSION(MyInt , long double, !cTrivial, float_to_integral, signed_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(MyFloat , long double, !cTrivial, float_to_float , signed_to_signed , builtin_to_udt , !cSubRanged );
DEFINE_CONVERSION(boost::uint8_t , MyInt, !cTrivial, integral_to_integral, signed_to_unsigned, udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(boost::int8_t , MyInt, !cTrivial, integral_to_integral, signed_to_signed , udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(boost::uint16_t , MyInt, !cTrivial, integral_to_integral, signed_to_unsigned, udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(boost::int16_t , MyInt, !cTrivial, integral_to_integral, signed_to_signed , udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(boost::uint32_t , MyInt, !cTrivial, integral_to_integral, signed_to_unsigned, udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(boost::int32_t , MyInt, !cTrivial, integral_to_integral, signed_to_signed , udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(float , MyInt, !cTrivial, integral_to_float , signed_to_signed , udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(double , MyInt, !cTrivial, integral_to_float , signed_to_signed , udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(long double , MyInt, !cTrivial, integral_to_float , signed_to_signed , udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(MyInt , MyInt, cTrivial, integral_to_integral, signed_to_signed , udt_to_udt ,!cSubRanged );
DEFINE_CONVERSION(MyFloat , MyInt, !cTrivial, integral_to_float , signed_to_signed , udt_to_udt ,!cSubRanged );
DEFINE_CONVERSION(boost::uint8_t , MyFloat, !cTrivial, float_to_integral, signed_to_unsigned, udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(boost::int8_t , MyFloat, !cTrivial, float_to_integral, signed_to_signed , udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(boost::uint16_t , MyFloat, !cTrivial, float_to_integral, signed_to_unsigned, udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(boost::int16_t , MyFloat, !cTrivial, float_to_integral, signed_to_signed , udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(boost::uint32_t , MyFloat, !cTrivial, float_to_integral, signed_to_unsigned, udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(boost::int32_t , MyFloat, !cTrivial, float_to_integral, signed_to_signed , udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(float , MyFloat, !cTrivial, float_to_float , signed_to_signed , udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(double , MyFloat, !cTrivial, float_to_float , signed_to_signed , udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(long double , MyFloat, !cTrivial, float_to_float , signed_to_signed , udt_to_builtin , cSubRanged );
DEFINE_CONVERSION(MyInt , MyFloat, !cTrivial, float_to_integral, signed_to_signed , udt_to_udt ,!cSubRanged );
DEFINE_CONVERSION(MyFloat , MyFloat, cTrivial, float_to_float , signed_to_signed , udt_to_udt ,!cSubRanged );
//
// The test is performed by comparing each field of
// boost::numeric::conversion_traits<T,S>
// with the fields of
// expected_traits<T,S>
// which is a traits class constructed explicitely for each combination
// of the built-in arithmetic types.
//
template<class T,
class S,
class Supertype,
class Subtype,
class Subranged,
class Trivial
>
struct expected_traits
{
typedef typename my_int_float_mixture <T,S>::type int_float_mixture ;
typedef typename my_sign_mixture <T,S>::type sign_mixture ;
typedef typename my_udt_builtin_mixture <T,S>::type udt_builtin_mixture ;
typedef Subranged subranged ;
typedef Trivial trivial ;
typedef Supertype supertype ;
typedef Subtype subtype ;
} ;
// This is used by the test engine to generate a expected_traits from T and S.
//
template<class T, class S>
struct generate_expected_traits
{
typedef expected_traits<T, S, T, S, mpl::false_, mpl::true_ > trivial ;
typedef expected_traits<T, S, S, T, mpl::true_ , mpl::false_ > subranged ;
typedef expected_traits<T, S, T, S, mpl::false_, mpl::false_ > non_subranged ;
typedef typename my_is_subranged<T,S>::type IsSubranged ;
typedef typename my_is_trivial <T,S>::type IsTrivial ;
typedef typename mpl::if_<IsSubranged,subranged,non_subranged>::type non_trivial ;
typedef typename mpl::if_<IsTrivial,trivial,non_trivial>::type type ;
} ;
// This macro generates the code that compares a non-type field
// in boost::numeric::conversion_traits<> with its corresponding field
// in expected_traits<>
//
#define TEST_VALUE_FIELD(Name) \
typedef typename traits::Name BOOST_PP_CAT(t,Name) ; \
typedef typename expected::Name BOOST_PP_CAT(x,Name) ; \
BOOST_CHECK_MESSAGE ( ( BOOST_PP_CAT(t,Name)::value == BOOST_PP_CAT(x,Name)::value ) , \
"conversion_traits<" << typeid(T).name() << "," << typeid(S).name() \
<< ">::" << #Name << " = " << to_string(BOOST_PP_CAT(t,Name)::value) \
<< ". Expected: " << to_string(BOOST_PP_CAT(x,Name)::value) \
) ;
// This macro generates the code that compares a type field
// in numeric::conversion_traits<> with its corresponding field
// in expected_traits<>
//
#define TEST_TYPE_FIELD(Name) \
typedef typename traits::Name BOOST_PP_CAT(t,Name) ; \
typedef typename expected::Name BOOST_PP_CAT(x,Name) ; \
BOOST_CHECK_MESSAGE ( ( typeid(BOOST_PP_CAT(t,Name)) == typeid(BOOST_PP_CAT(x,Name)) ) , \
"conversion_traits<" << typeid(T).name() << "," << typeid(S).name() \
<< ">::" << #Name << " = " << typeid(BOOST_PP_CAT(t,Name)).name() \
<< ". Expected: " << typeid(BOOST_PP_CAT(x,Name)).name() \
) ;
//
// Test core.
// Compares each field of boost::numeric::conversion_traits<T,S>
// with the corresponding field of expected_traits<T,S>
//
template<class T, class S>
void test_traits_base( MATCH_FNTPL_ARG(T), MATCH_FNTPL_ARG(S) )
{
typedef boost::numeric::conversion_traits<T,S> traits ;
typedef typename generate_expected_traits<T,S>::type expected ;
TEST_VALUE_FIELD(int_float_mixture) ;
TEST_VALUE_FIELD(sign_mixture) ;
TEST_VALUE_FIELD(udt_builtin_mixture) ;
TEST_VALUE_FIELD(subranged) ;
TEST_VALUE_FIELD(trivial) ;
TEST_TYPE_FIELD (supertype) ;
TEST_TYPE_FIELD (subtype) ;
}
template<class S>
void test_traits_from( MATCH_FNTPL_ARG(S) )
{
test_traits_base( SET_FNTPL_ARG(boost::uint8_t) ,SET_FNTPL_ARG(S) );
test_traits_base( SET_FNTPL_ARG(boost::int8_t) ,SET_FNTPL_ARG(S) );
test_traits_base( SET_FNTPL_ARG(boost::uint16_t) ,SET_FNTPL_ARG(S) );
test_traits_base( SET_FNTPL_ARG(boost::int16_t) ,SET_FNTPL_ARG(S) );
test_traits_base( SET_FNTPL_ARG(boost::uint32_t) ,SET_FNTPL_ARG(S) );
test_traits_base( SET_FNTPL_ARG(boost::int32_t) ,SET_FNTPL_ARG(S) );
test_traits_base( SET_FNTPL_ARG(float) ,SET_FNTPL_ARG(S) );
test_traits_base( SET_FNTPL_ARG(double) ,SET_FNTPL_ARG(S) );
test_traits_base( SET_FNTPL_ARG(long double) ,SET_FNTPL_ARG(S) );
test_traits_base( SET_FNTPL_ARG(MyInt) ,SET_FNTPL_ARG(S) );
test_traits_base( SET_FNTPL_ARG(MyFloat) ,SET_FNTPL_ARG(S) );
}
void test_traits()
{
test_traits_from( SET_FNTPL_ARG(boost::uint8_t) );
test_traits_from( SET_FNTPL_ARG(boost::int8_t) );
test_traits_from( SET_FNTPL_ARG(boost::uint16_t) );
test_traits_from( SET_FNTPL_ARG(boost::int16_t) );
test_traits_from( SET_FNTPL_ARG(boost::uint32_t) );
test_traits_from( SET_FNTPL_ARG(boost::int32_t) );
test_traits_from( SET_FNTPL_ARG(float) );
test_traits_from( SET_FNTPL_ARG(double) );
test_traits_from( SET_FNTPL_ARG(long double) );
test_traits_from( SET_FNTPL_ARG(MyInt) );
test_traits_from( SET_FNTPL_ARG(MyFloat) );
}
int test_main( int, char * [])
{
std::cout << std::setprecision( std::numeric_limits<long double>::digits10 ) ;
test_traits();
return 0;
}
//---------------------------------------------------------------------------
@@ -0,0 +1,242 @@
// Copyright (C) 2005, Fernando Luis Cacciola Carballal.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
#include "boost/config.hpp"
#include "boost/utility.hpp"
#include "boost/limits.hpp"
#include "boost/utility.hpp"
#include<iostream>
#include<iomanip>
#include<string>
#include<cmath>
#include "boost/test/included/test_exec_monitor.hpp"
#include "boost/numeric/conversion/cast.hpp"
using namespace std ;
using namespace boost;
using namespace numeric;
//
// This example illustrates how to add support for user defined types (UDTs)
// to the Boost Numeric Conversion Library.
// It is assumed that you are familiar with the following documentation:
//
//
//
// The minimum requirement is that boost::is_arithmetic<UDT> evaluates to false
// (Otherwise the converter code will try to examine the UDT as a built-in type)
//
//
// Let's start with the simpliest case of an UDT which supports standard conversions
//
struct Double
{
Double( double v ) : mV(v) {}
operator double() const { return mV ; }
double mV ;
} ;
double dv = (numeric_limits<double>::max)() ;
double fv = (numeric_limits<float >::max)() ;
Double Dv(dv);
Double Fv(fv);
void simplest_case()
{
//
// conversion_traits<>::udt_builtin_mixture works out of the box as long as boost::is_arithmetic<UDT> yields false
//
BOOST_CHECK( (conversion_traits<double,Double>::udt_builtin_mixture::value == udt_to_builtin) ) ;
BOOST_CHECK( (conversion_traits<Double,double>::udt_builtin_mixture::value == builtin_to_udt) ) ;
BOOST_CHECK( (conversion_traits<Double,Double>::udt_builtin_mixture::value == udt_to_udt ) ) ;
// BY DEFINITION, a conversion from UDT to Builtin is subranged. No attempt is made to actually compare ranges.
BOOST_CHECK( (conversion_traits<double,Double>::subranged::value) == true ) ;
BOOST_CHECK( (conversion_traits<Double,double>::subranged::value) == false ) ;
//
// Conversions to/from FLOATING types, if already supported by an UDT
// are also supported out-of-the-box by converter<> in its default configuration.
//
BOOST_CHECK( numeric_cast<double>(Dv) == static_cast<double>(Dv) ) ;
BOOST_CHECK( numeric_cast<Double>(dv) == static_cast<Double>(dv) ) ;
BOOST_CHECK( numeric_cast<float> (Dv) == static_cast<float> (Dv) ) ;
BOOST_CHECK( numeric_cast<Double>(fv) == static_cast<Double>(fv) ) ;
//
// Range checking is disabled by default if an UDT is either the source or target of the conversion.
//
BOOST_CHECK( (converter<float,double>::out_of_range(dv) == cPosOverflow) );
BOOST_CHECK( (converter<float,Double>::out_of_range(Dv) == cInRange) );
}
//
// The conversion_traits<> class and therefore the converter<> class looks at
// numeric_limits<UDT>::is_integer/is_signed to generate the proper float_in and sign mixtures.
// In most implementations, is_integer/is_signed are both false for UDTs if there is no explicit specialization for it.
// Therefore, the converter<> will see any UDT for which numeric_limits<> is not specialized as Float AND unsigned.
// Signess is used in the converter<> for range checking, but range checking is disabled by default for UDTs, so,
// normally, signess is mostly irrelevant as far as the library is concerned, except for the numeric_traits<>::sign_mixture
// entry.
// is_integer, however, is relevant in that if the conversion is from a float type to an integer type, the conversion is
// "rounding" and the rounder policies will participate.
// ALL implemented rounder policies require proper definitions for floor(udt) and ceil(udt).
// These names will be searched for using ADL, so, if you need to convert TO integral types from a UDT,
// you need to supply those functions along with the UDT in right namespace (that is, any namespace that allows
// ADL to find them)
// If your UDT doesn't supply floor/ceil, conversions to integer types
// won't compile unless a custom Float2IntRounder is used.
Double floor ( Double v ) { return Double(std::floor(v.mV)) ; }
Double ceil ( Double v ) { return Double(std::ceil (v.mV)) ; }
void rounding()
{
BOOST_CHECK( numeric_cast<int>(Dv) == static_cast<int>(Dv) ) ;
}
//
// If your UDT can't or won't provide floor/ceil you can set-up and use your own
// Float2IntRounder policy (though doing this is not always required as shown so far)
//
struct DoubleToInt
{
static Double nearbyint ( Double const& s ) { return Double(static_cast<int>(s)); }
typedef mpl::integral_c< std::float_round_style, std::round_toward_zero> round_style ;
} ;
void custom_rounding()
{
typedef converter<int
,Double
,conversion_traits<int,Double>
,void // By default UDT disable range checking so this won't be used
,DoubleToInt
>
DoubleToIntConverter ;
BOOST_CHECK( DoubleToIntConverter::convert(Dv) == static_cast<int>(Dv) ) ;
}
//
// In the next Level of complexity, your UDTs might not support conversion operators
//
struct Float
{
Float( float v ) : mV(v) {}
float mV ;
} ;
struct Int
{
Int( int v ) : mV(v) {}
int mV ;
} ;
typedef conversion_traits<Int,Float> Float2IntTraits ;
typedef conversion_traits<Float,Int> Int2FloatTraits ;
namespace boost { namespace numeric
{
//
// Though static_cast<> won't work with them you can still use numeric_cast<> by specializing
// raw_converter as follows:
//
template<> struct raw_converter<Float2IntTraits>
{
typedef Float2IntTraits::result_type result_type ;
typedef Float2IntTraits::argument_type argument_type ;
static result_type low_level_convert ( argument_type s ) { return Int((int)s.mV); }
} ;
template<> struct raw_converter<Int2FloatTraits>
{
typedef Int2FloatTraits::result_type result_type ;
typedef Int2FloatTraits::argument_type argument_type ;
static result_type low_level_convert ( argument_type s ) { return Float(s.mV); }
} ;
} }
void custom_raw_converter()
{
Float f (12.34);
Int i (12);
Float fi(12);
BOOST_CHECK(numeric_cast<Int> (f).mV == i .mV ) ;
BOOST_CHECK(numeric_cast<Float>(i).mV == fi.mV ) ;
}
//
// Alterntively, the custom raw_converter classes can be defined non-instrusively
// (not as specializations) and passed along as policies
//
struct Float2IntRawConverter
{
static Int low_level_convert ( Float const& s ) { return Int((int)s.mV); }
} ;
struct Int2FloatRawConverter
{
static Float low_level_convert ( Int const& s ) { return Float(s.mV); }
} ;
void custom_raw_converter2()
{
Float f (12.34);
Int i (12);
Float fi(12);
typedef converter<Int
,Float
,Float2IntTraits
,void // By default UDT disable range checking so this won't be used
,void // Float2Int Rounder won't be used if Int isn't marked as integer via numeric_limits<>
,Float2IntRawConverter
>
Float2IntConverter ;
BOOST_CHECK(Float2IntConverter::convert(f).mV == i .mV ) ;
}
int test_main( int, char* [] )
{
cout << setprecision( numeric_limits<long double>::digits10 ) ;
simplest_case();
rounding();
custom_rounding();
custom_raw_converter();
custom_raw_converter2();
return 0;
}
@@ -0,0 +1,309 @@
// (C) Copyright 2003, Fernando Luis Cacciola Carballal.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
#include<iostream>
#include<iomanip>
#include<string>
#include<typeinfo>
#include<vector>
#include<algorithm>
#include "boost/numeric/conversion/converter.hpp"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "test_helpers.cpp"
#include "test_helpers2.cpp"
#include "test_helpers3.cpp"
using namespace std ;
using namespace boost ;
using namespace numeric ;
using namespace MyUDT ;
//-------------------------------------------------------------------------
// These are the typical steps that are required to install support for
// conversions from/to UDT which need special treatment.
//-------------------------------------------------------------------------
//
// (1) Instantiate specific convesions traits.
// This step is only for convenience.
// These traits instances are required in order to define the specializations
// that follow (and which *are required* to make the library work with MyInt and MyFloat)
//
namespace MyUDT {
typedef conversion_traits<double , MyFloat> MyFloat_to_double_Traits;
typedef conversion_traits<int , MyFloat> MyFloat_to_int_Traits;
typedef conversion_traits<MyInt , MyFloat> MyFloat_to_MyInt_Traits;
typedef conversion_traits<int , MyInt > MyInt_to_int_Traits;
typedef conversion_traits<MyFloat, MyInt > MyInt_to_MyFloat_Traits;
typedef conversion_traits<MyInt , double > double_to_MyInt_Traits;
} // namespace MyUDT
//
// (2) Define suitable raw converters.
//
// Our sample UDTs don't support implicit conversions.
// Therefore, the default raw_converter<> doesn't work,
// and we need to define our own.
//
// There are two ways of doing this:
//
// (a) One is to simply specialize boost::numeric::raw_converter<> directly.
// This way, the default converter will work out of the box, which means, for instance,
// that numeric_cast<> can be used with these UDTs.
//
// (b) Define a user class with the appropriate interface and supply it explicitely
// as a policy to a converter instance.
//
// This test uses chice (a).
//
namespace boost {
namespace numeric {
template<>
struct raw_converter<MyUDT::MyFloat_to_double_Traits>
{
static double low_level_convert ( MyUDT::MyFloat const& s )
{ return s.to_builtin() ; }
} ;
template<>
struct raw_converter<MyUDT::MyFloat_to_int_Traits>
{
static int low_level_convert ( MyUDT::MyFloat const& s )
{ return static_cast<int>( s.to_builtin() ) ; }
} ;
template<>
struct raw_converter<MyUDT::MyFloat_to_MyInt_Traits>
{
static MyUDT::MyInt low_level_convert ( MyUDT::MyFloat const& s )
{ return MyUDT::MyInt( static_cast<int>(s.to_builtin()) ) ; }
} ;
template<>
struct raw_converter<MyUDT::MyInt_to_int_Traits>
{
static int low_level_convert ( MyUDT::MyInt const& s ) { return s.to_builtin() ; }
} ;
template<>
struct raw_converter<MyUDT::MyInt_to_MyFloat_Traits>
{
static MyUDT::MyFloat low_level_convert ( MyUDT::MyInt const& s )
{
return MyUDT::MyFloat( static_cast<double>(s.to_builtin()) ) ;
}
} ;
template<>
struct raw_converter<MyUDT::double_to_MyInt_Traits>
{
static MyUDT::MyInt low_level_convert ( double s )
{ return MyUDT::MyInt( static_cast<int>(s) ) ; }
} ;
} // namespace numeric
} // namespace boost
//
// (3) Define suitable range checkers
//
// By default, if a UDT is involved in a conversion, internal range checking is disabled.
// This is so because a UDT type can have any sort of range, even unbounded, thus
// the library doesn't attempt to automatically figure out the appropriate range checking logic.
// (as it does when builtin types are involved)
// However, this situation is a bit unsufficient in practice, specially from doing narrowing (subranged)
// conversions from UDTs.
// The library provides a rudimentary hook to help this out: The user can plug in his own
// range checker to the converter instance.
//
// This test shows how to define and use a custom range checker.
//
namespace MyUDT {
//
// The following are metaprogramming tools to allow us the implement the
// MyCustomRangeChecker generically, for either builtin or UDT types.
//
// get_builtin_type<N>::type extracts the built-in type of our UDT's
//
template<class N> struct get_builtin_type { typedef N type ; } ;
template<> struct get_builtin_type<MyInt> { typedef int type ; } ;
template<> struct get_builtin_type<MyFloat> { typedef double type ; } ;
// U extract_builtin ( T s ) returns 's' converted to the corresponding built-in type U.
//
template<class N>
struct extract_builtin
{
static N apply ( N n ) { return n ; }
} ;
template<>
struct extract_builtin<MyInt>
{
static int apply ( MyInt const& n ) { return n.to_builtin() ; }
} ;
template<>
struct extract_builtin<MyFloat>
{
static double apply ( MyFloat const& n ) { return n.to_builtin() ; }
} ;
template<class Traits>
struct MyCustomRangeChecker
{
typedef typename Traits::argument_type argument_type ;
// This custom range checker uses the fact that our 'fake' UDT are merely wrappers
// around builtin types; so it just forward the logic to the correspoding range
// checkers for the wrapped builtin types.
//
typedef typename Traits::source_type S ;
typedef typename Traits::target_type T ;
// NOTE: S and/or T can be either UDT or builtin types.
typedef typename get_builtin_type<S>::type builtinS ;
typedef typename get_builtin_type<T>::type builtinT ;
// NOTE: The internal range checker used by default is *built* when you instantiate
// a converter<> with a given Traits according to the properties of the involved types.
// Currently, there is no way to instantiate this range checker as a separate class.
// However, you can see it as part of the interface of the converter
// (since the converter inherits from it)
// Therefore, here we instantiate a converter corresponding to the builtin types to access
// their associated builtin range checker.
//
typedef boost::numeric::converter<builtinT,builtinS> InternalConverter ;
static range_check_result out_of_range ( argument_type s )
{
return InternalConverter::out_of_range( extract_builtin<S>::apply(s) );
}
static void validate_range ( argument_type s )
{
return InternalConverter::validate_range( extract_builtin<S>::apply(s) );
}
} ;
} // namespace MyUDT
//
// Test here
//
void test_udt_conversions_with_defaults()
{
cout << "Testing UDT conversion with default policies\n" ;
// MyInt <--> int
int mibv = rand();
MyInt miv(mibv);
TEST_SUCCEEDING_CONVERSION_DEF(MyInt,int,miv,mibv);
TEST_SUCCEEDING_CONVERSION_DEF(int,MyInt,mibv,miv);
// MyFloat <--> double
double mfbv = static_cast<double>(rand()) / 3.0 ;
MyFloat mfv (mfbv);
TEST_SUCCEEDING_CONVERSION_DEF(MyFloat,double,mfv,mfbv);
TEST_SUCCEEDING_CONVERSION_DEF(double,MyFloat,mfbv,mfv);
// MyInt <--> MyFloat
MyInt miv2 ( static_cast<int>(mfbv) );
MyFloat miv2F ( static_cast<int>(mfbv) );
MyFloat mfv2 ( static_cast<double>(mibv) );
MyInt mfv2I ( static_cast<double>(mibv) );
TEST_SUCCEEDING_CONVERSION_DEF(MyFloat,MyInt,miv2F,miv2);
TEST_SUCCEEDING_CONVERSION_DEF(MyInt,MyFloat,mfv2I,mfv2);
}
template<class T, class S>
struct GenerateCustomConverter
{
typedef conversion_traits<T,S> Traits;
typedef def_overflow_handler OverflowHandler ;
typedef Trunc<S> Float2IntRounder ;
typedef raw_converter<Traits> RawConverter ;
typedef MyCustomRangeChecker<Traits> RangeChecker ;
typedef converter<T,S,Traits,OverflowHandler,Float2IntRounder,RawConverter,RangeChecker> type ;
} ;
void test_udt_conversions_with_custom_range_checking()
{
cout << "Testing UDT conversions with custom range checker\n" ;
int mibv = rand();
MyFloat mfv ( static_cast<double>(mibv) );
typedef GenerateCustomConverter<MyFloat,int>::type int_to_MyFloat_Conv ;
TEST_SUCCEEDING_CONVERSION( int_to_MyFloat_Conv, MyFloat, int, mfv, mibv );
int mibv2 = rand();
MyInt miv (mibv2);
MyFloat mfv2 ( static_cast<double>(mibv2) );
typedef GenerateCustomConverter<MyFloat,MyInt>::type MyInt_to_MyFloat_Conv ;
TEST_SUCCEEDING_CONVERSION( MyInt_to_MyFloat_Conv, MyFloat, MyInt, mfv2, miv );
double mfbv = bounds<double>::highest();
typedef GenerateCustomConverter<MyInt,double>::type double_to_MyInt_Conv ;
TEST_POS_OVERFLOW_CONVERSION( double_to_MyInt_Conv, MyInt, double, mfbv );
MyFloat mfv3 ( bounds<double>::lowest() ) ;
typedef GenerateCustomConverter<int,MyFloat>::type MyFloat_to_int_Conv ;
TEST_NEG_OVERFLOW_CONVERSION( MyFloat_to_int_Conv, int, MyFloat, mfv3 );
}
int test_main( int, char* [] )
{
cout << setprecision( numeric_limits<long double>::digits10 ) ;
test_udt_conversions_with_defaults();
test_udt_conversions_with_custom_range_checking();
return 0;
}
+14
View File
@@ -0,0 +1,14 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=ublas/doc/index.html">
</head>
<body>
Automatic redirection failed, please go to
<a href="ublas/doc/index.html">ublas/doc/index.html</a>.&nbsp;<hr>
<p>© Copyright Beman Dawes, 2001</p>
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>
+11
View File
@@ -0,0 +1,11 @@
# Boost.Interval Library Jamfile
#
# Copyright (c) 2018 James E. King III
#
# Use, modification, and distribution are subject to the
# Boost Software License, Version 1.0. (See accompanying file
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
# please order by name to ease maintenance
build-project examples ;
build-project test ;
+23
View File
@@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
+34
View File
@@ -0,0 +1,34 @@
Interval, part of the collection of [Boost C++ Libraries](http://github.com/boostorg), is intended to help manipulating mathematical intervals.
### License
Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt).
### Properties
* C++03
* Header-only
### Build Status
Branch | Travis | Appveyor | Coverity Scan | codecov.io | Deps | Docs | Tests |
:-------------: | ------ | -------- | ------------- | ---------- | ---- | ---- | ----- |
[`master`](https://github.com/boostorg/interval/tree/master) | [![Build Status](https://travis-ci.org/boostorg/interval.svg?branch=master)](https://travis-ci.org/boostorg/interval) | [![Build status](https://ci.appveyor.com/api/projects/status/wx6gsonby36or5m2/branch/master?svg=true)](https://ci.appveyor.com/project/jeking3/interval-o0u28/branch/master) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/17151/badge.svg)](https://scan.coverity.com/projects/boostorg-interval) | [![codecov](https://codecov.io/gh/boostorg/interval/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/interval/branch/master) | [![Deps](https://img.shields.io/badge/deps-master-brightgreen.svg)](https://pdimov.github.io/boostdep-report/master/interval.html) | [![Documentation](https://img.shields.io/badge/docs-master-brightgreen.svg)](http://www.boost.org/doc/libs/master/doc/html/interval.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-master-brightgreen.svg)](http://www.boost.org/development/tests/master/developer/interval.html)
[`develop`](https://github.com/boostorg/interval/tree/develop) | [![Build Status](https://travis-ci.org/boostorg/interval.svg?branch=develop)](https://travis-ci.org/boostorg/interval) | [![Build status](https://ci.appveyor.com/api/projects/status/wx6gsonby36or5m2/branch/develop?svg=true)](https://ci.appveyor.com/project/jeking3/interval-o0u28/branch/develop) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/17151/badge.svg)](https://scan.coverity.com/projects/boostorg-interval) | [![codecov](https://codecov.io/gh/boostorg/interval/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/interval/branch/develop) | [![Deps](https://img.shields.io/badge/deps-develop-brightgreen.svg)](https://pdimov.github.io/boostdep-report/develop/interval.html) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](http://www.boost.org/doc/libs/develop/doc/html/interval.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](http://www.boost.org/development/tests/develop/developer/interval.html)
### Directories
| Name | Purpose |
| ----------- | ------------------------------ |
| `doc` | documentation |
| `examples` | use case examples |
| `include` | headers |
| `test` | unit tests |
### More inintervalion
* [Ask questions](http://stackoverflow.com/questions/ask?tags=c%2B%2B,boost,boost-interval): Be sure to read the documentation first as Boost.Interval has specific requirements.
* [Report bugs](https://github.com/boostorg/interval/issues): Be sure to mention Boost version, platform and compiler you're using. A small compilable code sample to reproduce the problem is always good as well.
* [Submit Pull Requests](https://github.com/boostorg/interval/pulls) against the **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). Be sure to include tests proving your changes work properly.
* Discussions about the library are held on the [Boost developers mailing list](http://www.boost.org/community/groups.html#main). Be sure to read the [discussion policy](http://www.boost.org/community/policy.html) before posting and add the `[interval]` tag at the beginning of the subject line.
+252
View File
@@ -0,0 +1,252 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
<title>Checking policies</title>
</head>
<body>
<h1>Checking policies</h1>
<p>A checking policy controls how the <code>interval</code> class will deal
with special cases like: empty intervals, infinite numbers, invalid
values.</p>
<p>For example, let's consider <code>operator+(interval, T)</code>. The
second argument could be an invalid value (for a floating-point number, it
is a NaN). What to do in such a case? First, we could say that the second
argument can never be an invalid number. Second, we could also say such a
situation can arise but is forbidden. Third, we could allow such values and
generate an empty interval when encountered. And there is many other
possibilities.</p>
<p>It is the reason why such a policy is used: there is a lot of
interesting behaviors and it would be sad to arbitrarily select one of
these.</p>
<h2>Requirements</h2>
<p>The checking class should satisfy the following requirement (in the form
of an interface):</p>
<pre>
/* requirements for checking policy */
struct checking
{
static T pos_inf();
static T neg_inf();
static T nan();
static bool is_nan(const T&amp;);
static T empty_lower();
static T empty_upper();
static bool is_empty(const T&amp;, const T&amp;);
};
</pre>
<p>The first two functions, <code>pos_inf</code> and <code>neg_inf</code>,
are invoked each time the library has to create the infinite bound of an
interval. For example, <code>interval::whole</code> computes
<code>interval(checking::neg_inf(), checking::pos_inf())</code>. If
infinite values are allowed and
<code>std::numeric_limits&lt;T&gt;::infinity()</code> returns a correct
value, such a value can be used.</p>
<p>Next comes <code>nan</code>. This function is used each time a function
need to return a value of type <code>T</code> but is unable to compute it.
It only happens when one of the arguments of the function is invalid. For
example, if you ask what the median value of an empty interval is,
<code>nan</code> will be used. But please remember: <code>lower</code> and
<code>upper</code> directly return the value stocked in the interval; so,
if the interval is empty, <code>lower</code> will not answer
<code>by</code> a call to <code>checking::nan</code> (but will return the
same value than <code>checking::empty_lower</code> could return).</p>
<p><code>empty_lower</code> and <code>empty_upper</code> respectively
return the lower and upper bound of the empty interval. There is no
requirements for <code>empty_lower</code> and <code>empty_upper</code> to
return the same value than <code>checking::nan</code>. For example, if the
type <code>T</code> does not have any invalid value, the
<code>empty_</code> functions can return the [1;0] interval.</p>
<p><code>is_nan</code> is used to test if a value of type <code>T</code> is
invalid or not. <code>is_empty</code> tests if the interval formed by the
two arguments is empty or not. Such tests will generally be at the
beginning of each function which involves an argument of type
<code>T</code>. If one of the inputs is declared invalid, the the function
will try to produce an invalid value or an input interval.</p>
<h2>Synopsis</h2>
<pre>
namespace boost {
namespace numeric {
namespace interval_lib {
template&lt;class T&gt;
struct checking_base;
template&lt;class T, class Checking = checking_base&lt;T&gt;, class Exception = exception_create_empty&lt;T&gt; &gt;
struct checking_no_empty;
template&lt;class T, class Checking = checking_base&lt;T&gt; &gt;
struct checking_no_nan;
template&lt;class T, class Checking = checking_base&lt;T&gt;, class Exception = exception_invalid_number&lt;T&gt; &gt;
struct checking_catch_nan;
template&lt;class T&gt; struct exception_create_empty { T operator()(); };
template&lt;class T&gt; struct exception_invalid_number { void operator()(); };
} // namespace numeric
} // namespace interval_lib
} // namespace boost
</pre>
<h2>Predefined classes</h2>
<p>In order to simplify the customization of the policy, some templates are
already defined in the library.</p>
<p>First of all, there is <code>checking_base</code>. Thanks to the
information provided by <code>std::numeric_limits&lt;T&gt;</code>, this
class is able to generate a base for the policy. If <code>T</code> has
quiet NaNs (as said by <code>numeric_limits::has_quiet_NaN</code>), then
the value is used for <code>nan</code>, <code>empty_lower</code>,
<code>empty_upper</code>; and a basic test is used for <code>is_nan</code>
(it is <code>x!=x</code>). If <code>T</code> does not have quiet NaNs, then
<code>nan</code> is an <code>assert(false)</code>, the empty interval is
[1,0], and <code>is_nan</code> always return <code>false</code>. As for
<code>nan</code>, <code>pos_inf</code> returns
<code>numeric_limits::infinity()</code> if possible, or is an
<code>assert(false</code>) otherwise. <code>neg_inf</code> returns the
opposite. Finally, <code>is_empty(T l,T u)</code> is always defined by
<code>!(l&lt;=u)</code>.</p>
<p>Next comes <code>checking_no_empty</code>. Using it means that each time
an empty interval should be produced (by <code>empty_lower</code> and
<code>empty_upper</code>), the function object given by the
<code>Exception</code> argument of the template is invoked and the value it
returns is propagated. So, if <code>Exception</code> is appropriately
defined (for example it could throw an exception, hence the name of the
argument), you can be sure no empty interval will ever be created. So
<code>is_empty</code> will always return <code>false</code> (since there is
no need to test for an empty interval). And as explained before, in that
case we can also replace <code>nan</code> by an <code>assert(false)</code>;
you will be sure no invalid number will ever be produced. If this template
is not used, it implicitly means that all the functions can produce empty
intervals and they correctly deal with empty interval arguments.</p>
<p>Finally there are <code>checking_no_nan</code> and
<code>checking_catch_nan</code>. The first one expresses the functions of
the library will never get an invalid number as argument. So
<code>is_nan</code> will only return <code>false</code>. The other one
means the arguments can be an invalid number but in that case,
<code>is_nan</code> will call the function object <code>Exception</code>
and return <code>false</code>. Indeed, this template means invalid numbers
should never make their way through to the body of the function. If none of
this two templates is used, it implicitly means that all the functions can
get invalid number arguments and they will correctly deal with them.</p>
<p><code>exception_create_empty</code> throws
<code>std::runtime_error</code> with the message <code>"boost::interval:
empty interval created"</code> and <code>exception_invalid_number</code>
throws <code>std::invalid_argument</code> with the message
<code>"boost::interval: invalid number"</code>.</p>
<h2>Customizing your own checking policy</h2>
<p>In order to define a suitable policy, you need to correctly say what you
expect from your interval class. First of all, are you interested in
getting empty intervals at the end of a calculus? If you do not want to
obtain empty intervals, <code>empty_lower</code> and
<code>empty_upper</code> have to fail when invoked (they can throw an
exception, set a flag, etc). However, if no function is able to produce an
empty interval, it is no more necessary to do the test, so
<code>is_empty</code> may always return <code>false</code>. In this case, a
good compiler will do a lot of optimizations.</p>
<p>You could also be interested in getting empty intervals at the end of
the calculus. For example, if you need to transform an array of unsure
values (or intervals) in a new array of intervals, you may not want to stop
the conversion at the first encountered problem. So
<code>empty_lower</code> and <code>empty_upper</code> need to return
suitable values in order to define an empty interval (you can use an upper
bound which is not greater or equal than the lower bound for example); and
<code>is_empty</code> must be able to distinguish empty intervals from the
valid intervals.</p>
<p>Another important question is: is it possible that some base numbers
(objects of type <code>T</code>) are invalid? And if it is possible, are
they allowed or not ? If it is not possible, no test is necessary;
<code>is_nan</code> may always return <code>false</code>. In this case too,
a good compiler will do a lot of optimizations. If function arguments can
hold invalid numbers, two cases must be considered according to whether
they are allowed or not. If they are allowed, <code>is_nan</code> just has
to test if they are invalid or not. If they are forbidden,
<code>is_nan</code> should fail (exception, assert, etc.) when invoked on
an invalid argument and return <code>false</code> otherwise. The value
returned by <code>nan</code> does not have any interest since the interval
functions are guaranteed not to produce invalid interval bounds unless the
user passes invalid numbers to the constructors. So you can put an assert
inside if you do not trust the library. :-)</p>
<p>And finally, you need to decide what to do with <code>nan</code> if it
has not already been decided at the beginning, and with
<code>pos_inf</code> and <code>neg_inf</code>. These functions should
return a value or start an exceptional behavior (especially if the base
type does not have corresponding values).</p>
<h2>Some examples</h2>
<ul>
<li>If you need a checking policy that allows the library to correctly
manipulate data, even if they contain invalid numbers and empty
intervals, then <code>checking_base&lt;T&gt;</code> is a
possibility.</li>
<li>If you do not want empty intervals to be created and are not sure all
the numbers are valid, then <code>checking_catch_nan&lt;T,
checking_no_empty&lt;T&gt; &gt;</code> can help you.</li>
<li>If all the numbers will be valid and if no empty interval is supposed
to be created (or if you do not want them to be created), then you can
use <code>checking_no_nan&lt;T, checking_no_empty&lt;T&gt; &gt;</code>.
Please note that if <code>T</code> does not have a way to represent
invalid numbers, then this policy will behave the same way as
<code>checking_no_empty&lt;T&gt;</code>. This is the default policy and
it is also called <code>interval_lib::checking_strict</code>.</li>
<li>If all numerical data are valid but the algorithm can produce and
manipulate empty intervals, then <code>checking_no_nan&lt;T&gt;</code>
should be used.</li>
<li>Similarly, if invalid data have to be signaled and the algorithm can
manipulate empty intervals, the <code>checking_catch_nan&lt;T&gt;</code>
is a solution.</li>
<li>If you do not mind having undefined results when an empty interval or
an interval number is produced, your best bet is to create your own
policy by overloading <code>checking_base</code> and modifying
<code>is_nan</code> et <code>is_empty</code> in order for them to always
return <code>false</code>. It is probably the fastest checking policy
available; however, it suffers from its deficient security.</li>
</ul>
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
<p><i>Copyright &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;nnimann, Polytechnic University<br>
Copyright &copy; 2003-2004 Guillaume Melquiond</i></p>
<p><i>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
or copy at <a href=
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
</body>
</html>
+204
View File
@@ -0,0 +1,204 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
<title>Comparisons</title>
</head>
<body>
<h1>Comparisons</h1>
<p>As was said before, the definition of the comparison operators induces a
slight problem. There are many ways to define them, depending of the return
type or the expected order. It is the reason why the meaning of the
operators is not fixed once and for all.</p>
<p>The way the operators are defined could have been influenced by a
policy, as it is already the case for the rounding and the checking.
However, comparisons are more an external property of the the class rather
than an internal one. They are meant to be locally modified, independantly
of the type of the intervals.</p>
<p>The operators <code>&lt;</code>, <code>&lt;=</code>, <code>&gt;</code>,
<code>&gt;=</code>, <code>==</code>, <code>!=</code> are defined each time;
and like the arithmetic operators they can take an argument of the base
type. However, due to technical limitations, this base type can only be the
second argument; so the operators are unfortunately not fully symmetric.
The return type is not always <code>bool</code>, since some interesting
results can be achieved by using a tri-state return type. So here is the
common signatures of the operators:</p>
<pre>
template&lt;class T, class Policies1, class Policies2&gt;
return_type operator== (const interval&lt;T, Policies1&gt;&amp;, const interval&lt;T, Policies2&gt;&amp;);
template&lt;class T, class Policies&gt;
return_type operator== (const interval&lt;T, Policies&gt;&amp;, const T&amp;);
</pre>
<h2>vided comparisons</h2>
<h3>Default comparison</h3>
<p>If nothing is specified, the meaning of the comparison operators are an
extension of the operator on the base type. More precisely, if one of the
argument is invalid or empty, an exception is thrown. If the arguments are
valid, the following rules are applied to determine the result of
[<i>a</i>,<i>b</i>] <code>op</code> [<i>c</i>,<i>d</i>] (just consider
<i>c</i> <code>==</code> <i>d</i> if the second argument is of type
<code>T</code>):</p>
<ul>
<li>if &forall; <i>x</i> &isin; [<i>a</i>,<i>b</i>] &forall; <i>y</i>
&isin; [<i>c</i>,<i>d</i>] <code>(</code><i>x</i> <code>op</code>
y<code>)</code>, then <code>true</code></li>
<li>if &forall; <i>x</i> &isin; [<i>a</i>,<i>b</i>] &forall; <i>y</i>
&isin; [<i>c</i>,<i>d</i>] <code>!(</code><i>x</i> <code>op</code>
y<code>)</code>, then <code>false</code></li>
<li>otherwise throw an exception.</li>
</ul>
<p>This comparison allows to replace base types by interval types without
changing the meaning of a program. Indeed, if no exception is thrown, the
result is the same as before; and if an exception is thrown, the previous
comparison was unsure and should have been rewritten.</p>
<h3>Other comparisons</h3>
<p>The other comparisons are selected by using a namespace. These
namespaces are located under
<code>boost::numeric::interval_lib::compare</code> and are invoked by:</p>
<pre>
using namespace boost::numeric::interval_lib::compare::the_comparison_to_select;
</pre>
<p>After this line, the default meaning of the operators will have been
replaced by the meaning located in the namespace. Please note that because
of C++ lookup rules, it is not possible to use two namespaces one after
another and they must be used in different block hierarchies. Otherwise the
compiler will complain about ambiguous operators. To summarize:</p>
<pre>
// example 1: BAD
using namespace compare1;
...
using namespace compare2;
...
// example 2: GOOD
{ using namespace compare1;
... }
{ using namespace compare2;
... }
// example 3: BAD
using namespace compare1;
...
{ using namespace compare2;
... }
</pre>
<p>Now comes the list of the provided comparisons. They all are located in
their respective header files under
<code>&lt;boost/numeric/interval/compare/...&gt;</code>. And as for the
default comparison, the operators will generally complain by throwing an
exception if feed by invalid values.</p>
<ul>
<li><code>certain</code>: this comparison is equivalent to the default
scheme with the exceptional case mapped to <code>false</code>. So these
operators answer <code>true</code> only when the comparison is verified
for all pairs of elements.</li>
<li><code>possible</code>: this time, the exceptional case is mapped to
<code>true</code>. The operators answer <code>true</code> as soon as the
comparison is verified for a pair of elements.<br></li>
<li><code>lexicographic</code>: the lexicographic order (the lower bounds
are first compared, and if it is not enough to know the result, the upper
bounds are then compared). This order does not have a meaning in interval
arithmetic. However, since it is the natural total order on pair of
(totally ordered) numbers, it may be handy in some cases.</li>
<li><code>set</code>: the set inclusion partial order. This time, an
empty interval is not considered to be invalid (but an invalid number is
still invalid). <code>&lt;=</code> and <code>&lt;</code> are the subset
and proper subset relations; and <code>&gt;=</code> and <code>&gt;</code>
are the superset and proper superset relations.</li>
<li><code>tribool</code>: this comparison relies on the Boost tristate
boolean library and changes the default operators so that an explicit
indeterminate value is returned in the third case instead of throwing an
exception.</li>
</ul>
<h3>Exception</h3>
<pre>
namespace boost {
namespace numeric {
namespace interval_lib {
class comparison_error: std::runtime_error; // "boost::interval: uncertain comparison"
} // namespace interval_lib
} // namespace numeric
} // namespace boost
</pre>
<h2>Explicit comparison functions</h2>
<p>In some situation, you may want to perform direct comparisons on the
bounds and avoid the indeterminate case that appears with default
operators. Some functions are provided for this purpose. They expect their
arguments to be valid and return a result after only one comparison. Their
names are composed by <code>cer</code> (for "certain", if the default
comparison is true, the result is true) or <code>pos</code> (for
"possible", if the default comparison is false, the result is false)
followed by <code>lt</code>, <code>le</code>, <code>gt</code>,
<code>ge</code>, <code>eq</code> or <code>ne</code>. They are located in
<code>&lt;boost/numeric/interval/compare/explicit.hpp&gt;</code>. Each of
these functions takes two parameters and returns a boolean; the parameters
are expected to be valid, undefined behavior may result otherwise. For
example, the definition of the "certainly less than" comparison is:</p>
<pre>
namespace boost {
namespace numeric {
namespace interval_lib {
template&lt;class T, class Policies1, class Policies2&gt;
bool cerlt(const interval&lt;T, Policies1&gt;&amp; x, const interval&lt;T, Policies2&gt;&amp; y);
template&lt;class T, class Policies&gt;
bool cerlt(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template&lt;class T, class Policies&gt;
bool cerlt(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
} // namespace interval_lib
} // namespace numeric
} // namespace boost
</pre>
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
<p><i>Copyright &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;nnimann, Polytechnic University<br>
Copyright &copy; 2003 Guillaume Melquiond</i></p>
<p><i>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
or copy at <a href=
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
</body>
</html>
+211
View File
@@ -0,0 +1,211 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
<title>Tests and Examples</title>
</head>
<body lang="en">
<h1>Tests and Examples</h1>
<h2>A first example</h2>
<p>This example shows how to design a function which takes a polynomial and
a value and returns the sign of this polynomial at this point. This
function is a filter: if the answer is not guaranteed, the functions says
so. The reason of using a filter rather than a simple evaluation function
is: computations with floating-point numbers will incur approximations and
it can be enough to change the sign of the polynomial. So, in order to
validate the result, the function will use interval arithmetic.</p>
<p>The first step is the inclusion of the appropriate headers. Because the
function will handle floating-point bounds, the easiest solution is:</p>
<pre>
#include &lt;boost/numeric/interval.hpp&gt;
</pre>
<p>Now, let's begin the function. The polynomial is given by the array of
its coefficients and its size (strictly greater to its degree). In order to
simplify the code, two namespaces of the library are included.</p>
<pre>
int sign_polynomial(double x, double P[], int sz) {
using namespace boost::numeric;
using namespace interval_lib;
</pre>
<p>Then we can define the interval type. Since no special behavior is
required, the default policies are enough:</p>
<pre>
typedef interval&lt;double&gt; I;
</pre>
<p>For the evaluation, let's just use the Horner scheme with interval
arithmetic. The library overloads all the arithmetic operators and provides
mixed operations, so the only difference between the code with and without
interval arithmetic lies in the type of the iterated value
<code>y</code>:</p>
<pre>
I y = P[sz - 1];
for(int i = sz - 2; i &gt;= 0; i--)
y = y * x + P[i];
</pre>
<p>The last step is the computation of the sign of <code>y</code>. It is
done by choosing an appropriate comparison scheme and then doing the
comparison with the usual operators:</p>
<pre>
using namespace compare::certain;
if (y &gt; 0.) return 1;
if (y &lt; 0.) return -1;
return 0;
}
</pre>
<p>The answer <code>0</code> does not mean the polynomial is zero at this
point. It only means the answer is not known since <code>y</code> contains
zero and thus does not have a precise sign.</p>
<p>Now we have the expected function. However, due to the poor
implementations of floating-point rounding in most of the processors, it
can be useful to say to optimize the code; or rather, to let the library
optimize it. The main condition for this optimization is that the interval
code should not be mixed with floating-point code. In this example, it is
the case, since all the operations done in the functions involve the
library. So the code can be rewritten:</p>
<pre>
int sign_polynomial(double x, double P[], int sz) {
using namespace boost::numeric;
using namespace interval_lib;
typedef interval&lt;double&gt; I_aux;
I_aux::traits_type::rounding rnd;
typedef unprotect&lt;I_aux&gt;::type I;
I y = P[sz - 1];
for(int i = sz - 2; i &gt;= 0; i--)
y = y * x + P[i];
using namespace compare::certain;
if (y &gt; 0.) return 1;
if (y &lt; 0.) return -1;
return 0;
}
</pre>
<p>The difference between this code and the previous is the use of another
interval type. This new type <code>I</code> indicates to the library that
all the computations can be done without caring for the rounding mode. And
because of that, it is up to the function to care about it: a rounding
object need to be alive whenever the optimized type is used.</p>
<h2>Other tests and examples</h2>
<p>In <code>libs/numeric/interval/test/</code> and
<code>libs/numeric/interval/examples/</code> are some test and example
programs.. The examples illustrate a few uses of intervals. For a general
description and considerations on using this library, and some potential
domains of application, please read this <a href=
"guide.htm">mini-guide</a>.</p>
<h3>Tests</h3>
<p>The test programs are as follows. Please note that they require the use
of the Boost.test library and can be automatically tested by using
<code>bjam</code> (except for interval_test.cpp).</p>
<p><b>add.cpp</b> tests if the additive and subtractive operators and the
respective _std and _opp rounding functions are correctly implemented. It
is done by using symbolic expressions as a base type.</p>
<p><b>cmp.cpp</b>, <b>cmp_lex.cpp</b>, <b>cmp_set.cpp</b>, and
<b>cmp_tribool.cpp</b> test if the operators <code>&lt;</code>
<code>&gt;</code> <code>&lt;=</code> <code>&gt;=</code> <code>==</code>
<code>!=</code> behave correctly for the default, lexicographic, set, and
tristate comparisons. <b>cmp_exp.cpp</b> tests the explicit comparison
functions <code>cer..</code> and <code>pos..</code> behave correctly.
<b>cmp_exn.cpp</b> tests if the various policies correctly detect
exceptional cases. All these tests use some simple intervals ([1,2] and
[3,4], [1,3] and [2,4], [1,2] and [2,3], etc).</p>
<p><b>det.cpp</b> tests if the <code>_std</code> and <code>_opp</code>
versions in protected and unprotected mode produce the same result when
Gauss scheme is used on an unstable matrix (in order to exercise rounding).
The tests are done for <code>interval&lt;float&gt;</code> and
<code>interval&lt;double&gt;</code>.</p>
<p><b>fmod.cpp</b> defines a minimalistic version of
<code>interval&lt;int&gt;</code> and uses it in order to test
<code>fmod</code> on some specific interval values.</p>
<p><b>mul.cpp</b> exercises the multiplication, the finite division, the
square and the square root with some integer intervals leading to exact
results.</p>
<p><b>pi.cpp</b> tests if the interval value of &pi; (for <code>int</code>,
<code>float</code> and <code>double</code> base types) contains the number
&pi; (defined with 21 decimal digits) and if it is a subset of
[&pi;&plusmn;1ulp] (in order to ensure some precision).</p>
<p><b>pow.cpp</b> tests if the <code>pow</code> function behaves correctly
on some simple test cases.</p>
<p><b>test_float.cpp</b> exercises the arithmetic operations of the library
for floating point base types.</p>
<p><b>interval_test.cpp</b> tests if the interval library respects the
inclusion property of interval arithmetic by computing some functions and
operations for both <code>double</code> and
<code>interval&lt;double&gt;</code>.</p>
<h2>Examples</h2>
<p><b>filter.cpp</b> contains filters for computational geometry able to
find the sign of a determinant. This example is inspired by the article
<em>Interval arithmetic yields efficient dynamic filters for computational
geometry</em> by Br&ouml;nnimann, Burnikel and Pion, 2001.</p>
<p><b>findroot_demo.cpp</b> finds zeros of some functions by using
dichotomy and even produces gnuplot data for one of them. The processor has
to correctly handle elementary functions for this example to properly
work.</p>
<p><b>horner.cpp</b> is a really basic example of unprotecting the interval
operations for a whole function (which computes the value of a polynomial
by using Horner scheme).</p>
<p><b>io.cpp</b> shows some stream input and output operators for intervals
.The wide variety of possibilities explains why the library do not
implement i/o operators and they are left to the user.</p>
<p><b>newton-raphson.cpp</b> is an implementation of a specialized version
of Newton-Raphson algorithm for finding the zeros of a function knowing its
derivative. It exercises unprotecting, full division, some set operations
and empty intervals.</p>
<p><b>transc.cpp</b> implements the transcendental part of the rounding
policy for <code>double</code> by using an external library (the MPFR
subset of GMP in this case).</p>
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
<p><i>Copyright &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;nnimann, Polytechnic University<br>
Copyright &copy; 2003 Guillaume Melquiond</i></p>
<p><i>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
or copy at <a href=
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
</body>
</html>
+122
View File
@@ -0,0 +1,122 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
<title>Choosing Your Own Interval Type</title>
</head>
<body lang="en">
<h1>Choosing Your Own Interval Type</h1>
<p>First of all, you need to select your base type. In order to obtain an
useful interval type, the numbers should respect some requirements. Please
refer to <a href="numbers.htm">this page</a> in order to see them. When
your base type is robust enough, you can go to the next step: the choice of
the policies.</p>
<p>As you should already know if you did not come to this page by accident,
the <code>interval</code> class expect a policies argument describing the
<a href="rounding.htm">rounding</a> and <a href="checking.htm">checking</a>
policies. The first thing to do is to verify if the default policies are or
are not adapted to your case. If your base type is not <code>float</code>,
<code>double</code>, or <code>long double</code>, the default rounding
policy is probably not adapted. However, by specializing
<code>interval_lib::rounded_math</code> to your base type, the default
rounding policy will be suitable.</p>
<p>The default policies define an interval type that performs precise
computations (for <code>float</code>, <code>double</code>, <code>long
double</code>), detects invalid numbers and throws exception each times an
empty interval is created. This is a brief description and you should refer
to the corresponding sections for a more precise description of the default
policies. Unless you need some special behavior, this default type is
usable in a lot of situations.</p>
<p>After having completely defined the interval type (and its policies),
the only thing left to do is to verify that the constants are defined and
<code>std::numeric_limits</code> is correct (if needed). Now you can use
your brand new interval type.</p>
<h2>Some Examples</h2>
<h3>Solving systems</h3>
<p>If you use the interval library in order to solve equation and
inequation systems by bisection, something like
<code>boost::interval&lt;double&gt;</code> is probably what you need. The
computations are precise, and they may be fast if enclosed in a protected
rounding mode block (see the <a href="rounding.htm#perf">performance</a>
section). The comparison are "certain"; it is probably the most used type
of comparison, and the other comparisons are still accessible by the
explicit comparison functions. The checking forbid empty interval; they are
not needed since there would be an empty interval at end of the computation
if an empty interval is created during the computation, and no root would
be inside. The checking also forbid invalid numbers (NaN for floating-point
numbers). It can be a minor performance hit if you only use exact
floating-point constants (which are clearly not NaNs); however, if
performance really does matter, you will probably use a good compiler which
knows how to inline functions and all these annoying little tests will
magically disappear (if not, it is time to upgrade your compiler).</p>
<h3>Manipulating wide intervals</h3>
<p>You may want to use the library on intervals with imprecise bounds or on
inexact numbers. In particular, it may be an existing algorithm that you
want to rewrite and simplify by using the library. In that case, you are
not really interested by the inclusion property; you are only interested by
the computation algorithms the library provides. So you do not need to use
any rounding; the checking also may not be useful. Use an "exact
computation" rounding (you are allowed to think the name strangely applies
to the situation) and a checking that never tests for any invalid numbers
or empty intervals. By doing that, you will obtain library functions
reduced to their minimum (an addition of two intervals will only be two
additions of numbers).</p>
<h3>Computing ranges</h3>
<p>The inputs of your program may be empty intervals or invalid values (for
example, a database can allow undefined values in some field) and the core
of your program could also do some non-arithmetic computations that do not
always propagate empty intervals. For example, in the library, the
<code>hull</code> function can happily receive an empty interval but not
generate an empty interval if the other input is valid. The
<code>intersect</code> function is also able to produce empty intervals if
the intervals do not overlap. In that case, it is not really interesting if
an exception is thrown each time an empty interval is produced or an
invalid value is used; it would be better to generate and propagate empty
intervals. So you need to change the checking policy to something like
<code>interval_lib::checking_base&lt;T&gt;</code>.</p>
<h3>Switching interval types</h3>
<p>This example does not deal with a full case, but with a situation that
can occur often. Sometimes, it can be useful to change the policies of an
interval by converting it to another type. For example, this happens when
you use an unprotected version of the interval type in order to speed up
the computations; it is a change of the rounding policy. It also happens
when you want to temporarily allow empty intervals to be created; it is a
change of the checking policy. These changes should not be prohibited: they
can greatly enhance a program (lisibility, interest, performance).</p>
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
<p><i>Copyright &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;nnimann, Polytechnic University</i></p>
<p><i>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
or copy at <a href=
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
</body>
</html>
+218
View File
@@ -0,0 +1,218 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
<title>Headers Inclusion</title>
</head>
<body lang="en">
<h1>Headers Inclusion</h1>
<p>The easiest way to access to the library is by including the main
header:</p>
<pre>
#include &lt;boost/numeric/interval.hpp&gt;
</pre>
<p>This header will include almost all the other headers (except the ones
listed as extensions). However, you may not want to access all the
functionalities of the library. So this page stands as a reminder for the
whole structure of the library.
<code>&lt;boost/numeric/interval.hpp&gt;</code> is the only header to be
located directly under <code>boost/numeric</code>; all the other headers
are located in the subdirectory <code>boost/numeric/interval</code>. And
each time this documentation will refer to
<code>interval/something.hpp</code>, it is
<code>&lt;boost/numeric/interval/something.hpp&gt;</code>.</p>
<p>Please also note that all the following headers are independent and can
easily be pre-compiled if necessary (for compilers which support
pre-compiled headers of course).</p>
<h2>Function definitions</h2>
<p>The following headers contain the definition of the
<code>interval</code> class and all the friendly functions and
operators.</p>
<h3><code>interval/interval.hpp</code></h3>
<p>This header contains the definition and the declaration of the
<code>interval</code> class. However, this class is templated and the
default template parameters are not available by this header. In
particular, this header does not provide the default specialization of the
<code>interval</code> class for the floating-point types
(<code>interval&lt;float&gt;</code>, <code>interval&lt;double&gt;</code>
and <code>interval&lt;long double&gt;</code>). So, unless you use your own
policies, this header is not really useful on its own.</p>
<h3><code>interval/utility.hpp</code></h3>
<p>In this header are all the functions that do not expect any arithmetic
property from the base number type. It only expects the bounds to be
ordered; but it should not surprise you since it is a requirement of the
whole library. You will find in this header the definitions of access and
related functions: <code>lower</code>, <code>upper</code>,
<code>checked_lower</code>, <code>checked_upper</code>,
<code>median</code>, <code>width</code>, <code>widen</code>. There are also
the set-like functions: <code>in,</code> <code>zero_in</code>,
<code>empty</code>, <code>subset</code>, <code>proper_subset</code>,
<code>overlap</code>, <code>singleton</code>, <code>equal</code>,
<code>intersect</code>, <code>hull</code>, <code>bisect</code>. Finally,
<code>abs</code>, <code>min</code>, and <code>max</code> are defined.</p>
<h3><code>interval/arith.hpp</code></h3>
<p>Here are the binary operators <code>+</code>, <code>-</code>,
<code>*</code>, <code>/</code> and the unary operator <code>-</code>.</p>
<h3><code>interval/arith2.hpp</code></h3>
<p>This header defines <code>fmod</code>, <code>square</code>,
<code>sqrt</code>, <code>pow</code>, and <code>root</code>.</p>
<h3><code>interval/arith3.hpp</code></h3>
<p>The third arithmetic header: it provides the functions <code>add</code>,
<code>sub</code>, <code>mul</code>, and <code>div</code>. The type of their
arguments is the base number type.</p>
<h3><code>interval/transc.hpp</code></h3>
<p>It is the last of the headers with mathematical functions; it provides
the following functions: <code>cos</code>, <code>sin</code>,
<code>tan</code>, <code>acos</code>, <code>asin</code>, <code>atan</code>,
<code>cosh</code>, <code>sinh</code>, <code>tanh</code>,
<code>acosh</code>, <code>asinh</code>, <code>atanh</code>,
<code>exp</code>, and <code>log</code>.</p>
<h2>Policies</h2>
<p>The following headers define some policies. They may be needed if you
use the default policies.</p>
<h3><code>interval/rounded_arith.hpp</code></h3>
<p>This header defines the three provided rounding policies for the
arithmetic functions: <code>rounded_arith_std</code>,
<code>rounded_arith_opp</code>, <code>rounded_arith_exact</code>.</p>
<h3><code>interval/rounded_transc.hpp</code></h3>
<p>This header defines the three provided rounding policies for the
transcendental functions: <code>rounded_transc_std</code>,
<code>rounded_transc_opp</code>, <code>rounded_transc_exact</code>. It is
separated from <code>rounded_arith.hpp</code> since the transcendental part
of the rounding policy is probably less useful than the arithmetic
part.</p>
<h3><code>interval/hw_rounding.hpp</code></h3>
<p>Here are full rounding policies for the basic floating-point types. The
policies are processor-dependent; and to allow the user code to be
portable, they only define the common subset of the hardware available
functions, which are the arithmetic functions of the rounding policy.</p>
<h3><code>interval/checking.hpp</code></h3>
<p>This header provides the predefined checking policies:
<code>checking_base</code>, <code>checking_no_empty</code>,
<code>checking_no_nan</code>, <code>checking_catch_nan</code>,
<code>checking_strict</code>.</p>
<h3><code>interval/policies.hpp</code></h3>
<p>Here are defined the helpers for manipulating policies. It contains
<code>policies</code> (and so is needed for using default policies),
<code>change_rounding</code>, <code>change_checking</code>,
<code>unprotect</code>, etc.</p>
<h2>Comparisons</h2>
<h3><code>interval/compare.hpp</code></h3>
<p>This header includes all the following headers. They provide some
predefined comparison namespaces.</p>
<h3><code>interval/compare/certain.hpp</code></h3>
<p>Here is <code>compare::certain</code>.</p>
<h3><code>interval/compare/possible.hpp</code></h3>
<p>And here is its friend <code>compare::possible</code>.</p>
<h3><code>interval/compare/explicit.hpp</code></h3>
<p>The explicit comparison functions <code>cerlt</code>,
<code>posge</code>, etc are defined in this header.</p>
<h3><code>interval/compare/lexicographic.hpp</code></h3>
<p>This header provides <code>compare::lexicographic</code>.</p>
<h3><code>interval/compare/set.hpp</code></h3>
<p>This header provides <code>compare::set</code>.</p>
<h2>Extensions</h2>
<p>The following headers are not included by <code>interval.hpp</code> and
will usually provide not always desirable capabilities.</p>
<h3><code>interval/io.hpp</code></h3>
<p>Here are defined basic stream operators <code>&lt;&lt;</code> and
<code>&gt;&gt;</code>. They should only be used as a first approach and
later be replaced by a customized version.</p>
<h3><code>interval/limits.hpp</code></h3>
<p>A specialization of <code>std::numeric_limits</code> adapted to the
interval type.</p>
<h3><code>interval/compare/tribool.hpp</code></h3>
<p>This header provides a comparison namespace
<code>compare::tribool</code> especially adapted to a tristate boolean.</p>
<h3><code>interval/ext/integer.hpp</code></h3>
<p>This header provides mixed operations between intervals and integers. It
is done by converting the integer to the base number type. Because this
comparison is not always correct (for a big <code>int</code> may not be
exactly convertible to <code>float</code>), this header is not
automatically included and the user should ensure that this behavior is
compatible with what she wants to do (if it is only to multiply some
intervals by 2, it probably is a good thing to include this header).</p>
<h3><code>interval/ext/x86_fast_rounding_control.hpp</code></h3>
<p>This header defines a new rounding policy allowing to workaround the
precision problem of the x86 processors (and so speeding up the
computations). However, it only is a partial solution and it shouldn't be
used when there is a possibility of underflow or overflow.</p>
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
<p><i>Copyright &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;nnimann, Polytechnic University<br>
Copyright &copy; 2003-2006 Guillaume Melquiond, ENS Lyon</i></p>
<p><i>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
or copy at <a href=
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
</body>
</html>
+13
View File
@@ -0,0 +1,13 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=interval.htm">
</head>
<body>
Automatic redirection failed, please go to
<a href="interval.htm">interval.htm</a>.&nbsp;<hr>
<p>© Copyright Beman Dawes, 2001</p>
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
</body>
</html>
File diff suppressed because it is too large Load Diff
+176
View File
@@ -0,0 +1,176 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
<title>Numbers Requirements</title>
</head>
<body lang="en">
<h1>Numbers Requirements</h1>
<p>What we call "number" is the base type of the <code>interval</code>
class. The interval library expect a lot of properties from this base type
in order to respect the inclusion property. All these properties are
already detailed in the other sections of this documentation; but we will
try to summarize them here.</p>
<h3>Ordering</h3>
<p>The numbers need to be supplied with an ordering. This ordering
expresses itself by the operators <code>&lt; &lt;= =&gt; &gt; == !=</code>.
It must be a total order (reflexivity, antisymmetry, transitivity, and each
pair of numbers is ordered). So <code>complex&lt;T&gt;</code> will not be a
good candidate for the base type; if you need the inclusion property of
interval property, you should use <code>complex&lt; interval&lt;T&gt;
&gt;</code> in place of <code>interval&lt; complex&lt;T&gt; &gt;</code>
(but unfortunately, <code>complex</code> only provides specialization).</p>
<p>Please note that invalid numbers are not concerned by the order; it can
even be conceptually better if a comparison with these invalid numbers is
always <code>false</code> (except for <code>!=</code>). If your checking
policy uses <code>interval_lib::checking_base</code> and your base type
contains invalid numbers, then this property is needed:
<code>nan!=nan</code> (here <code>nan</code> is an invalid number). If this
property is not present, then you should not use <code>checking_base</code>
directly.</p>
<p>Interval arithmetic involves a lot of comparison to zero. By default,
they are done by comparing the numbers to
<code>static_cast&lt;T&gt;(0)</code>. However, if the format of the numbers
allows some faster comparisons when dealing with zero, the template
functions in the <code>interval_lib::user</code> namespace can be
specialized:</p>
<pre>
namespace user {
template&lt;class T&gt; inline bool is_zero(T const &amp;v) { return v == static_cast&lt;T&gt;(0); }
template&lt;class T&gt; inline bool is_neg (T const &amp;v) { return v &lt; static_cast&lt;T&gt;(0); }
template&lt;class T&gt; inline bool is_pos (T const &amp;v) { return v &gt; static_cast&lt;T&gt;(0); }
}
</pre>
<h3>Numeric limits</h3>
<p>Another remark about the checking policy. It normally is powerful enough
to handle the exceptional behavior that the basic type could induce; in
particular infinite and invalid numbers (thanks to the four functions
<code>pos_inf</code>, <code>neg_inf</code>, <code>nan</code> and
<code>is_nan</code>). However, if you use
<code>interval_lib::checking_base</code> (and the default checking policy
uses it), your base type should have a correctly specialized
<code>std::numeric_limits&lt;T&gt;</code>. In particular, the values
<code>has_infinity</code> and <code>has_quiet_NaN</code>, and the functions
<code>infinity</code> and <code>quiet_NaN</code> should be accordingly
defined.</p>
<p>So, to summarize, if you do not rely on the default policy and do not
use <code>interval_lib::checking_base</code>, it is not necessary to have a
specialization of the numeric limits for your base type.</p>
<h3>Mathematical properties</h3>
<p>Ensuring the numbers are correctly ordered is not enough. The basic
operators should also respect some properties depending on the order. Here
they are:</p>
<ul>
<li>0 &le; <i>x</i> &rArr; -<i>x</i> &le; 0</li>
<li><i>x</i> &le; <i>y</i> &rArr; -<i>y</i> &le; -<i>x</i></li>
<li><i>x</i> &le; <i>y</i> &rArr; <i>x</i>+<i>z</i> &le;
<i>y</i>+<i>z</i></li>
<li><i>x</i> &le; <i>y</i> and <i>z</i> &ge; 0 &rArr;
<i>x</i>&times;<i>z</i> &le; <i>y</i>&times;<i>z</i></li>
<li>0 &lt; <i>x</i> &le; <i>y</i> &rArr; 0 &lt; 1/<i>y</i> &le;
1/<i>x</i></li>
</ul>
<p>The previous properties are also used (and enough) for <code>abs</code>,
<code>square</code> and <code>pow</code>. For all the transcendental
functions (including <code>sqrt</code>), other properties are needed. These
functions should have the same properties than the corresponding real
functions. For example, the expected properties for <code>cos</code>
are:</p>
<ul>
<li><code>cos</code> is defined for all the valid numbers;</li>
<li>it is 2&pi;-periodic;</li>
<li><code>cos</code>(2&pi;-<i>x</i>) is equal to
<code>cos</code>(<i>x</i>);</li>
<li><code>cos</code> is a decreasing function on [0,2&pi;].</li>
</ul>
<h3>Rounding</h3>
<p>If you work with a base type and no inexact result is ever computed, you
can skip the rest of this paragraph. You can also skip it if you are not
interested in the inclusion property (if approximate results are enough).
If you are still reading, it is probably because you want to know the basic
properties the rounding policy should validate.</p>
<p>Whichever operation or function you consider, the following property
should be respected: <code>f_down(x,y) &lt;= f(x,y) &lt;= f_up(x,y)</code>.
Here, <code>f</code> denotes the infinitely precise function computed and
<code>f_down</code> and <code>f_up</code> are functions which return
possibly inexact values but of the correct type (the base type). If
possible, they should try to return the nearest representable value, but it
is not always easy.</p>
<h3>Constants</h3>
<p>In order for the trigonometric functions to correctly work, the library
need to know the value of the &pi; constant (and also &pi;/2 and 2&pi;).
Since these constants may not be representable in the base type, the
library does not have to know the exact value: a lower bound and an upper
bound are enough. If these values are not provided by the user, the default
values will be used: they are integer values (so &pi; is bounded by 3 and
4).</p>
<h3>Operators and conversions</h3>
<p>As explained at the beginning, the comparison operators should be
defined for the base type. The rounding policy defines a lot of functions
used by the interval library. So the arithmetic operators do not need to be
defined for the base type (unless required by one of the predefined
classes). However, there is an exception: the unary minus need to be
defined. Moreover, this operator should only provide exact results; it is
the reason why the rounding policy does not provide some negation
functions.</p>
<p>The conversion from <code>int</code> to the base type needs to be
defined (only a few values need to be available: -1, 0, 1, 2). The
conversion the other way around is provided by the rounding policy
(<code>int_down</code> and <code>int_up</code> members); and no other
conversion is strictly needed. However, it may be valuable to provide as
much conversions as possible in the rounding policy (<code>conv_down</code>
and <code>conv_up</code> members) in order to benefit from interval
conversions.</p>
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
<p><i>Copyright &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;nnimann, Polytechnic University<br>
Copyright &copy; 2004 Guillaume Melquiond</i></p>
<p><i>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
or copy at <a href=
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
</body>
</html>
+80
View File
@@ -0,0 +1,80 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
<title>Policies</title>
</head>
<body lang="en">
<h1>Policies</h1>
<p>The <code>interval</code> template requires two arguments. The first
corresponds to the base type chosen for the bounds. And the second defines
the <a href="rounding.htm">rounding</a> and <a href=
"checking.htm">checking</a> behaviors of the newly constructed class. This
second argument is not mandatory but may need some customizations. In order
to ease the manipulations, some helper templates are provided in
<code>interval/policies.hpp</code>.</p>
<pre>
namespace boost {
namespace numeric {
namespace interval_lib {
template&lt;class Rounding, class Checking&gt;
struct policies {
typedef Rounding rounding;
typedef Checking checking;
};
template&lt;class OldInterval, class NewRounding&gt;
struct change_rounding {
typedef ... type;
};
template&lt;class OldInterval, class NewChecking&gt;
struct change_checking {
typedef ... type;
};
template&lt;class OldInterval&gt;
struct unprotect {
typedef ... type;
};
} // namespace interval_lib
} // namespace numeric
} // namespace boost
</pre>
<p>The <code>policies</code> template should be used whenever the user
needs to define a policy structure for an <code>interval</code> class.
<code>change_rounding</code> and <code>change_checking</code> can be used
to get the type of a new interval by changing one of the policies of an old
interval; the new type is available thanks to the type definition
<code>type</code>. Finally, <code>unprotect</code> looks like
<code>change_rounding</code> and directly changes the rounding of an
interval to its unprotected version (a better explanation is available
<a href="rounding.htm#perfexp">here</a>).</p>
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
<p><i>Copyright &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;nnimann, Polytechnic University</i></p>
<p><i>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
or copy at <a href=
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
</body>
</html>
+632
View File
@@ -0,0 +1,632 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
<title>Rounding Policies</title>
</head>
<body lang="en">
<h1>Rounding Policies</h1>
<p>In order to be as general as possible, the library uses a class to
compute all the necessary functions rounded upward or downward. This class
is the first parameter of <code>policies</code>, it is also the type named
<code>rounding</code> in the policy definition of
<code>interval</code>.</p>
<p>By default, it is <code>interval_lib::rounded_math&lt;T&gt;</code>. The
class <code>interval_lib::rounded_math</code> is already specialized for
the standard floating types (<code>float</code> , <code>double</code> and
<code>long double</code>). So if the base type of your intervals is not one
of these, a good solution would probably be to provide a specialization of
this class. But if the default specialization of
<code>rounded_math&lt;T&gt;</code> for <code>float</code>,
<code>double</code>, or <code>long double</code> is not what you seek, or
you do not want to specialize
<code>interval_lib::rounded_math&lt;T&gt;</code> (say because you prefer to
work in your own namespace) you can also define your own rounding policy
and pass it directly to <code>interval_lib::policies</code>.</p>
<h2>Requirements</h2>
<p>Here comes what the class is supposed to provide. The domains are
written next to their respective functions (as you can see, the functions
do not have to worry about invalid values, but they have to handle infinite
arguments).</p>
<pre>
/* Rounding requirements */
struct rounding {
// default constructor, destructor
rounding();
~rounding();
// mathematical operations
T add_down(T, T); // [-&infin;;+&infin;][-&infin;;+&infin;]
T add_up (T, T); // [-&infin;;+&infin;][-&infin;;+&infin;]
T sub_down(T, T); // [-&infin;;+&infin;][-&infin;;+&infin;]
T sub_up (T, T); // [-&infin;;+&infin;][-&infin;;+&infin;]
T mul_down(T, T); // [-&infin;;+&infin;][-&infin;;+&infin;]
T mul_up (T, T); // [-&infin;;+&infin;][-&infin;;+&infin;]
T div_down(T, T); // [-&infin;;+&infin;]([-&infin;;+&infin;]-{0})
T div_up (T, T); // [-&infin;;+&infin;]([-&infin;;+&infin;]-{0})
T sqrt_down(T); // ]0;+&infin;]
T sqrt_up (T); // ]0;+&infin;]
T exp_down(T); // [-&infin;;+&infin;]
T exp_up (T); // [-&infin;;+&infin;]
T log_down(T); // ]0;+&infin;]
T log_up (T); // ]0;+&infin;]
T cos_down(T); // [0;2&pi;]
T cos_up (T); // [0;2&pi;]
T tan_down(T); // ]-&pi;/2;&pi;/2[
T tan_up (T); // ]-&pi;/2;&pi;/2[
T asin_down(T); // [-1;1]
T asin_up (T); // [-1;1]
T acos_down(T); // [-1;1]
T acos_up (T); // [-1;1]
T atan_down(T); // [-&infin;;+&infin;]
T atan_up (T); // [-&infin;;+&infin;]
T sinh_down(T); // [-&infin;;+&infin;]
T sinh_up (T); // [-&infin;;+&infin;]
T cosh_down(T); // [-&infin;;+&infin;]
T cosh_up (T); // [-&infin;;+&infin;]
T tanh_down(T); // [-&infin;;+&infin;]
T tanh_up (T); // [-&infin;;+&infin;]
T asinh_down(T); // [-&infin;;+&infin;]
T asinh_up (T); // [-&infin;;+&infin;]
T acosh_down(T); // [1;+&infin;]
T acosh_up (T); // [1;+&infin;]
T atanh_down(T); // [-1;1]
T atanh_up (T); // [-1;1]
T median(T, T); // [-&infin;;+&infin;][-&infin;;+&infin;]
T int_down(T); // [-&infin;;+&infin;]
T int_up (T); // [-&infin;;+&infin;]
// conversion functions
T conv_down(U);
T conv_up (U);
// unprotected rounding class
typedef ... unprotected_rounding;
};
</pre>
<p>The constructor and destructor of the rounding class have a very
important semantic requirement: they are responsible for setting and
resetting the rounding modes of the computation on T. For instance, if T is
a standard floating point type and floating point computation is performed
according to the Standard IEEE 754, the constructor can save the current
rounding state, each <code>_up</code> (resp. <code>_down</code>) function
will round up (resp. down), and the destructor will restore the saved
rounding state. Indeed this is the behavior of the default rounding
policy.</p>
<p>The meaning of all the mathematical functions up until
<code>atanh_up</code> is clear: each function returns number representable
in the type <code>T</code> which is a lower bound (for <code>_down</code>)
or upper bound (for <code>_up</code>) on the true mathematical result of
the corresponding function. The function <code>median</code> computes the
average of its two arguments rounded to its nearest representable number.
The functions <code>int_down</code> and <code>int_up</code> compute the
nearest integer smaller or bigger than their argument. Finally,
<code>conv_down</code> and <code>conv_up</code> are responsible of the
conversions of values of other types to the base number type: the first one
must round down the value and the second one must round it up.</p>
<p>The type <code>unprotected_rounding</code> allows to remove all
controls. For reasons why one might to do this, see the <a href=
"#Protection">protection</a> paragraph below.</p>
<h2>Overview of the provided classes</h2>
<p>A lot of classes are provided. The classes are organized by level. At
the bottom is the class <code>rounding_control</code>. At the next level
come <code>rounded_arith_exact</code>, <code>rounded_arith_std</code> and
<code>rounded_arith_opp</code>. Then there are
<code>rounded_transc_dummy</code>, <code>rounded_transc_exact</code>,
<code>rounded_transc_std</code> and <code>rounded_transc_opp</code>. And
finally are <code>save_state</code> and <code>save_state_nothing</code>.
Each of these classes provide a set of members that are required by the
classes of the next level. For example, a <code>rounded_transc_...</code>
class needs the members of a <code>rounded_arith_...</code> class.</p>
<p>When they exist in two versions <code>_std</code> and <code>_opp</code>,
the first one does switch the rounding mode each time, and the second one
tries to keep it oriented toward plus infinity. The main purpose of the
<code>_opp</code> version is to speed up the computations through the use
of the "opposite trick" (see the <a href="#perf">performance notes</a>).
This version requires the rounding mode to be upward before entering any
computation functions of the class. It guarantees that the rounding mode
will still be upward at the exit of the functions.</p>
<p>Please note that it is really a very bad idea to mix the
<code>_opp</code> version with the <code>_std</code> since they do not have
compatible properties.</p>
<p>There is a third version named <code>_exact</code> which computes the
functions without changing the rounding mode. It is an "exact" version
because it is intended for a base type that produces exact results.</p>
<p>The last version is the <code>_dummy</code> version. It does not do any
computations but still produces compatible results.</p>
<p>Please note that it is possible to use the "exact" version for an
inexact base type, e.g. <code>float</code> or <code>double</code>. In that
case, the inclusion property is no longer guaranteed, but this can be
useful to speed up the computation when the inclusion property is not
desired strictly. For instance, in computer graphics, a small error due to
floating-point roundoff is acceptable as long as an approximate version of
the inclusion property holds.</p>
<p>Here comes what each class defines. Later, when they will be described
more thoroughly, these members will not be repeated. Please come back here
in order to see them. Inheritance is also used to avoid repetitions.</p>
<pre>
template &lt;class T&gt;
struct rounding_control
{
typedef ... rounding_mode;
void set_rounding_mode(rounding_mode);
void get_rounding_mode(rounding_mode&amp;);
void downward ();
void upward ();
void to_nearest();
T to_int(T);
T force_rounding(T);
};
template &lt;class T, class Rounding&gt;
struct rounded_arith_... : Rounding
{
void init();
T add_down(T, T);
T add_up (T, T);
T sub_down(T, T);
T sub_up (T, T);
T mul_down(T, T);
T mul_up (T, T);
T div_down(T, T);
T div_up (T, T);
T sqrt_down(T);
T sqrt_up (T);
T median(T, T);
T int_down(T);
T int_up (T);
};
template &lt;class T, class Rounding&gt;
struct rounded_transc_... : Rounding
{
T exp_down(T);
T exp_up (T);
T log_down(T);
T log_up (T);
T cos_down(T);
T cos_up (T);
T tan_down(T);
T tan_up (T);
T asin_down(T);
T asin_up (T);
T acos_down(T);
T acos_up (T);
T atan_down(T);
T atan_up (T);
T sinh_down(T);
T sinh_up (T);
T cosh_down(T);
T cosh_up (T);
T tanh_down(T);
T tanh_up (T);
T asinh_down(T);
T asinh_up (T);
T acosh_down(T);
T acosh_up (T);
T atanh_down(T);
T atanh_up (T);
};
template &lt;class Rounding&gt;
struct save_state_... : Rounding
{
save_state_...();
~save_state_...();
typedef ... unprotected_rounding;
};
</pre>
<h2>Synopsis</h2>
<pre>
namespace boost {
namespace numeric {
namespace interval_lib {
<span style="color: #FF0000">/* basic rounding control */</span>
template &lt;class T&gt; struct rounding_control;
<span style="color: #FF0000">/* arithmetic functions rounding */</span>
template &lt;class T, class Rounding = rounding_control&lt;T&gt; &gt; struct rounded_arith_exact;
template &lt;class T, class Rounding = rounding_control&lt;T&gt; &gt; struct rounded_arith_std;
template &lt;class T, class Rounding = rounding_control&lt;T&gt; &gt; struct rounded_arith_opp;
<span style="color: #FF0000">/* transcendental functions rounding */</span>
template &lt;class T, class Rounding&gt; struct rounded_transc_dummy;
template &lt;class T, class Rounding = rounded_arith_exact&lt;T&gt; &gt; struct rounded_transc_exact;
template &lt;class T, class Rounding = rounded_arith_std&lt;T&gt; &gt; struct rounded_transc_std;
template &lt;class T, class Rounding = rounded_arith_opp&lt;T&gt; &gt; struct rounded_transc_opp;
<span style="color: #FF0000">/* rounding-state-saving classes */</span>
template &lt;class Rounding&gt; struct save_state;
template &lt;class Rounding&gt; struct save_state_nothing;
<span style="color: #FF0000">/* default policy for type T */</span>
template &lt;class T&gt; struct rounded_math;
template &lt;&gt; struct rounded_math&lt;float&gt;;
template &lt;&gt; struct rounded_math&lt;double&gt;;
<span style=
"color: #FF0000">/* some metaprogramming to convert a protected to unprotected rounding */</span>
template &lt;class I&gt; struct unprotect;
} // namespace interval_lib
} // namespace numeric
} // namespace boost
</pre>
<h2>Description of the provided classes</h2>
<p>We now describe each class in the order they appear in the definition of
a rounding policy (this outermost-to-innermost order is the reverse order
from the synopsis).</p>
<h3 id="Protection">Protection control</h3>
<p>Protection refers to the fact that the interval operations will be
surrounded by rounding mode controls. Unprotecting a class means to remove
all the rounding controls. Each rounding policy provides a type
<code>unprotected_rounding</code>. The required type
<code>unprotected_rounding</code> gives another rounding class that enables
to work when nested inside rounding. For example, the first three lines
below should all produce the same result (because the first operation is
the rounding constructor, and the last is its destructor, which take care
of setting the rounding modes); and the last line is allowed to have an
undefined behavior (since no rounding constructor or destructor is ever
called).</p>
<pre>
T c; { rounding rnd; c = rnd.add_down(a, b); }
T c; { rounding rnd1; { rounding rnd2; c = rnd2.add_down(a, b); } }
T c; { rounding rnd1; { rounding::unprotected_rounding rnd2; c = rnd2.add_down(a, b); } }
T d; { rounding::unprotected_rounding rnd; d = rnd.add_down(a, b); }
</pre>
<p>Naturally <code>rounding::unprotected_rounding</code> may simply be
<code>rounding</code> itself. But it can improve performance if it is a
simplified version with empty constructor and destructor. In order to avoid
undefined behaviors, in the library, an object of type
<code>rounding::unprotected_rounding</code> is guaranteed to be created
only when an object of type <code>rounding</code> is already alive. See the
<a href="#perf">performance notes</a> for some additional details.</p>
<p>The support library defines a metaprogramming class template
<code>unprotect</code> which takes an interval type <code>I</code> and
returns an interval type <code>unprotect&lt;I&gt;::type</code> where the
rounding policy has been unprotected. Some information about the types:
<code>interval&lt;T, interval_lib::policies&lt;Rounding, _&gt;
&gt;::traits_type::rounding</code> <b>is</b> the same type as
<code>Rounding</code>, and <code>unprotect&lt;interval&lt;T,
interval_lib::policies&lt;Rounding, _&gt; &gt; &gt;::type</code> <b>is</b>
the same type as <code>interval&lt;T,
interval_lib::policies&lt;Rounding::unprotected, _&gt; &gt;</code>.</p>
<h3>State saving</h3>
<p>First comes <code>save_state</code>. This class is responsible for
saving the current rounding mode and calling init in its constructor, and
for restoring the saved rounding mode in its destructor. This class also
defines the <code>unprotected_rounding</code> type.</p>
<p>If the rounding mode does not require any state-saving or
initialization, <code>save_state_nothing</code> can be used instead of
<code>save_state</code>.</p>
<h3>Transcendental functions</h3>
<p>The classes <code>rounded_transc_exact</code>,
<code>rounded_transc_std</code> and <code>rounded_transc_opp</code> expect
the std namespace to provide the functions exp log cos tan acos asin atan
cosh sinh tanh acosh asinh atanh. For the <code>_std</code> and
<code>_opp</code> versions, all these functions should respect the current
rounding mode fixed by a call to downward or upward.</p>
<p><strong>Please note:</strong> Unfortunately, the latter is rarely the
case. It is the reason why a class <code>rounded_transc_dummy</code> is
provided which does not depend on the functions from the std namespace.
There is no magic, however. The functions of
<code>rounded_transc_dummy</code> do not compute anything. They only return
valid values. For example, <code>cos_down</code> always returns -1. In this
way, we do verify the inclusion property for the default implementation,
even if this has strictly no value for the user. In order to have useful
values, another policy should be used explicitely, which will most likely
lead to a violation of the inclusion property. In this way, we ensure that
the violation is clearly pointed out to the user who then knows what he
stands against. This class could have been used as the default
transcendental rounding class, but it was decided it would be better for
the compilation to fail due to missing declarations rather than succeed
thanks to valid but unusable functions.</p>
<h3>Basic arithmetic functions</h3>
<p>The classes <code>rounded_arith_std</code> and
<code>rounded_arith_opp</code> expect the operators + - * / and the
function <code>std::sqrt</code> to respect the current rounding mode.</p>
<p>The class <code>rounded_arith_exact</code> requires
<code>std::floor</code> and <code>std::ceil</code> to be defined since it
can not rely on <code>to_int</code>.</p>
<h3>Rounding control</h3>
<p>The functions defined by each of the previous classes did not need any
explanation. For example, the behavior of <code>add_down</code> is to
compute the sum of two numbers rounded downward. For
<code>rounding_control</code>, the situation is a bit more complex.</p>
<p>The basic function is <code>force_rounding</code> which returns its
argument correctly rounded accordingly to the current rounding mode if it
was not already the case. This function is necessary to handle delayed
rounding. Indeed, depending on the way the computations are done, the
intermediate results may be internally stored in a more precise format and
it can lead to a wrong rounding. So the function enforces the rounding.
<a href="#extreg">Here</a> is an example of what happens when the rounding
is not enforced.</p>
<p>The function <code>get_rounding_mode</code> returns the current rounding
mode, <code>set_rounding_mode</code> sets the rounding mode back to a
previous value returned by <code>get_rounding_mode</code>.
<code>downward</code>, <code>upward</code> and <code>to_nearest</code> sets
the rounding mode in one of the three directions. This rounding mode should
be global to all the functions that use the type <code>T</code>. For
example, after a call to <code>downward</code>,
<code>force_rounding(x+y)</code> is expected to return the sum rounded
toward -&infin;.</p>
<p>The function <code>to_int</code> computes the nearest integer
accordingly to the current rounding mode.</p>
<p>The non-specialized version of <code>rounding_control</code> does not do
anything. The functions for the rounding mode are empty, and
<code>to_int</code> and <code>force_rounding</code> are identity functions.
The <code>pi_</code> constant functions return suitable integers (for
example, <code>pi_up</code> returns <code>T(4)</code>).</p>
<p>The class template <code>rounding_control</code> is specialized for
<code>float</code>, <code>double</code> and <code>long double</code> in
order to best use the floating point unit of the computer.</p>
<h2>Template class <tt>rounded_math</tt></h2>
<p>The default policy (aka <code>rounded_math&lt;T&gt;</code>) is simply
defined as:</p>
<pre>
template &lt;class T&gt; struct rounded_math&lt;T&gt; : save_state_nothing&lt;rounded_arith_exact&lt;T&gt; &gt; {};
</pre>
<p>and the specializations for <code>float</code>, <code>double</code> and
<code>long double</code> use <code>rounded_arith_opp</code>, as in:</p>
<pre>
template &lt;&gt; struct rounded_math&lt;float&gt; : save_state&lt;rounded_arith_opp&lt;float&gt; &gt; {};
template &lt;&gt; struct rounded_math&lt;double&gt; : save_state&lt;rounded_arith_opp&lt;double&gt; &gt; {};
template &lt;&gt; struct rounded_math&lt;long double&gt; : save_state&lt;rounded_arith_opp&lt;long double&gt; &gt; {};
</pre>
<h2 id="perf">Performance Issues</h2>
<p>This paragraph deals mostly with the performance of the library with
intervals using the floating-point unit (FPU) of the computer. Let's
consider the sum of [<i>a</i>,<i>b</i>] and [<i>c</i>,<i>d</i>] as an
example. The result is [<code>down</code>(<i>a</i>+<i>c</i>),
<code>up</code>(<i>b</i>+<i>d</i>)], where <code>down</code> and
<code>up</code> indicate the rounding mode needed.</p>
<h3>Rounding Mode Switch</h3>
<p>If the FPU is able to use a different rounding mode for each operation,
there is no problem. For example, it's the case for the Alpha processor:
each floating-point instruction can specify a different rounding mode.
However, the IEEE-754 Standard does not require such a behavior. So most of
the FPUs only provide some instructions to set the rounding mode for all
subsequent operations. And generally, these instructions need to flush the
pipeline of the FPU.</p>
<p>In this situation, the time needed to sum [<i>a</i>,<i>b</i>] and
[<i>c</i>,<i>d</i>] is far worse than the time needed to calculate
<i>a</i>+<i>b</i> and <i>c</i>+<i>d</i> since the two additions cannot be
parallelized. Consequently, the objective is to diminish the number of
rounding mode switches.</p>
<p>If this library is not used to provide exact computations, but only for
pair arithmetic, the solution is quite simple: do not use rounding. In that
case, doing the sum [<i>a</i>,<i>b</i>] and [<i>c</i>,<i>d</i>] will be as
fast as computing <i>a</i>+<i>b</i> and <i>c</i>+<i>d</i>. Everything is
perfect.</p>
<p>However, if exact computations are required, such a solution is totally
unthinkable. So, are we penniless? No, there is still a trick available.
Indeed, down(<i>a</i>+<i>c</i>) = -up(-<i>a</i>-<i>c</i>) if the unary
minus is an exact operation. It is now possible to calculate the whole sum
with the same rounding mode. Generally, the cost of the mode switching is
worse than the cost of the sign changes.</p>
<h4>Speeding up consecutive operations</h4>
<p>The interval addition is not the only operation; most of the interval
operations can be computed by setting the rounding direction of the FPU
only once. So the operations of the floating point rounding policy assume
that the direction is correctly set. This assumption is usually not true in
a program (the user and the standard library expect the rounding direction
to be to nearest), so these operations have to be enclosed in a shell that
sets the floating point environment. This protection is done by the
constructor and destructor of the rounding policy.</p>
<p>Les us now consider the case of two consecutive interval additions:
[<i>a</i>,<i>b</i>] + [<i>c</i>,<i>d</i>] + [<i>e</i>,<i>f</i>]. The
generated code should look like:</p>
<pre>
init_rounding_mode(); // rounding object construction during the first addition
t1 = -(-a - c);
t2 = b + d;
restore_rounding_mode(); // rounding object destruction
init_rounding_mode(); // rounding object construction during the second addition
x = -(-t1 - e);
y = t2 + f;
restore_rounding_mode(); // rounding object destruction
// the result is the interval [x,y]
</pre>
<p>Between the two operations, the rounding direction is restored, and then
initialized again. Ideally, compilers should be able to optimize this
useless code away. But unfortunately they are not, and this slows the code
down by an order of magnitude. In order to avoid this bottleneck, the user
can tell to the interval operations that they do not need to be protected
anymore. It will then be up to the user to protect the interval
computations. The compiler will then be able to generate such a code:</p>
<pre>
init_rounding_mode(); // done by the user
x = -(-a - c - e);
y = b + d + f;
restore_rounding_mode(); // done by the user
</pre>
<p>The user will have to create a rounding object. And as long as this
object is alive, unprotected versions of the interval operations can be
used. They are selected by using an interval type with a specific rounding
policy. If the initial interval type is <code>I</code>, then
<code>I::traits_type::rounding</code> is the type of the rounding object,
and <code>interval_lib::unprotect&lt;I&gt;::type</code> is the type of the
unprotected interval type.</p>
<p>Because the rounding mode of the FPU is changed during the life of the
rounding object, any arithmetic floating point operation that does not
involve the interval library can lead to unexpected results. And
reciprocally, using unprotected interval operation when no rounding object
is alive will produce intervals that are not guaranteed anymore to contain
the real result.</p>
<h4 id="perfexp">Example</h4>
<p>Here is an example of Horner's scheme to compute the value of a polynom.
The rounding mode switches are disabled for the whole computation.</p>
<pre>
// I is an interval class, the polynom is a simple array
template&lt;class I&gt;
I horner(const I&amp; x, const I p[], int n) {
// save and initialize the rounding mode
typename I::traits_type::rounding rnd;
// define the unprotected version of the interval type
typedef typename boost::numeric::interval_lib::unprotect&lt;I&gt;::type R;
const R&amp; a = x;
R y = p[n - 1];
for(int i = n - 2; i &gt;= 0; i--) {
y = y * a + (const R&amp;)(p[i]);
}
return y;
// restore the rounding mode with the destruction of rnd
}
</pre>
<p>Please note that a rounding object is specially created in order to
protect all the interval computations. Each interval of type I is converted
in an interval of type R before any operations. If this conversion is not
done, the result is still correct, but the interest of this whole
optimization has disappeared. Whenever possible, it is good to convert to
<code>const R&amp;</code> instead of <code>R</code>: indeed, the function
could already be called inside an unprotection block so the types
<code>R</code> and <code>I</code> would be the same interval, no need for a
conversion.</p>
<h4>Uninteresting remark</h4>
<p>It was said at the beginning that the Alpha processors can use a
specific rounding mode for each operation. However, due to the instruction
format, the rounding toward plus infinity is not available. Only the
rounding toward minus infinity can be used. So the trick using the change
of sign becomes essential, but there is no need to save and restore the
rounding mode on both sides of an operation.</p>
<h3 id="extreg">Extended Registers</h3>
<p>There is another problem besides the cost of the rounding mode switch.
Some FPUs use extended registers (for example, float computations will be
done with double registers, or double computations with long double
registers). Consequently, many problems can arise.</p>
<p>The first one is due to to the extended precision of the mantissa. The
rounding is also done on this extended precision. And consequently, we
still have down(<i>a</i>+<i>b</i>) = -up(-<i>a</i>-<i>b</i>) in the
extended registers. But back to the standard precision, we now have
down(<i>a</i>+<i>b</i>) &lt; -up(-<i>a</i>-<i>b</i>) instead of an
equality. A solution could be not to use this method. But there still are
other problems, with the comparisons between numbers for example.</p>
<p>Naturally, there is also a problem with the extended precision of the
exponent. To illustrate this problem, let <i>m</i> be the biggest number
before +<i>inf</i>. If we calculate 2*[<i>m</i>,<i>m</i>], the answer
should be [<i>m</i>,<i>inf</i>]. But due to the extended registers, the FPU
will first store [<i>2m</i>,<i>2m</i>] and then convert it to
[<i>inf</i>,<i>inf</i>] at the end of the calculus (when the rounding mode
is toward +<i>inf</i>). So the answer is no more accurate.</p>
<p>There is only one solution: to force the FPU to convert the extended
values back to standard precision after each operation. Some FPUs provide
an instruction able to do this conversion (for example the PowerPC
processors). But for the FPUs that do not provide it (the x86 processors),
the only solution is to write the values to memory and read them back. Such
an operation is obviously very expensive.</p>
<h2>Some Examples</h2>
<p>Here come several cases:</p>
<ul>
<li>if you need precise computations with the <code>float</code> or
<code>double</code> types, use the default
<code>rounded_math&lt;T&gt;</code>;</li>
<li>for fast wide intervals without any rounding nor precision, use
<code>save_state_nothing&lt;rounded_transc_exact&lt;T&gt;
&gt;</code>;</li>
<li>for an exact type (like int or rational with a little help for
infinite and NaN values) without support for transcendental functions,
the solution could be
<code>save_state_nothing&lt;rounded_transc_dummy&lt;T,
rounded_arith_exact&lt;T&gt; &gt; &gt;</code> or directly
<code>save_state_nothing&lt;rounded_arith_exact&lt;T&gt;
&gt;</code>;</li>
<li>if it is a more complex case than the previous ones, the best thing
is probably to directly define your own policy.</li>
</ul>
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
<p><i>Copyright &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;nnimann, Polytechnic University<br>
Copyright &copy; 2004-2005 Guillaume Melquiond, ENS Lyon</i></p>
<p><i>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
or copy at <a href=
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
</body>
</html>
+67
View File
@@ -0,0 +1,67 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
<title>Interval-TODO.htm</title>
</head>
<body lang="en">
<h1>TODO list for the Interval Arithmetic library</h1>
<h2>Comments from the review process</h2>
<ul>
<li>It would be nice to have a 100% portable Rounding policy class based
on LIA-1 only, with no additional requirement such as IEEE 754 or even
more.</li>
<li>For pi and other constants, we should fetch them from the Math
constants library when it is ready.</li>
</ul>
<h2>Various items</h2>
<ul>
<li>Support the <code>-mfpmath=sse</code> option of g++ for Pentium IV
optimized code. This requires a different rounding policy class.</li>
<li>Have an optimized specialization of
<code>interval&lt;double&gt;</code> using SSE2 instructions? Tricky.</li>
<li>Write a traits specialization for <code>interval&lt;MPFR&gt;</code>,
and other non-built-in number types.</li>
<li>Have a robust implementation of transcendental functions over the
built-in floating point types (e.g. using MPFR)?</li>
<li>Safe conversions from <code>interval&lt;double&gt;</code> to
<code>interval&lt;float&gt;</code>? Requires partial specialization.</li>
<li>It would be nice to use the expression template mechanism to
automatically use the more efficient unprotected rounding mode version
for small subexpressions (although you can do bigger expressions by
hand).</li>
</ul>
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
<p><i>Copyright &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;nnimann, Polytechnic University</i></p>
<p><i>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
or copy at <a href=
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
</body>
</html>
+20
View File
@@ -0,0 +1,20 @@
# Boost.Interval Library example Jamfile
#
# Copyright (c) 2018 James E. King III
#
# Distributed under the Boost Software License, Version 1.0. (See accompany-
# ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import testing ;
{
test-suite interval-examples
: [ compile filter.cpp : <build>yes <toolset>msvc-10.0:<build>no ] # ambiguous sin()
[ compile findroot_demo.cpp ]
[ compile horner.cpp ]
[ compile io.cpp ]
[ compile newton-raphson.cpp ]
[ compile rational.cpp ]
# [ compile transc.cpp ] requires gmp3, mpfr
;
}
+209
View File
@@ -0,0 +1,209 @@
/* Boost example/filter.cpp
* two examples of filters for computing the sign of a determinant
* the second filter is based on an idea presented in
* "Interval arithmetic yields efficient dynamic filters for computational
* geometry" by Brönnimann, Burnikel and Pion, 2001
*
* Copyright 2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
#include <cstring>
#include <iostream>
namespace dummy {
using namespace boost;
using namespace numeric;
using namespace interval_lib;
typedef save_state<rounded_arith_opp<double> > R;
typedef checking_no_nan<double, checking_no_empty<double> > P;
typedef interval<double, policies<R, P> > I;
}
template<class T>
class vector {
T* ptr;
public:
vector(int d) { ptr = (T*)malloc(sizeof(T) * d); }
~vector() { free(ptr); }
const T& operator[](int i) const { return ptr[i]; }
T& operator[](int i) { return ptr[i]; }
};
template<class T>
class matrix {
int dim;
T* ptr;
public:
matrix(int d): dim(d) { ptr = (T*)malloc(sizeof(T) * dim * dim); }
~matrix() { free(ptr); }
int get_dim() const { return dim; }
void assign(const matrix<T> &a) { memcpy(ptr, a.ptr, sizeof(T) * dim * dim); }
const T* operator[](int i) const { return &(ptr[i * dim]); }
T* operator[](int i) { return &(ptr[i * dim]); }
};
typedef dummy::I I_dbl;
/* compute the sign of a determinant using an interval LU-decomposition; the
function answers 1 or -1 if the determinant is positive or negative (and
more importantly, the result must be provable), or 0 if the algorithm was
unable to get a correct sign */
int det_sign_algo1(const matrix<double> &a) {
int dim = a.get_dim();
vector<int> p(dim);
for(int i = 0; i < dim; i++) p[i] = i;
int sig = 1;
I_dbl::traits_type::rounding rnd;
typedef boost::numeric::interval_lib::unprotect<I_dbl>::type I;
matrix<I> u(dim);
for(int i = 0; i < dim; i++) {
const double* line1 = a[i];
I* line2 = u[i];
for(int j = 0; j < dim; j++)
line2[j] = line1[j];
}
// computation of L and U
for(int i = 0; i < dim; i++) {
// partial pivoting
{
int pivot = i;
double max = 0;
for(int j = i; j < dim; j++) {
const I &v = u[p[j]][i];
if (zero_in(v)) continue;
double m = norm(v);
if (m > max) { max = m; pivot = j; }
}
if (max == 0) return 0;
if (pivot != i) {
sig = -sig;
int tmp = p[i];
p[i] = p[pivot];
p[pivot] = tmp;
}
}
// U[i,?]
{
I *line1 = u[p[i]];
const I &pivot = line1[i];
if (boost::numeric::interval_lib::cerlt(pivot, 0.)) sig = -sig;
for(int k = i + 1; k < dim; k++) {
I *line2 = u[p[k]];
I fact = line2[i] / pivot;
for(int j = i + 1; j < dim; j++) line2[j] -= fact * line1[j];
}
}
}
return sig;
}
/* compute the sign of a determinant using a floating-point LU-decomposition
and an a posteriori interval validation; the meaning of the answer is the
same as previously */
int det_sign_algo2(const matrix<double> &a) {
int dim = a.get_dim();
vector<int> p(dim);
for(int i = 0; i < dim; i++) p[i] = i;
int sig = 1;
matrix<double> lui(dim);
{
// computation of L and U
matrix<double> lu(dim);
lu.assign(a);
for(int i = 0; i < dim; i++) {
// partial pivoting
{
int pivot = i;
double max = std::abs(lu[p[i]][i]);
for(int j = i + 1; j < dim; j++) {
double m = std::abs(lu[p[j]][i]);
if (m > max) { max = m; pivot = j; }
}
if (max == 0) return 0;
if (pivot != i) {
sig = -sig;
int tmp = p[i];
p[i] = p[pivot];
p[pivot] = tmp;
}
}
// L[?,i] and U[i,?]
{
double *line1 = lu[p[i]];
double pivot = line1[i];
if (pivot < 0) sig = -sig;
for(int k = i + 1; k < dim; k++) {
double *line2 = lu[p[k]];
double fact = line2[i] / pivot;
line2[i] = fact;
for(int j = i + 1; j < dim; j++) line2[j] -= line1[j] * fact;
}
}
}
// computation of approximate inverses: Li and Ui
for(int j = 0; j < dim; j++) {
for(int i = j + 1; i < dim; i++) {
double *line = lu[p[i]];
double s = - line[j];
for(int k = j + 1; k < i; k++) s -= line[k] * lui[k][j];
lui[i][j] = s;
}
lui[j][j] = 1 / lu[p[j]][j];
for(int i = j - 1; i >= 0; i--) {
double *line = lu[p[i]];
double s = 0;
for(int k = i + 1; k <= j; k++) s -= line[k] * lui[k][j];
lui[i][j] = s / line[i];
}
}
}
// norm of PAUiLi-I computed with intervals
{
I_dbl::traits_type::rounding rnd;
typedef boost::numeric::interval_lib::unprotect<I_dbl>::type I;
vector<I> m1(dim);
vector<I> m2(dim);
for(int i = 0; i < dim; i++) {
for(int j = 0; j < dim; j++) m1[j] = 0;
const double *l1 = a[p[i]];
for(int j = 0; j < dim; j++) {
double v = l1[j]; // PA[i,j]
double *l2 = lui[j]; // Ui[j,?]
for(int k = j; k < dim; k++) {
using boost::numeric::interval_lib::mul;
m1[k] += mul<I>(v, l2[k]); // PAUi[i,k]
}
}
for(int j = 0; j < dim; j++) m2[j] = m1[j]; // PAUi[i,j] * Li[j,j]
for(int j = 1; j < dim; j++) {
const I &v = m1[j]; // PAUi[i,j]
double *l2 = lui[j]; // Li[j,?]
for(int k = 0; k < j; k++)
m2[k] += v * l2[k]; // PAUiLi[i,k]
}
m2[i] -= 1; // PAUiLi-I
double ss = 0;
for(int i = 0; i < dim; i++) ss = rnd.add_up(ss, norm(m2[i]));
if (ss >= 1) return 0;
}
}
return sig;
}
int main() {
int dim = 20;
matrix<double> m(dim);
for(int i = 0; i < dim; i++) for(int j = 0; j < dim; j++)
m[i][j] = /*1 / (i-j-0.001)*/ cos(1+i*sin(1 + j)) /*1./(1+i+j)*/;
// compute the sign of the determinant of a "strange" matrix with the two
// algorithms, the first should fail and the second succeed
std::cout << det_sign_algo1(m) << " " << det_sign_algo2(m) << std::endl;
}
@@ -0,0 +1,171 @@
/* Boost example/findroot_demo.cpp
* find zero points of some function by dichotomy
*
* Copyright 2000 Jens Maurer
* Copyright 2002-2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*
* The idea and the 2D function are based on RVInterval,
* which contains the following copyright notice:
This file is copyrighted 1996 by Ronald Van Iwaarden.
Permission is hereby granted, without written agreement and
without license or royalty fees, to use, copy, modify, and
distribute this software and its documentation for any
purpose, subject to the following conditions:
The above license notice and this permission notice shall
appear in all copies or substantial portions of this software.
The name "RVInterval" cannot be used for any modified form of
this software that does not originate from the authors.
Nevertheless, the name "RVInterval" may and should be used to
designate the optimization software implemented and described
in this package, even if embedded in any other system, as long
as any portion of this code remains.
The authors specifically disclaim any warranties, including,
but not limited to, the implied warranties of merchantability
and fitness for a particular purpose. The software provided
hereunder is on an "as is" basis, and the authors have no
obligation to provide maintenance, support, updates,
enhancements, or modifications. In no event shall the authors
be liable to any party for direct, indirect, special,
incidental, or consequential damages arising out of the use of
this software and its documentation.
*/
#include <boost/numeric/interval.hpp> // must be first for <limits> workaround
#include <boost/numeric/interval/io.hpp>
#include <list>
#include <deque>
#include <vector>
#include <fstream>
#include <iostream>
template<class T>
struct test_func2d
{
T operator()(T x, T y) const
{
return sin(x)*cos(y) - exp(x*y)/45.0 * (pow(x+y, 2)+100.0) -
cos(sin(y))*y/4.0;
}
};
template <class T>
struct test_func1d
{
T operator()(T x) const
{
return sin(x)/(x*x+1.0);
}
};
template<class T>
struct test_func1d_2
{
T operator()(T x) const
{
using std::sqrt;
return sqrt(x*x-1.0);
}
};
template<class Function, class I>
void find_zeros(std::ostream & os, Function f, I searchrange)
{
std::list<I> l, done;
l.push_back(searchrange);
while(!l.empty()) {
I range = l.front();
l.pop_front();
I val = f(range);
if (zero_in(val)) {
if(width(range) < 1e-6) {
os << range << '\n';
continue;
}
// there's still a solution hidden somewhere
std::pair<I,I> p = bisect(range);
l.push_back(p.first);
l.push_back(p.second);
}
}
}
template<class T>
std::ostream &operator<<(std::ostream &os, const std::pair<T, T> &x) {
os << "(" << x.first << ", " << x.second << ")";
return os;
}
template<class T, class Policies>
std::ostream &operator<<(std::ostream &os,
const boost::numeric::interval<T, Policies> &x) {
os << "[" << x.lower() << ", " << x.upper() << "]";
return os;
}
static const double epsilon = 5e-3;
template<class Function, class I>
void find_zeros(std::ostream & os, Function f, I rx, I ry)
{
typedef std::pair<I, I> rectangle;
typedef std::deque<rectangle> container;
container l, done;
// l.reserve(50);
l.push_back(std::make_pair(rx, ry));
for(int i = 1; !l.empty(); ++i) {
rectangle rect = l.front();
l.pop_front();
I val = f(rect.first, rect.second);
if (zero_in(val)) {
if(width(rect.first) < epsilon && width(rect.second) < epsilon) {
os << median(rect.first) << " " << median(rect.second) << " "
<< lower(rect.first) << " " << upper(rect.first) << " "
<< lower(rect.second) << " " << upper(rect.second)
<< '\n';
} else {
if(width(rect.first) > width(rect.second)) {
std::pair<I,I> p = bisect(rect.first);
l.push_back(std::make_pair(p.first, rect.second));
l.push_back(std::make_pair(p.second, rect.second));
} else {
std::pair<I,I> p = bisect(rect.second);
l.push_back(std::make_pair(rect.first, p.first));
l.push_back(std::make_pair(rect.first, p.second));
}
}
}
if(i % 10000 == 0)
std::cerr << "\rIteration " << i << ", l.size() = " << l.size();
}
std::cerr << '\n';
}
int main()
{
using namespace boost;
using namespace numeric;
using namespace interval_lib;
typedef interval<double,
policies<save_state<rounded_transc_opp<double> >,
checking_base<double> > > I;
std::cout << "Zero points of sin(x)/(x*x+1)\n";
find_zeros(std::cout, test_func1d<I>(), I(-11, 10));
std::cout << "Zero points of sqrt(x*x-1)\n";
find_zeros(std::cout, test_func1d_2<I>(), I(-5, 6));
std::cout << "Zero points of Van Iwaarden's 2D function\n";
std::ofstream f("func2d.data");
find_zeros(f, test_func2d<I>(), I(-20, 20), I(-20, 20));
std::cout << "Use gnuplot, command 'plot \"func2d.data\" with dots' to plot\n";
}
+47
View File
@@ -0,0 +1,47 @@
/* Boost example/horner.cpp
* example of unprotecting rounding for a whole function computation
*
* Copyright 2002-2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
#include <iostream>
// I is an interval class, the polynom is a simple array
template<class I>
I horner(const I& x, const I p[], int n) {
// initialize and restore the rounding mode
typename I::traits_type::rounding rnd;
// define the unprotected version of the interval type
typedef typename boost::numeric::interval_lib::unprotect<I>::type R;
const R& a = x;
R y = p[n - 1];
for(int i = n - 2; i >= 0; i--) {
y = y * a + (const R&)(p[i]);
}
return y;
// restore the rounding mode with the destruction of rnd
}
template<class T, class Policies>
std::ostream &operator<<(std::ostream &os,
const boost::numeric::interval<T, Policies> &x) {
os << "[" << x.lower() << ", " << x.upper() << "]";
return os;
}
int main() {
typedef boost::numeric::interval<double> I;
I p[3] = { -1.0, 0, 1.0 };
I x = 1.0;
std::cout << horner(x, p, 3) << std::endl;
return 0;
}
+172
View File
@@ -0,0 +1,172 @@
/* Boost examples/io.cpp
* show some exampleso of i/o operators
* thanks to all the people who commented on this point, particularly on
* the Boost mailing-list
*
* Copyright 2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
#include <boost/io/ios_state.hpp>
#include <cmath>
#include <cassert>
namespace io_std {
template<class T, class Policies, class CharType, class CharTraits>
std::basic_ostream<CharType, CharTraits> &operator<<
(std::basic_ostream<CharType, CharTraits> &stream,
const boost::numeric::interval<T, Policies> &value)
{
if (empty(value)) {
return stream << "[]";
} else {
return stream << '[' << lower(value) << ',' << upper(value) << ']';
}
}
} // namespace io_std
namespace io_sngl {
template<class T, class Policies, class CharType, class CharTraits>
std::basic_ostream<CharType, CharTraits> &operator<<
(std::basic_ostream<CharType, CharTraits> &stream,
const boost::numeric::interval<T, Policies> &value)
{
if (empty(value)) {
return stream << "[]";
} else if (singleton(value)) {
return stream << '[' << lower(value) << ']';
} else {
return stream << '[' << lower(value) << ',' << upper(value) << ']';
}
}
} // namespace io_sngl
namespace io_wdth {
template<class T, class Policies, class CharType, class CharTraits>
std::basic_ostream<CharType, CharTraits> &operator<<
(std::basic_ostream<CharType, CharTraits> &stream,
const boost::numeric::interval<T, Policies> &value)
{
if (empty(value)) {
return stream << "nothing";
} else {
return stream << median(value) << " ± " << width(value) / 2;
}
}
} // namespace io_wdth
namespace io_prec {
template<class T, class Policies, class CharType, class CharTraits>
std::basic_ostream<CharType, CharTraits> &operator<<
(std::basic_ostream<CharType, CharTraits> &stream,
const boost::numeric::interval<T, Policies> &value)
{
if (empty(value)) {
return stream << "nothing";
} else if (singleton(value)) {
boost::io::ios_precision_saver state(stream, std::numeric_limits<T>::digits10);
return stream << lower(value);
} else if (zero_in(value)) {
return stream << "0~";
} else {
const T rel = width(value) / norm(value);
int range = - (int)std::log10(rel);
boost::io::ios_precision_saver state(stream, range);
return stream << median(value);
}
}
} // namespace io_prec
namespace io_wide {
template<class T, class Policies, class CharType, class CharTraits>
std::basic_ostream<CharType, CharTraits> &operator<<
(std::basic_ostream<CharType, CharTraits> &stream,
const boost::numeric::interval<T, Policies> &value)
{
if (empty(value)) {
return stream << "nothing";
} else if (singleton(value)) {
boost::io::ios_precision_saver state(stream, std::numeric_limits<T>::digits10);
return stream << lower(value);
} else if (zero_in(value)) {
return stream << "0~";
} else {
std::streamsize p = stream.precision();
// FIXME poor man's power of 10, only up to 1E-15
p = (p > 15) ? 15 : p - 1;
double eps = 1.0; for(; p > 0; --p) { eps /= 10; }
T eps2 = static_cast<T>(eps / 2) * norm(value);
boost::numeric::interval<T, Policies> r = widen(value, eps2);
return stream << '[' << lower(r) << ',' << upper(r) << ']';
}
}
} // namespace io_wide
template<class T, class Policies, class CharType, class CharTraits> inline
std::basic_istream<CharType, CharTraits> &operator>>
(std::basic_istream<CharType, CharTraits> &stream,
boost::numeric::interval<T, Policies> &value)
{
T l, u;
char c = 0;
stream >> c;
if (c == '[') {
stream >> l >> c;
if (c == ',') stream >> u >> c; else u = l;
if (c != ']') stream.setstate(stream.failbit);
} else {
stream.putback(c);
stream >> l;
u = l;
}
if (stream)
value.assign(l, u);
else
value = boost::numeric::interval<T, Policies>::empty();
return stream;
}
// Test program
#include <iostream>
int main()
{
using namespace boost;
using namespace numeric;
using namespace interval_lib;
typedef interval<double,
policies<rounded_math<double>,
checking_base<double> > > I;
I tab[] = { I::empty(), I(1,1), I(1,2), I(-1,1), I(12.34,12.35),
I(1234.56,1234.57), I(123456.78, 123456.79), I::empty() };
unsigned int len = sizeof(tab) / sizeof(I);
std::cout << "Enter an interval: (it will be the last shown)\n";
std::cin >> tab[len - 1];
for(unsigned int i = 0; i < len; ++i) {
{ using namespace io_std; std::cout << tab[i] << '\n'; }
{ using namespace io_sngl; std::cout << tab[i] << '\n'; }
{ using namespace io_wdth; std::cout << tab[i] << '\n'; }
{ using namespace io_prec; std::cout << tab[i] << '\n'; }
{ using namespace io_wide; std::cout << tab[i] << '\n'; }
std::cout << '\n';
}
}
@@ -0,0 +1,146 @@
/* Boost example/newton-raphson.cpp
* Newton iteration for intervals
*
* Copyright 2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
#include <vector>
#include <algorithm>
#include <utility>
#include <iostream>
#include <iomanip>
template <class I> I f(const I& x)
{ return x * (x - 1.) * (x - 2.) * (x - 3.) * (x - 4.); }
template <class I> I f_diff(const I& x)
{ return (((5. * x - 40.) * x + 105.) * x - 100.) * x + 24.; }
static const double max_width = 1e-10;
static const double alpha = 0.75;
using namespace boost;
using namespace numeric;
using namespace interval_lib;
// First method: no empty intervals
typedef interval<double> I1_aux;
typedef unprotect<I1_aux>::type I1;
std::vector<I1> newton_raphson(const I1& xs) {
std::vector<I1> l, res;
I1 vf, vd, x, x1, x2;
l.push_back(xs);
while (!l.empty()) {
x = l.back();
l.pop_back();
bool x2_used;
double xx = median(x);
vf = f<I1>(xx);
vd = f_diff<I1>(x);
if (zero_in(vf) && zero_in(vd)) {
x1 = I1::whole();
x2_used = false;
} else {
x1 = xx - division_part1(vf, vd, x2_used);
if (x2_used) x2 = xx - division_part2(vf, vd);
}
if (overlap(x1, x)) x1 = intersect(x, x1);
else if (x2_used) { x1 = x2; x2_used = false; }
else continue;
if (x2_used) {
if (overlap(x2, x)) x2 = intersect(x, x2);
else x2_used = false;
}
if (x2_used && width(x2) > width(x1)) std::swap(x1, x2);
if (!zero_in(f(x1))) {
if (x2_used) { x1 = x2; x2_used = false; }
else continue;
}
if (width(x1) < max_width) res.push_back(x1);
else if (width(x1) > alpha * width(x)) {
std::pair<I1, I1> p = bisect(x);
if (zero_in(f(p.first))) l.push_back(p.first);
x2 = p.second;
x2_used = true;
} else l.push_back(x1);
if (x2_used && zero_in(f(x2))) {
if (width(x2) < max_width) res.push_back(x2);
else l.push_back(x2);
}
}
return res;
}
// Second method: with empty intervals
typedef change_checking<I1_aux, checking_no_nan<double> >::type I2_aux;
typedef unprotect<I2_aux>::type I2;
std::vector<I2> newton_raphson(const I2& xs) {
std::vector<I2> l, res;
I2 vf, vd, x, x1, x2;
l.push_back(xs);
while (!l.empty()) {
x = l.back();
l.pop_back();
double xx = median(x);
vf = f<I2>(xx);
vd = f_diff<I2>(x);
if (zero_in(vf) && zero_in(vd)) {
x1 = x;
x2 = I2::empty();
} else {
bool x2_used;
x1 = intersect(x, xx - division_part1(vf, vd, x2_used));
x2 = intersect(x, xx - division_part2(vf, vd, x2_used));
}
if (width(x2) > width(x1)) std::swap(x1, x2);
if (empty(x1) || !zero_in(f(x1))) {
if (!empty(x2)) { x1 = x2; x2 = I2::empty(); }
else continue;
}
if (width(x1) < max_width) res.push_back(x1);
else if (width(x1) > alpha * width(x)) {
std::pair<I2, I2> p = bisect(x);
if (zero_in(f(p.first))) l.push_back(p.first);
x2 = p.second;
} else l.push_back(x1);
if (!empty(x2) && zero_in(f(x2))) {
if (width(x2) < max_width) res.push_back(x2);
else l.push_back(x2);
}
}
return res;
}
template<class T, class Policies>
std::ostream &operator<<(std::ostream &os,
const boost::numeric::interval<T, Policies> &x) {
os << "[" << x.lower() << ", " << x.upper() << "]";
return os;
}
int main() {
{
I1_aux::traits_type::rounding rnd;
std::vector<I1> res = newton_raphson(I1(-1, 5.1));
std::cout << "Results: " << std::endl << std::setprecision(12);
for(std::vector<I1>::const_iterator i = res.begin(); i != res.end(); ++i)
std::cout << " " << *i << std::endl;
std::cout << std::endl;
}
{
I2_aux::traits_type::rounding rnd;
std::vector<I2> res = newton_raphson(I2(-1, 5.1));
std::cout << "Results: " << std::endl << std::setprecision(12);
for(std::vector<I2>::const_iterator i = res.begin(); i != res.end(); ++i)
std::cout << " " << *i << std::endl;
std::cout << std::endl;
}
}
@@ -0,0 +1,43 @@
/* Boost example/rational.cpp
* example program of how to use interval< rational<> >
*
* Copyright 2002-2003 Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
// it would have been enough to only include:
// <boost/numeric/interval.hpp>
// but it's a bit overkill to include processor intrinsics
// and transcendental functions, so we do it by ourselves
#include <boost/numeric/interval/interval.hpp> // base class
#include <boost/numeric/interval/rounded_arith.hpp> // default arithmetic rounding policy
#include <boost/numeric/interval/checking.hpp> // default checking policy
#include <boost/numeric/interval/arith.hpp> // += *= -= etc
#include <boost/numeric/interval/policies.hpp> // default policy
#include <boost/rational.hpp>
#include <iostream>
typedef boost::rational<int> Rat;
typedef boost::numeric::interval<Rat> Interval;
std::ostream& operator<<(std::ostream& os, const Interval& r) {
os << "[" << r.lower() << "," << r.upper() << "]";
return os;
}
int main() {
Rat p(2, 3), q(3, 4);
Interval z(4, 5);
Interval a(p, q);
a += z;
z *= q;
a -= p;
a /= q;
std::cout << z << std::endl;
std::cout << a << std::endl;
}
+90
View File
@@ -0,0 +1,90 @@
/* Boost example/transc.cpp
* how to use an external library (GMP/MPFR in this case) in order to
* get correct transcendental functions on intervals
*
* Copyright 2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
//extern "C" {
#include <gmp.h>
#include <mpfr.h>
//}
#include <iostream>
struct full_rounding:
boost::numeric::interval_lib::rounded_arith_opp<double>
{
private:
typedef int mpfr_func(mpfr_t, const __mpfr_struct*, mp_rnd_t);
double invoke_mpfr(double x, mpfr_func f, mp_rnd_t r) {
mpfr_t xx;
mpfr_init_set_d(xx, x, GMP_RNDN);
f(xx, xx, r);
double res = mpfr_get_d(xx, r);
mpfr_clear(xx);
return res;
}
public:
# define GENR_FUNC(name) \
double name##_down(double x) { return invoke_mpfr(x, mpfr_##name, GMP_RNDD); } \
double name##_up (double x) { return invoke_mpfr(x, mpfr_##name, GMP_RNDU); }
GENR_FUNC(exp)
GENR_FUNC(log)
GENR_FUNC(sin)
GENR_FUNC(cos)
GENR_FUNC(tan)
GENR_FUNC(asin)
GENR_FUNC(acos)
GENR_FUNC(atan)
GENR_FUNC(sinh)
GENR_FUNC(cosh)
GENR_FUNC(tanh)
GENR_FUNC(asinh)
GENR_FUNC(acosh)
GENR_FUNC(atanh)
};
namespace dummy {
using namespace boost;
using namespace numeric;
using namespace interval_lib;
typedef save_state<full_rounding> R;
typedef checking_strict<double> P;
typedef interval<double, policies<R, P> > I;
};
typedef dummy::I I;
template<class os_t>
os_t& operator<<(os_t &os, const I &a) {
os << '[' << a.lower() << ',' << a.upper() << ']';
return os;
}
int main() {
I x(0.5, 2.5);
std::cout << "x = " << x << std::endl;
std::cout.precision(16);
# define GENR_TEST(name) \
std::cout << #name "(x) = " << name(x) << std::endl
GENR_TEST(exp);
GENR_TEST(log);
GENR_TEST(sin);
GENR_TEST(cos);
GENR_TEST(tan);
GENR_TEST(asin);
GENR_TEST(acos);
GENR_TEST(atan);
GENR_TEST(sinh);
GENR_TEST(cosh);
GENR_TEST(tanh);
GENR_TEST(asinh);
GENR_TEST(acosh);
GENR_TEST(atanh);
return 0;
}
+13
View File
@@ -0,0 +1,13 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=doc/interval.htm">
</head>
<body>
Automatic redirection failed, please go to
<a href="doc/interval.htm">doc/interval.htm</a>.&nbsp;<hr>
<p>&copy; Copyright Beman Dawes, 2001</p>
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
</body>
</html>
+19
View File
@@ -0,0 +1,19 @@
{
"key": "numeric/interval",
"name": "Interval",
"authors": [
"Guillaume Melquiond",
"Hervé Brönnimann",
"Sylvain Pion"
],
"description": "Extends the usual arithmetic functions to mathematical intervals.",
"documentation": "doc/interval.htm",
"category": [
"Math"
],
"maintainers": [
"Sylvain Pion <Sylvain.Pion -at- sophia.inria.fr>",
"Herve Bronnimann <hbr -at- poly.edu>",
"Guillaume Melquiond <guillaume.melquiond -at- ens-lyon.fr>"
]
}
+55
View File
@@ -0,0 +1,55 @@
# Boost Interval Library test Jamfile
#
# Copyright 2003 Guillaume Melquiond
#
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or
# copy at http://www.boost.org/LICENSE_1_0.txt)
project
:
source-location $(BOOST_ROOT)
:
requirements
# Enable dynamic rounding on Tru64 (Alpha CPU).
<toolset>hp_cxx,<os>OSF:<cflags>"-fprm d"
<toolset>gcc,<os>OSF:<cflags>-mfp-rounding-mode=d
<toolset>gcc:<cxxflags>-frounding-math
<toolset>msvc:<cxxflags>/fp\:strict
;
# bring in rules for testing
import testing ;
{
test-suite numeric/interval :
[ compile libs/numeric/interval/test/integer.cpp ]
[ run libs/numeric/interval/test/add.cpp ]
[ run libs/numeric/interval/test/det.cpp ]
[ run libs/numeric/interval/test/fmod.cpp ]
[ run libs/numeric/interval/test/msvc_x64_flags.cpp : : : <build>no <toolset>msvc:<build>yes ]
[ run libs/numeric/interval/test/mul.cpp ]
[ run libs/numeric/interval/test/overflow.cpp ]
[ run libs/numeric/interval/test/pi.cpp ]
[ run libs/numeric/interval/test/pow.cpp ]
[ run libs/numeric/interval/test/cmp.cpp
../../../test/build//boost_test_exec_monitor/<link>static ]
[ run libs/numeric/interval/test/cmp_exn.cpp
../../../test/build//boost_test_exec_monitor/<link>static ]
[ run libs/numeric/interval/test/cmp_exp.cpp
../../../test/build//boost_test_exec_monitor/<link>static ]
[ run libs/numeric/interval/test/cmp_lex.cpp
../../../test/build//boost_test_exec_monitor/<link>static ]
[ run libs/numeric/interval/test/cmp_set.cpp
../../../test/build//boost_test_exec_monitor/<link>static ]
# https://github.com/boostorg/interval/issues/15
# [ run libs/numeric/interval/test/cmp_tribool.cpp
# ../../../test/build//boost_test_exec_monitor/<link>static ]
[ run libs/numeric/interval/test/test_float.cpp
../../../test/build//boost_test_exec_monitor/<link>static
: : : <build>yes <toolset>msvc-10.0:<build>no ]
# https://github.com/boostorg/interval/issues/17
;
}
+243
View File
@@ -0,0 +1,243 @@
/* Boost test/add.cpp
* test with symbolic operations if the addition algorithm is correct
*
* Copyright 2002-2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval/interval.hpp>
#include <boost/numeric/interval/arith.hpp>
#include <boost/numeric/interval/rounding.hpp>
#include <boost/numeric/interval/rounded_arith.hpp>
#include <boost/numeric/interval/utility.hpp>
#include <boost/numeric/interval/policies.hpp>
#include <boost/test/minimal.hpp>
#include "bugs.hpp"
typedef enum { EXPR_VAR, EXPR_NEG, EXPR_UP, EXPR_DOWN, EXPR_ADD, EXPR_SUB } e_type;
struct expr;
struct pexpr {
expr *ptr;
expr* operator->() { return ptr; }
pexpr(expr *p = NULL): ptr(p) { }
};
struct expr {
e_type type;
int var;
pexpr e;
pexpr e1, e2;
};
pexpr var(int v) {
pexpr e = new expr;
e->type = EXPR_VAR;
e->var = v;
return e;
}
pexpr operator+(pexpr, pexpr);
pexpr operator-(pexpr, pexpr);
pexpr operator-(pexpr);
pexpr operator+(pexpr a, pexpr b) {
if (a->type == EXPR_NEG) return b - a->e;
if (b->type == EXPR_NEG) return a - b->e;
if (a->type == EXPR_VAR && b->type == EXPR_VAR && a->var > b->var) return b + a;
pexpr c = new expr;
c->type = EXPR_ADD;
c->e1 = a;
c->e2 = b;
return c;
}
pexpr operator-(pexpr a, pexpr b) {
if (b->type == EXPR_NEG) return a + b->e;
pexpr c = new expr;
c->type = EXPR_SUB;
c->e1 = a;
c->e2 = b;
return c;
}
pexpr down(pexpr a) {
pexpr e = new expr;
e->type = EXPR_DOWN;
e->e = a;
return e;
}
pexpr up(pexpr a) {
pexpr e = new expr;
e->type = EXPR_UP;
e->e = a;
return e;
}
pexpr operator-(pexpr a) {
if (a->type == EXPR_NEG) return a->e;
if (a->type == EXPR_UP) return down(-a->e);
if (a->type == EXPR_DOWN) return up(-a->e);
if (a->type == EXPR_SUB) return a->e2 - a->e1;
if (a->type == EXPR_ADD) return -a->e1 - a->e2;
pexpr e = new expr;
e->type = EXPR_NEG;
e->e = a;
return e;
}
bool operator==(pexpr a, pexpr b) {
if (a->type != b->type) return false;
if (a->type == EXPR_VAR) return a->var == b->var;
if (a->type == EXPR_DOWN || a->type == EXPR_UP || a->type == EXPR_NEG)
return a->e == b->e;
return a->e1 == b->e1 && a->e2 == b->e2;
}
bool operator<=(pexpr, pexpr) { return true; }
namespace boost {
namespace numeric {
namespace interval_lib {
template<>
struct rounding_control<pexpr> {
typedef enum { RND_U, RND_M, RND_D } rounding_mode;
static rounding_mode mode;
rounding_control() { mode = RND_M; }
void get_rounding_mode(rounding_mode& m) { m = mode; }
void set_rounding_mode(rounding_mode m) { mode = m; }
void upward() { mode = RND_U; }
void downward() { mode = RND_D; }
pexpr force_rounding(pexpr a) {
switch (mode) {
case RND_U: return up(a);
case RND_D: return down(a);
default: throw "Unset rounding mode";
}
}
};
rounding_control<pexpr>::rounding_mode rounding_control<pexpr>::mode = RND_M;
} // namespace interval_lib
} // namespace numeric
} // namespace boost
template<class I>
bool test_neg() {
I a(var(0), var(1));
return equal(-a, I(-var(1), -var(0)));
}
template<class I>
bool test_add() {
I a(var(0), var(1)), b(var(2), var(3));
return equal(a + b, I(down(var(0) + var(2)), up(var(1) + var(3))));
}
template<class I>
bool test_add1() {
I a(var(0), var(1));
return equal(a + var(2), I(down(var(0) + var(2)), up(var(1) + var(2))));
}
template<class I>
bool test_add2() {
I a(var(0), var(1));
return equal(var(2) + a, I(down(var(0) + var(2)), up(var(1) + var(2))));
}
template<class I>
bool test_sub() {
I a(var(0), var(1)), b(var(2), var(3));
return equal(a - b, I(down(var(0) - var(3)), up(var(1) - var(2))));
}
template<class I>
bool test_sub1() {
I a(var(0), var(1));
return equal(a - var(2), I(down(var(0) - var(2)), up(var(1) - var(2))));
}
template<class I>
bool test_sub2() {
I a(var(0), var(1));
return equal(var(2) - a, I(down(var(2) - var(1)), up(var(2) - var(0))));
}
template<class I>
bool test_addeq() {
I a(var(0), var(1)), b(var(2), var(3));
return equal(a += b, I(down(var(0) + var(2)), up(var(1) + var(3))));
}
template<class I>
bool test_addeq1() {
I a(var(0), var(1));
return equal(a += var(2), I(down(var(0) + var(2)), up(var(1) + var(2))));
}
template<class I>
bool test_subeq() {
I a(var(0), var(1)), b(var(2), var(3));
return equal(a -= b, I(down(var(0) - var(3)), up(var(1) - var(2))));
}
template<class I>
bool test_subeq1() {
I a(var(0), var(1));
return equal(a -= var(2), I(down(var(0) - var(2)), up(var(1) - var(2))));
}
struct my_checking
{
static pexpr pos_inf() { throw; }
static pexpr neg_inf() { throw; }
static pexpr nan() { throw; }
static bool is_nan(const pexpr&) { return false; }
static pexpr empty_lower() { throw; }
static pexpr empty_upper() { throw; }
static bool is_empty(const pexpr&, const pexpr&) { return false; }
};
template<class Rounding>
struct my_interval {
private:
typedef boost::numeric::interval_lib::save_state<Rounding> my_rounding;
typedef boost::numeric::interval_lib::policies<my_rounding, my_checking> my_policies;
public:
typedef boost::numeric::interval<pexpr, my_policies> type;
};
int test_main(int, char *[]) {
typedef my_interval<boost::numeric::interval_lib::rounded_arith_std<pexpr> >::type I1;
typedef my_interval<boost::numeric::interval_lib::rounded_arith_opp<pexpr> >::type I2;
BOOST_CHECK((test_neg<I1>()));
BOOST_CHECK((test_neg<I2>()));
BOOST_CHECK((test_add<I1>()));
BOOST_CHECK((test_add<I2>()));
BOOST_CHECK((test_add1<I1>()));
BOOST_CHECK((test_add1<I2>()));
BOOST_CHECK((test_add2<I1>()));
BOOST_CHECK((test_add2<I2>()));
BOOST_CHECK((test_sub<I1>()));
BOOST_CHECK((test_sub<I2>()));
BOOST_CHECK((test_sub1<I1>()));
BOOST_CHECK((test_sub1<I2>()));
BOOST_CHECK((test_sub2<I1>()));
BOOST_CHECK((test_sub2<I2>()));
BOOST_CHECK((test_addeq<I1>()));
BOOST_CHECK((test_addeq<I2>()));
BOOST_CHECK((test_addeq1<I1>()));
BOOST_CHECK((test_addeq1<I2>()));
BOOST_CHECK((test_subeq<I1>()));
BOOST_CHECK((test_subeq<I2>()));
BOOST_CHECK((test_subeq1<I1>()));
BOOST_CHECK((test_subeq1<I2>()));
return 0;
}
+43
View File
@@ -0,0 +1,43 @@
/* Boost test/bugs.hpp
* Handles namespace resolution quirks in older compilers and braindead
* warnings [Herve, June 3rd 2003]
*
* Copyright 2002-2003 Hervé Brönnimann
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
// Borland compiler complains about unused variables a bit easily and
// incorrectly
#ifdef __BORLANDC__
namespace detail {
template <class T> inline void ignore_unused_variable_warning(const T&) { }
inline void ignore_warnings() {
# ifdef BOOST_NUMERIC_INTERVAL_CONSTANTS_HPP
using namespace boost::numeric::interval_lib::constants;
ignore_unused_variable_warning( pi_f_l );
ignore_unused_variable_warning( pi_f_u );
ignore_unused_variable_warning( pi_d_l );
ignore_unused_variable_warning( pi_d_u );
# endif
}
}
#endif
// Some compilers are broken with respect to name resolution
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) || defined( __BORLANDC__)
using namespace boost;
using namespace numeric;
using namespace interval_lib;
#endif
+215
View File
@@ -0,0 +1,215 @@
/* Boost test/cmp.cpp
* test standard comparison functions
*
* Copyright 2002-2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include "cmp_header.hpp"
// comparisons between [1,2] and [3,4]
static void test_12_34() {
const I a(1,2), b(3,4);
BOOST_CHECK(a < b);
BOOST_CHECK(a <= b);
BOOST_CHECK(!(a > b));
BOOST_CHECK(!(a >= b));
BOOST_CHECK(b > a);
BOOST_CHECK(b >= a);
BOOST_CHECK(!(b < a));
BOOST_CHECK(!(b <= a));
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,3] and [2,4]
static void test_13_24() {
const I a(1,3), b(2,4);
BOOST_C_EXN(a < b);
BOOST_C_EXN(a <= b);
BOOST_C_EXN(a > b);
BOOST_C_EXN(a >= b);
BOOST_C_EXN(b < a);
BOOST_C_EXN(b <= a);
BOOST_C_EXN(b > a);
BOOST_C_EXN(b >= a);
BOOST_C_EXN(a == b);
BOOST_C_EXN(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and [2,3]
static void test_12_23() {
const I a(1,2), b(2,3);
BOOST_C_EXN(a < b);
BOOST_CHECK(a <= b);
BOOST_CHECK(!(a > b));
BOOST_C_EXN(a >= b);
BOOST_CHECK(!(b < a));
BOOST_C_EXN(b <= a);
BOOST_C_EXN(b > a);
BOOST_CHECK(b >= a);
BOOST_C_EXN(a == b);
BOOST_C_EXN(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and 0
static void test_12_0() {
const I a(1,2);
const int b = 0;
BOOST_CHECK(!(a < b));
BOOST_CHECK(!(a <= b));
BOOST_CHECK(a > b);
BOOST_CHECK(a >= b);
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and 1
static void test_12_1() {
const I a(1,2);
const int b = 1;
BOOST_CHECK(!(a < b));
BOOST_C_EXN(a <= b);
BOOST_C_EXN(a > b);
BOOST_CHECK(a >= b);
BOOST_C_EXN(a == b);
BOOST_C_EXN(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and 2
static void test_12_2() {
const I a(1,2);
const int b = 2;
BOOST_C_EXN(a < b);
BOOST_CHECK(a <= b);
BOOST_CHECK(!(a > b));
BOOST_C_EXN(a >= b);
BOOST_C_EXN(a == b);
BOOST_C_EXN(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and 3
static void test_12_3() {
const I a(1,2);
const int b = 3;
BOOST_CHECK(a < b);
BOOST_CHECK(a <= b);
BOOST_CHECK(!(a > b));
BOOST_CHECK(!(a >= b));
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and [1,2]
static void test_12_12() {
const I a(1,2), b(1,2);
BOOST_C_EXN(a == b);
BOOST_C_EXN(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,1] and [1,1]
static void test_11_11() {
const I a(1,1), b(1,1);
BOOST_CHECK(a == b);
BOOST_CHECK(!(a != b));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,1] and 1
static void test_11_1() {
const I a(1,1);
const int b = 1;
BOOST_CHECK(a == b);
BOOST_CHECK(!(a != b));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
int test_main(int, char *[]) {
test_12_34();
test_13_24();
test_12_23();
test_12_0();
test_12_1();
test_12_2();
test_12_3();
test_12_12();
test_11_11();
test_11_1();
return 0;
}
+230
View File
@@ -0,0 +1,230 @@
/* Boost test/cmp_exn.cpp
* test policies with respect to exception throwing
*
* Copyright 2004 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval/interval.hpp>
#include <boost/numeric/interval/checking.hpp>
#include <boost/numeric/interval/compare.hpp>
#include <boost/numeric/interval/policies.hpp>
#include <boost/numeric/interval/compare/tribool.hpp>
#include <boost/test/test_tools.hpp>
struct my_checking
{
static int nan() { return -1; }
static bool is_nan(int x) { return x < 0; }
static int empty_lower() { return -1; }
static int empty_upper() { return -1; }
static bool is_empty(int l, int u) { return l == -1 && u == -1; }
};
struct empty_class {};
typedef boost::numeric::interval_lib::policies< empty_class, my_checking >
my_policies;
typedef boost::numeric::interval<int, my_policies> I;
#define BOOST_C_EXN(e) \
BOOST_CHECK_THROW(e, boost::numeric::interval_lib::comparison_error)
static void test_cer()
{
I const a(I::empty()), b(1,2);
int const c = 0, d = my_checking::nan();
using namespace boost::numeric::interval_lib::compare::certain;
BOOST_C_EXN(a < b);
BOOST_C_EXN(a <= b);
BOOST_C_EXN(a > b);
BOOST_C_EXN(a >= b);
BOOST_C_EXN(a == b);
BOOST_C_EXN(a != b);
BOOST_C_EXN(b < a);
BOOST_C_EXN(b <= a);
BOOST_C_EXN(b > a);
BOOST_C_EXN(b >= a);
BOOST_C_EXN(b == a);
BOOST_C_EXN(b != a);
BOOST_C_EXN(a < c);
BOOST_C_EXN(a <= c);
BOOST_C_EXN(a > c);
BOOST_C_EXN(a >= c);
BOOST_C_EXN(a == c);
BOOST_C_EXN(a != c);
BOOST_C_EXN(b < d);
BOOST_C_EXN(b <= d);
BOOST_C_EXN(b > d);
BOOST_C_EXN(b >= d);
BOOST_C_EXN(b == d);
BOOST_C_EXN(b != d);
}
static void test_def()
{
I const a(I::empty()), b(1,2);
int const c = 0, d = my_checking::nan();
BOOST_C_EXN(a < b);
BOOST_C_EXN(a <= b);
BOOST_C_EXN(a > b);
BOOST_C_EXN(a >= b);
BOOST_C_EXN(a == b);
BOOST_C_EXN(a != b);
BOOST_C_EXN(b < a);
BOOST_C_EXN(b <= a);
BOOST_C_EXN(b > a);
BOOST_C_EXN(b >= a);
BOOST_C_EXN(b == a);
BOOST_C_EXN(b != a);
BOOST_C_EXN(a < c);
BOOST_C_EXN(a <= c);
BOOST_C_EXN(a > c);
BOOST_C_EXN(a >= c);
BOOST_C_EXN(a == c);
BOOST_C_EXN(a != c);
BOOST_C_EXN(b < d);
BOOST_C_EXN(b <= d);
BOOST_C_EXN(b > d);
BOOST_C_EXN(b >= d);
BOOST_C_EXN(b == d);
BOOST_C_EXN(b != d);
}
static void test_lex()
{
I const a(I::empty()), b(1,2);
int const c = 0, d = my_checking::nan();
using namespace boost::numeric::interval_lib::compare::lexicographic;
BOOST_C_EXN(a < b);
BOOST_C_EXN(a <= b);
BOOST_C_EXN(a > b);
BOOST_C_EXN(a >= b);
BOOST_C_EXN(a == b);
BOOST_C_EXN(a != b);
BOOST_C_EXN(b < a);
BOOST_C_EXN(b <= a);
BOOST_C_EXN(b > a);
BOOST_C_EXN(b >= a);
BOOST_C_EXN(b == a);
BOOST_C_EXN(b != a);
BOOST_C_EXN(a < c);
BOOST_C_EXN(a <= c);
BOOST_C_EXN(a > c);
BOOST_C_EXN(a >= c);
BOOST_C_EXN(a == c);
BOOST_C_EXN(a != c);
BOOST_C_EXN(b < d);
BOOST_C_EXN(b <= d);
BOOST_C_EXN(b > d);
BOOST_C_EXN(b >= d);
BOOST_C_EXN(b == d);
BOOST_C_EXN(b != d);
}
static void test_pos()
{
I const a(I::empty()), b(1,2);
int const c = 0, d = my_checking::nan();
using namespace boost::numeric::interval_lib::compare::possible;
BOOST_C_EXN(a < b);
BOOST_C_EXN(a <= b);
BOOST_C_EXN(a > b);
BOOST_C_EXN(a >= b);
BOOST_C_EXN(a == b);
BOOST_C_EXN(a != b);
BOOST_C_EXN(b < a);
BOOST_C_EXN(b <= a);
BOOST_C_EXN(b > a);
BOOST_C_EXN(b >= a);
BOOST_C_EXN(b == a);
BOOST_C_EXN(b != a);
BOOST_C_EXN(a < c);
BOOST_C_EXN(a <= c);
BOOST_C_EXN(a > c);
BOOST_C_EXN(a >= c);
BOOST_C_EXN(a == c);
BOOST_C_EXN(a != c);
BOOST_C_EXN(b < d);
BOOST_C_EXN(b <= d);
BOOST_C_EXN(b > d);
BOOST_C_EXN(b >= d);
BOOST_C_EXN(b == d);
BOOST_C_EXN(b != d);
}
static void test_set()
{
I const a(I::empty()), b(1,2);
int const c = 0;
using namespace boost::numeric::interval_lib::compare::set;
BOOST_C_EXN(a < c);
BOOST_C_EXN(a <= c);
BOOST_C_EXN(a > c);
BOOST_C_EXN(a >= c);
BOOST_C_EXN(a == c);
BOOST_C_EXN(a != c);
BOOST_C_EXN(b < c);
BOOST_C_EXN(b <= c);
BOOST_C_EXN(b > c);
BOOST_C_EXN(b >= c);
BOOST_C_EXN(b == c);
BOOST_C_EXN(b != c);
}
static void test_tri()
{
I const a(I::empty()), b(1,2);
int const c = 0, d = my_checking::nan();
using namespace boost::numeric::interval_lib::compare::tribool;
BOOST_C_EXN(a < b);
BOOST_C_EXN(a <= b);
BOOST_C_EXN(a > b);
BOOST_C_EXN(a >= b);
BOOST_C_EXN(a == b);
BOOST_C_EXN(a != b);
BOOST_C_EXN(b < a);
BOOST_C_EXN(b <= a);
BOOST_C_EXN(b > a);
BOOST_C_EXN(b >= a);
BOOST_C_EXN(b == a);
BOOST_C_EXN(b != a);
BOOST_C_EXN(a < c);
BOOST_C_EXN(a <= c);
BOOST_C_EXN(a > c);
BOOST_C_EXN(a >= c);
BOOST_C_EXN(a == c);
BOOST_C_EXN(a != c);
BOOST_C_EXN(b < d);
BOOST_C_EXN(b <= d);
BOOST_C_EXN(b > d);
BOOST_C_EXN(b >= d);
BOOST_C_EXN(b == d);
BOOST_C_EXN(b != d);
}
int test_main(int, char *[]) {
test_cer();
test_def();
test_lex();
test_pos();
test_set();
test_tri();
return 0;
}
+366
View File
@@ -0,0 +1,366 @@
/* Boost test/cmp_exp.cpp
* test explicit comparison functions
*
* Copyright 2002-2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include "cmp_header.hpp"
// comparisons between [1,2] and [3,4]
static void test_12_34() {
const I a(1,2), b(3,4);
BOOST_CHECK(cerlt(a, b));
BOOST_CHECK(cerle(a, b));
BOOST_CHECK(!cergt(a, b));
BOOST_CHECK(!cerge(a, b));
BOOST_CHECK(!cerlt(b, a));
BOOST_CHECK(!cerle(b, a));
BOOST_CHECK(cergt(b, a));
BOOST_CHECK(cerge(b, a));
BOOST_CHECK(poslt(a, b));
BOOST_CHECK(posle(a, b));
BOOST_CHECK(!posgt(a, b));
BOOST_CHECK(!posge(a, b));
BOOST_CHECK(!poslt(b, a));
BOOST_CHECK(!posle(b, a));
BOOST_CHECK(posgt(b, a));
BOOST_CHECK(posge(b, a));
BOOST_CHECK(!cereq(a, b));
BOOST_CHECK(cerne(a, b));
BOOST_CHECK(!poseq(a, b));
BOOST_CHECK(posne(a, b));
BOOST_CHECK(!cereq(b, a));
BOOST_CHECK(cerne(b, a));
BOOST_CHECK(!poseq(b, a));
BOOST_CHECK(posne(b, a));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,3] and [2,4]
static void test_13_24() {
const I a(1,3), b(2,4);
BOOST_CHECK(!cerlt(a, b));
BOOST_CHECK(!cerle(a, b));
BOOST_CHECK(!cergt(a, b));
BOOST_CHECK(!cerge(a, b));
BOOST_CHECK(!cerlt(b, a));
BOOST_CHECK(!cerle(b, a));
BOOST_CHECK(!cergt(b, a));
BOOST_CHECK(!cerge(b, a));
BOOST_CHECK(poslt(a, b));
BOOST_CHECK(posle(a, b));
BOOST_CHECK(posgt(a, b));
BOOST_CHECK(posge(a, b));
BOOST_CHECK(poslt(b, a));
BOOST_CHECK(posle(b, a));
BOOST_CHECK(posgt(b, a));
BOOST_CHECK(posge(b, a));
BOOST_CHECK(!cereq(a, b));
BOOST_CHECK(!cerne(a, b));
BOOST_CHECK(poseq(a, b));
BOOST_CHECK(posne(a, b));
BOOST_CHECK(!cereq(b, a));
BOOST_CHECK(!cerne(b, a));
BOOST_CHECK(poseq(b, a));
BOOST_CHECK(posne(b, a));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and [2,3]
static void test_12_23() {
const I a(1,2), b(2,3);
BOOST_CHECK(!cerlt(a, b));
BOOST_CHECK(cerle(a, b));
BOOST_CHECK(!cergt(a, b));
BOOST_CHECK(!cerge(a, b));
BOOST_CHECK(!cerlt(b, a));
BOOST_CHECK(!cerle(b, a));
BOOST_CHECK(!cergt(b, a));
BOOST_CHECK(cerge(b, a));
BOOST_CHECK(poslt(a, b));
BOOST_CHECK(posle(a, b));
BOOST_CHECK(!posgt(a, b));
BOOST_CHECK(posge(a, b));
BOOST_CHECK(!poslt(b, a));
BOOST_CHECK(posle(b, a));
BOOST_CHECK(posgt(b, a));
BOOST_CHECK(posge(b, a));
BOOST_CHECK(!cereq(a, b));
BOOST_CHECK(!cerne(a, b));
BOOST_CHECK(poseq(a, b));
BOOST_CHECK(posne(a, b));
BOOST_CHECK(!cereq(b, a));
BOOST_CHECK(!cerne(b, a));
BOOST_CHECK(poseq(b, a));
BOOST_CHECK(posne(b, a));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and 0
static void test_12_0() {
const I a(1,2);
const int b = 0;
BOOST_CHECK(!cerlt(a, b));
BOOST_CHECK(!cerle(a, b));
BOOST_CHECK(cergt(a, b));
BOOST_CHECK(cerge(a, b));
BOOST_CHECK(cerlt(b, a));
BOOST_CHECK(cerle(b, a));
BOOST_CHECK(!cergt(b, a));
BOOST_CHECK(!cerge(b, a));
BOOST_CHECK(!poslt(a, b));
BOOST_CHECK(!posle(a, b));
BOOST_CHECK(posgt(a, b));
BOOST_CHECK(posge(a, b));
BOOST_CHECK(poslt(b, a));
BOOST_CHECK(posle(b, a));
BOOST_CHECK(!posgt(b, a));
BOOST_CHECK(!posge(b, a));
BOOST_CHECK(!cereq(a, b));
BOOST_CHECK(cerne(a, b));
BOOST_CHECK(!poseq(a, b));
BOOST_CHECK(posne(a, b));
BOOST_CHECK(!cereq(b, a));
BOOST_CHECK(cerne(b, a));
BOOST_CHECK(!poseq(b, a));
BOOST_CHECK(posne(b, a));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and 1
static void test_12_1() {
const I a(1,2);
const int b = 1;
BOOST_CHECK(!cerlt(a, b));
BOOST_CHECK(!cerle(a, b));
BOOST_CHECK(!cergt(a, b));
BOOST_CHECK(cerge(a, b));
BOOST_CHECK(!cerlt(b, a));
BOOST_CHECK(cerle(b, a));
BOOST_CHECK(!cergt(b, a));
BOOST_CHECK(!cerge(b, a));
BOOST_CHECK(!poslt(a, b));
BOOST_CHECK(posle(a, b));
BOOST_CHECK(posgt(a, b));
BOOST_CHECK(posge(a, b));
BOOST_CHECK(poslt(b, a));
BOOST_CHECK(posle(b, a));
BOOST_CHECK(!posgt(b, a));
BOOST_CHECK(posge(b, a));
BOOST_CHECK(!cereq(a, b));
BOOST_CHECK(!cerne(a, b));
BOOST_CHECK(poseq(a, b));
BOOST_CHECK(posne(a, b));
BOOST_CHECK(!cereq(b, a));
BOOST_CHECK(!cerne(b, a));
BOOST_CHECK(poseq(b, a));
BOOST_CHECK(posne(b, a));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and 2
static void test_12_2() {
const I a(1,2);
const int b = 2;
BOOST_CHECK(!cerlt(a, b));
BOOST_CHECK(cerle(a, b));
BOOST_CHECK(!cergt(a, b));
BOOST_CHECK(!cerge(a, b));
BOOST_CHECK(!cerlt(b, a));
BOOST_CHECK(!cerle(b, a));
BOOST_CHECK(!cergt(b, a));
BOOST_CHECK(cerge(b, a));
BOOST_CHECK(poslt(a, b));
BOOST_CHECK(posle(a, b));
BOOST_CHECK(!posgt(a, b));
BOOST_CHECK(posge(a, b));
BOOST_CHECK(!poslt(b, a));
BOOST_CHECK(posle(b, a));
BOOST_CHECK(posgt(b, a));
BOOST_CHECK(posge(b, a));
BOOST_CHECK(!cereq(a, b));
BOOST_CHECK(!cerne(a, b));
BOOST_CHECK(poseq(a, b));
BOOST_CHECK(posne(a, b));
BOOST_CHECK(!cereq(b, a));
BOOST_CHECK(!cerne(b, a));
BOOST_CHECK(poseq(b, a));
BOOST_CHECK(posne(b, a));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and 3
static void test_12_3() {
const I a(1,2);
const int b = 3;
BOOST_CHECK(cerlt(a, b));
BOOST_CHECK(cerle(a, b));
BOOST_CHECK(!cergt(a, b));
BOOST_CHECK(!cerge(a, b));
BOOST_CHECK(!cerlt(b, a));
BOOST_CHECK(!cerle(b, a));
BOOST_CHECK(cergt(b, a));
BOOST_CHECK(cerge(b, a));
BOOST_CHECK(poslt(a, b));
BOOST_CHECK(posle(a, b));
BOOST_CHECK(!posgt(a, b));
BOOST_CHECK(!posge(a, b));
BOOST_CHECK(!poslt(b, a));
BOOST_CHECK(!posle(b, a));
BOOST_CHECK(posgt(b, a));
BOOST_CHECK(posge(b, a));
BOOST_CHECK(!cereq(a, b));
BOOST_CHECK(cerne(a, b));
BOOST_CHECK(!poseq(a, b));
BOOST_CHECK(posne(a, b));
BOOST_CHECK(!cereq(b, a));
BOOST_CHECK(cerne(b, a));
BOOST_CHECK(!poseq(b, a));
BOOST_CHECK(posne(b, a));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
static void test_12_12() {
const I a(1,2), b(1,2);
BOOST_CHECK(!cereq(a, b));
BOOST_CHECK(!cerne(a, b));
BOOST_CHECK(poseq(a, b));
BOOST_CHECK(posne(a, b));
BOOST_CHECK(!cereq(b, a));
BOOST_CHECK(!cerne(b, a));
BOOST_CHECK(poseq(b, a));
BOOST_CHECK(posne(b, a));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
static void test_11_11() {
const I a(1,1), b(1,1);
BOOST_CHECK(cereq(a, b));
BOOST_CHECK(!cerne(a, b));
BOOST_CHECK(poseq(a, b));
BOOST_CHECK(!posne(a, b));
BOOST_CHECK(cereq(b, a));
BOOST_CHECK(!cerne(b, a));
BOOST_CHECK(poseq(b, a));
BOOST_CHECK(!posne(b, a));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
static void test_11_1() {
const I a(1,1);
const int b = 1;
BOOST_CHECK(cereq(a, b));
BOOST_CHECK(!cerne(a, b));
BOOST_CHECK(poseq(a, b));
BOOST_CHECK(!posne(a, b));
BOOST_CHECK(cereq(b, a));
BOOST_CHECK(!cerne(b, a));
BOOST_CHECK(poseq(b, a));
BOOST_CHECK(!posne(b, a));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
int test_main(int, char *[]) {
test_12_34();
test_13_24();
test_12_23();
test_12_0();
test_12_1();
test_12_2();
test_12_3();
test_12_12();
test_11_11();
test_11_1();
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
/* Boost test/cmp_header.hpp header file
*
* Copyright 2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval/interval.hpp>
#include <boost/numeric/interval/checking.hpp>
#include <boost/numeric/interval/compare.hpp>
#include <boost/numeric/interval/policies.hpp>
#include <boost/test/test_tools.hpp>
#include "bugs.hpp"
struct empty_class {};
typedef boost::numeric::interval_lib::policies
<empty_class, boost::numeric::interval_lib::checking_base<int> >
my_policies;
typedef boost::numeric::interval<int, my_policies> I;
#define BOOST_C_EXN(e) \
BOOST_CHECK_THROW(e, boost::numeric::interval_lib::comparison_error)
+217
View File
@@ -0,0 +1,217 @@
/* Boost test/cmp_lex.cpp
* test compare::lexicographic
*
* Copyright 2002-2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include "cmp_header.hpp"
using namespace boost::numeric::interval_lib::compare::lexicographic;
// comparisons between [1,2] and [3,4]
static void test_12_34() {
const I a(1,2), b(3,4);
BOOST_CHECK(a < b);
BOOST_CHECK(a <= b);
BOOST_CHECK(!(a > b));
BOOST_CHECK(!(a >= b));
BOOST_CHECK(b > a);
BOOST_CHECK(b >= a);
BOOST_CHECK(!(b < a));
BOOST_CHECK(!(b <= a));
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,3] and [2,4]
static void test_13_24() {
const I a(1,3), b(2,4);
BOOST_CHECK(a < b);
BOOST_CHECK(a <= b);
BOOST_CHECK(!(a > b));
BOOST_CHECK(!(a >= b));
BOOST_CHECK(!(b < a));
BOOST_CHECK(!(b <= a));
BOOST_CHECK(b > a);
BOOST_CHECK(b >= a);
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and [2,3]
static void test_12_23() {
const I a(1,2), b(2,3);
BOOST_CHECK(a < b);
BOOST_CHECK(a <= b);
BOOST_CHECK(!(a > b));
BOOST_CHECK(!(a >= b));
BOOST_CHECK(!(b < a));
BOOST_CHECK(!(b <= a));
BOOST_CHECK(b > a);
BOOST_CHECK(b >= a);
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and 0
static void test_12_0() {
const I a(1,2);
const int b = 0;
BOOST_CHECK(!(a < b));
BOOST_CHECK(!(a <= b));
BOOST_CHECK(a > b);
BOOST_CHECK(a >= b);
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and 1
static void test_12_1() {
const I a(1,2);
const int b = 1;
BOOST_CHECK(!(a < b));
BOOST_CHECK(!(a <= b));
BOOST_CHECK(a > b);
BOOST_CHECK(a >= b);
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and 2
static void test_12_2() {
const I a(1,2);
const int b = 2;
BOOST_CHECK(a < b);
BOOST_CHECK(a <= b);
BOOST_CHECK(!(a > b));
BOOST_CHECK(!(a >= b));
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and 3
static void test_12_3() {
const I a(1,2);
const int b = 3;
BOOST_CHECK(a < b);
BOOST_CHECK(a <= b);
BOOST_CHECK(!(a > b));
BOOST_CHECK(!(a >= b));
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
static void test_12_12() {
const I a(1,2), b(1,2);
BOOST_CHECK(a == b);
BOOST_CHECK(!(a != b));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
static void test_11_11() {
const I a(1,1), b(1,1);
BOOST_CHECK(a == b);
BOOST_CHECK(!(a != b));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
static void test_11_1() {
const I a(1,1);
const int b = 1;
BOOST_CHECK(a == b);
BOOST_CHECK(!(a != b));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
int test_main(int, char *[]) {
test_12_34();
test_13_24();
test_12_23();
test_12_0();
test_12_1();
test_12_2();
test_12_3();
test_12_12();
test_11_11();
test_11_1();
return 0;
}
+218
View File
@@ -0,0 +1,218 @@
/* Boost test/cmp_set.cpp
* test compare::set
*
* Copyright 2004 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include "cmp_header.hpp"
using namespace boost::numeric::interval_lib::compare::set;
// comparisons between [1,2] and [3,4]
static void test_12_34() {
const I a(1,2), b(3,4);
BOOST_CHECK(!(a < b));
BOOST_CHECK(!(a <= b));
BOOST_CHECK(!(a > b));
BOOST_CHECK(!(a >= b));
BOOST_CHECK(!(b > a));
BOOST_CHECK(!(b >= a));
BOOST_CHECK(!(b < a));
BOOST_CHECK(!(b <= a));
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,3] and [2,4]
static void test_13_24() {
const I a(1,3), b(2,4);
BOOST_CHECK(!(a < b));
BOOST_CHECK(!(a <= b));
BOOST_CHECK(!(a > b));
BOOST_CHECK(!(a >= b));
BOOST_CHECK(!(b < a));
BOOST_CHECK(!(b <= a));
BOOST_CHECK(!(b > a));
BOOST_CHECK(!(b >= a));
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,4] and [2,3]
static void test_14_23() {
const I a(1,4), b(2,3);
BOOST_CHECK(!(a < b));
BOOST_CHECK(!(a <= b));
BOOST_CHECK(a > b);
BOOST_CHECK(a >= b);
BOOST_CHECK(b < a);
BOOST_CHECK(b <= a);
BOOST_CHECK(!(b > a));
BOOST_CHECK(!(b >= a));
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and [2,3]
static void test_12_23() {
const I a(1,2), b(2,3);
BOOST_CHECK(!(a < b));
BOOST_CHECK(!(a <= b));
BOOST_CHECK(!(a > b));
BOOST_CHECK(!(a >= b));
BOOST_CHECK(!(b < a));
BOOST_CHECK(!(b <= a));
BOOST_CHECK(!(b > a));
BOOST_CHECK(!(b >= a));
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and empty set
static void test_12_E() {
I a(1, 2), b(I::empty());
BOOST_CHECK(!(a < b));
BOOST_CHECK(!(a <= b));
BOOST_CHECK(a > b);
BOOST_CHECK(a >= b);
BOOST_CHECK(b < a);
BOOST_CHECK(b <= a);
BOOST_CHECK(!(b > a));
BOOST_CHECK(!(b >= a));
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between two empty sets
static void test_E_E() {
I a(I::empty()), b(I::empty());
BOOST_CHECK(!(a < b));
BOOST_CHECK(a <= b);
BOOST_CHECK(!(a > b));
BOOST_CHECK(a >= b);
BOOST_CHECK(!(b < a));
BOOST_CHECK(b <= a);
BOOST_CHECK(!(b > a));
BOOST_CHECK(b >= a);
BOOST_CHECK(a == b);
BOOST_CHECK(!(a != b));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and [1,2]
static void test_12_12() {
const I a(1,2), b(1,2);
BOOST_CHECK(!(a < b));
BOOST_CHECK(a <= b);
BOOST_CHECK(!(a > b));
BOOST_CHECK(a >= b);
BOOST_CHECK(!(b < a));
BOOST_CHECK(b <= a);
BOOST_CHECK(!(b > a));
BOOST_CHECK(b >= a);
BOOST_CHECK(a == b);
BOOST_CHECK(!(a != b));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,1] and [1,1]
static void test_11_11() {
const I a(1,1), b(1,1);
BOOST_CHECK(!(a < b));
BOOST_CHECK(a <= b);
BOOST_CHECK(!(a > b));
BOOST_CHECK(a >= b);
BOOST_CHECK(!(b < a));
BOOST_CHECK(b <= a);
BOOST_CHECK(!(b > a));
BOOST_CHECK(b >= a);
BOOST_CHECK(a == b);
BOOST_CHECK(!(a != b));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
int test_main(int, char *[]) {
test_12_34();
test_13_24();
test_14_23();
test_12_23();
test_12_E();
test_E_E();
test_12_12();
test_11_11();
return 0;
}
+224
View File
@@ -0,0 +1,224 @@
/* Boost test/cmp_tribool.cpp
* test compare::tribool
*
* Copyright 2004 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include "cmp_header.hpp"
#include <boost/numeric/interval/compare/tribool.hpp>
using namespace boost::numeric::interval_lib::compare::tribool;
// comparisons between [1,2] and [3,4]
static void test_12_34() {
const I a(1,2), b(3,4);
BOOST_CHECK(a < b);
BOOST_CHECK(a <= b);
BOOST_CHECK(!(a > b));
BOOST_CHECK(!(a >= b));
BOOST_CHECK(b > a);
BOOST_CHECK(b >= a);
BOOST_CHECK(!(b < a));
BOOST_CHECK(!(b <= a));
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,3] and [2,4]
static void test_13_24() {
const I a(1,3), b(2,4);
BOOST_CHECK(indeterminate(a < b));
BOOST_CHECK(indeterminate(a <= b));
BOOST_CHECK(indeterminate(a > b));
BOOST_CHECK(indeterminate(a >= b));
BOOST_CHECK(indeterminate(b < a));
BOOST_CHECK(indeterminate(b <= a));
BOOST_CHECK(indeterminate(b > a));
BOOST_CHECK(indeterminate(b >= a));
BOOST_CHECK(indeterminate(a == b));
BOOST_CHECK(indeterminate(a != b));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and [2,3]
static void test_12_23() {
const I a(1,2), b(2,3);
BOOST_CHECK(indeterminate(a < b));
BOOST_CHECK(a <= b);
BOOST_CHECK(!(a > b));
BOOST_CHECK(indeterminate(a >= b));
BOOST_CHECK(!(b < a));
BOOST_CHECK(indeterminate(b <= a));
BOOST_CHECK(indeterminate(b > a));
BOOST_CHECK(b >= a);
BOOST_CHECK(indeterminate(a == b));
BOOST_CHECK(indeterminate(a != b));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and 0
static void test_12_0() {
const I a(1,2);
const int b = 0;
BOOST_CHECK(!(a < b));
BOOST_CHECK(!(a <= b));
BOOST_CHECK(a > b);
BOOST_CHECK(a >= b);
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and 1
static void test_12_1() {
const I a(1,2);
const int b = 1;
BOOST_CHECK(!(a < b));
BOOST_CHECK(indeterminate(a <= b));
BOOST_CHECK(indeterminate(a > b));
BOOST_CHECK(a >= b);
BOOST_CHECK(indeterminate(a == b));
BOOST_CHECK(indeterminate(a != b));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and 2
static void test_12_2() {
const I a(1,2);
const int b = 2;
BOOST_CHECK(indeterminate(a < b));
BOOST_CHECK(a <= b);
BOOST_CHECK(!(a > b));
BOOST_CHECK(indeterminate(a >= b));
BOOST_CHECK(indeterminate(a == b));
BOOST_CHECK(indeterminate(a != b));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and 3
static void test_12_3() {
const I a(1,2);
const int b = 3;
BOOST_CHECK(a < b);
BOOST_CHECK(a <= b);
BOOST_CHECK(!(a > b));
BOOST_CHECK(!(a >= b));
BOOST_CHECK(!(a == b));
BOOST_CHECK(a != b);
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,2] and [1,2]
static void test_12_12() {
const I a(1,2), b(1,2);
BOOST_CHECK(indeterminate(a == b));
BOOST_CHECK(indeterminate(a != b));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,1] and [1,1]
static void test_11_11() {
const I a(1,1), b(1,1);
BOOST_CHECK(a == b);
BOOST_CHECK(!(a != b));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
// comparisons between [1,1] and 1
static void test_11_1() {
const I a(1,1);
const int b = 1;
BOOST_CHECK(a == b);
BOOST_CHECK(!(a != b));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(a);
::detail::ignore_unused_variable_warning(b);
# endif
}
int test_main(int, char *[]) {
test_12_34();
test_13_24();
test_12_23();
test_12_0();
test_12_1();
test_12_2();
test_12_3();
test_12_12();
test_11_11();
test_11_1();
return 0;
}
+103
View File
@@ -0,0 +1,103 @@
/* Boost test/det.cpp
* test protected and unprotected rounding on an unstable determinant
*
* Copyright 2002-2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
#include <boost/test/minimal.hpp>
#include "bugs.hpp"
#define size 8
template<class I>
void det(I (&mat)[size][size]) {
for(int i = 0; i < size; i++)
for(int j = 0; j < size; j++)
mat[i][j] = I(1) / I(i + j + 1);
for(int i = 0; i < size - 1; i++) {
int m = i, n = i;
typename I::base_type v = 0;
for(int a = i; a < size; a++)
for(int b = i; b < size; b++) {
typename I::base_type w = abs(mat[a][b]).lower();
if (w > v) { m = a; n = b; v = w; }
}
if (n != i)
for(int a = 0; a < size; a++) {
I t = mat[a][n];
mat[a][n] = mat[a][i];
mat[a][i] = t;
}
if (m != i)
for(int b = i; b < size; b++) {
I t = mat[m][b];
mat[m][b] = mat[m][i];
mat[m][i] = t;
}
if (((m + n) & 1) == 1) { };
I c = mat[i][i];
for(int j = i + 1; j < size; j++) {
I f = mat[j][i] / c;
for(int k = i; k < size; k++)
mat[j][k] -= f * mat[i][k];
}
if (zero_in(c)) return;
}
}
namespace my_namespace {
using namespace boost;
using namespace numeric;
using namespace interval_lib;
template<class T>
struct variants {
typedef interval<T> I_op;
typedef typename change_rounding<I_op, save_state<rounded_arith_std<T> > >::type I_sp;
typedef typename unprotect<I_op>::type I_ou;
typedef typename unprotect<I_sp>::type I_su;
typedef T type;
};
}
template<class T>
bool test() {
typedef my_namespace::variants<double> types;
types::I_op mat_op[size][size];
types::I_sp mat_sp[size][size];
types::I_ou mat_ou[size][size];
types::I_su mat_su[size][size];
det(mat_op);
det(mat_sp);
{ types::I_op::traits_type::rounding rnd; det(mat_ou); }
{ types::I_sp::traits_type::rounding rnd; det(mat_su); }
for(int i = 0; i < size; i++)
for(int j = 0; j < size; j++) {
typedef types::I_op I;
I d_op = mat_op[i][j];
I d_sp = mat_sp[i][j];
I d_ou = mat_ou[i][j];
I d_su = mat_su[i][j];
if (!(equal(d_op, d_sp) && equal(d_sp, d_ou) && equal(d_ou, d_su)))
return false;
}
return true;
}
int test_main(int, char *[]) {
BOOST_CHECK(test<float>());
BOOST_CHECK(test<double>());
BOOST_CHECK(test<long double>());
# ifdef __BORLANDC__
::detail::ignore_warnings();
# endif
return 0;
}
+53
View File
@@ -0,0 +1,53 @@
/* Boost test/fmod.cpp
* test the fmod with specially crafted integer intervals
*
* Copyright 2002-2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval/interval.hpp>
#include <boost/numeric/interval/arith.hpp>
#include <boost/numeric/interval/arith2.hpp>
#include <boost/numeric/interval/utility.hpp>
#include <boost/numeric/interval/checking.hpp>
#include <boost/numeric/interval/rounding.hpp>
#include <boost/test/minimal.hpp>
#include "bugs.hpp"
struct my_rounded_arith {
int sub_down(int x, int y) { return x - y; }
int sub_up (int x, int y) { return x - y; }
int mul_down(int x, int y) { return x * y; }
int mul_up (int x, int y) { return x * y; }
int div_down(int x, int y) {
int q = x / y;
return (x % y < 0) ? (q - 1) : q;
}
int int_down(int x) { return x; }
};
using namespace boost;
using namespace numeric;
using namespace interval_lib;
typedef change_rounding<interval<int>, save_state_nothing<my_rounded_arith> >::type I;
int test_main(int, char *[]) {
BOOST_CHECK(equal(fmod(I(6,9), 7), I(6,9)));
BOOST_CHECK(equal(fmod(6, I(7,8)), I(6,6)));
BOOST_CHECK(equal(fmod(I(6,9), I(7,8)), I(6,9)));
BOOST_CHECK(equal(fmod(I(13,17), 7), I(6,10)));
BOOST_CHECK(equal(fmod(13, I(7,8)), I(5,6)));
BOOST_CHECK(equal(fmod(I(13,17), I(7,8)), I(5,10)));
BOOST_CHECK(equal(fmod(I(-17,-13), 7), I(4,8)));
BOOST_CHECK(equal(fmod(-17, I(7,8)), I(4,7)));
BOOST_CHECK(equal(fmod(I(-17,-13), I(7,8)), I(4,11)));
return 0;
}
+24
View File
@@ -0,0 +1,24 @@
/* Boost test/integer.cpp
* test int extension
*
* Copyright 2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
#include <boost/numeric/interval/ext/integer.hpp>
#include "bugs.hpp"
typedef boost::numeric::interval<float> I;
int main() {
I x, y;
x = 4 - (2 * y + 1) / 3;
# ifdef __BORLANDC__
::detail::ignore_warnings();
# endif
return 0;
}
@@ -0,0 +1,21 @@
/* Boost test/msvc_x64_flags.cpp
* Test for amd64\ieee.c(102) : Assertion failed: (mask&~(_MCW_DN|_MCW_EM|_MCW_RC))==0.
* This happens with MSVC on x64 in Debug mode. See ticket #4964.
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
#include <boost/test/minimal.hpp>
#include "bugs.hpp"
int test_main(int, char *[]) {
boost::numeric::interval<double> i(0.0, 0.0);
boost::numeric::interval<double> i2 = 60.0 - i;
# ifdef __BORLANDC__
::detail::ignore_warnings();
# endif
return 0;
}
+124
View File
@@ -0,0 +1,124 @@
/* Boost test/mul.cpp
* test multiplication, division, square and square root on some intervals
*
* Copyright 2002-2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
#include <boost/test/minimal.hpp>
#include "bugs.hpp"
typedef boost::numeric::interval<double> I;
static double min BOOST_PREVENT_MACRO_SUBSTITUTION (double a, double b, double c, double d) {
return (std::min)((std::min)(a, b), (std::min)(c, d));
}
static double max BOOST_PREVENT_MACRO_SUBSTITUTION (double a, double b, double c, double d) {
return (std::max)((std::max)(a, b), (std::max)(c, d));
}
static bool test_mul(double al, double au, double bl, double bu) {
I a(al, au), b(bl, bu);
I c = a * b;
return c.lower() == (min)(al*bl, al*bu, au*bl, au*bu)
&& c.upper() == (max)(al*bl, al*bu, au*bl, au*bu);
}
static bool test_mul1(double ac, double bl, double bu) {
I a(ac), b(bl, bu);
I c = ac * b;
I d = b * ac;
I e = a * b;
return equal(c, d) && equal(d, e);
}
static bool test_div(double al, double au, double bl, double bu) {
I a(al, au), b(bl, bu);
I c = a / b;
return c.lower() == (min)(al/bl, al/bu, au/bl, au/bu)
&& c.upper() == (max)(al/bl, al/bu, au/bl, au/bu);
}
static bool test_div1(double al, double au, double bc) {
I a(al, au), b(bc);
I c = a / bc;
I d = a / b;
return equal(c, d);
}
static bool test_div2(double ac, double bl, double bu) {
I a(ac), b(bl, bu);
I c = ac / b;
I d = a / b;
return equal(c, d);
}
static bool test_square(double al, double au) {
I a(al, au);
I b = square(a);
I c = a * a;
return b.upper() == c.upper() &&
(b.lower() == c.lower() || (c.lower() <= 0 && b.lower() == 0));
}
static bool test_sqrt(double al, double au) {
I a(al, au);
I b = square(sqrt(a));
return subset(abs(a), b);
}
int test_main(int, char*[]) {
BOOST_CHECK(test_mul(2, 3, 5, 7));
BOOST_CHECK(test_mul(2, 3, -5, 7));
BOOST_CHECK(test_mul(2, 3, -7, -5));
BOOST_CHECK(test_mul(-2, 3, 5, 7));
BOOST_CHECK(test_mul(-2, 3, -5, 7));
BOOST_CHECK(test_mul(-2, 3, -7, -5));
BOOST_CHECK(test_mul(-3, -2, 5, 7));
BOOST_CHECK(test_mul(-3, -2, -5, 7));
BOOST_CHECK(test_mul(-3, -2, -7, -5));
BOOST_CHECK(test_mul1(3, 5, 7));
BOOST_CHECK(test_mul1(3, -5, 7));
BOOST_CHECK(test_mul1(3, -7, -5));
BOOST_CHECK(test_mul1(-3, 5, 7));
BOOST_CHECK(test_mul1(-3, -5, 7));
BOOST_CHECK(test_mul1(-3, -7, -5));
BOOST_CHECK(test_div(30, 42, 2, 3));
BOOST_CHECK(test_div(30, 42, -3, -2));
BOOST_CHECK(test_div(-30, 42, 2, 3));
BOOST_CHECK(test_div(-30, 42, -3, -2));
BOOST_CHECK(test_div(-42, -30, 2, 3));
BOOST_CHECK(test_div(-42, -30, -3, -2));
BOOST_CHECK(test_div1(30, 42, 3));
BOOST_CHECK(test_div1(30, 42, -3));
BOOST_CHECK(test_div1(-30, 42, 3));
BOOST_CHECK(test_div1(-30, 42, -3));
BOOST_CHECK(test_div1(-42, -30, 3));
BOOST_CHECK(test_div1(-42, -30, -3));
BOOST_CHECK(test_div2(30, 2, 3));
BOOST_CHECK(test_div2(30, -3, -2));
BOOST_CHECK(test_div2(-30, 2, 3));
BOOST_CHECK(test_div2(-30, -3, -2));
BOOST_CHECK(test_square(2, 3));
BOOST_CHECK(test_square(-2, 3));
BOOST_CHECK(test_square(-3, 2));
BOOST_CHECK(test_sqrt(2, 3));
BOOST_CHECK(test_sqrt(5, 7));
BOOST_CHECK(test_sqrt(-1, 2));
# ifdef __BORLANDC__
::detail::ignore_warnings();
# endif
return 0;
}
+44
View File
@@ -0,0 +1,44 @@
/* Boost test/overflow.cpp
* test if extended precision exponent does not disturb interval computation
*
* Copyright 2002-2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
#include <boost/test/minimal.hpp>
#include "bugs.hpp"
template<class I>
void test_one(typename I::base_type x, typename I::base_type f) {
I y = x;
typename I::base_type g = 1 / f;
const int nb = 10000;
for(int i = 0; i < nb; i++) y *= f;
for(int i = 0; i < nb; i++) y *= g;
BOOST_CHECK(in(x, y));
# ifdef __BORLANDC__
::detail::ignore_unused_variable_warning(nb);
# endif
}
template<class I>
void test() {
test_one<I>(1., 25.);
test_one<I>(1., 0.04);
test_one<I>(-1., 25.);
test_one<I>(-1., 0.04);
}
int test_main(int, char *[]) {
test<boost::numeric::interval<float> >();
test<boost::numeric::interval<double> >();
//test<boost::numeric::interval<long double> >();
# ifdef __BORLANDC__
::detail::ignore_warnings();
# endif
return 0;
}
+59
View File
@@ -0,0 +1,59 @@
/* Boost test/pi.cpp
* test if the pi constant is correctly defined
*
* Copyright 2002-2003 Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
#include <boost/limits.hpp>
#include <boost/test/minimal.hpp>
#include "bugs.hpp"
#define PI 3.14159265358979323846
typedef boost::numeric::interval<int> I_i;
typedef boost::numeric::interval<float> I_f;
typedef boost::numeric::interval<double> I_d;
typedef boost::numeric::interval<long double> I_ld;
using boost::numeric::interval_lib::pi;
using boost::numeric::interval_lib::pi_half;
using boost::numeric::interval_lib::pi_twice;
int test_main(int, char *[]) {
I_i pi_i = pi<I_i>();
I_f pi_f = pi<I_f>();
I_d pi_d = pi<I_d>();
I_ld pi_ld = pi<I_ld>();
BOOST_CHECK(in((int) PI, pi_i));
BOOST_CHECK(in((float) PI, pi_f));
BOOST_CHECK(in((double)PI, pi_d));
BOOST_CHECK(subset(pi_i, widen(I_i((int) PI), 1)));
BOOST_CHECK(subset(pi_f, widen(I_f((float) PI), (std::numeric_limits<float> ::min)())));
BOOST_CHECK(subset(pi_d, widen(I_d((double)PI), (std::numeric_limits<double>::min)())));
// We can't test the following equalities for interval<int>.
I_f pi_f_half = pi_half<I_f>();
I_f pi_f_twice = pi_twice<I_f>();
I_d pi_d_half = pi_half<I_d>();
I_d pi_d_twice = pi_twice<I_d>();
I_ld pi_ld_half = pi_half<I_ld>();
I_ld pi_ld_twice = pi_twice<I_ld>();
BOOST_CHECK(equal(2.0f * pi_f_half, pi_f));
BOOST_CHECK(equal(2.0 * pi_d_half, pi_d));
BOOST_CHECK(equal(2.0l * pi_ld_half, pi_ld));
BOOST_CHECK(equal(2.0f * pi_f, pi_f_twice));
BOOST_CHECK(equal(2.0 * pi_d, pi_d_twice));
BOOST_CHECK(equal(2.0l * pi_ld, pi_ld_twice));
return 0;
}
+42
View File
@@ -0,0 +1,42 @@
/* Boost test/pow.cpp
* test the pow function
*
* Copyright 2002-2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
#include <boost/test/minimal.hpp>
#include "bugs.hpp"
bool test_pow(double al, double au, double bl, double bu, int p) {
typedef boost::numeric::interval<double> I;
I b = pow(I(al, au), p);
return b.lower() == bl && b.upper() == bu;
}
int test_main(int, char *[]) {
BOOST_CHECK(test_pow(2, 3, 8, 27, 3));
BOOST_CHECK(test_pow(2, 3, 16, 81, 4));
BOOST_CHECK(test_pow(-3, 2, -27, 8, 3));
BOOST_CHECK(test_pow(-3, 2, 0, 81, 4));
BOOST_CHECK(test_pow(-3, -2, -27, -8, 3));
BOOST_CHECK(test_pow(-3, -2, 16, 81, 4));
BOOST_CHECK(test_pow(2, 4, 1./64, 1./8, -3));
BOOST_CHECK(test_pow(2, 4, 1./256, 1./16, -4));
BOOST_CHECK(test_pow(-4, -2, -1./8, -1./64, -3));
BOOST_CHECK(test_pow(-4, -2, 1./256, 1./16, -4));
BOOST_CHECK(test_pow(2, 3, 1, 1, 0));
BOOST_CHECK(test_pow(-3, 2, 1, 1, 0));
BOOST_CHECK(test_pow(-3, -2, 1, 1, 0));
# ifdef __BORLANDC__
::detail::ignore_warnings();
# endif
return 0;
}
+128
View File
@@ -0,0 +1,128 @@
/* Boost test/test_float.cpp
* test arithmetic operations on a range of intervals
*
* Copyright 2003 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
* copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/numeric/interval.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/config.hpp>
#include "bugs.hpp"
/* All the following tests should be BOOST_CHECK; however, if a test fails,
the probability is high that hundreds of other tests will fail, so it is
replaced by BOOST_REQUIRE to avoid flooding the logs. */
template<class T, class F>
void test_unary() {
typedef typename F::I I;
for(I a(-10., -9.91); a.lower() <= 10.; a += 0.3) {
if (!F::validate(a)) continue;
I rI = F::f_I(a);
T rT1 = F::f_T(a.lower()), rT2 = F::f_T(a.upper()),
rT3 = F::f_T(median(a));
BOOST_REQUIRE(in(rT1, rI));
BOOST_REQUIRE(in(rT2, rI));
BOOST_REQUIRE(in(rT3, rI));
}
}
template<class T, class F>
void test_binary() {
typedef typename F::I I;
for(I a(-10., -9.91); a.lower() <= 10.; a += 0.3) {
for(I b(-10., -9.91); b.lower() <= 10.; b += 0.3) {
if (!F::validate(a, b)) continue;
T al = a.lower(), au = a.upper(), bl = b.lower(), bu = b.upper();
I rII = F::f_II(a, b);
I rIT1 = F::f_IT(a, bl), rIT2 = F::f_IT(a, bu);
I rTI1 = F::f_TI(al, b), rTI2 = F::f_TI(au, b);
I rTT1 = F::f_TT(al, bl), rTT2 = F::f_TT(al, bu);
I rTT3 = F::f_TT(au, bl), rTT4 = F::f_TT(au, bu);
BOOST_REQUIRE(subset(rTT1, rIT1));
BOOST_REQUIRE(subset(rTT3, rIT1));
BOOST_REQUIRE(subset(rTT2, rIT2));
BOOST_REQUIRE(subset(rTT4, rIT2));
BOOST_REQUIRE(subset(rTT1, rTI1));
BOOST_REQUIRE(subset(rTT2, rTI1));
BOOST_REQUIRE(subset(rTT3, rTI2));
BOOST_REQUIRE(subset(rTT4, rTI2));
BOOST_REQUIRE(subset(rIT1, rII));
BOOST_REQUIRE(subset(rIT2, rII));
BOOST_REQUIRE(subset(rTI1, rII));
BOOST_REQUIRE(subset(rTI2, rII));
}
}
}
#define new_unary_bunch(name, op, val) \
template<class T> \
struct name { \
typedef boost::numeric::interval<T> I; \
static I f_I(const I& a) { return op(a); } \
static T f_T(const T& a) { return op(a); } \
static bool validate(const I& a) { return val; } \
}
//#ifndef BOOST_NO_STDC_NAMESPACE
using std::abs;
using std::sqrt;
//#endif
new_unary_bunch(bunch_pos, +, true);
new_unary_bunch(bunch_neg, -, true);
new_unary_bunch(bunch_sqrt, sqrt, a.lower() >= 0.);
new_unary_bunch(bunch_abs, abs, true);
template<class T>
void test_all_unaries() {
BOOST_TEST_CHECKPOINT("pos"); test_unary<T, bunch_pos<T> >();
BOOST_TEST_CHECKPOINT("neg"); test_unary<T, bunch_neg<T> >();
BOOST_TEST_CHECKPOINT("sqrt"); test_unary<T, bunch_sqrt<T> >();
BOOST_TEST_CHECKPOINT("abs"); test_unary<T, bunch_abs<T> >();
}
#define new_binary_bunch(name, op, val) \
template<class T> \
struct bunch_##name { \
typedef boost::numeric::interval<T> I; \
static I f_II(const I& a, const I& b) { return a op b; } \
static I f_IT(const I& a, const T& b) { return a op b; } \
static I f_TI(const T& a, const I& b) { return a op b; } \
static I f_TT(const T& a, const T& b) \
{ return boost::numeric::interval_lib::name<I>(a,b); } \
static bool validate(const I& a, const I& b) { return val; } \
}
new_binary_bunch(add, +, true);
new_binary_bunch(sub, -, true);
new_binary_bunch(mul, *, true);
new_binary_bunch(div, /, !zero_in(b));
template<class T>
void test_all_binaries() {
BOOST_TEST_CHECKPOINT("add"); test_binary<T, bunch_add<T> >();
BOOST_TEST_CHECKPOINT("sub"); test_binary<T, bunch_sub<T> >();
BOOST_TEST_CHECKPOINT("mul"); test_binary<T, bunch_mul<T> >();
BOOST_TEST_CHECKPOINT("div"); test_binary<T, bunch_div<T> >();
}
int test_main(int, char *[]) {
BOOST_TEST_CHECKPOINT("float tests");
test_all_unaries<float> ();
test_all_binaries<float> ();
BOOST_TEST_CHECKPOINT("double tests");
test_all_unaries<double>();
test_all_binaries<double>();
//BOOST_TEST_CHECKPOINT("long double tests");
//test_all_unaries<long double>();
//test_all_binaries<long double>();
# ifdef __BORLANDC__
::detail::ignore_warnings();
# endif
return 0;
}
+9
View File
@@ -0,0 +1,9 @@
odeint 2.1
* versioning system
* generation functions
* bugfixing
odeint 2.2 (still running)
* removing same_size and resize from state_wrapper into separate functions
+3
View File
@@ -0,0 +1,3 @@
[![Build Status](https://travis-ci.org/headmyshoulder/odeint-v2.svg?branch=master)](https://travis-ci.org/headmyshoulder/odeint-v2)
odeint is a highly flexible library for solving ordinary differential equations.
+277
View File
@@ -0,0 +1,277 @@
# Copyright 2009-2013 Karsten Ahnert
# Copyright 2011-2012 Mario Mulansky
# Copyright 2012 Daniel James
# Copyright 2013 Pascal Germroth
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
using quickbook ;
using boostbook ;
using doxygen ;
import modules ;
path-constant here : . ;
project : requirements
<include>$(BOOST_ROOT)/tools/auto_index/include
;
if --enable-index in [ modules.peek : ARGV ]
{
ECHO "Building the odeint docs with automatic index generation enabled." ;
using auto-index ;
project : requirements
<auto-index>on
<auto-index-verbose>on
# Choose indexing method (separately for html and pdf):
<format>html:<auto-index-internal>on # on (or off) to use internally generated indexes.
# <format>html:<xsl:param>generate.index=0 # Don't let the XSL stylesheets generate indexes.
<format>pdf:<auto-index-internal>off # on (or off) to use internally generated indexes.
# <auto-index-type>index # Use <index>...</index> as the XML wrapper.
<format>pdf:<xsl:param>index.on.type=1 # For the native stylesheets to generate the different indexes.
# PDF native index support is probably better for PDFs as then you actually get page numbers.
<auto-index-script>odeint.idx # Specifies the name of the index script to load.
<auto-index-prefix>../include
# Inform Quickbook that there is to be an index(es).
<quickbook-define>enable_index
;
}
else
{
ECHO "Building the odeint docs with automatic index generation disabled. To get an auto-index, try building with --enable-index." ;
}
doxygen reference
:
# [ glob ../include/boost/numeric/odeint/*.hpp ]
[ glob ../include/boost/numeric/odeint/stepper/*.hpp ]
[ glob ../incude/boost/numeric/odeint/stepper/base/*.hpp ]
# [ glob ../include/boost/numeric/odeint/stepper/generation/*.hpp ]
[ glob ../include/boost/numeric/odeint/integrate/*.hpp : ../include/boost/numeric/odeint/integrate/null_observer.hpp ../include/boost/numeric/odeint/integrate/observer_collection.hpp ]
[ glob ../include/boost/numeric/odeint/iterator/*.hpp ]
# [ glob ../include/boost/numeric/odeint/iterator/impl/*.hpp ]
# [ glob ../include/boost/numeric/odeint/algebra/*.hpp ]
# [ glob ../include/boost/numeric/odeint/util/*.hpp ]
# ../include/boost/numeric/odeint.hpp
:
# Lots of parameters passed to Doxygen. You can see these in the doxygen docs, or the Wizard Expert tab displays them.
# If you have successfuly built your Doxygen docs standalone using the Wizard (strongly recommended as it is much quicker).
# The values in your project's doxyfile are what to put as the Doxygen parameters passed below.
<doxygen:param>WARNINGS=YES
<doxygen:param>WARN_LOGFILE=AutoDoxywarnings.log
<doxygen:param>WARN_IF_UNDOCUMENTED=NO # Default NO but useful if you aim to Doxygen document *all* members.
<doxygen:param>QUIET=NO
<doxygen:param>WARN_NO_PARAMDOC=NO # Default no, but YES useful if you aim to document all function parameters.
<doxygen:param>DOXYFILE_ENCODING=UTF-8
<doxygen:param>PROJECT_NAME="odeint"
<doxygen:param>PROJECT_NUMBER=2.2
<doxygen:param>TAB_SIZE=2
<doxygen:param>SORT_MEMBER_DOCS=NO
<doxygen:param>SORT_BRIEF_DOCS=NO
<doxygen:param>SORT_MEMBERS_CTORS_1ST=NO
<doxygen:param>EXTRACT_PRIVATE=NO
<doxygen:param>INLINE_INHERITED_MEMB=YES
<doxygen:param>INHERIT_DOCS=YES
<doxygen:param>EXTRACT_STATIC=YES
<doxygen:param>EXTRACT_ANON_NSPACES=NO
<doxygen:param>EXTRACT_LOCAL_CLASSES=YES
<doxygen:param>EXTRACT_LOCAL_METHODS=YES
<doxygen:param>HIDE_UNDOC_MEMBERS=NO
<doxygen:param>HIDE_UNDOC_CLASSES=YES
<doxygen:param>HIDE_FRIEND_COMPOUNDS=NO
#<doxygen:param>HIDE_INBODY_DOCS=NO
<doxygen:param>INTERNAL_DOCS=YES
<doxygen:param>CASE_SENSE_NAMES=NO
<doxygen:param>HIDE_SCOPE_NAMES=NO
# Preprocessor settings.
# Some ugly examples of predefined macro calls (from Boost.Units library) :(
<doxygen:param>"PREDEFINED= \\
\"BOOST_UNITS_STATIC_CONSTANT(a,b)=static const b a\" \\
\"BOOST_UNITS_TYPEOF(a)=typeof(a)\" \\
\"BOOST_PREVENT_MACRO_SUBSTITUTION=\" \\
\"BOOST_UNITS_HAS_TYPEOF=1\" \\
\"DOXYGEN_SKIP=1\" "
<doxygen:param>ENABLE_PREPROCESSING=YES # Evaluates all C-preprocessor directives found in files.
<doxygen:param>MACRO_EXPANSION=YES # Will expand all macro names.
<doxygen:param>EXPAND_ONLY_PREDEF=YES # Only predefined macros expanded. See units library for an example.
<doxygen:param>SEARCH_INCLUDES=YES # Search #include files found.
<doxygen:param>INLINE_INFO=YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] is inserted in the documentation for inline members.
<doxygen:param>SHOW_INCLUDE_FILES=NO # List of the files that are included by a file in the documentation of that file.
<doxygen:param>REPEAT_BRIEF=YES # Prepend the brief description of a member or function before the detailed description
<doxygen:param>BRIEF_MEMBER_DESC=YES # Include brief member descriptions after the members that are listed in the file and class
<doxygen:param>MULTILINE_CPP_IS_BRIEF=YES # Treat a multi-line C++ special comment block (i.e. a block of //! or /// comments) as a brief description.
# May be best to always use \brief and \details to avoid ambiguity?
# <doxygen:param>STRIP_FROM_PATH=NO # Most useful to leave default to strip just the directory from which Doxygen is run.
# Yes gives the full path, but NO is more useful, only giving enough to be
# <doxygen:param>CPP_CLI_SUPPORT=NO # unless, most unusually, you are compiled for a 'managed' CLI application.
<doxygen:param>SHOW_USED_FILES=YES # Default YES to show a list files used to generate documention.
<doxygen:param>SHOW_DIRECTORIES=YES # Default NO, but useful to show directory heirarchy.
<doxygen:param>SHOW_FILES=YES # Default YES is to include a tab for a page of files listed. Useful.
<doxygen:param>SHOW_NAMESPACES=YES # Default YES to include tab for list of namespaces. Useful if you have namespacess other than boost::
<doxygen:param>FILE_PATTERNS= # Types of files to be used as input. Default includes *.c *.cc *.cxx *.cpp *.c++ *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp *.h++ *.py
# Might include .qbk?
<doxygen:param>RECURSIVE=YES # Search recursively down subdirectories.
<doxygen:param>EXCLUDE= # Files or directories that should be excluded from INPUT source files.
# Headers and footers are actually rather attractive,
# <doxygen:param>HTML_HEADER="doxygen/checks_doxygen_header.html" # A sample including a draft stamp and 'Not_Yet_In_Boost' logo.
# Take care that if you use this (recommended), you need to ensure that the html
# <doxygen:param>HTML_FOOTER="doxygen/checks_doxygen_footer.html" # This is very useful to add copyright, date of revision, versioning etc.
# A custom stylesheet is also useful, as the default syntax coloring is 'unusual' ;-)
<doxygen:param>HTML_STYLESHEET="doxygen/doxygen.css" # Placed in the doxygen directory,
# this will change to your choice of C++ syntax coloring when viewing source from Doxygen.
# Users can place (or edit) their own personal choice CSS file here.
# Default is just Reference but you can provide your own title for reference section here.
<xsl:param>"boost.doxygen.reftitle=odeint Reference"
;
xml odeint
:
odeint.qbk
:
;
boostbook standalone
:
odeint
:
# Path for links to Boost:
#<xsl:param>boost.root=\$(local-boost-root) # Link to Boost logo boost.png
# Links are relative and trying to make absolute does NOT work.
# And remember that all links MUST (unless in quotes) use backslash, not forward that is trip char.
<xsl:param>boost.root=../../../../.. # OK but link to I:/boost_trunk/boost.png
# Also control links to admonitions, so need to set separately.
#<xsl:param>boost.root=../../../../../../../boost_1_47_0 # OK file:///I:/boost_1_48_0/boost.png
# Quickbook [@boost:/boost/units/detail/utility.hpp] should make it relative to xsl parameter boost.root.
# Use the your own local Boost stylesheet:
# <xsl:param>html.stylesheet=../html/boostbook.css
# Some general style settings:
# see http://docbook.sourceforge.net/release/xsl/current/doc/html/index.html
<xsl:param>table.footnote.number.format=1 # Identifies the format used for footnote numbers in tables.
<xsl:param>footnote.number.format=1 # Identifies the format used for text footnote numbers.
# Default to not including the Boost logo in the navbar, when one expressly asks to include the navbar.
# Boost jamroot now includes
# Default to not include a navbar.
#<xsl:param>nav.layout=none # No navigation bar (home, prev, next).
# defining creates a runtime error: Global parameter nav.layout already defined
#<xsl:param>nav.layout=horizontal # to get a horizontal navigation bar (you probably DO want this).
<xsl:param>boost.image.src=logo.jpg #
<xsl:param>boost.image.width=294 # Width of logo in pixels.
<xsl:param>boost.image.height=127 # Height of logo in pixels.
# HTML options:
# ------------
<xsl:param>navig.graphics=1 # Use graphics not text for navigation.
<xsl:param>chunk.section.depth=2 # How far down we chunk nested sections, basically all of them.
<xsl:param>chunk.first.sections=1 # Don't put the first section on the same page as the TOC.
<xsl:param>toc.section.depth=2 # How far down sections get TOCs.
<xsl:param>toc.max.depth=2 # Max depth in each TOC.
<xsl:param>generate.section.toc.level=3 # How far down we go with TOCs.
#<format>html:<xsl:param>admon.graphics.extension=".png" # default type for admonitions (important, warning, note ...)
#<format>html:<xsl:param>admon.graphics.path=$(nav-images)/ # path to admonition (warning, note...) image (.png) files.
# <xsl:param name="draft.watermark.image">http://docbook.sourceforge.net/release/images/draft.png</xsl:param>
# but use a local copy of draft.png.
# PDF Options:
# -----------
# TOC Generation
<xsl:param>fop1.extensions=0 # DISable extensions for FOP version 0.90 and later .
<format>pdf:<xsl:param>fop.extensions=0 # DISable extensions for FOP version 0.20.5 and earlier.
<format>pdf:<xsl:param>xep.extensions=1 # Use XEP extension- PDF bookmarks, document information and better index processing.
# No indent on body text:
<format>pdf:<xsl:param>body.start.indent=0pt #
<format>pdf:<xsl:param>paper.type=A4 # Paper type = A4
# http://xml.resource.org/public/rfc/html/rfc2346.html
# Making Postscript and PDF International, J Palme, RFC 2346 recommends
# If you are using US letter paper format, ensure that both left and right margins are at least 21 mm (0.8 in).
# If you are using A4 paper, ensure that both the top and bottom margins are at least 33 mm (1.3 in).
# Margins sizes:
#<format>pdf:<xsl:param>page.margin.top=1.3in
#<format>pdf:<xsl:param>page.margin.inner=0.8in
#<format>pdf:<xsl:param>page.margin.bottom=1.3in
#<format>pdf:<xsl:param>page.margin.outer=0.8in
# http://docbook.sourceforge.net/release/xsl/current/doc/index.html
# DocBook XSL Stylesheets: Reference Documentation.
# Yes, we want graphics for admonishments:
<xsl:param>admon.graphics=1
# Set these one for PDF generation *only*:
# In PDF format, default PNG graphics are awful, so better use SVG images (type .svg) instead.
<format>pdf:<xsl:param>admon.graphics.extension=".svg" #
<format>pdf:<xsl:param>use.role.for.mediaobject=1 # Use print role on next line.
<format>pdf:<xsl:param>preferred.mediaobject.role=print # pdf role is to be printed.
<format>pdf:<xsl:param>img.src.path=$(here)/html/ # Path of image (.svg) files. (Note trailing /) ?
#<format>pdf:<xsl:param>admon.graphics.path=$(nav_images)/ # path to admonition (warning, note...) image (.svg) files.
#<format>pdf:<xsl:param>draft.mode="yes" # Yes if draft watermark wanted!
#<format>pdf:<xsl:param>draft.watermark.image="draft.png" # Watermark (local copy).
#<format>pdf:<xsl:param>draft.watermark.image=http://docbook.sourceforge.net/release/images/draft.png # Watermark.
<dependency>reference # Doxygen reference section
# <dependency>pdf-install # final pdf
# <dependency>png-install # Boost standard icons in both png
# <dependency>svg-install # and svg.
;
# To install a copy of 'master' boostbook.css and logo.
# install html : ../../../doc/html/boostbook.css ;
# install ../ : ../../../boost.png ;
# Install (copy) the 'master' copy of boostbook Cascading Style sheet
# from your current Boost-root to the /doc/html folder.
# path-constant boost-root : [ modules.peek : BOOST ] ;
# install css-install : $(boost-root)/doc/src/boostbook.css : <location>html ;
# path-constant boost-root : [ modules.peek : BOOST ] ;
# Install (copy) the 'master' copies of all icon images (both PNG and SVG)
# and the Boost logo from your current Boost-root
# to the local /doc/html/images folder so that html is complete and standalone.
# install png-install : [ glob $(boost-root)/doc/src/images/*.png $(boost-root)/boost.png ] : <location>html/images ;
# install svg-install : [ glob $(boost-root)/doc/src/images/*.svg ] : <location>html/images ;
# install unordered_pdf : standalone/<format>pdf : <location>. ;
# explicit unordered_pdf ;
# The explicit rule is there so that it's only installed when the target is explicitly named.
# Effectively copies the file from \bin folder to the \doc folder.
# install pdf-install : standalone : <location>. <install-type>PDF ;
# But will not work as expected if doxygen and/or autoindex is used
# because a modified pdf file is created, so this command below
# will rename the file to the expected filename, here quick_auto_dox_index.pdf.
# <location>. means installed in same place as this jamfile, /doc.
install pdfinstall : standalone : <install-type>PDF <location>. <name>odeint.pdf ;
install callouts : [ glob src/images/callouts/*.png ] : <location>html/images/callouts ;
@@ -0,0 +1,37 @@
[/============================================================================
Boost.odeint
Copyright 2011-2012 Karsten Ahnert
Copyright 2011-2012 Mario Mulansky
Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[section Acknowledgments]
[/
* Steven Watanabe for managing the Boost review process.
* All people who participated in the odeint review process on the Boost mailing list.
* Paul Bristow for helping with the documentation.
* The Google Summer Of Code (GSOC) program for funding and Andrew Sutton for supervising us during the GSOC and for lots of useful discussions and feedback about many implementation details..
* Joachim Faulhaber for motivating us to participate in the Boost review process and many detailed comments about the library.
* All users of odeint. They are the main motivation for our efforts.
[h3 Contributers]
* Andreas Angelopoulos implemented the sparse matrix implicit Euler stepper using the MTL4 library.
* Rajeev Singh implemented the stiff Van der Pol oscillator example.
* Sylwester Arabas improved the documentation.
* Denis Demidov provided the adaption to the VexCL and Viennacl libraries.
* Christoph Koke provided improved binders.
* Lee Hodgkinson provided the black hole example.
]
[endsect]
+27
View File
@@ -0,0 +1,27 @@
[/============================================================================
Boost.odeint
Copyright 2011-2012 Karsten Ahnert
Copyright 2011 Mario Mulansky
Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[section:concepts Concepts]
[# odeint.concepts]
[include concepts/system.qbk]
[include concepts/second_order_system.qbk]
[include concepts/symplectic_system.qbk]
[include concepts/implicit_system.qbk]
[include concepts/stepper.qbk]
[include concepts/error_stepper.qbk]
[include concepts/controlled_stepper.qbk]
[include concepts/dense_output_stepper.qbk]
[include concepts/state_algebra_operations.qbk]
[include concepts/state_wrapper.qbk]
[endsect]
@@ -0,0 +1,74 @@
[/============================================================================
Boost.odeint
Copyright 2011-2012 Karsten Ahnert
Copyright 2011 Mario Mulansky
Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[section Controlled Stepper]
This concept specifies the interface a controlled stepper has to fulfill to be used within __integrate_functions.
[heading Description]
A controlled stepper following this Controlled Stepper concept provides the possibility to perform one step of the solution /x(t)/ of an ODE with step-size /dt/ to obtain /x(t+dt)/ with a given step-size /dt/.
Depending on an error estimate of the solution the step might be rejected and a smaller step-size is suggested.
[heading Associated types]
* '''<para>'''[*state_type]'''</para>'''
'''<para>'''`Stepper::state_type`'''</para>'''
'''<para>'''The type characterizing the state of the ODE, hence ['x].'''</para>'''
* '''<para>'''[*deriv_type]'''</para>'''
'''<para>'''`Stepper::deriv_type`'''</para>'''
'''<para>'''The type characterizing the derivative of the ODE, hence ['d x/dt].'''</para>'''
* '''<para>'''[*time_type]'''</para>'''
'''<para>'''`Stepper::time_type`'''</para>'''
'''<para>'''The type characterizing the dependent variable of the ODE, hence the time ['t].'''</para>'''
* '''<para>'''[*value_type]'''</para>'''
'''<para>'''`Stepper::value_type`'''</para>'''
'''<para>'''The numerical data type which is used within the stepper, something like `float`, `double`, `complex&lt; double &gt;`.'''</para>'''
* '''<para>'''[*stepper_category]'''</para>'''
'''<para>'''`Stepper::stepper_category`'''</para>'''
'''<para>'''A tag type characterizing the category of the stepper. This type must be convertible to `controlled_stepper_tag`.'''</para>'''
[heading Notation]
[variablelist
[[`ControlledStepper`] [A type that is a model of Controlled Stepper]]
[[`State`] [A type representing the state /x/ of the ODE]]
[[`Time`] [A type representing the time /t/ of the ODE]]
[[`stepper`] [An object of type `ControlledStepper`]]
[[`x`] [Object of type `State`]]
[[`t`, `dt`] [Objects of type `Time`]]
[[`sys`] [An object defining the ODE, should be a model of __system, __symplectic_system, __simple_symplectic_system or __implicit_system.]]
]
[heading Valid Expressions]
[table
[[Name] [Expression] [Type] [Semantics]]
[[Do step] [``stepper.try_step( sys , x , t , dt )``] [`controlled_step_result`] [Tries one step of step size `dt`. If the step was successful, `success` is returned, the resulting state is written to `x`, the new time is stored in `t` and `dt` now contains a new (possibly larger) step-size for the next step. If the error was too big, `rejected` is returned and the results are neglected - `x` and `t` are unchanged and `dt` now contains a reduced step-size to be used for the next try.] ]
[/ [Do step with reference] [`stepper.try_step( boost::ref(sys) , x , t , dt )`] [`void`] [Same as above with `System` as reference] ]
]
[heading Models]
* `controlled_error_stepper< runge_kutta_cash_karp54 >`
* `controlled_error_stepper_fsal< runge_kutta_dopri5 >`
* `controlled_error_stepper< runge_kutta_fehlberg78 >`
* `rosenbrock4_controller`
* `bulirsch_stoer`
[endsect]
@@ -0,0 +1,85 @@
[/============================================================================
Boost.odeint
Copyright (c) 2009-2013 Karsten Ahnert
Copyright (c) 2009-2013 Mario Mulansky
Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[section Dense Output Stepper]
This concept specifies the interface a dense output stepper has to fulfill to be used within __integrate_functions.
[heading Description]
A dense output stepper following this Dense Output Stepper concept provides the possibility to perform a single step of the solution /x(t)/ of an ODE to obtain /x(t+dt)/.
The step-size `dt` might be adjusted automatically due to error control.
Dense output steppers also can interpolate the solution to calculate the state /x(t')/ at any point /t <= t' <= t+dt/.
[heading Associated types]
* '''<para>'''[*state_type]'''</para>'''
'''<para>'''`Stepper::state_type`'''</para>'''
'''<para>'''The type characterizing the state of the ODE, hence ['x].'''</para>'''
* '''<para>'''[*deriv_type]'''</para>'''
'''<para>'''`Stepper::deriv_type`'''</para>'''
'''<para>'''The type characterizing the derivative of the ODE, hence ['d x/dt].'''</para>'''
* '''<para>'''[*time_type]'''</para>'''
'''<para>'''`Stepper::time_type`'''</para>'''
'''<para>'''The type characterizing the dependent variable of the ODE, hence the time ['t].'''</para>'''
* '''<para>'''[*value_type]'''</para>'''
'''<para>'''`Stepper::value_type`'''</para>'''
'''<para>'''The numerical data type which is used within the stepper, something like `float`, `double`, `complex&lt; double &gt;`.'''</para>'''
* '''<para>'''[*stepper_category]'''</para>'''
'''<para>'''`Stepper::stepper_category`'''</para>'''
'''<para>'''A tag type characterizing the category of the stepper. This type must be convertible to `dense_output_stepper_tag`.'''</para>'''
[heading Notation]
[variablelist
[[`Stepper`] [A type that is a model of Dense Output Stepper]]
[[`State`] [A type representing the state /x/ of the ODE]]
[[`stepper`] [An object of type `Stepper`]]
[[`x0`, `x`] [Object of type `State`]]
[[`t0`, `dt0`, `t`] [Objects of type `Stepper::time_type`]]
[[`sys`] [An object defining the ODE, should be a model of __system, __symplectic_system, __simple_symplectic_system or __implicit_system.]]
]
[heading Valid Expressions]
[table
[[Name] [Expression] [Type] [Semantics]]
[[Initialize integration] [`stepper.initialize( x0 , t0 , dt0 )`] [void] [Initializes the stepper with initial values `x0`, `t0` and `dt0`.]]
[[Do step] [`stepper.do_step( sys )`] [`std::pair< Stepper::time_type , Stepper::time_type >`] [Performs one step using the ODE defined by `sys`. The step-size might be changed internally due to error control. This function returns a pair containing `t` and `t+dt` representing the interval for which interpolation can be performed.] ]
[/ [Do step with reference] [`stepper.do_step( boost::ref( sys ) )`] [`std::pair< Stepper::time_type , Stepper::time_type >`] [Same as above with `System` as reference] ]
[[Do interpolation] [`stepper.calc_state( t_inter , x )`] [`void`] [Performs the interpolation to calculate /x(t[sub inter]/) where /t <= t[sub inter] <= t+dt/.]]
[[Get current time] [`stepper.current_time()`] [`const Stepper::time_type&`] [Returns the current time /t+dt/ of the stepper, that is the end time of the last step and the starting time for the next call of `do_step`]]
[[Get current state] [`stepper.current_state()`] [`const Stepper::state_type&`] [Returns the current state of the stepper, that is /x(t+dt)/, the state at the time returned by `stepper.current_time()`]]
[[Get current time step] [`stepper.current_time_step()`] [`const
Stepper::time_type&`] [Returns the current step size of the stepper, that is
/dt/]]
]
[heading Models]
* `dense_output_controlled_explicit_fsal< controlled_error_stepper_fsal< runge_kutta_dopri5 >`
* `bulirsch_stoer_dense_out`
* `rosenbrock4_dense_output`
[endsect]
@@ -0,0 +1,101 @@
[/============================================================================
Boost.odeint
Copyright 2011-2013 Karsten Ahnert
Copyright 2011 Mario Mulansky
Copyright 2012 Sylwester Arabas
Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[section Error Stepper]
This concepts specifies the interface an error stepper has to fulfill to be used within a ControlledErrorStepper. An error stepper must always fulfill the stepper concept. This can trivially implemented by
``
template< class System >
error_stepper::do_step( System sys , state_type &x , time_type t , time_type dt )
{
state_type xerr;
// allocate xerr
do_step( sys , x , t , dt , xerr );
}
``
[heading Description]
An error stepper following this Error Stepper concept is capable of doing one step of the solution /x(t)/ of an ODE with step-size /dt/ to obtain /x(t+dt)/ and also computing an error estimate ['x[sub err]] of the result.
Error Steppers can be Runge-Kutta steppers, symplectic steppers as well as implicit steppers.
Based on the stepper type, the ODE is defined as __system, __symplectic_system, __simple_symplectic_system or __implicit_system.
[heading Refinement of]
* DefaultConstructable
* CopyConstructable
* Stepper
[heading Associated types]
* '''<para>'''[*state_type]'''</para>'''
'''<para>'''`Stepper::state_type`'''</para>'''
'''<para>'''The type characterizing the state of the ODE, hence ['x].'''</para>'''
* '''<para>'''[*deriv_type]'''</para>'''
'''<para>'''`Stepper::deriv_type`'''</para>'''
'''<para>'''The type characterizing the derivative of the ODE, hence ['d x/dt].'''</para>'''
* '''<para>'''[*time_type]'''</para>'''
'''<para>'''`Stepper::time_type`'''</para>'''
'''<para>'''The type characterizing the dependent variable of the ODE, hence the time ['t].'''</para>'''
* '''<para>'''[*value_type]'''</para>'''
'''<para>'''`Stepper::value_type`'''</para>'''
'''<para>'''The numerical data type which is used within the stepper, something like `float`, `double`, `complex&lt; double &gt;`.'''</para>'''
* '''<para>'''[*order_type]'''</para>'''
'''<para>'''`Stepper::order_type`'''</para>'''
'''<para>'''The type characterizing the order of the ODE, typically `unsigned short`.'''</para>'''
* '''<para>'''[*stepper_category]'''</para>'''
'''<para>'''`Stepper::stepper_category`'''</para>'''
'''<para>'''A tag type characterizing the category of the stepper. This type must be convertible to `error_stepper_tag`.'''</para>'''
[heading Notation]
[variablelist
[[`ErrorStepper`] [A type that is a model of Error Stepper]]
[[`State`] [A type representing the state /x/ of the ODE]]
[[`Error`] [A type representing the error calculated by the stepper, usually same as `State`]]
[[`Time`] [A type representing the time /t/ of the ODE]]
[[`stepper`] [An object of type `ErrorStepper`]]
[[`x`] [Object of type `State`]]
[[`xerr`] [Object of type `Error`]]
[[`t`, `dt`] [Objects of type `Time`]]
[[`sys`] [An object defining the ODE, should be a model of either __system, __symplectic_system, __simple_symplectic_system or __implicit_system.]]
]
[heading Valid Expressions]
[table
[[Name] [Expression] [Type] [Semantics]]
[[Get the stepper order] [`stepper.order()`] [`order_type`] [Returns the order of the stepper for one step without error estimation.]]
[[Get the stepper order] [`stepper.stepper_order()`] [`order_type`] [Returns the order of the stepper for one error estimation step which is used for error calculation.]]
[[Get the error order] [`stepper.errorr_order()`] [`order_type`] [Returns the order of the error step which is used for error calculation.]]
[[Do step] [`stepper.do_step( sys , x , t , dt )`] [`void`] [Performs one step of step size `dt`. The newly obtained state is written in-place to `x`.] ]
[[Do step with error estimation] [`stepper.do_step( sys , x , t , dt , xerr )`] [`void`] [Performs one step of step size `dt` with error estimation. The newly obtained state is written in-place to `x` and the estimated error to `xerr`.] ]
[/ [Do step with reference] [`stepper.do_step( boost::ref(sys) , x , t , dt , xerr )`] [`void`] [Performs one step of step size `dt`. The newly obtained state is written in-place to `x` and the estimated error to `xerr`.] ]
]
[heading Models]
* `runge_kutta_cash_karp54`
* `runge_kutta_dopri5`
* `runge_kutta_fehlberg78`
* `rosenbrock4`
[endsect]
@@ -0,0 +1,43 @@
[/============================================================================
Boost.odeint
Copyright 2011 Mario Mulansky
Copyright 2011-2012 Karsten Ahnert
Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[section Implicit System]
[heading Description]
This concept describes how to define a ODE that can be solved by an implicit routine.
Implicit routines need not only the function /f(x,t)/ but also the Jacobian /df/dx = A(x,t)/.
/A/ is a matrix and implicit routines need to solve the linear problem /Ax = b/.
In odeint this is implemented with use of __ublas, therefore, the ['state_type] implicit routines is ['ublas::vector] and the matrix is defined as ['ublas::matrix].
[heading Notation]
[variablelist
[[`System`] [A type that is a model of `Implicit System`]]
[[`Time`] [A type representing the time of the ODE]]
[[`sys`] [An object of type `System`]]
[[`x`] [Object of type ublas::vector]]
[[`dxdt`] [Object of type ublas::vector]]
[[`jacobi`] [Object of type ublas::matrix]]
[[`t`] [Object of type `Time`]]
]
[heading Valid Expressions]
[table
[[Name] [Expression] [Type] [Semantics]]
[[Calculate ['dx/dt := f(x,t)]] [`sys.first( x , dxdt , t )`] [`void`] [Calculates `f(x,t)`, the result is stored into dxdt] ]
[[Calculate ['A := df/dx (x,t)]] [`sys.second( x , jacobi , t )`] [`void`] [Calculates the Jacobian of /f/ at /x/,/t/, the result is stored into `jacobi`] ]
]
[endsect]
@@ -0,0 +1,44 @@
[/============================================================================
Boost.odeint
Copyright (c) 2009-2013 Karsten Ahnert
Copyright (c) 2009-2013 Mario Mulansky
Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[section Second Order System]
[heading Description]
The Second Order System concept models the algorithmic implementation of the rhs for steppers requirering the second order
derivative, hence the r.h.s. of the ODE ['x'' = f(x,x',t)]. The only requirement for this concept is that it should be callable
with a specific parameter syntax (see below). A Second Order System is typically implemented as a function or a functor.
Systems fulfilling this concept are required by the Velocity Verlet method.
[heading Notation]
[variablelist
[[`System`] [A type that is a model of Second Order System]]
[[`Space`] [A type representing the state /x/ of the ODE]]
[[`Velocity`] [A type representing the derivative /x'/ of the ODE]]
[[`Acceleration`] [A type representing the second order derivative /x''/ of the ODE]]
[[`Time`] [A type representing the time]]
[[`sys`] [An object of type `System`]]
[[`x`] [Object of type `Space`]]
[[`v`] [Object of type `Velocity`]]
[[`a`] [Object of type `Acceleration`]]
[[`t`] [Object of type `Time`]]
]
[heading Valid expressions]
[table
[[Name] [Expression] [Type] [Semantics]]
[[Calculate ['x'' := f(x,x',t)]] [`sys( x , v , a , t )`] [`void`] [Calculates f(x,x',t), the result is stored into a.] ]
]
[endsect]
@@ -0,0 +1,126 @@
[/============================================================================
Boost.odeint
Copyright 2011 Mario Mulansky
Copyright 2012 Karsten Ahnert
Copyright 2013 Pascal Germroth
Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[section State Algebra Operations]
[note The following does not apply to implicit steppers like implicit_euler or Rosenbrock 4 as there the `state_type` can not be changed from `ublas::vector` and no algebra/operations are used.]
[heading Description]
The `State`, `Algebra` and `Operations` together define a concept describing how the mathematical vector operations required for the stepper algorithms are performed.
The typical vector operation done within steppers is
['*y* = __Sigma __alpha[sub i] [*x[sub i]]].
The `State` represents the state variable of an ODE, usually denoted with /x/.
Algorithmically, the state is often realized as a `vector< double >` or `array< double , N >`, however, the genericity of odeint enables you to basically use anything as a state type.
The algorithmic counterpart of such mathematical expressions is divided into two parts.
First, the `Algebra` is used to account for the vector character of the equation.
In the case of a `vector` as state type this means the `Algebra` is responsible for iteration over all vector elements.
Second, the `Operations` are used to represent the actual operation applied to each of the vector elements.
So the `Algebra` iterates over all elements of the `State`s and calls an operation taken from the `Operations` for each element.
This is where `State`, `Algebra` and `Operations` have to work together to make odeint running.
Please have a look at the `range_algebra` and `default_operations` to see an example how this is implemented.
In the following we describe how `State`, `Algebra` and `Operations` are used together within the stepper implementations.
[section Operations]
[heading Notation]
[variablelist
[[`Operations`] [The operations type]]
[/[`Time`] [A type representing the time type of steppers]]
[[`Value1`, ... , `ValueN`] [Types representing the value or time type of stepper]]
[[`Scale`] [Type of the scale operation]]
[[`scale`] [Object of type `Scale`]]
[[[^ScaleSum['N]]] [Type that represents a general scale_sum operation, [^/N/] should be replaced by a number from 1 to 14.]]
[[[^scale_sum['N]]] [Object of type [^ScaleSum['N]], [^/N/] should be replaced by a number from 1 to 14.]]
[[`ScaleSumSwap2`] [Type of the scale sum swap operation]]
[[`scale_sum_swap2`] [Object of type `ScaleSumSwap2`]]
[[`a1, a2, ...`] [Objects of type `Value1`, `Value2`, ...]]
[[`y, x1, x2, ...`] [Objects of `State`'s value type]]
]
[heading Valid Expressions]
[table
[[Name] [Expression] [Type] [Semantics]]
[[Get scale operation] [`Operations::scale< Value >`] [`Scale`] [Get `Scale` from `Operations`]]
[[`Scale` constructor] [`Scale< Value >( a )`] [`Scale`] [Constructs a `Scale` object]]
[[`Scale` operation] [`scale( x )`] [`void`] [Calculates `x *= a`]]
[[Get general `scale_sum` operation] [[^Operations::scale_sum['N]< Value1 , ... , ValueN >]] [[^ScaleSum['N]]] [Get the [^ScaleSum['N]] type from `Operations`, [^/N/] should be replaced by a number from 1 to 14.]]
[[`scale_sum` constructor] [[^ScaleSum['N]< Value1 , ... , ValueN >( a1 , ... , aN )]] [[^ScaleSum['N]]] [Constructs a `scale_sum` object given [^/N/] parameter values with [^/N/] between 1 and 14.]]
[[`scale_sum` operation] [[^scale_sum['N]( y , x1 , ... , xN )]] [`void`] [Calculates `y = a1*x1 + a2*x2 + ... + aN*xN`. Note that this is an [^/N/+1]-ary function call.]]
[[Get scale sum swap operation] [`Operations::scale_sum_swap2< Value1 , Value2 >`] [`ScaleSumSwap2`] [Get scale sum swap from operations]]
[[`ScaleSumSwap2` constructor] [`ScaleSumSwap2< Value1 , Value2 >( a1 , a2 )`] [`ScaleSumSwap2`] [Constructor]]
[[`ScaleSumSwap2` operation] [`scale_sum_swap2( x1 , x2 , x3 )`] [`void`] [Calculates `tmp = x1`, `x1 = a1*x2 + a2*x3` and `x2 = tmp`.]]
]
[endsect]
[section Algebra]
[heading Notation]
[variablelist
[[`State`] [The state type]]
[[`Algebra`] [The algebra type]]
[[[^Operation['N]]] [An [^/N/]-ary operation type, [^/N/] should be a number from 1 to 14.]]
[[`algebra`] [Object of type `Algebra`]]
[[[^operation['N]]] [Object of type [^Operation['N]]]]
[[`y, x1, x2, ...`] [Objects of type `State`]]
]
[heading Valid Expressions]
[table
[[Name] [Expression] [Type] [Semantics]]
[[Vector Operation with arity 2] [`algebra.for_each2( y , x , operation2 )`] [void] [Calls `operation2( y_i , x_i )` for each element `y_i` of `y` and `x_i` of `x`.]]
[[Vector Operation with arity 3] [`algebra.for_each3( y , x1 , x2 , operation3 )`] [void] [Calls `operation3( y_i , x1_i , x2_i )` for each element `y_i` of `y` and `x1_i` of `x1` and `x2_i` of `x2`.]]
[[Vector Operation with arity [^/N/]] [[^algebra.for_each['N]( y , x1 , ... , xN , operation['N] )]] [void] [Calls [^operation['N]( y_i , x1_i , ... , xN_i )] for each element `y_i` of `y` and `x1_i` of `x1` and so on. [^/N/] should be replaced by a number between 1 and 14.]]
]
[endsect]
[section Pre-Defined implementations]
As standard configuration odeint uses the `range_algebra` and `default_operations` which suffices most situations.
However, a few more possibilities exist either to gain better performance or to ensure interoperability with other libraries.
In the following we list the existing `Algebra`/`Operations` configurations that can be used in the steppers.
[table
[[`State`] [`Algebra`] [`Operations`] [Remarks]]
[[Anything supporting __boost_range, like `std::vector`, `std::list`, `boost::array`,... based on a `value_type` that supports operators +,* (typically `double`)] [`range_algebra`] [`default_operations`] [Standard implementation, applicable for most typical situations.]]
[[`boost::array` based on a `value_type` that supports operators +,*] [`array_algebra`] [`default_operations`] [Special implementation for boost::array with better performance than `range_algebra`]]
[[Anything that defines operators + within itself and * with scalar (Mathematically spoken, anything that is a vector space).] [`vector_space_algebra`] [`default_operations`] [For the use of __controlled_stepper, the template `vector_space_reduce` has to be instantiated.]]
[[`thrust::device_vector`, `thrust::host_vector`] [`thrust_algebra`] [`thrust_operations`] [For running odeint on CUDA devices by using __thrust]]
[[Any RandomAccessRange] [`openmp_range_algebra`] [`default_operations`] [OpenMP-parallelised range algebra]]
[[`openmp_state`] [`openmp_algebra`] [`default_operations`] [OpenMP-parallelised algebra for split data]]
[[`boost::array` or anything which allocates the elements in a C-like manner] [`vector_space_algebra`] [`mkl_operations`] [Using the __intel_mkl in odeint for maximum performance. Currently, only the RK4 stepper is supported.]]
]
[endsect]
[section Example expressions]
[table
[[Name] [Expression] [Type] [Semantics]]
[[Vector operation] [`algebra.for_each3( y , x1 , x2 , Operations::scale_sum2< Value1 , Value2 >( a1 , a2 ) )`] [void] [Calculates ['*y* = a1 *x1* + a2 *x2*]]]
]
[endsect]
[endsect]
@@ -0,0 +1,39 @@
[/============================================================================
Boost.odeint
Copyright 2011 Mario Mulansky
Copyright 2012 Karsten Ahnert
Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[section State Wrapper]
[heading Description]
The `State Wrapper` concept describes the way odeint creates temporary state objects to store intermediate results within the stepper's `do_step` methods.
[heading Notation]
[variablelist
[[`State`] [A type that is the `state_type` of the ODE]]
[[`WrappedState`] [A type that is a model of State Wrapper for the state type `State`.]]
[[`x`] [Object of type `State`]]
[[`w`] [Object of type `WrappedState`]]
]
[heading Valid Expressions]
[table
[[Name] [Expression] [Type] [Semantics]]
[[Get resizeability] [`is_resizeable< State >`] [`boost::false_type` or `boost::true_type`] [Returns `boost::true_type` if the `State` is resizeable, `boost::false_type` otherwise.]]
[[Create `WrappedState` type] [`state_wrapper< State >`] [`WrappedState`] [Creates the type for a `WrappedState` for the state type `State`]]
[[Constructor] [`WrappedState()`] [`WrappedState`] [Constructs a state wrapper with an empty state]]
[[Copy Constructor] [`WrappedState( w )`] [`WrappedState`] [Constructs a state wrapper with a state of the same size as the state in `w`]]
[[Get state] [`w.m_v`] [`State`] [Returns the `State` object of this state wrapper.]]
]
[endsect]
@@ -0,0 +1,93 @@
[/============================================================================
Boost.odeint
Copyright 2011-2012 Karsten Ahnert
Copyright 2011 Mario Mulansky
Copyright 2012 Sylwester Arabas
Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[section Stepper]
This concepts specifies the interface a simple stepper has to fulfill to be used within the __integrate_functions.
[heading Description]
The basic stepper concept.
A basic stepper following this Stepper concept is able to perform a single step of the solution /x(t)/ of an ODE to obtain /x(t+dt)/ using a given step size /dt/.
Basic steppers can be Runge-Kutta steppers, symplectic steppers as well as implicit steppers.
Depending on the actual stepper, the ODE is defined as __system, __symplectic_system, __simple_symplectic_system or __implicit_system.
Note that all error steppers are also basic steppers.
[heading Refinement of]
* DefaultConstructable
* CopyConstructable
[heading Associated types]
* '''<para>'''[*state_type]'''</para>'''
'''<para>'''`Stepper::state_type`'''</para>'''
'''<para>'''The type characterizing the state of the ODE, hence ['x].'''</para>'''
* '''<para>'''[*deriv_type]'''</para>'''
'''<para>'''`Stepper::deriv_type`'''</para>'''
'''<para>'''The type characterizing the derivative of the ODE, hence ['d x/dt].'''</para>'''
* '''<para>'''[*time_type]'''</para>'''
'''<para>'''`Stepper::time_type`'''</para>'''
'''<para>'''The type characterizing the dependent variable of the ODE, hence the time ['t].'''</para>'''
* '''<para>'''[*value_type]'''</para>'''
'''<para>'''`Stepper::value_type`'''</para>'''
'''<para>'''The numerical data type which is used within the stepper, something like `float`, `double`, `complex&lt; double &gt;`.'''</para>'''
* '''<para>'''[*order_type]'''</para>'''
'''<para>'''`Stepper::order_type`'''</para>'''
'''<para>'''The type characterizing the order of the ODE, typically `unsigned short`.'''</para>'''
* '''<para>'''[*stepper_category]'''</para>'''
'''<para>'''`Stepper::stepper_category`'''</para>'''
'''<para>'''A tag type characterizing the category of the stepper. This type must be convertible to `stepper_tag`.'''</para>'''
[heading Notation]
[variablelist
[[`Stepper`] [A type that is a model of Stepper]]
[[`State`] [A type representing the state /x/ of the ODE]]
[[`Time`] [A type representing the time /t/ of the ODE]]
[[`stepper`] [An object of type `Stepper`]]
[[`x`] [Object of type `State`]]
[[`t`, `dt`] [Objects of type `Time`]]
[[`sys`] [An object defining the ODE. Depending on the Stepper this might be a model of __system, __symplectic_system, __simple_symplectic_system or __implicit_system ]]
]
[heading Valid Expressions]
[table
[[Name] [Expression] [Type] [Semantics]]
[[Get the order] [`stepper.order()`] [`order_type`] [Returns the order of the stepper.]]
[[Do step] [`stepper.do_step( sys , x , t , dt )`] [`void`] [Performs one step of step size `dt`. The newly obtained state is written in place in `x`.] ]
[/ [Do step with reference] [`stepper.do_step( boost::ref(sys) , x , t , dt )`] [`void`] [Performs one step of step size `dt`. The newly obtained state is written in place in `x`.] ]
[/ [Do step out-of-place] [`stepper.do_step( sys , in , t , out , dt )`] [`void`] [Performs one step. The newly obtained state is written to `out`] ]
]
[heading Models]
* `runge_kutta4`
* `euler`
* `runge_kutta_cash_karp54`
* `runge_kutta_dopri5`
* `runge_kutta_fehlberg78`
* `modified_midpoint`
* `rosenbrock4`
[endsect]
@@ -0,0 +1,99 @@
[/============================================================================
Boost.odeint
Copyright 2011 Mario Mulansky
Copyright 2011-2012 Karsten Ahnert
Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[section Symplectic System]
[heading Description]
This concept describes how to define a symplectic system written with generalized coordinate `q` and generalized momentum `p`:
[' q'(t) = f(p) ]
[' p'(t) = g(q) ]
Such a situation is typically found for Hamiltonian systems with a separable Hamiltonian:
[' H(p,q) = H[sub kin](p) + V(q) ]
which gives the equations of motion:
[' q'(t) = dH[sub kin] / dp = f(p) ]
[' p'(t) = dV / dq = g(q) ]
The algorithmic implementation of this situation is described by a pair of callable objects for /f/ and /g/ with a specific parameter signature.
Such a system should be implemented as a std::pair of functions or a functors.
Symplectic systems are used in symplectic steppers like `symplectic_rkn_sb3a_mclachlan`.
[heading Notation]
[variablelist
[[`System`] [A type that is a model of SymplecticSystem]]
[[`Coor`] [The type of the coordinate ['q]]]
[[`Momentum`] [The type of the momentum ['p]]]
[[`CoorDeriv`] [The type of the derivative of coordinate ['q']]]
[[`MomentumDeriv`] [The type of the derivative of momentum ['p']]]
[[`sys`] [An object of the type `System`]]
[[`q`] [Object of type Coor]]
[[`p`] [Object of type Momentum]]
[[`dqdt`] [Object of type CoorDeriv]]
[[`dpdt`] [Object of type MomentumDeriv]]
]
[heading Valid expressions]
[table
[[Name] [Expression] [Type] [Semantics]]
[[Check for pair] [`boost::is_pair< System >::type`] [`boost::mpl::true_`] [Check if System is a pair]]
[[Calculate ['dq/dt = f(p)]] [`sys.first( p , dqdt )`] [`void`] [Calculates ['f(p)], the result is stored into `dqdt`] ]
[[Calculate ['dp/dt = g(q)]] [`sys.second( q , dpdt )`] [`void`] [Calculates ['g(q)], the result is stored into `dpdt`] ]
]
[endsect]
[section Simple Symplectic System]
[heading Description]
In most Hamiltonian systems the kinetic term is a quadratic term in the momentum ['H[sub kin] = p^2 / 2m] and in many cases it is possible to rescale coordinates and set /m=1/ which leads to a trivial equation of motion:
[' q'(t) = f(p) = p. ]
while for /p'/ we still have the general form
[' p'(t) = g(q) ]
As this case is very frequent we introduced a concept where only the nontrivial equation for /p'/ has to be provided to the symplectic stepper.
We call this concept ['SimpleSymplecticSystem]
[heading Notation]
[variablelist
[[System] [A type that is a model of SimpleSymplecticSystem]]
[[Coor] [The type of the coordinate ['q]]]
[[MomentumDeriv] [The type of the derivative of momentum ['p']]]
[[sys] [An object that models System]]
[[q] [Object of type Coor]]
[[dpdt] [Object of type MomentumDeriv]]
]
[heading Valid Expressions]
[table
[[Name] [Expression] [Type] [Semantics]]
[[Check for pair] [`boost::is_pair< System >::type`] [`boost::mpl::false_`] [Check if System is a pair, should be evaluated to false in this case.]]
[[Calculate ['dp/dt = g(q)]] [`sys( q , dpdt )`] [`void`] [Calculates ['g(q)], the result is stored into `dpdt`] ]
]
[endsect]
@@ -0,0 +1,43 @@
[/============================================================================
Boost.odeint
Copyright 2011 Mario Mulansky
Copyright 2011-2012 Karsten Ahnert
Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[section System]
[heading Description]
The System concept models the algorithmic implementation of the rhs. of the ODE ['x' = f(x,t)].
The only requirement for this concept is that it should be callable with a specific parameter syntax (see below).
A System is typically implemented as a function or a functor.
Systems fulfilling this concept are required by all Runge-Kutta steppers as well as the Bulirsch-Stoer steppers.
However, symplectic and implicit steppers work with other system concepts, see __symplectic_system and __implicit_system.
[heading Notation]
[variablelist
[[`System`] [A type that is a model of System]]
[[`State`] [A type representing the state /x/ of the ODE]]
[[`Deriv`] [A type representing the derivative /x'/ of the ODE]]
[[`Time`] [A type representing the time]]
[[`sys`] [An object of type `System`]]
[[`x`] [Object of type `State`]]
[[`dxdt`] [Object of type `Deriv`]]
[[`t`] [Object of type `Time`]]
]
[heading Valid expressions]
[table
[[Name] [Expression] [Type] [Semantics]]
[[Calculate ['dx/dt := f(x,t)]] [`sys( x , dxdt , t )`] [`void`] [Calculates f(x,t), the result is stored into dxdt] ]
]
[endsect]
@@ -0,0 +1,55 @@
[/============================================================================
Boost.odeint
Copyright 2011-2012 Karsten Ahnert
Copyright 2011-2012 Mario Mulansky
Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[table Adaptive step size algorithms
[ [Stepper] [Tolerance formula] [Norm] [Step size adaption] ]
[ [`controlled_runge_kutta`]
[
['val = || | err[subl i] | / ( __epsilon[subl abs] + __epsilon[subl rel] * ( a[subl x] | x[subl i] | + a[subl dxdt] | | dxdt[subl i] | )|| ]
]
[['||x|| = max( x[subl i] )]]
[
['val > 1 : dt[subl new] = dt[subl current] max( 0.9 pow( val , -1 / ( O[subl E] - 1 ) ) , 0.2 )]
['val < 0.5 : dt[subl new] = dt[subl current] min( 0.9 pow( val , -1 / O[subl S] ) , 5 )]
['else : dt[subl new] = dt[subl current]]
] ]
[ [`rosenbrock4_controller`]
[
['val = || err[subl i] / ( __epsilon[subl abs] + __epsilon[subl rel] max( | x[subl i] | , | xold[subl i] | ) ) || ]
]
[['||x||=(__Sigma[subl i] x[subl i][super 2])[super 1/2]]]
[
['fac = max( 1 / 6 , min( 5 , pow( val , 1 / 4 ) / 0.9 ) ]
['fac2 = max( 1 / 6 , min( 5 , dt[subl old] / dt[subl current] pow( val[super 2] / val[subl old] , 1 / 4 ) / 0.9 ) ]
['val > 1 : dt[subl new] = dt[subl current] / fac ]
['val < 1 : dt[subl new] = dt[subl current] / max( fac , fac2 ) ]
]
]
[ [bulirsch_stoer] [['tol=1/2]] [-] [['dt[subl new] = dt[subl old][super 1/a]]] ]
]
[/
safe = 0.9 , fac1 = 5.0 , fac2 = 1.0 / 6.0
value_type fac_pred = ( m_dt_old / dt ) * pow( err * err / m_err_old , 0.25 ) / safe;
fac_pred = std::max( fac2 , std::min( fac1 , fac_pred ) );
fac = std::max( fac , fac_pred );
dt_new = dt / fac;
fac = max( fac2 , min( fac1 , pow( err , 0.25 ) / safe ) )
]
+30
View File
@@ -0,0 +1,30 @@
[/============================================================================
Boost.odeint
Copyright 2011-2012 Karsten Ahnert
Copyright 2011-2012 Mario Mulansky
Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[section odeint in detail]
[include details_steppers.qbk]
[include details_generation_functions.qbk]
[include details_integrate_functions.qbk]
[include details_iterators.qbk]
[include details_state_types_algebras_operations.qbk]
[include details_boost_ref.qbk]
[include details_boost_range.qbk]
[include details_bind_member_functions.qbk]
[endsect]

Some files were not shown because too many files have changed in this diff Show More