Boost logo

Boost-Commit :

From: steven_watanabe_at_[hidden]
Date: 2007-06-01 21:25:17


Author: steven_watanabe
Date: 2007-06-01 21:25:15 EDT (Fri, 01 Jun 2007)
New Revision: 4417
URL: http://svn.boost.org/trac/boost/changeset/4417

Log:
Made heterogeneous->heterogeneous conversion work

Added:
   sandbox/units/boost/units/detail/heterogeneous_conversion.hpp
Text files modified:
   sandbox/units/boost/units/conversion.hpp | 23 +++++++++++++++++++++++
   sandbox/units/libs/units/test/test_conversion.cpp | 18 +++++++++---------
   2 files changed, 32 insertions(+), 9 deletions(-)

Modified: sandbox/units/boost/units/conversion.hpp
==============================================================================
--- sandbox/units/boost/units/conversion.hpp (original)
+++ sandbox/units/boost/units/conversion.hpp 2007-06-01 21:25:15 EDT (Fri, 01 Jun 2007)
@@ -23,6 +23,7 @@
 #include <boost/units/heterogeneous_system.hpp>
 #include <boost/units/detail/one.hpp>
 #include <boost/units/detail/static_rational_power.hpp>
+#include <boost/units/detail/heterogeneous_conversion.hpp>
 
 namespace boost {
 
@@ -264,6 +265,28 @@
     }
 };
 
+template<class D, class S1, class T1, class S2, class T2>
+struct conversion_helper<quantity<unit<D, heterogeneous_system<S1> >, T1>, quantity<unit<D, heterogeneous_system<S2> >, T2> > {
+ typedef quantity<unit<D, heterogeneous_system<S1> >, T1> source_type;
+ typedef quantity<unit<D, heterogeneous_system<S2> >, T2> destination_type;
+ typedef typename detail::extract_base_units<mpl::size<typename S1::type>::value>::template apply<typename mpl::begin<typename S1::type>::type, mpl::list0<> >::type from_base_units;
+ typedef typename detail::extract_base_units<mpl::size<typename S2::type>::value>::template apply<typename mpl::begin<typename S2::type>::type, from_base_units>::type all_base_units;
+ typedef typename detail::make_homogeneous_system<all_base_units>::type system;
+ static destination_type convert(const source_type& source) {
+ return(destination_type::from_value(source.value() *
+ (detail::conversion_impl<mpl::size<typename S1::type>::value>::template apply<
+ typename mpl::begin<typename S1::type>::type,
+ system
+ >::value() /
+ detail::conversion_impl<mpl::size<typename S2::type>::value>::template apply<
+ typename mpl::begin<typename S2::type>::type,
+ system
+ >::value()
+ )
+ ));
+ }
+};
+
 namespace detail {
 
 template<class Source, class Dest>

Added: sandbox/units/boost/units/detail/heterogeneous_conversion.hpp
==============================================================================
--- (empty file)
+++ sandbox/units/boost/units/detail/heterogeneous_conversion.hpp 2007-06-01 21:25:15 EDT (Fri, 01 Jun 2007)
@@ -0,0 +1,314 @@
+// mcs::units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2007 Matthias Christian Schabel
+// Copyright (C) 2007 Steven Watanabe
+//
+// 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)
+
+#ifndef BOOST_UNITS_DETAIL_HETEROGENEOUS_CONVERSION_HPP
+#define BOOST_UNITS_DETAIL_HETEROGENEOUS_CONVERSION_HPP
+
+#include <boost/mpl/list/list0.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/begin.hpp>
+#include <boost/mpl/push_front.hpp>
+
+#include <boost/mpl/print.hpp>
+
+#include <boost/units/static_rational.hpp>
+#include <boost/units/detail/linear_algebra.hpp>
+
+namespace boost {
+
+namespace units {
+
+namespace detail {
+
+struct solve_end {
+ template<class Begin, class Y>
+ struct apply {
+ typedef mpl::list0<> type;
+ };
+};
+
+struct no_solution {};
+
+template<class X1, class X2, class Next>
+struct solve_normal {
+ template<class Begin, class Y>
+ struct apply {
+ typedef typename mpl::next<Begin>::type next;
+ typedef typename mpl::push_front<
+ typename Next::template apply<next, Y>::type,
+ typename mpl::minus<
+ typename mpl::times<X1, Y>::type,
+ typename mpl::times<X2, typename mpl::deref<Begin>::type>::type
+ >::type
+ >::type type;
+ };
+};
+
+template<class Next>
+struct solve_leading_zeroes {
+ template<class Begin>
+ struct apply {
+ typedef typename mpl::push_front<
+ typename Next::template apply<typename mpl::next<Begin>::type>::type,
+ typename mpl::deref<Begin>::type
+ >::type type;
+ };
+ typedef solve_leading_zeroes type;
+};
+
+template<>
+struct solve_leading_zeroes<no_solution> {
+ typedef no_solution type;
+};
+
+template<class Next>
+struct solve_first_non_zero {
+ template<class Begin>
+ struct apply {
+ typedef typename Next::template apply<
+ typename mpl::next<Begin>::type,
+ typename mpl::deref<Begin>::type
+ >::type type;
+ };
+};
+
+template<class Next>
+struct solve_internal_zero {
+ template<class Begin, class Y>
+ struct apply {
+ typedef typename mpl::push_front<
+ typename Next::template apply<typename mpl::next<Begin>::type, Y>::type,
+ typename mpl::deref<Begin>::type
+ >::type type;
+ };
+};
+
+template<class T>
+struct make_solve_list_internal_zero {
+ template<class Next, class X>
+ struct apply {
+ typedef solve_normal<X, T, Next> type;
+ };
+};
+
+template<>
+struct make_solve_list_internal_zero<static_rational<0> > {
+ template<class Next, class X>
+ struct apply {
+ typedef typename solve_internal_zero<Next> type;
+ };
+};
+
+template<int N>
+struct make_solve_list_normal {
+ template<class Begin, class X>
+ struct apply {
+ typedef typename make_solve_list_internal_zero<
+ typename mpl::deref<Begin>::type
+ >::template apply<
+ typename make_solve_list_normal<N-1>::template apply<typename mpl::next<Begin>::type, X>::type,
+ X
+ >::type type;
+ };
+};
+
+template<>
+struct make_solve_list_normal<0> {
+ template<class Begin, class X>
+ struct apply {
+ typedef solve_end type;
+ };
+};
+
+template<int N>
+struct make_solve_list_leading_zeroes;
+
+template<class T>
+struct make_solve_list_first_non_zero {
+ template<class Begin, int N>
+ struct apply {
+ typedef solve_first_non_zero<
+ typename make_solve_list_normal<N-1>::template apply<
+ typename mpl::next<Begin>::type,
+ typename mpl::deref<Begin>::type
+ >::type
+ > type;
+ };
+};
+
+template<>
+struct make_solve_list_first_non_zero<static_rational<0> > {
+ template<class Begin, int N>
+ struct apply {
+ typedef typename solve_leading_zeroes<
+ typename make_solve_list_leading_zeroes<N-1>::template apply<
+ typename mpl::next<Begin>::type
+ >::type
+ >::type type;
+ };
+};
+
+template<int N>
+struct make_solve_list_leading_zeroes {
+ template<class Begin>
+ struct apply {
+ typedef typename make_solve_list_first_non_zero<typename mpl::deref<Begin>::type>::template apply<Begin, N>::type type;
+ };
+};
+
+template<>
+struct make_solve_list_leading_zeroes<0> {
+ template<class Begin>
+ struct apply {
+ typedef no_solution type;
+ };
+};
+
+template<int N>
+struct try_add_unit_impl {
+ template<class Begin, class L>
+ struct apply {
+ typedef typename try_add_unit_impl<N-1>::template apply<typename mpl::next<Begin>::type, L>::type next;
+ typedef typename mpl::deref<Begin>::type::template apply<typename mpl::begin<next>::type>::type type;
+ BOOST_STATIC_ASSERT((mpl::size<next>::value - 1 == mpl::size<type>::value));
+ };
+};
+
+template<>
+struct try_add_unit_impl<0> {
+ template<class Begin, class L>
+ struct apply {
+ typedef L type;
+ };
+};
+
+template<int N>
+struct make_homogeneous_system_impl;
+
+template<class T, bool is_done>
+struct make_homogeneous_system_func;
+
+template<class T>
+struct make_homogeneous_system_func<T, false> {
+ template<class Begin, class Current, class Units, class Dimensions, int N>
+ struct apply {
+ typedef typename make_homogeneous_system_impl<N-1>::template apply<
+ typename mpl::next<Begin>::type,
+ typename mpl::push_front<Current, T>::type,
+ typename mpl::push_front<Units, typename mpl::deref<Begin>::type>::type,
+ Dimensions
+ >::type type;
+ };
+};
+
+template<class T>
+struct make_homogeneous_system_func<T, true> {
+ template<class Begin, class Current, class Units, class Dimensions, int N>
+ struct apply {
+ typedef typename mpl::push_front<Units, typename mpl::deref<Begin>::type>::type type;
+ };
+};
+
+template<>
+struct make_homogeneous_system_func<no_solution, false> {
+ template<class Begin, class Current, class Units, class Dimensions, int N>
+ struct apply {
+ typedef typename make_homogeneous_system_impl<N-1>::template apply<
+ typename mpl::next<Begin>::type,
+ Current,
+ Units,
+ Dimensions
+ >::type type;
+ };
+};
+
+template<>
+struct make_homogeneous_system_func<no_solution, true> {
+ template<class Begin, class Current, class Units, class Dimensions, int N>
+ struct apply {
+ typedef typename make_homogeneous_system_impl<N-1>::template apply<
+ typename mpl::next<Begin>::type,
+ Current,
+ Units,
+ Dimensions
+ >::type type;
+ };
+};
+
+template<int N>
+struct make_homogeneous_system_impl {
+ template<class Begin, class Current, class Units, class Dimensions>
+ struct apply {
+ typedef typename expand_dimensions<mpl::size<Dimensions>::value>::template apply<
+ typename mpl::begin<Dimensions>::type,
+ typename mpl::begin<typename mpl::deref<Begin>::type::dimension_type>::type
+ >::type dimensions;
+ typedef typename try_add_unit_impl<mpl::size<Current>::value>::template apply<typename mpl::begin<Current>::type, dimensions>::type new_element;
+ typedef typename make_solve_list_leading_zeroes<mpl::size<new_element>::value>::template apply<typename mpl::begin<new_element>::type>::type new_func;
+ typedef typename make_homogeneous_system_func<
+ new_func,
+ ((mpl::size<Current>::value)+1) == (mpl::size<Dimensions>::value)
+ >::template apply<Begin, Current, Units, Dimensions, N>::type type;
+ };
+};
+
+template<>
+struct make_homogeneous_system_impl<0> {
+ template<class Begin, class Current, class Units, class Dimensions>
+ struct apply {
+ typedef Units type;
+ };
+};
+
+template<class Units>
+struct make_homogeneous_system {
+ typedef typename find_base_dimensions<Units>::type base_dimensions;
+ typedef homogeneous_system<
+ typename bubble_sort<
+ typename make_homogeneous_system_impl<
+ mpl::size<Units>::value
+ >::template apply<
+ typename mpl::begin<Units>::type,
+ mpl::list0<>,
+ mpl::list0<>,
+ base_dimensions
+ >::type
+ >::type
+ > type;
+};
+
+template<int N>
+struct extract_base_units {
+ template<class Begin, class T>
+ struct apply {
+ typedef typename mpl::push_front<
+ typename extract_base_units<N-1>::template apply<typename mpl::next<Begin>::type, T>::type,
+ typename mpl::deref<Begin>::type::tag_type
+ >::type type;
+ };
+};
+
+template<>
+struct extract_base_units<0> {
+ template<class Begin, class T>
+ struct apply {
+ typedef T type;
+ };
+};
+
+}
+
+}
+
+}
+
+#endif

Modified: sandbox/units/libs/units/test/test_conversion.cpp
==============================================================================
--- sandbox/units/libs/units/test/test_conversion.cpp (original)
+++ sandbox/units/libs/units/test/test_conversion.cpp 2007-06-01 21:25:15 EDT (Fri, 01 Jun 2007)
@@ -64,9 +64,9 @@
     bu::quantity<mixed_energy_1> e1(2.0 * mixed_energy_1());
 
     //heterogeneous->heterogeneous is broken
- //bu::quantity<mixed_energy_2> e2(e1);
+ bu::quantity<mixed_energy_2> e2(e1);
 
- //BOOST_CHECK((std::abs(e2.value() - 20.0) < .0001));
+ BOOST_CHECK((std::abs(e2.value() - 20.0) < .0001));
 
     bu::quantity<bu::SI::energy> e3(e1);
     BOOST_CHECK((std::abs(e3.value() - .0002) < .0001));
@@ -102,15 +102,15 @@
 
     typedef bu::multiply_typeof_helper<bu::SI::length, bu::CGS::length>::type m_cm;
     typedef bu::divide_typeof_helper<m_cm, m_cm>::type heterogeneous_dimensionless;
-// bu::quantity<heterogeneous_dimensionless> dimensionless_test2(1.0*bu::CGS::dyne/bu::SI::newton);
-// BOOST_CHECK(dimensionless_test2.value() == 1e-5);
-// bu::quantity<bu::divide_typeof_helper<bu::CGS::force, bu::SI::force>::type> dimensionless_test3(dimensionless_test2);
-// BOOST_UNITS_CHECK_CLOSE(dimensionless_test3.value(), 1.0);
+ bu::quantity<heterogeneous_dimensionless> dimensionless_test2(1.0*bu::CGS::dyne/bu::SI::newton);
+ BOOST_CHECK(dimensionless_test2.value() == 1e-5);
+ bu::quantity<bu::divide_typeof_helper<bu::CGS::force, bu::SI::force>::type> dimensionless_test3(dimensionless_test2);
+ BOOST_UNITS_CHECK_CLOSE(dimensionless_test3.value(), 1.0);
 
     //m/cm -> g/kg
-// bu::quantity<bu::divide_typeof_helper<bu::SI::length, bu::CGS::length>::type> dimensionless_test4(2.0 * bu::SI::meters / bu::CGS::centimeters);
-// bu::quantity<bu::divide_typeof_helper<bu::CGS::mass, bu::SI::mass>::type> dimensionless_test5(dimensionless_test4);
-// BOOST_UNITS_CHECK_CLOSE(dimensionless_test5.value(), 2e5);
+ bu::quantity<bu::divide_typeof_helper<bu::SI::length, bu::CGS::length>::type> dimensionless_test4(2.0 * bu::SI::meters / bu::CGS::centimeters);
+ bu::quantity<bu::divide_typeof_helper<bu::CGS::mass, bu::SI::mass>::type> dimensionless_test5(dimensionless_test4);
+ BOOST_UNITS_CHECK_CLOSE(dimensionless_test5.value(), 2e5);
 
     return(0);
 }


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