$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: steven_watanabe_at_[hidden]
Date: 2007-05-29 16:53:15
Author: steven_watanabe
Date: 2007-05-29 16:53:15 EDT (Tue, 29 May 2007)
New Revision: 4355
URL: http://svn.boost.org/trac/boost/changeset/4355
Log:
Implemented bidirectional affine conversions
Text files modified: 
   sandbox/units/boost/units/absolute.hpp               |    61 ++++++++++++++++++++++++++++++++++----- 
   sandbox/units/boost/units/systems/base_units.hpp     |     4 +-                                      
   sandbox/units/libs/units/example/unit_example_20.cpp |    45 -----------------------------           
   3 files changed, 54 insertions(+), 56 deletions(-)
Modified: sandbox/units/boost/units/absolute.hpp
==============================================================================
--- sandbox/units/boost/units/absolute.hpp	(original)
+++ sandbox/units/boost/units/absolute.hpp	2007-05-29 16:53:15 EDT (Tue, 29 May 2007)
@@ -13,6 +13,8 @@
 
 #include <iosfwd>
 
+#include <boost/type_traits/is_base_and_derived.hpp>
+
 #include <boost/units/conversion.hpp>
 
 namespace boost {
@@ -41,15 +43,47 @@
         value_type   val_;
 };
 
+namespace detail {
+
+struct undefined_affine_conversion_base {};
+
+}
+
 template<class From, class To>
-struct affine_conversion_helper {
-    //F = 9/5 C + 32
-    //5/9 F = C + 32 * 5/9
-    //C = 5/9 F - 32 * 5/9
-    typedef typename affine_conversion_helper<To, From>::type type;
-    static type value() { return(-affine_conversion_helper<To, From>::value() * conversion_factor<type>(From(), To())); }
+struct affine_conversion_helper : detail::undefined_affine_conversion_base {};
+
+namespace detail {
+
+template<bool IsDefined, bool ReverseIsDefined>
+struct affine_conversion_impl;
+
+template<bool ReverseIsDefined>
+struct affine_conversion_impl<true, ReverseIsDefined> {
+    template<class Unit1, class Unit2, class T0, class T1>
+    struct apply {
+        static T1 value(const T0& t0) {
+            return(
+                t0 * 
+                conversion_factor(Unit1(), Unit2()) +
+                affine_conversion_helper<typename reduce_unit<Unit1>::type, typename reduce_unit<Unit2>::type>::value());
+        }
+    };
+};
+
+template<>
+struct affine_conversion_impl<false, true> {
+    template<class Unit1, class Unit2, class T0, class T1>
+    struct apply {
+        static T1 value(const T0& t0) {
+            return(
+                (t0 - affine_conversion_helper<typename reduce_unit<Unit2>::type, typename reduce_unit<Unit1>::type>::value()) * 
+                conversion_factor(Unit1(), Unit2()));
+        }
+    };
 };
 
+}
+
 template<class Unit1, class T1, class Unit2, class T2>
 struct conversion_helper<quantity<absolute<Unit1>, T1>, quantity<absolute<Unit2>, T2> > {
     typedef quantity<absolute<Unit1>, T1> from_quantity_type;
@@ -57,9 +91,18 @@
     static to_quantity_type convert(const from_quantity_type& source) {
         return(
             to_quantity_type::from_value(
-                source.value() *
-                conversion_factor(Unit1(), Unit2()) +
-                affine_conversion_helper<typename reduce_unit<Unit1>::type, typename reduce_unit<Unit2>::type>::value()));
+                detail::affine_conversion_impl<
+                    !boost::is_base_and_derived<
+                        detail::undefined_affine_conversion_base, 
+                        affine_conversion_helper<typename reduce_unit<Unit1>::type, typename reduce_unit<Unit2>::type>
+                    >::value,
+                    !boost::is_base_and_derived<
+                        detail::undefined_affine_conversion_base,
+                        affine_conversion_helper<typename reduce_unit<Unit2>::type, typename reduce_unit<Unit1>::type>
+                    >::value
+                >::template apply<Unit1, Unit2, T1, T2>::value(source.value())
+            )
+        );
     }
 };
 
Modified: sandbox/units/boost/units/systems/base_units.hpp
==============================================================================
--- sandbox/units/boost/units/systems/base_units.hpp	(original)
+++ sandbox/units/boost/units/systems/base_units.hpp	2007-05-29 16:53:15 EDT (Tue, 29 May 2007)
@@ -122,8 +122,8 @@
 BOOST_UNITS_DEFINE_CONVERSION(boost::units::kelvin_tag, boost::units::fahrenheit_tag::unit_type, double, 9.0/5.0);
 BOOST_UNITS_DEFINE_CONVERSION(boost::units::celsius_tag, boost::units::fahrenheit_tag::unit_type, double, 9.0/5.0);
 
-BOOST_UNITS_DEFINE_AFFINE_CONVERSION(boost::units::kelvin_tag::unit_type, boost::units::celsius_tag::unit_type, double, 273.15);
-BOOST_UNITS_DEFINE_AFFINE_CONVERSION(boost::units::kelvin_tag::unit_type, boost::units::fahrenheit_tag::unit_type, double, 273.15 * 9.0 / 5.0 + 32.0);
+BOOST_UNITS_DEFINE_AFFINE_CONVERSION(boost::units::kelvin_tag::unit_type, boost::units::celsius_tag::unit_type, double, -273.15);
+BOOST_UNITS_DEFINE_AFFINE_CONVERSION(boost::units::kelvin_tag::unit_type, boost::units::fahrenheit_tag::unit_type, double, -273.15 * 9.0 / 5.0 + 32.0);
 BOOST_UNITS_DEFINE_AFFINE_CONVERSION(boost::units::celsius_tag::unit_type, boost::units::fahrenheit_tag::unit_type, double, 32.0);
 
 BOOST_UNITS_DEFINE_CONVERSION(boost::units::radian_tag, boost::units::degree_tag::unit_type, double, 180/3.14159265358979323846);
Modified: sandbox/units/libs/units/example/unit_example_20.cpp
==============================================================================
--- sandbox/units/libs/units/example/unit_example_20.cpp	(original)
+++ sandbox/units/libs/units/example/unit_example_20.cpp	2007-05-29 16:53:15 EDT (Tue, 29 May 2007)
@@ -44,8 +44,6 @@
 #include <boost/units/systems/si/temperature.hpp>
 #include <boost/units/detail/utility.hpp>
 
-BOOST_UNITS_DEFINE_AFFINE_CONVERSION(boost::units::fahrenheit_tag::unit_type, boost::units::kelvin_tag::unit_type, double, 273.15 + 5.0 / 9.0 * 32.0);
-
 using namespace boost::units;
 
 namespace boost {
@@ -75,48 +73,6 @@
     public mpl::true_
 { };
 
-//template<class Y>
-//class conversion_helper< quantity<unit<temperature_type,fahrenheit::system>,absolute<Y> >,
-//                         quantity<unit<temperature_type,SI::system>,absolute<Y> > >
-//{
-//    public:
-//        typedef unit<temperature_type,fahrenheit::system>   unit1_type;
-//        typedef unit<temperature_type,SI::system>           unit2_type;
-//        
-//        typedef quantity<unit1_type,absolute<Y> >           from_quantity_type;
-//        typedef quantity<unit2_type,absolute<Y> >           to_quantity_type;
-//
-//        static
-//        to_quantity_type
-//        convert(const from_quantity_type& source)
-//        {
-//            const typename from_quantity_type::value_type&   in(source.value());
-//            
-//            return to_quantity_type::from_value((in.value()-32)*(5.0/9.0) + 273.15);
-//        }
-//};
-//
-//template<class Y>
-//class conversion_helper< quantity<unit<temperature_type,fahrenheit::system>,Y>,
-//                         quantity<unit<temperature_type,SI::system>,Y> >
-//{
-//    public:
-//        typedef unit<temperature_type,fahrenheit::system>   unit1_type;
-//        typedef unit<temperature_type,SI::system>           unit2_type;
-//        
-//        typedef quantity<unit1_type,Y>                      from_quantity_type;
-//        typedef quantity<unit2_type,Y>                      to_quantity_type;
-//
-//        static
-//        to_quantity_type
-//        convert(const from_quantity_type& source)
-//        {
-//            const typename from_quantity_type::value_type&   in(source.value());
-//            
-//            return to_quantity_type::from_value(in*(5.0/9.0));
-//        }
-//};
-
 } // namespace units
 
 } // namespace boost
@@ -189,4 +145,3 @@
         return(-1);
     }
 }
-