Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r78112 - in sandbox/fixed_point: boost/fixed_point libs/fixed_point/example
From: vicente.botet_at_[hidden]
Date: 2012-04-21 08:26:53


Author: viboes
Date: 2012-04-21 08:26:52 EDT (Sat, 21 Apr 2012)
New Revision: 78112
URL: http://svn.boost.org/trac/boost/changeset/78112

Log:
FixedPoint: Added more comments + refactor conversion from arithmetic types
Text files modified:
   sandbox/fixed_point/boost/fixed_point/number.hpp | 486 +++++++++++++++++++++++++++++++--------
   sandbox/fixed_point/libs/fixed_point/example/ex_xx.cpp | 22
   2 files changed, 398 insertions(+), 110 deletions(-)

Modified: sandbox/fixed_point/boost/fixed_point/number.hpp
==============================================================================
--- sandbox/fixed_point/boost/fixed_point/number.hpp (original)
+++ sandbox/fixed_point/boost/fixed_point/number.hpp 2012-04-21 08:26:52 EDT (Sat, 21 Apr 2012)
@@ -26,6 +26,7 @@
 #include <boost/type_traits/is_signed.hpp>
 #include <boost/type_traits/is_arithmetic.hpp>
 #include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_floating_point.hpp>
 #include <boost/utility/enable_if.hpp>
 #include <boost/assert.hpp>
 #include <boost/static_assert.hpp>
@@ -34,13 +35,16 @@
 #include <boost/integer/static_log2.hpp>
 #include <boost/ratio/detail/mpl/abs.hpp>
 #include <limits>
+#include <stdexcept>
 #include <cmath>
 #include <boost/integer_traits.hpp>
 
 #include <boost/config.hpp>
 //#include <boost/fixed_point/config.hpp>
+//#include <boost/fixed_point/number_fwd.hpp>
 //#include <boost/fixed_point/round/nearest_odd.hpp>
 //#include <boost/fixed_point/overflow/exception.hpp>
+//#include <boost/fixed_point/detail/helpers.hpp>
 
 #include <limits>
 
@@ -48,6 +52,7 @@
 {
   namespace fixed_point
   {
+ //#include <boost/fixed_point/detail/helpers.hpp>
     namespace detail
     {
 
@@ -129,26 +134,71 @@
 
     }
 
+ //#include <boost/fixed_point/overflow/exceptions.hpp>
     /**
      * Exception throw when there is a positive overflow.
      */
- struct positive_overflow
+ class positive_overflow: public std::overflow_error
     {
+ public:
+ positive_overflow() :
+ std::overflow_error("FixedPoint: positive overflow")
+ {
+ }
+ explicit positive_overflow(const std::string& what_arg) :
+ std::overflow_error(what_arg)
+ {
+ }
+ explicit positive_overflow(const char* what_arg) :
+ std::overflow_error(what_arg)
+ {
+ }
     };
+
     /**
      * Exception throw when there is a negative overflow.
      */
- struct negative_overflow
+ class negative_overflow: public std::underflow_error
     {
+ public:
+ negative_overflow() :
+ std::underflow_error("FixedPoint: negative overflow")
+ {
+ }
+ explicit negative_overflow(const std::string& what_arg) :
+ std::underflow_error(what_arg)
+ {
+ }
+ explicit negative_overflow(const char* what_arg) :
+ std::underflow_error(what_arg)
+ {
+ }
     };
 
- /**
- * Namespace for rounding policies.
- */
     namespace round
     {
+#if defined(BOOST_FIXED_POINT_DOXYGEN_INVOKED)
+ /**
+ * When the computation is not exact, rounding will be to one of the two nearest representable values.
+ * The algorithm for choosing between these values is the rounding mode.
+ * Different applications desire different modes, so programmers may specify its own rounding mode.
+ * However the library provides the usual rounding policies.
+ * All of them follwos the following this stereotype
+ *
+ */
+
+ struct stereotype
+ {
+ BOOST_STATIC_CONSTEXPR
+ std::float_round_style round_style;
+ template <typename From, typename To>
+ static typename To::underlying_type round(From const& rhs);
+ template <typename To, typename From>
+ static typename To::underlying_type round_divide(From const& lhs, From const& rhs);
+ };
+#endif
       /**
- * Use the fastest rounding.
+ * Speed is more important than the choice in value.
        */
       struct fastest
       {
@@ -158,11 +208,31 @@
 
       /**
        * Rounds toward negative infinity.
+ *
+ * This mode is useful in interval arithmetic.
        */
       struct negative
       {
         BOOST_STATIC_CONSTEXPR
         std::float_round_style round_style = std::round_toward_neg_infinity;
+
+ template <typename From, typename To>
+ static typename To::underlying_type round_integral(From const& rhs)
+ {
+ BOOST_STATIC_CONSTEXPR boost::uintmax_t d = To::resolution_exp;
+ typedef typename detail::max_type<is_signed<typename To::underlying_type>::value>::type tmp_type;
+ BOOST_STATIC_ASSERT(d < (8 * sizeof(tmp_type)));
+
+ tmp_type res = tmp_type(rhs) >> d;
+ return res;
+ }
+
+ template <typename From, typename To>
+ static typename To::underlying_type round_float_point(From const& rhs)
+ {
+ return To::integer_part(rhs / To::template factor<From>());
+ }
+
         template <typename From, typename To>
         static typename To::underlying_type round(From const& rhs)
         {
@@ -207,11 +277,34 @@
       };
       /**
        * Rounds toward zero.
+ *
+ * This mode is useful in implementing integral arithmetic.
        */
       struct truncated
       {
         BOOST_STATIC_CONSTEXPR
         std::float_round_style round_style = std::round_toward_zero;
+
+ template <typename From, typename To>
+ static typename To::underlying_type round_integral(From const& rhs)
+ {
+ BOOST_STATIC_CONSTEXPR boost::uintmax_t d = To::resolution_exp;
+ typedef typename detail::max_type<is_signed<typename To::underlying_type>::value>::type tmp_type;
+ BOOST_STATIC_ASSERT(d < (8 * sizeof(tmp_type)));
+
+ tmp_type m( ( (rhs > 0) ? rhs : -rhs));
+ tmp_type s( ( (rhs > 0) ? +1 : -1));
+
+ tmp_type res = s * (m >> d);
+ return res;
+ }
+
+ template <typename From, typename To>
+ static typename To::underlying_type round_float_point(From const& rhs)
+ {
+ return To::integer_part(rhs / To::template factor<From>());
+ }
+
         template <typename From, typename To>
         static typename To::underlying_type round(From const& rhs)
         {
@@ -239,11 +332,36 @@
       };
       /**
        * Rounds toward positive infinity.
+ *
+ * This mode is useful in interval arithmetic.
        */
       struct positive
       {
         BOOST_STATIC_CONSTEXPR
         std::float_round_style round_style = std::round_toward_infinity;
+
+ template <typename From, typename To>
+ static typename To::underlying_type round_integral(From const& rhs)
+ {
+ BOOST_STATIC_CONSTEXPR boost::uintmax_t d = To::resolution_exp;
+ typedef typename detail::max_type<is_signed<typename To::underlying_type>::value>::type tmp_type;
+ BOOST_STATIC_ASSERT(d < (8 * sizeof(tmp_type)));
+
+ BOOST_STATIC_CONSTEXPR tmp_type w = (1<<d)-1;
+ tmp_type i = rhs;
+
+ BOOST_ASSERT(i <= (integer_traits<tmp_type>::const_max - w));
+
+ tmp_type res = (i + w) >> d;
+ return res;
+ }
+
+ template <typename From, typename To>
+ static typename To::underlying_type round_float_point(From const& rhs)
+ {
+ return To::integer_part(rhs / To::template factor<From>());
+ }
+
         template <typename From, typename To>
         static typename To::underlying_type round(From const& rhs)
         {
@@ -291,7 +409,9 @@
         }
       };
       /**
- * Rounds to nearest half up.
+ * Round towards the nearest value, but exactly-half values are rounded towards maximum magnitude.
+ *
+ * This mode is the standard school algorithm.
        */
       struct nearest_half_up
       {
@@ -307,7 +427,8 @@
         std::float_round_style round_style = std::round_to_nearest;
       };
       /**
- * Rounds to nearest even.
+ * Round towards the nearest value, but exactly-half values are rounded towards even values.
+ * This mode has more balance than the classic mode.
        */
       struct nearest_even
       {
@@ -315,7 +436,8 @@
         std::float_round_style round_style = std::round_to_nearest;
       };
       /**
- * Rounds to nearest odd.
+ * Round towards the nearest value, but exactly-half values are rounded towards odd values.
+ * This mode has as much balance as the near_even mode, but preserves more information.
        */
       struct nearest_odd
       {
@@ -324,13 +446,39 @@
       };
     }
 
- /**
- * Namespace for overflow policies.
- */
     namespace overflow
     {
+
+#if defined(BOOST_FIXED_POINT_DOXYGEN_INVOKED)
       /**
- * Overflow is impossible and ensured by the user.
+ * Since the range of intermediate values grow to hold all possible values, and variables have a static range and
+ * resolution, construction and assignment may need to reduce the range and resolution.
+ * Reducing the resolution is done with a rounding mode associated with the variable.
+ * When the dynamic value exceeds the range of variable, the assignment overflows.
+ *
+ * When an overflow does occur, the desirable behavior depends on the application, so programmers may specify the
+ * overflow mode with his own specific overflow policy. The library provides however the usual ones.
+ * All of them follows the following stereotype
+ */
+ struct stereotype
+ {
+ BOOST_STATIC_CONSTEXPR
+ bool is_modulo;
+
+ template <typename T, typename U>
+ static BOOST_CONSTEXPR
+ typename T::underlying_type
+ on_negative_overflow(U value);
+
+ template <typename T, typename U>
+ static BOOST_CONSTEXPR
+ typename T::underlying_type
+ on_positive_overflow(U value);
+ };
+#endif
+ /**
+ * Programmer analysis of the program has determined that overflow cannot occur.
+ * Uses of this mode should be accompanied by an argument supporting the conclusion.
        *
        * An assertion is raised on debug mode.
        */
@@ -358,9 +506,7 @@
         }
       };
       /**
- * Overflow is undefined.
- *
- * Usually uses the fastest overflow approach.
+ * Programmers are willing to accept undefined behavior in the event of an overflow.
        */
       struct undefined
       {
@@ -379,6 +525,7 @@
           return value;
         }
       };
+#if ! defined(BOOST_FIXED_POINT_DOXYGEN_INVOKED)
       namespace detail
       {
         template <typename T, typename U, bool TisSigned = T::is_signed>
@@ -422,8 +569,11 @@
           }
         };
       }
+#endif
+
       /**
- * Overflow results are wrapped.
+ * The assigned value is the dynamic value @c mod the range of the variable.
+ * This mode makes sense only with unsigned numbers. It is useful for angular measures.
        */
       struct modulus
       {
@@ -443,7 +593,7 @@
         }
       };
       /**
- * On overflow the results is the nearest.
+ * If the dynamic value exceeds the range of the variable, assign the nearest representable value.
        */
       struct saturate
       {
@@ -464,7 +614,7 @@
 
       };
       /**
- * On overflow an exception is thrown.
+ * If the dynamic value exceeds the range of the variable, throw an exception of derived from std::overflow_error.
        */
       struct exception
       {
@@ -491,6 +641,27 @@
     {
 
       /**
+ * Every storage policy must define two meta-functions <c>signed_integer_type<Range, Resolution>::type</c> and
+ * <c>unsigned_integer_type<Range, Resolution>::type</c>.
+ */
+ struct stereotype
+ {
+ /**
+ * Gets the signed integer type with enough bits to manage with
+ * the Range and Resolution.
+ */
+ template <int Range, int Resolution>
+ struct signed_integer_type;
+
+ /**
+ * Gets the unsigned integer type with enough bits to manage with
+ * the Range and Resolution
+ */
+ template <int Range, int Resolution>
+ struct unsigned_integer_type;
+ };
+
+ /**
        * The storage is undefined.
        */
       struct undefined
@@ -551,13 +722,33 @@
     }
 
     /**
- * Namespace for conversion policies.
+ * Since fixed points have different range and resolution the user needs to convert from one type to another.
+ *
+ * When the target type has a larger range and a more precise resolution than the source type, the conversion is implicit.
+ * Otherwise, as the conversion could loss information, the conversion should be explicit to be safe.
+ * Anyway some domains could consider that working with fixed-points should mimic the builtin and expect this conversion to be implicit.
+ * If for this reason that the library manage with both cases via the conversion policy.
+ *
+ * The conversion from builtins arithmetic types suffer from the same loss of information issue but
+ * some users could find an implicit conversion more natural.
+ *
+ * Conversions to builtins arithmetic types is a different concern.
+ * There is no know way to enable conversions operator subject to conditions on the type.
+ * The library has taken a conservative approach and only explicit conversions are provided.
+ * The user could always wrap the type and provide implicit conversion.
+ *
      */
     namespace conversion
     {
+ /**
+ * Used to state that a conversion needs to be explicit.
+ */
       struct explicitly
       {
       };
+ /**
+ * Used to state that a conversion needs to be implicit.
+ */
       struct implicitly
       {
       };
@@ -568,9 +759,37 @@
      */
     namespace arithmetic
     {
+ /*
+ * The range and resolution of the result of basic operations are deduced to try to hold the mathematical results.
+ * This deduction depends on the bound policy.
+ *
+ * - unbounded: The range and resolution of the result of basic operations are large enough to hold the mathematical results.
+ *
+ * Overflow in template argument computation is undefined behavior.
+ * In practice, overflow is unlikely to be a significant problem because even small machines can represent
+ * numbers with thousands of bits and because compiler can diagnose overflow in template arguments.
+ *
+ * The special case in the operations is division, where the mathematical result may require an infinite
+ * number of bits. The actual value must be rounded to a representable value.
+ * The above resolution is sufficient to ensure that if the mathematical result is not zero, the fixed-point
+ * result is not zero.
+ * Furthermore, assuming values have an error of one-half ULP, the defined resolution is close to the error
+ * bound in the computation.
+ *
+ * - bounded: As far as the result type is large enough to hold mathematical results it behaves as the unbounded one.
+ * When the bounding type is not enough large the operation is undefined.
+ * The user need to use functions that have the expected result type as parameter.
+ *
+ * Overflow while computing the arithmetic operations can be detected in this bounded cases.
+ *
+ */
       struct open
       {
       };
+ /*
+ * The range and resolution of the result is the one of the argument operations.
+ * In order to mix different fixed points, the user could be forced to convert explicitly the arguments to the expected type.
+ */
       struct closed
       {
       };
@@ -581,9 +800,19 @@
      */
     namespace bound
     {
+ /**
+ * Bounded fixed points types are closed, that is that the result of an arithmetic operations will be
+ * closed only if both arguments are closed.
+ * The range and resolution are bounded by the larger integral type provided by the compiler.
+ *
+ */
       struct bounded
       {
       };
+
+ /**
+ * The range and resolution of the result of basic operations are large enough to hold the mathematical results.
+ */
       struct unbounded
       {
       };
@@ -748,6 +977,7 @@
     template <class From, class To>
     To number_cast(From const& from);
 
+ //#include <boost/fixed_point/detail/helpers.hpp>
     namespace detail
     {
       template <typename T, int Range, int Resolution >
@@ -1678,47 +1908,48 @@
       typename default_type<F1,F2>::type
> type;
     };
-#endif
-
- template <typename T, typename U>
- struct is_more_precisse;
+#endif // BOOST_FIXED_POINT_DOXYGEN_INVOKED
+ namespace detail
+ {
+ template <typename T, typename U>
+ struct is_more_precisse;
 
-#if ! defined(BOOST_FIXED_POINT_DOXYGEN_INVOKED)
- template <
- int R1, int P1, typename RP1, typename OP1, typename F1,
- int R2, int P2, typename RP2, typename OP2, typename F2
- >
- struct is_more_precisse<real_t<R1,P1,RP1,OP1,F1>, real_t<R2,P2,RP2,OP2,F2> > :
- mpl::and_ <
- mpl::less_equal < mpl::int_<R2>, mpl::int_<R1> >,
- mpl::greater_equal < mpl::int_<P2>, mpl::int_<P1> >
- >
- {};
+ template <
+ int R1, int P1, typename RP1, typename OP1, typename F1,
+ int R2, int P2, typename RP2, typename OP2, typename F2
+ >
+ struct is_more_precisse<real_t<R1,P1,RP1,OP1,F1>, real_t<R2,P2,RP2,OP2,F2> > :
+ mpl::and_ <
+ mpl::less_equal < mpl::int_<R2>, mpl::int_<R1> >,
+ mpl::greater_equal < mpl::int_<P2>, mpl::int_<P1> >
+ >
+ {};
 
- template <
- int R1, int P1, typename RP1, typename OP1, typename F1,
- int R2, int P2, typename RP2, typename OP2, typename F2
- >
- struct is_more_precisse<real_t<R1,P1,RP1,OP1,F1>, ureal_t<R2,P2,RP2,OP2,F2> > :
- mpl::and_ <
- mpl::less_equal < mpl::int_<R2>, mpl::int_<R1> >,
- mpl::greater_equal < mpl::int_<P2>, mpl::int_<P1> >
- >
- {};
+ template <
+ int R1, int P1, typename RP1, typename OP1, typename F1,
+ int R2, int P2, typename RP2, typename OP2, typename F2
+ >
+ struct is_more_precisse<real_t<R1,P1,RP1,OP1,F1>, ureal_t<R2,P2,RP2,OP2,F2> > :
+ mpl::and_ <
+ mpl::less_equal < mpl::int_<R2>, mpl::int_<R1> >,
+ mpl::greater_equal < mpl::int_<P2>, mpl::int_<P1> >
+ >
+ {};
 
- template <
- int R1, int P1, typename RP1, typename OP1, typename F1,
- int R2, int P2, typename RP2, typename OP2, typename F2
- >
- struct is_more_precisse<ureal_t<R1,P1,RP1,OP1,F1>, ureal_t<R2,P2,RP2,OP2,F2> > :
- mpl::and_ <
- mpl::less_equal < mpl::int_<R2>, mpl::int_<R1> >,
- mpl::greater_equal < mpl::int_<P2>, mpl::int_<P1> >
- >
- {};
+ template <
+ int R1, int P1, typename RP1, typename OP1, typename F1,
+ int R2, int P2, typename RP2, typename OP2, typename F2
+ >
+ struct is_more_precisse<ureal_t<R1,P1,RP1,OP1,F1>, ureal_t<R2,P2,RP2,OP2,F2> > :
+ mpl::and_ <
+ mpl::less_equal < mpl::int_<R2>, mpl::int_<R1> >,
+ mpl::greater_equal < mpl::int_<P2>, mpl::int_<P1> >
+ >
+ {};
+ }
 
     template <typename S, typename T>
- struct is_convertible : is_more_precisse<T,S>
+ struct is_convertible : detail::is_more_precisse<T,S>
     {};
 
     template <typename S, typename T, bool IsArithmetic=is_arithmetic<S>::value >
@@ -1727,7 +1958,7 @@
     struct is_explicitly_convertible<S,T,false> :
     mpl::and_<
     mpl::not_<allows_implicit_conversion_from_fp<T> >,
- mpl::not_<is_more_precisse<T,S> >
+ mpl::not_<detail::is_more_precisse<T,S> >
>
     {};
 
@@ -1742,7 +1973,7 @@
     struct is_implicitly_convertible<S,T,false> :
     mpl::and_<
     allows_implicit_conversion_from_fp<T>,
- mpl::not_<is_more_precisse<T,S> >
+ mpl::not_<detail::is_more_precisse<T,S> >
>
     {};
 
@@ -1750,7 +1981,6 @@
     struct is_implicitly_convertible<S,T,true> :
     allows_implicit_conversion_from_builtin<T>
     {};
-#endif
 
     /**
      * @brief Signed fixed point number.
@@ -1771,8 +2001,10 @@
       BOOST_MPL_ASSERT_MSG(Range>=Resolution,
           RANGE_MUST_BE_GREATER_EQUAL_THAN_RESOLUTION, (mpl::int_<Range>,mpl::int_<Resolution>));
 #endif
- public:
 
+ public:
+ //! this type
+ typedef real_t self_type;
       // name the template parameters
       //! the Range parameter.
       BOOST_STATIC_CONSTEXPR int range_exp = Range;
@@ -1839,7 +2071,7 @@
        *
        * @Effects Adapt the resolution of @c rhs to this resolution.
        * @Throws Nothing.
- * @Notes This overload participates in overload resolution only if the source @c is_convertible to the target.
+ * @Remark This overload participates in overload resolution only if the source @c is_convertible to the target.
        */
       template <int R, int P, typename RP, typename OP, typename F>
       real_t(real_t<R,P,RP,OP,F> const& rhs
@@ -1847,7 +2079,7 @@
           , typename boost::enable_if<is_convertible<real_t<R,P,RP,OP,F>, real_t > >::type* = 0
 #endif
       )
- : value_(fixed_point::detail::fxp_number_cast<real_t<R,P,RP,OP,F>, real_t, true, true>()(rhs).count())
+ : value_(fixed_point::detail::fxp_number_cast<real_t<R,P,RP,OP,F>, real_t>()(rhs).count())
       {
       }
       /**
@@ -1858,7 +2090,7 @@
        *
        * @Effects Adapt the resolution of @c rhs to this resolution.
        * @Throws Nothing.
- * @Notes This overload participates in overload resolution only if the source @c is_convertible to the target.
+ * @Remark This overload participates in overload resolution only if the source @c is_convertible to the target.
        */
       template <int R, int P, typename RP, typename OP, typename F>
       real_t(ureal_t<R,P,RP,OP,F> const& rhs
@@ -1866,7 +2098,7 @@
           , typename boost::enable_if<is_convertible<ureal_t<R,P,RP,OP,F>, real_t > >::type* = 0
 #endif
       )
- : value_(fixed_point::detail::fxp_number_cast<ureal_t<R,P,RP,OP,F>, real_t, true, true>()(rhs).count())
+ : value_(fixed_point::detail::fxp_number_cast<ureal_t<R,P,RP,OP,F>, real_t>()(rhs).count())
       {
       }
 
@@ -1878,7 +2110,7 @@
        *
        * @Effects Rounds and check overflow if needed.
        * @Throws Whatever the target overflow policy can throw.
- * @Notes This overload participates in overload resolution only if the source @c is_explicitly_convertible to the target.
+ * @Remark This overload participates in overload resolution only if the source @c is_explicitly_convertible to the target.
        */
       template <int R, int P, typename RP, typename OP, typename F>
       explicit real_t(real_t<R,P,RP,OP,F> const& rhs
@@ -1901,7 +2133,7 @@
        *
        * @Effects Rounds and check overflow if needed.
        * @Throws Whatever the target overflow policy can throw.
- * @Notes This overload participates in overload resolution only if the source @c is_implicitly_convertible to the target.
+ * @Remark This overload participates in overload resolution only if the source @c is_implicitly_convertible to the target.
        */
       template <int R, int P, typename RP, typename OP, typename F>
       real_t(real_t<R,P,RP,OP,F> const& rhs
@@ -1924,7 +2156,7 @@
        *
        * @Throws Whatever the target overflow policy can throw.
        * @Effects Rounds and check overflow if needed.
- * @Notes This overload participates in overload resolution only if the source @c is_explicitly_convertible to the target.
+ * @Remark This overload participates in overload resolution only if the source @c is_explicitly_convertible to the target.
        */
       template <int R, int P, typename RP, typename OP, typename F>
       explicit real_t(ureal_t<R,P,RP,OP,F> const& rhs
@@ -1947,7 +2179,7 @@
        *
        * @Effects Rounds and check overflow if needed.
        * @Throws Whatever the target overflow policy can throw.
- * @Notes This overload participates in overload resolution only if the source @c is_implicitly_convertible to the target.
+ * @Remark This overload participates in overload resolution only if the source @c is_implicitly_convertible to the target.
        */
       template <int R, int P, typename RP, typename OP, typename F>
       real_t(ureal_t<R,P,RP,OP,F> const& rhs
@@ -1970,7 +2202,7 @@
        *
        * @Effects Rounds and check overflow if needed.
        * @Throws Whatever the target overflow policy can throw.
- * @Notes This overload participates in overload resolution only if the source @c is_implicitly_convertible to the target.
+ * @Remark This overload participates in overload resolution only if the source @c is_implicitly_convertible to the target.
        */
 
       template <int R, int P, typename RP, typename OP, typename F>
@@ -1989,7 +2221,7 @@
        *
        * @Effects Rounds and check overflow if needed.
        * @Throws Whatever the target overflow policy can throw.
- * @Notes This overload participates in overload resolution only if the source @c is_implicitly_convertible to the target.
+ * @Remark This overload participates in overload resolution only if the source @c is_implicitly_convertible to the target.
        */
       template <int R, int P, typename RP, typename OP, typename F>
       real_t(convert_tag<ureal_t<R,P,RP,OP,F> > rhs)
@@ -2140,33 +2372,53 @@
       {
         return underlying_type(std::floor(x));
       }
+ template <typename I>
+ static underlying_type classify(I i
+#if !defined(BOOST_FIXED_POINT_DOXYGEN_INVOKED)
+ , typename boost::enable_if<is_integral<I> >::type* = 0
+#endif
+ )
+ {
+ // Round
+ underlying_type indx = rounding_type::template round_integral<I, self_type>(i);
+ // Overflow
+ if (indx > max_index)
+ {
+ return overflow_type::template on_positive_overflow<self_type,underlying_type>(indx);
+ }
+ if (indx < min_index)
+ {
+ return overflow_type::template on_negative_overflow<self_type,underlying_type>(indx);
+ }
+
+ return indx;
+ }
+
       template <typename FP>
- static underlying_type classify(FP x)
+ static underlying_type classify(FP x
+#if !defined(BOOST_FIXED_POINT_DOXYGEN_INVOKED)
+ , typename boost::enable_if<is_floating_point<FP> >::type* = 0
+#endif
+ )
       {
 
- // underlying_type indx = rounding_type::template round<To>(x)
- // // Overflow
- // if (x>max().as<FP>())
- // {
- // return overflow_type::template on_positive_overflow<To,underlying_type>(indx)));
- // }
- // if (rhs.count() < (typename From::underlying_type(To::min_index)<<(P2-P1)))
- // {
- // return To(index(OP2::template on_negative_overflow<To,underlying_type>(indx)));
- // }
- //
- // // Round
- // return To(index(RP2::template round<From,To>(rhs)));
-
- if (x<min().as<FP>())
- return min_index;
- if (x>max().as<FP>())
- return max_index;
- return integer_part(x/factor<FP>());
+ // Round
+ underlying_type indx = rounding_type::template round_float_point<FP,self_type>(x);
+ // Overflow
+ if (indx > max_index)
+ {
+ return overflow_type::template on_positive_overflow<self_type,underlying_type>(indx);
+ }
+ if (indx < min_index)
+ {
+ return overflow_type::template on_negative_overflow<self_type,underlying_type>(indx);
+ }
+
+ return indx;
       }
 
       /**
- * Implicit conversion from arithmetic @T.
+ * Implicit conversion from arithmetic @c T.
        */
       template <typename T>
       real_t(T x
@@ -2175,7 +2427,7 @@
 #endif
       ) : value_(fixed_point::detail::arthm_number_cast<T, real_t>()(x).count())
       {}
- //! explicit conversion from arithmetic @T.
+ //! explicit conversion from arithmetic @c T.
       template <typename T>
       explicit real_t(T x
 #if !defined(BOOST_FIXED_POINT_DOXYGEN_INVOKED)
@@ -2380,6 +2632,8 @@
 #endif
 
     public:
+ //! this type
+ typedef ureal_t self_type;
 
       // name the template parameters
       //! the Range parameter.
@@ -2443,7 +2697,7 @@
       ureal_t(ureal_t<R,P,RP,OP,F> const& rhs
           , typename boost::enable_if<is_convertible<ureal_t<R,P,RP,OP,F>, ureal_t > >::type* = 0
       )
- : value_(fixed_point::detail::fxp_number_cast<ureal_t<R,P,RP,OP,F>, ureal_t, true, true>()(rhs).count())
+ : value_(fixed_point::detail::fxp_number_cast<ureal_t<R,P,RP,OP,F>, ureal_t>()(rhs).count())
       {
       }
 
@@ -2561,12 +2815,46 @@
 
         return k*factor<FP>();
       }
+
+ template <typename I>
+ static underlying_type classify(I i
+#if !defined(BOOST_FIXED_POINT_DOXYGEN_INVOKED)
+ , typename boost::enable_if<is_integral<I> >::type* = 0
+#endif
+ )
+ {
+ if (i<0)
+ return overflow_type::template on_negative_overflow<self_type,underlying_type>(0);
+ // Round
+ underlying_type indx = rounding_type::template round_integral<I, self_type>(i);
+ // Overflow
+ if (indx > max_index)
+ {
+ return overflow_type::template on_positive_overflow<self_type,underlying_type>(indx);
+ }
+
+ return indx;
+ }
+
       template <typename FP>
- static underlying_type classify(FP x)
+ static underlying_type classify(FP x
+#if !defined(BOOST_FIXED_POINT_DOXYGEN_INVOKED)
+ , typename boost::enable_if<is_floating_point<FP> >::type* = 0
+#endif
+ )
       {
- if (x<min().as<FP>()) return min_index;
- if (x>max().as<FP>()) return max_index;
- return integer_part(x/factor<FP>());
+ if (x<0)
+ return overflow_type::template on_negative_overflow<self_type,underlying_type>(0);
+
+ // Round
+ underlying_type indx = rounding_type::template round_float_point<FP,self_type>(x);
+ // Overflow
+ if (indx > max_index)
+ {
+ return overflow_type::template on_positive_overflow<self_type,underlying_type>(indx);
+ }
+
+ return indx;
       }
 
       //! implicit conversion from int
@@ -2827,7 +3115,7 @@
 #else
     ureal_t< static_log2<mpl::abs<mpl::int_<Times+1> >::type::value>::value+Resolution, Resolution>
 #endif
- to_unsigned_number()
+ to_ureal_t()
     {
       return ureal_t<
       static_log2<mpl::abs<mpl::int_<Times+1> >::type::value>::value+Resolution, Resolution
@@ -2850,7 +3138,7 @@
 #else
     real_t< static_log2<mpl::abs<mpl::int_<Times+1> >::type::value>::value+Resolution, Resolution>
 #endif
- to_signed_number()
+ to_real_t()
     {
       return real_t<
       static_log2<mpl::abs<mpl::int_<Times+1> >::type::value>::value+Resolution, Resolution

Modified: sandbox/fixed_point/libs/fixed_point/example/ex_xx.cpp
==============================================================================
--- sandbox/fixed_point/libs/fixed_point/example/ex_xx.cpp (original)
+++ sandbox/fixed_point/libs/fixed_point/example/ex_xx.cpp 2012-04-21 08:26:52 EDT (Sat, 21 Apr 2012)
@@ -16,17 +16,17 @@
 
 pixel blend(pixel a, pixel b)
 {
- BOOST_AUTO(scale, (to_unsigned_number<255, 0> ()));
+ BOOST_AUTO(scale, (to_ureal_t<255, 0> ()));
   BOOST_AUTO(a_r, a.r / scale);
   BOOST_AUTO(b_r, b.r / scale);
   (void) a_r;
   (void) b_r;
- BOOST_AUTO(aia, b.a * (to_unsigned_number<1, 0> () - a.a));
+ BOOST_AUTO(aia, b.a * (to_ureal_t<1, 0> () - a.a));
   BOOST_AUTO(c_a, a.a + aia);
   BOOST_AUTO(c_r, (a.r * a.a + b.r * aia) / c_a);
   pixel c;
- c.a = number_cast<ureal_t<8, 0> > (c_a * to_unsigned_number<255, 0> ());
- c.r = number_cast<ureal_t<8, 0> > (c_r * to_unsigned_number<255, 0> ());
+ c.a = number_cast<ureal_t<8, 0> > (c_a * to_ureal_t<255, 0> ());
+ c.r = number_cast<ureal_t<8, 0> > (c_r * to_ureal_t<255, 0> ());
   return c;
 }
 
@@ -55,7 +55,7 @@
   }
   {
     std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
- ureal_t<2, -2, round::negative> n = to_unsigned_number<1, 0> (); //
+ ureal_t<2, -2, round::negative> n = to_ureal_t<1, 0> (); //
     std::cout << int(n.count()) << std::endl;
     BOOST_TEST(n.count() == 4);
   }
@@ -405,7 +405,7 @@
   }
   {
     std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
- ureal_t<4, -1> n1(-0.5f);
+ ureal_t<4, -1, round::negative, ::overflow::saturate> n1(-0.5f);
     BOOST_TEST(n1.count() == 0);
     BOOST_TEST(n1.as_float() == 0.0f);
   }
@@ -1045,27 +1045,27 @@
   // }
   {
     std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
- BOOST_AUTO(scale, (to_unsigned_number<255, 0> ()));
+ BOOST_AUTO(scale, (to_ureal_t<255, 0> ()));
     BOOST_TEST(scale.count() == 255);
   }
   {
     std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
- BOOST_AUTO(scale, (to_signed_number<255, 0> ()));
+ BOOST_AUTO(scale, (to_real_t<255, 0> ()));
     BOOST_TEST(scale.count() == 255);
   }
   {
     std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
- BOOST_AUTO(scale, (to_unsigned_number<1, -12> ()));
+ BOOST_AUTO(scale, (to_ureal_t<1, -12> ()));
     BOOST_TEST(scale.count() == 1);
   }
   {
     std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
- BOOST_AUTO(scale, (to_signed_number<1, -12> ()));
+ BOOST_AUTO(scale, (to_real_t<1, -12> ()));
     BOOST_TEST(scale.count() == 1);
   }
   {
     std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
- BOOST_AUTO(scale, (to_unsigned_number<3, 10> ()));
+ BOOST_AUTO(scale, (to_ureal_t<3, 10> ()));
     BOOST_TEST(scale.count() == 3);
   }
   {


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk