C:/nobackup/private/physical_svn/trunk/source/playground.cpp

Go to the documentation of this file.
00001 
00002 /* typelist of baseunits */
00003 
00004 /* invariants: position<number of baseunits, all positions different */
00005 
00006 /* conversion of a quantity between two unitsystems: 
00007    
00008    all dimensions with nonzero exponents in source unit 
00009    system must be present in the target unit system. 
00010 
00011    The conversion factor is the product of all base unit conversions. 
00012    How to determine these automatically?
00013 
00014 */
00015 
00016 
00017 #include <boost/mpl/vector.hpp>
00018 #include <boost/mpl/size.hpp>
00019 #include <boost/mpl/find.hpp>
00020 #include <boost/mpl/push_back.hpp>
00021 #include <boost/mpl/at.hpp>
00022 #include <boost/mpl/map.hpp>
00023 #include <boost/mpl/insert.hpp>
00024 #include <boost/mpl/pair.hpp>
00025 #include <boost/mpl/fold.hpp>
00026 #include <boost/mpl/multiplies.hpp>
00027 #include <boost/mpl/transform.hpp>
00028 #include <boost/mpl/erase_key.hpp>
00029 #include <boost/type_traits/is_same.hpp>
00030 #include <boost/static_assert.hpp>
00031 #include <boost/mpl/equal.hpp>
00032 
00033 // this one is taken from mcs::unit s..
00034 #include "physical/detail/static_rational.hpp"
00035 using mcs::units::static_rational;
00036 using mcs::units::static_multiply;
00037 using mcs::units::static_divide;
00038 
00039 
00040 
00041 /* implement some static_power functionality */
00042 /* please be aware that we can easily get out of the admissible range for integers 
00043    if we convert (1 km)^3 to (10^6mm)^3. 
00044    Thus we probably need some other representation: based on primes and exponents!
00045 */
00046 
00047 // absolute value
00048 template<int V> struct static_abs {
00049    BOOST_STATIC_CONSTANT(int, value= V>=0? V : -V);
00050 };
00051 
00052 // invert a rational
00053 template<typename R1> struct static_invert {
00054    typedef typename static_divide<static_rational<1,1>, R1>::type type;
00055 };
00056 
00057 // recursive definition
00058 template<typename R1, int EXP> struct static_power_impl {
00059    BOOST_STATIC_ASSERT(EXP>0);
00060    typedef typename static_power_impl<R1, EXP-1>::type part;
00061    typedef typename static_multiply<part, R1>::type  type;
00062 };   
00063    
00064 // partial specialisations
00065 template<typename R1> struct static_power_impl<R1, 1> {
00066    typedef R1 type;
00067 };
00068 
00069 template<typename R1> struct static_power_impl<R1, 0> {
00070    typedef static_rational<1,1> type;
00071 };
00072 
00073 // work on sign and invert the rational if necessary
00074 template<typename R1, int EXP> struct static_power {
00075    BOOST_STATIC_CONSTANT(int, E = static_abs<EXP>::value);
00076    BOOST_STATIC_ASSERT(E>=0);
00077    typedef typename static_power_impl<R1, E>::type part;
00078    typedef typename boost::mpl::if_c< (EXP>0), part, typename static_invert<part>::type>::type type;
00079 };
00080 
00081 
00082 // this should go to testing..
00083 BOOST_STATIC_ASSERT(( boost::is_same<static_power< static_rational<2,1>, -3>::type, static_rational<1,8> >::type::value));
00084 BOOST_STATIC_ASSERT(( boost::is_same<static_power< static_rational<2,1>, -2>::type, static_rational<1,4> >::type::value));
00085 BOOST_STATIC_ASSERT(( boost::is_same<static_power< static_rational<2,1>, -1>::type, static_rational<1,2> >::type::value));
00086 BOOST_STATIC_ASSERT(( boost::is_same<static_power< static_rational<2,1>, -0>::type, static_rational<1,1> >::type::value));
00087 BOOST_STATIC_ASSERT(( boost::is_same<static_power< static_rational<2,1>, 0>::type, static_rational<1,1> >::type::value));
00088 BOOST_STATIC_ASSERT(( boost::is_same<static_power< static_rational<2,1>, 1>::type, static_rational<2,1> >::type::value));
00089 BOOST_STATIC_ASSERT(( boost::is_same<static_power< static_rational<2,1>, 2>::type, static_rational<4,1> >::type::value));
00090 BOOST_STATIC_ASSERT(( boost::is_same<static_power< static_rational<2,1>, 3>::type, static_rational<8,1> >::type::value));
00091 
00092 BOOST_STATIC_ASSERT(( boost::is_same<static_power< static_rational<1,2>, -3>::type, static_rational<8,1> >::type::value));
00093 BOOST_STATIC_ASSERT(( boost::is_same<static_power< static_rational<1,2>, -2>::type, static_rational<4,1> >::type::value));
00094 BOOST_STATIC_ASSERT(( boost::is_same<static_power< static_rational<1,2>, -1>::type, static_rational<2,1> >::type::value));
00095 BOOST_STATIC_ASSERT(( boost::is_same<static_power< static_rational<1,2>, -0>::type, static_rational<1,1> >::type::value));
00096 BOOST_STATIC_ASSERT(( boost::is_same<static_power< static_rational<1,2>, 0>::type, static_rational<1,1> >::type::value));
00097 BOOST_STATIC_ASSERT(( boost::is_same<static_power< static_rational<1,2>, 1>::type, static_rational<1,2> >::type::value));
00098 BOOST_STATIC_ASSERT(( boost::is_same<static_power< static_rational<1,2>, 2>::type, static_rational<1,4> >::type::value));
00099 BOOST_STATIC_ASSERT(( boost::is_same<static_power< static_rational<1,2>, 3>::type, static_rational<1,8> >::type::value));
00100 
00101 
00102 
00103 
00104 namespace old_primes {
00105 
00106    struct yes { BOOST_STATIC_CONSTANT(int, value = 1); };
00107    
00108    struct no  { BOOST_STATIC_CONSTANT(int, value = 0); };
00109 
00110    template<int a, int b> struct is_divisible {
00111       typedef typename boost::mpl::if_c< (a/b)*b==a, yes, no>::type type;
00112       BOOST_STATIC_CONSTANT( int, value = type::value);
00113    };
00114 
00115    BOOST_STATIC_ASSERT(( is_divisible<8,1>::type::value ));
00116    BOOST_STATIC_ASSERT(( is_divisible<8,2>::type::value ));
00117    BOOST_STATIC_ASSERT(( is_divisible<8,4>::type::value ));
00118    BOOST_STATIC_ASSERT(( is_divisible<8,8>::type::value ));
00119    BOOST_STATIC_ASSERT(( !is_divisible<8,16>::type::value ));
00120    BOOST_STATIC_ASSERT(( !is_divisible<8,3>::type::value ));
00121 
00122 
00123    // to compute the prime decomposition of n, recursively loop over all(?) numbers up to n 
00124    // and build an appropriate typelist...
00125 
00126    template<int n> struct primes;
00127 
00128    template<> struct primes<1> {
00129       typedef boost::mpl::vector<> type;
00130    };
00131 
00132    template<> struct primes<2> {
00133       typedef boost::mpl::vector<boost::mpl::integral_c<int,2> > type;
00134    };
00135 
00136    template<> struct primes<3> {
00137       typedef boost::mpl::push_back<primes<2>::type, boost::mpl::integral_c<int,3> >::type type;
00138    };
00139 
00140    // ???
00141    
00142    // declaration
00143    template<typename n, typename upto> struct prime_decomposition;
00144 
00145    // specialisation for upto::value==1:
00146    template<typename n> struct prime_decomposition<n, boost::mpl::integral_c<int, 1> >{
00147       typedef boost::mpl::vector<> list;
00148       typedef n remainder;
00149    };
00150 
00151 
00152    // implementation for upto::value>1:
00153    template<typename n, typename upto> struct prime_decomposition {
00154       typedef boost::mpl::integral_c<int, upto::value-1> upto_m1;
00155       BOOST_STATIC_ASSERT(( upto_m1::value >= 1));
00156       
00157       typedef typename prime_decomposition<n, upto_m1> part_decomposition;
00158       typedef typename part_decomposition::remainder   part_remainder;
00159 
00160       typedef typename boost::mpl::if_c< is_divisible<part_remainder::value, upto::value>::type::value, 
00161          typename boost::mpl::push_back<typename part_decomposition::list, boost::mpl::integral_c<int, upto::value> >::type, // that additional integral_c should not be necessary
00162          typename part_decomposition::list >::type list;
00163 
00164       typedef typename boost::mpl::if_c< is_divisible<part_decomposition::remainder::value, upto::value>::type::value, 
00165          boost::mpl::integral_c<int, (part_decomposition::remainder::value / upto::value) >,
00166          typename part_decomposition::remainder >::type remainder;
00167 
00168    };
00169 
00170 
00171    // Yeah, it already nearly works (still need a loop instead of the "if":
00172    BOOST_STATIC_ASSERT(( boost::mpl::equal<typename prime_decomposition<boost::mpl::integral_c<int, 5>, boost::mpl::integral_c<int, 1> >::list, boost::mpl::vector<> >::type::value ));
00173    BOOST_STATIC_ASSERT(( boost::is_same<typename prime_decomposition<boost::mpl::integral_c<int, 5>, boost::mpl::integral_c<int, 1> >::remainder, boost::mpl::integral_c<int, 5> >::type::value ));
00174    
00175    BOOST_STATIC_ASSERT(( boost::mpl::equal<typename prime_decomposition<boost::mpl::integral_c<int, 5>, boost::mpl::integral_c<int, 2> >::list, boost::mpl::vector<> >::type::value ));
00176    BOOST_STATIC_ASSERT(( boost::is_same<typename prime_decomposition<boost::mpl::integral_c<int, 5>, boost::mpl::integral_c<int, 2> >::remainder, boost::mpl::integral_c<int, 5> >::type::value ));
00177 
00178    BOOST_STATIC_ASSERT(( boost::mpl::equal<typename prime_decomposition<boost::mpl::integral_c<int, 5>, boost::mpl::integral_c<int, 3> >::list, boost::mpl::vector<> >::type::value ));
00179    BOOST_STATIC_ASSERT(( boost::is_same<typename prime_decomposition<boost::mpl::integral_c<int, 5>, boost::mpl::integral_c<int, 3> >::remainder, boost::mpl::integral_c<int, 5> >::type::value ));
00180    
00181    BOOST_STATIC_ASSERT(( boost::mpl::equal<typename prime_decomposition<boost::mpl::integral_c<int, 5>, boost::mpl::integral_c<int, 4> >::list, boost::mpl::vector<> >::type::value ));
00182    BOOST_STATIC_ASSERT(( boost::is_same<typename prime_decomposition<boost::mpl::integral_c<int, 5>, boost::mpl::integral_c<int, 4> >::remainder, boost::mpl::integral_c<int, 5> >::type::value ));
00183 
00184    BOOST_STATIC_ASSERT(( boost::mpl::equal<typename prime_decomposition<boost::mpl::integral_c<int, 5>, boost::mpl::integral_c<int, 5> >::list, boost::mpl::vector<boost::mpl::integral_c<int, 5> > >::type::value ));
00185    BOOST_STATIC_ASSERT(( boost::is_same<typename prime_decomposition<boost::mpl::integral_c<int, 5>, boost::mpl::integral_c<int, 5> >::remainder, boost::mpl::integral_c<int, 1> >::type::value ));
00186 
00187    BOOST_STATIC_ASSERT(( boost::mpl::equal<typename prime_decomposition<boost::mpl::integral_c<int, 10>, boost::mpl::integral_c<int, 4> >::list, boost::mpl::vector<boost::mpl::integral_c<int, 2> > >::type::value ));
00188    BOOST_STATIC_ASSERT(( boost::is_same<typename prime_decomposition<boost::mpl::integral_c<int, 10>, boost::mpl::integral_c<int, 4> >::remainder, boost::mpl::integral_c<int, 5> >::type::value ));
00189 
00190    BOOST_STATIC_ASSERT(( boost::mpl::equal<typename prime_decomposition<boost::mpl::integral_c<int, 10>, boost::mpl::integral_c<int, 5> >::list, boost::mpl::vector<boost::mpl::integral_c<int, 2>, boost::mpl::integral_c<int, 5> > >::type::value ));
00191    BOOST_STATIC_ASSERT(( boost::is_same<typename prime_decomposition<boost::mpl::integral_c<int, 10>, boost::mpl::integral_c<int, 5> >::remainder, boost::mpl::integral_c<int, 1> >::type::value ));
00192 
00193 };
00194 
00195 
00196 namespace primes {
00197 
00198    namespace mpl=boost::mpl;
00199 
00200    struct yes { BOOST_STATIC_CONSTANT(int, value = 1); };
00201    
00202    struct no  { BOOST_STATIC_CONSTANT(int, value = 0); };
00203 
00204    template<int a, int b> struct is_divisible {
00205       typedef typename boost::mpl::if_c< (a/b)*b==a, yes, no>::type type;
00206       BOOST_STATIC_CONSTANT( int, value = type::value);
00207    };
00208 
00209    BOOST_STATIC_ASSERT(( is_divisible<8,1>::type::value ));
00210    BOOST_STATIC_ASSERT(( is_divisible<8,2>::type::value ));
00211    BOOST_STATIC_ASSERT(( is_divisible<8,4>::type::value ));
00212    BOOST_STATIC_ASSERT(( is_divisible<8,8>::type::value ));
00213    BOOST_STATIC_ASSERT(( !is_divisible<8,16>::type::value ));
00214    BOOST_STATIC_ASSERT(( !is_divisible<8,3>::type::value ));
00215 
00216 /*
00217    typedef mpl::map<> map_;
00218    typedef mpl::insert<map_, mpl::pair<mpl::integral_c<int, 5>, mpl::integral_c<int, 1> > >::type map_51;
00219    
00220    typedef mpl::insert<map_51, mpl::pair<mpl::integral_c<int, 5>, mpl::integral_c<int, 2> > >::type map_52;
00221 
00222    BOOST_STATIC_ASSERT(( mpl::size<map_51>::type::value == 1 ));
00223    BOOST_STATIC_ASSERT(( mpl::size<map_52>::type::value == 2 )); // XXXX This is not what I expected it to be!! FIXME!
00224 */
00225 
00226    template<class Map, class Pair> struct add_pair_impl {
00227       typedef typename Pair::first key;
00228       typedef typename Pair::second value;
00229       BOOST_STATIC_ASSERT(( mpl::has_key<Map, key>::type::value ));
00230       typedef typename mpl::at<Map, key>::type old_value;
00231       typedef typename mpl::erase_key<Map, key>::type map_erased;
00232       typedef typename mpl::insert< map_erased, mpl::pair<key, typename mpl::plus<old_value,value>::type > >::type type;
00233    };
00234 
00235 
00236    template<class Map, class Pair, bool> struct add_pair_dispatch;
00237 
00238    template<class Map, class Pair> struct add_pair_dispatch<Map, Pair, true> {
00239       typedef typename add_pair_impl<Map, Pair>::type type;
00240    };
00241 
00242    template<class Map, class Pair> struct add_pair_dispatch<Map, Pair, false> {
00243       typedef typename mpl::insert< Map, Pair >::type type;
00244    };
00245 
00246    template<class Map, class Pair> struct add_pair {
00247       typedef typename Pair::first key;
00248       BOOST_STATIC_CONSTANT( bool, has_key = (mpl::has_key<Map, key>::value) );
00249       typedef typename add_pair_dispatch<Map, Pair, has_key>::type type;
00250    };
00251 
00252    typedef mpl::map<> map_;
00253    typedef add_pair<map_, mpl::pair<mpl::integral_c<int, 5>, mpl::integral_c<int, 1> > >::type map_51;
00254    typedef add_pair<map_51, mpl::pair<mpl::integral_c<int, 5>, mpl::integral_c<int, 1> > >::type map_52;
00255 
00256    BOOST_STATIC_ASSERT(( mpl::size<map_>::type::value == 0 ));
00257    BOOST_STATIC_ASSERT(( mpl::size<map_51>::type::value == 1 ));
00258    BOOST_STATIC_ASSERT(( mpl::size<map_52>::type::value == 1 ));
00259 
00260 
00261 
00262 
00263 
00264    // container that hold the prime+exp map together with the remainder
00265    template<class Map, class Remainder> struct partial_prime_represenation {
00266       typedef Map map;
00267       typedef Remainder remainder;
00268    };
00269 
00270    // metafunction that takes a container, adds p to the map and divedes the remainder by p
00271    template<class PrimeDecomp, class p> struct reduce_prime_impl;
00272 
00273 
00274    template<class Map, class Remainder, class p> struct reduce_prime_impl<partial_prime_represenation<Map, Remainder>, p> {
00275       BOOST_STATIC_ASSERT(( is_divisible<Remainder::value, p::value>::type::value ));
00276       typedef typename boost::mpl::integral_c<int, Remainder::value/p::value>::type remainder;
00277       //typedef typename boost::mpl::insert<Map, boost::mpl::pair<p,boost::mpl::integral_c<int, 1> > >::type map;
00278       typedef typename add_pair<Map, mpl::pair<p, mpl::integral_c<int, 1> > >::type map;
00279       typedef partial_prime_represenation<map, remainder> type;
00280    };
00281 
00282 
00283    // some maps that represent primes+exponents
00284    typedef mpl::map<> empty_map;
00285    typedef mpl::map<mpl::pair<mpl::integral_c<int, 2>, mpl::integral_c<int, 1> > > map_2;
00286    typedef mpl::map<mpl::pair<mpl::integral_c<int, 2>, mpl::integral_c<int, 2> > > map_2_2;
00287    typedef mpl::map<mpl::pair<mpl::integral_c<int, 3>, mpl::integral_c<int, 1> > > map_3;
00288    typedef mpl::map<mpl::pair<mpl::integral_c<int, 3>, mpl::integral_c<int, 2> > > map_3_3;
00289    typedef mpl::map<mpl::pair<mpl::integral_c<int, 2>, mpl::integral_c<int, 1> >, 
00290                     mpl::pair<mpl::integral_c<int, 3>, mpl::integral_c<int, 1> > > map_2_3;
00291 
00292    BOOST_STATIC_ASSERT(( mpl::size<empty_map>::type::value == 0 ));
00293    BOOST_STATIC_ASSERT(( mpl::size<map_2>::type::value == 1 ));
00294 
00295 
00296    // multiply some numbers:
00297    using mpl::placeholders::_;
00298    using mpl::placeholders::_1;
00299    using mpl::placeholders::_2;
00300    typedef mpl::vector<mpl::integral_c<int,2>, mpl::integral_c<int,3>, mpl::integral_c<int,5> > prime_list_2_3_5;
00301    typedef mpl::fold<prime_list_2_3_5, mpl::integral_c<int, 1>, mpl::multiplies<_,_> >::type product_2_3_5;
00302    BOOST_STATIC_ASSERT(( product_2_3_5::value == 2*3*5 ));
00303 
00304    template<class n, class k> struct power_impl {
00305       typedef mpl::integral_c<int, 1> one;
00306       typedef typename mpl::multiplies< typename power_impl<n, typename mpl::minus<k,one>::type >::type, n>::type type;
00307    };
00308 
00309    template<class n> struct power_impl<n, mpl::integral_c<int, 1> > {
00310       typedef n type;
00311    };
00312 
00313    template<class n> struct power_impl<n, mpl::integral_c<int, 0> > {
00314       typedef mpl::integral_c<int, 1> type;
00315    };
00316 
00317    // accepts classes, gives class
00318    template<class n, class k> struct static_power {
00319       typedef typename power_impl<n, k>::type type;
00320    };
00321 
00322    // accepts ints, gives int
00323    template<int n, int k> struct int_power {
00324       typedef typename power_impl<mpl::integral_c<int, n>, mpl::integral_c<int, k> >::type type;
00325       BOOST_STATIC_CONSTANT(int, value = type::value);
00326    };
00327 
00328    // accepts pair of classes, gives class
00329    template<class pair> struct pair_power {
00330       typedef typename power_impl<typename pair::first, typename pair::second>::type type;
00331    };
00332 
00333    BOOST_STATIC_ASSERT(( int_power<1,1>::value == 1 ));
00334    BOOST_STATIC_ASSERT(( int_power<2,1>::value == 2 ));
00335    BOOST_STATIC_ASSERT(( int_power<2,2>::value == 4 ));
00336    BOOST_STATIC_ASSERT(( int_power<2,3>::value == 8 ));
00337 
00338 
00339    template<class V> struct static_abs;
00340    template<int k> struct static_abs<mpl::integral_c<int, k> > {
00341       typedef typename mpl::if_c< (k>0), mpl::integral_c<int, k>, mpl::integral_c<int, -k> >::type type;
00342    };
00343 
00344    
00345    template<class n, class k> struct rational_power {
00346       typedef mpl::integral_c<int, 1> one;
00347       typedef typename static_abs<k>::type exp;
00348       typedef typename power_impl<n, exp>::type part;
00349       typedef typename mpl::if_c< (k::value>=0), static_rational<part::value, one::value>, static_rational<one::value, part::value> >::type type;
00350    };
00351 
00352    // product of primes+exp
00353    typedef mpl::pair<mpl::integral_c<int, 2>, mpl::integral_c<int, 3> > pair_2_3;
00354    BOOST_STATIC_ASSERT(( pair_power<pair_2_3>::type::value == 8 ));
00355 
00356    // transform cannot produce vectors from maps...
00357    typedef mpl::vector<mpl::pair<mpl::integral_c<int, 2>, mpl::integral_c<int, 1> >, 
00358                  mpl::pair<mpl::integral_c<int, 3>, mpl::integral_c<int, 1> > > vec_map_2_3;
00359    // a vector of powers
00360    typedef mpl::transform< vec_map_2_3, pair_power<_> >::type vec_map_2_3_powers;
00361    typedef mpl::fold<vec_map_2_3_powers, mpl::integral_c<int, 1>, mpl::multiplies<_,_> >::type vec_map_2_3_total;
00362    BOOST_STATIC_ASSERT(( vec_map_2_3_total::value == 6 ));
00363 
00364    // However, what about starting with a mpl::map? 
00365    typedef mpl::fold<map_2_3, mpl::integral_c<int, 1>, mpl::multiplies<_1, pair_power<_2> > >::type vec_from_map_2_3_product;
00366    BOOST_STATIC_ASSERT(( vec_from_map_2_3_product::value == 6 ));
00367 
00368    // and now put this into some metafunction:
00369    template<class Map> struct static_map_multiply {
00370       typedef typename mpl::fold<Map, mpl::integral_c<int, 1>, mpl::multiplies<_1, pair_power<_2> > >::type type;
00371    };
00372    BOOST_STATIC_ASSERT(( static_map_multiply<map_2>::type::value == 2 ));
00373    BOOST_STATIC_ASSERT(( static_map_multiply<map_2_2>::type::value == 4 ));
00374    BOOST_STATIC_ASSERT(( static_map_multiply<map_3>::type::value == 3 ));
00375    BOOST_STATIC_ASSERT(( static_map_multiply<map_3_3>::type::value == 9 ));
00376 
00377    BOOST_STATIC_ASSERT(( static_map_multiply<map_>::type::value == 1 ));
00378    BOOST_STATIC_ASSERT(( static_map_multiply<map_51>::type::value == 5 ));
00379    BOOST_STATIC_ASSERT(( static_map_multiply<map_52>::type::value == 25 ));
00380 
00381 
00382    // forward declaration
00383    template<class PrimeDecomp, class p> struct reduce_prime;
00384 
00385    template<class PrimeDecomp, class p, bool divisible> struct reduce_prime_dispatch;
00386    
00387    template<class PrimeDecomp, class p> struct reduce_prime_dispatch<PrimeDecomp, p, true> {
00388       typedef typename reduce_prime_impl<PrimeDecomp, p>::type reduced;
00389       typedef typename reduce_prime<reduced, p>::type type;
00390    };
00391 
00392    template<class PrimeDecomp, class p> struct reduce_prime_dispatch<PrimeDecomp, p, false> {
00393       typedef PrimeDecomp type;
00394    };
00395 
00396 
00397 
00398    // metafunction that takes a container, adds p to the map and divedes the remainder by p as often as possible
00399    template<class PrimeDecomp, class p> struct reduce_prime {
00400       typedef typename PrimeDecomp::remainder Remainder;
00401       typedef typename reduce_prime_dispatch<PrimeDecomp, p, is_divisible<Remainder::value, p::value>::type::value>::type type;
00402    };
00403 
00404 
00405    template <class n> struct initial_decomp {
00406       BOOST_STATIC_ASSERT(( n::value >= 1 ));
00407       typedef typename partial_prime_represenation<mpl::map<>, n> type;
00408    };
00409 
00410    typedef initial_decomp<mpl::integral_c<int, 25> >::type init_decomp_25;
00411    BOOST_STATIC_ASSERT(( init_decomp_25::remainder::type::value == 25 )); 
00412    BOOST_STATIC_ASSERT(( mpl::size<init_decomp_25::map>::type::value == 0 )); 
00413    BOOST_STATIC_ASSERT(( static_map_multiply<init_decomp_25::map>::type::value == 1 )); 
00414 
00415 
00416    typedef reduce_prime<init_decomp_25, mpl::integral_c<int, 5> >::type reduced_25;
00417 
00418    BOOST_STATIC_ASSERT(( reduced_25::remainder::type::value == 1 )); 
00419    BOOST_STATIC_ASSERT(( mpl::size<reduced_25::map>::type::value == 1 )); 
00420    BOOST_STATIC_ASSERT(( static_map_multiply<reduced_25::map>::type::value == 25 )); 
00421 
00422 
00423    typedef initial_decomp<mpl::integral_c<int, 50> >::type init_decomp_50;
00424    BOOST_STATIC_ASSERT(( init_decomp_50::remainder::type::value == 50 )); 
00425    BOOST_STATIC_ASSERT(( mpl::size<init_decomp_50::map>::type::value == 0 )); 
00426    BOOST_STATIC_ASSERT(( static_map_multiply<init_decomp_50::map>::type::value == 1 )); 
00427 
00428    typedef reduce_prime<init_decomp_50, mpl::integral_c<int, 5> >::type reduced_50_5;
00429    BOOST_STATIC_ASSERT(( reduced_50_5::remainder::type::value == 2 )); 
00430    BOOST_STATIC_ASSERT(( mpl::size<reduced_50_5::map>::type::value == 1 )); 
00431    BOOST_STATIC_ASSERT(( static_map_multiply<reduced_50_5::map>::type::value == 25 )); 
00432 
00433    typedef reduce_prime<reduced_50_5, mpl::integral_c<int, 2> >::type reduced_50_5_2;
00434    BOOST_STATIC_ASSERT(( reduced_50_5_2::remainder::type::value == 1 )); 
00435    BOOST_STATIC_ASSERT(( mpl::size<reduced_50_5_2::map>::type::value == 2 )); 
00436    BOOST_STATIC_ASSERT(( static_map_multiply<reduced_50_5_2::map>::type::value == 50 )); 
00437 
00438 
00439 
00440    // n is integral class type, returns a decomposition
00441    template<typename n, typename upto> struct prime_decomposition {
00442       typedef boost::mpl::integral_c<int, upto::value-1> upto_m1;
00443       BOOST_STATIC_ASSERT(( upto_m1::value >= 1));
00444       
00445 
00446       typedef typename prime_decomposition<n, upto_m1>::type part_decomposition;
00447       typedef typename reduce_prime<part_decomposition, upto>::type type;
00448    };
00449 
00450 
00451    // n is integral class type, returns a decomposition
00452    template<typename n> struct prime_decomposition<n, mpl::integral_c<int, 1> > {
00453       typedef typename initial_decomp<n>::type type;
00454    };
00455 
00456    // n is integral class type, returns a map of primes & exponents
00457    template<typename n> struct primes {
00458       typedef typename prime_decomposition<n, n>::type decomposition;
00459       typedef typename decomposition::map type;
00460    };
00461 
00462 
00463    // 10 = 2^1 * 5^1
00464    typedef primes<mpl::integral_c<int, 10> >::type primes_10;
00465    BOOST_STATIC_ASSERT(( mpl::size<primes_10>::type::value == 2 ));
00466    BOOST_STATIC_ASSERT(( static_map_multiply<primes_10>::type::value == 10 )); 
00467 
00468    // 100 = 2^2 * 5^2
00469    typedef primes<mpl::integral_c<int, 100> >::type primes_100;
00470    BOOST_STATIC_ASSERT(( mpl::size<primes_100>::type::value == 2 ));
00471    BOOST_STATIC_ASSERT(( static_map_multiply<primes_100>::type::value == 100 )); 
00472 
00473 
00474 #if 1
00475    // internal compiler error somewhere above 430 , obviously memory overflow.
00476    // 1000 = 2^3 * 5^3
00477    typedef primes<mpl::integral_c<int, 430> >::type primes_1000;
00478    //BOOST_STATIC_ASSERT(( mpl::size<primes_1000>::type::value == 2 ));
00479    BOOST_STATIC_ASSERT(( static_map_multiply<primes_1000>::type::value == 430 )); 
00480 #endif
00481 
00482 
00483 #if 0
00484 
00485    typedef primes<1>::type primes_1;
00486    typedef primes<2>::type primes_2;
00487 //   typedef primes<3>::type primes_3;
00488 //   typedef primes<4>::type primes_4;
00489 
00490    // primes_1 = { };
00491    BOOST_STATIC_ASSERT(( boost::mpl::size<primes_1>::type::value == 0 ));
00492 
00493    // primes_2 = { 2^1 };
00494    //BOOST_STATIC_ASSERT(( boost::mpl::size<primes_2>::type::value == 1 ));
00495 
00496 
00497 
00498    //BOOST_STATIC_ASSERT(( prime_decomposition<boost::mpl::integral_c<int, 1>, boost::mpl::integral_c<int, 1> >::type::remainder ));
00499    //BOOST_STATIC_ASSERT(( prime_decomposition<boost::mpl::integral_c<int, 1>, boost::mpl::integral_c<int, 1> >::type::remainder ));
00500 #endif
00501 }
00502 
00503 namespace newprimes {
00504    // primes from AT&T:
00505    //2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271
00506 };
00507 namespace blub {
00508 
00509 
00510    // traits class, may be specialized for other basedimensions
00511 
00512    template <class UnitSystem, class BaseDimension>
00513    struct position {
00514       typedef typename boost::mpl::find<typename UnitSystem::base_dimensions, BaseDimension>::type iterator;
00515       BOOST_STATIC_CONSTANT(int, value = iterator::pos::value);
00516    };
00517 
00518    template<class UnitSystem, class dimension, class unit>
00519    struct extended_unit_system {
00520       struct extended {
00521       typedef extended unitsystem;
00522       typedef typename boost::mpl::push_back<typename UnitSystem::base_dimensions, dimension>::type base_dimensions;
00523       typedef typename boost::mpl::push_back<typename UnitSystem::base_units, unit>::type base_units;
00524 
00525       BOOST_STATIC_ASSERT(boost::mpl::size<typename UnitSystem::base_dimensions>::value == boost::mpl::size<typename UnitSystem::base_units>::value);
00526       BOOST_STATIC_ASSERT(boost::mpl::size<base_dimensions>::value == boost::mpl::size<typename UnitSystem::base_dimensions>::value+1);
00527       BOOST_STATIC_ASSERT(boost::mpl::size<base_units>::value == boost::mpl::size<typename UnitSystem::base_units>::value+1);
00528       BOOST_STATIC_ASSERT(boost::mpl::size<base_dimensions>::value == boost::mpl::size<base_units>::value);
00529 
00530       BOOST_STATIC_CONSTANT(int, number_baseunits = boost::mpl::size<base_dimensions>::value);
00531       };
00532       typedef extended type;
00533    };
00534 
00535 
00536    // general template declaration, only some specialisations are defined
00537    template<class unit1, class unit2> struct static_conversion_factor;
00538 
00539    // as a specialisation, the conversion to the very same unit has always conversion factor 1.
00540    template<class unit1> struct static_conversion_factor<unit1, unit1> { 
00541       typedef typename static_rational<1,1>::type type; 
00542    };
00543 
00544 
00545 
00546    template<class source_UnitSystem, class target_UnitSystem, int source_position>
00547    struct convert_baseunit_to_other_unit_system {
00548       
00549       // what dimension does this position represent?
00550       typedef typename boost::mpl::at<typename source_UnitSystem::base_dimensions, boost::mpl::int_<source_position> >::type BaseDimension;
00551 
00552       // what position is this very same BaseDimension in the target unit system?
00553       typedef typename boost::mpl::find<typename target_UnitSystem::base_dimensions, BaseDimension>::type target_iterator;
00554       BOOST_STATIC_CONSTANT(int, target_position = target_iterator::pos::value);
00555 
00556       // what is the unit used in source unit system
00557       typedef typename boost::mpl::at<typename source_UnitSystem::base_units, boost::mpl::int_<source_position> >::type source_unit;
00558 
00559       // what is the unit used in target unit system
00560       typedef typename boost::mpl::at<typename target_UnitSystem::base_units, boost::mpl::int_<target_position> >::type target_unit;
00561        
00562       typedef typename static_conversion_factor<source_unit, target_unit>::type conversion_factor;
00563    };
00564 
00565 
00566 
00567 
00568    // some dimension tags
00569    struct length              {};
00570    struct mass                {};
00571    struct time                {};
00572    struct electric_current    {};
00573    struct temperature         {};
00574    struct amount_of_substance {};
00575    struct luminous_intensity  {};
00576 
00577 
00578    // some unit tags
00579    struct meter {};
00580    struct kilogram {};
00581    struct second {};
00582    struct ampere {};
00583    struct kelvin {};
00584    struct mol {};
00585    struct candela {};
00586 
00587    struct centimeter {};
00588    struct gram {};
00589 
00590 
00591    template<> struct static_conversion_factor<meter, centimeter> { typedef static_rational<100,1>::type type; };
00592    template<> struct static_conversion_factor<centimeter, meter> { typedef static_rational<1,100>::type type; };
00593 
00594    template<> struct static_conversion_factor<kilogram, gram> { typedef static_rational<1000,1>::type type; };
00595    template<> struct static_conversion_factor<gram, kilogram> { typedef static_rational<1000,1>::type type; };
00596 
00597 
00598 
00599    // full SI set, this should be the default unit system
00600    struct SI {
00601       typedef SI unitsystem;
00602       typedef boost::mpl::vector<length, mass, time, electric_current, temperature, amount_of_substance, luminous_intensity> base_dimensions;
00603       typedef boost::mpl::vector<meter, kilogram, second, ampere, kelvin, mol, candela> base_units;
00604 
00605       BOOST_STATIC_ASSERT(boost::mpl::size<base_dimensions>::value == boost::mpl::size<base_units>::value);
00606       BOOST_STATIC_CONSTANT(int, number_baseunits = boost::mpl::size<base_dimensions>::value);
00607    };
00608 
00609    /* ******* some other unit systems ********* */
00610 
00611    // meter - kilogram - second
00612    struct MKS {
00613       typedef MKS unitsystem;
00614       typedef boost::mpl::vector<length, mass, time> base_dimensions;
00615       typedef boost::mpl::vector<meter, kilogram, second> base_units;
00616 
00617       BOOST_STATIC_ASSERT(boost::mpl::size<base_dimensions>::value == boost::mpl::size<base_units>::value);
00618       BOOST_STATIC_CONSTANT(int, number_baseunits = boost::mpl::size<base_dimensions>::value);
00619    };
00620 
00621 
00622 
00623    // centimeter - kilogram - second
00624    // same base dimensions as MKS, but other numerical (internal) representation, all quantities are convertible
00625    struct CGS {
00626       typedef CGS unitsystem;
00627       typedef boost::mpl::vector<length, mass, time> base_dimensions;
00628       typedef boost::mpl::vector<centimeter, gram, second> base_units;
00629 
00630       BOOST_STATIC_ASSERT(boost::mpl::size<base_dimensions>::value == boost::mpl::size<base_units>::value);
00631       BOOST_STATIC_CONSTANT(int, number_baseunits = boost::mpl::size<base_dimensions>::value);
00632    };
00633 
00634 
00635 
00636    // this should go to unit tests...  
00637    BOOST_STATIC_ASSERT((convert_baseunit_to_other_unit_system<MKS, CGS, 0>::target_position == 0));
00638    BOOST_STATIC_ASSERT((convert_baseunit_to_other_unit_system<MKS, CGS, 1>::target_position == 1));
00639    BOOST_STATIC_ASSERT((convert_baseunit_to_other_unit_system<MKS, CGS, 2>::target_position == 2));
00640 
00641    BOOST_STATIC_ASSERT(( boost::is_same<convert_baseunit_to_other_unit_system<MKS, CGS, 0>::conversion_factor, static_rational<100,1> >::type::value ));
00642    BOOST_STATIC_ASSERT(( boost::is_same<convert_baseunit_to_other_unit_system<MKS, CGS, 1>::conversion_factor, static_rational<1000,1> >::type::value ));
00643    BOOST_STATIC_ASSERT(( boost::is_same<convert_baseunit_to_other_unit_system<MKS, CGS, 2>::conversion_factor, static_rational<1,1> >::type::value ));
00644 
00645    BOOST_STATIC_ASSERT(( ! boost::is_same<convert_baseunit_to_other_unit_system<MKS, CGS, 0>::conversion_factor, static_rational<1,1> >::type::value ));
00646 
00647 
00648    // some further base dimensions
00649    struct customer_satisfaction {}; // unit = subjective assessment: 1..10
00650    struct subjective {};
00651 
00652    struct european_currency {};     // unit = EUR, euro_cent;
00653    struct us_currency {};           // unit = USD, us_cent;
00654 
00655 
00656    // SI with customer satisfaction as additional base dimension, some quantities are convertible
00657    typedef extended_unit_system<SI, customer_satisfaction, subjective>::type extended_SI;
00658 
00659 
00660    static const int meter_pos1 = position<SI, length>::value;
00661    static const int meter_pos2 = position<extended_SI, length>::value;
00662 
00663 
00664    BOOST_STATIC_ASSERT( meter_pos1 == meter_pos2 );
00665 
00666 
00667    /* ******************************************************************************** */
00668 
00669 };

Generated on Mon Apr 2 22:25:06 2007 for physical_svn by  doxygen 1.5.1-p1
hosted on SourceForge.net Logo