
On Dec 6, 2009, at 3:43 PM, vicente.botet wrote:
Hi Beman, Hi Howard,
With current implementation of the metafunction ratio_subtract I get the type from the test ratio_test.cpp
User1::Distance d( User1::mile(110) ); User1::Time t( boost::chrono::hours(2) );
typeof (d/t) is User1::quantity<boost::ratio<1,-1>, boost::ratio<1,1> >
So the following assignation do not works
User1::Speed s = d / t;
as User1::Speed is defined as
typedef quantity<boost::ratio<1>, boost::ratio<0> > Time; // second typedef quantity<boost::ratio<0>, boost::ratio<1> > Distance; // meter typedef quantity<boost::ratio<-1>, boost::ratio<1> > Speed; // meter/second
The code is a little bit triky, and I have not taken the time to understand why the resulting type is User1::quantity<boost::ratio<1,-1>, boost::ratio<1,1> > and not <boost::ratio<-1,1>, boost::ratio<1,1> > User1::quantity
There must be a bug in the ratio formation of num and den. It should not be possible to form a ratio such that ratio::den is not positive. [ratio.ratio]/1 states that D shall not be 0. [ratio.ratio]/2 specifies that gcd operates on the absolute values of N and D (and so gcd must be positive). den is specified to be abs(D)/gcd, which must be positive.
I have replaced the type by
typedef ratio<R1::num * R2::den - R2::num * R1::den,R1::den * R2::den> aux_type; typedef ratio<aux_type::num ,aux_type::den > type; // get normalized type
to follow the recommendation "The nested typedef type shall be a synonym for ratio<T1, T2> where T1 has the value R1::num *R2::den - R2::num * R1::den and T2 has the value R1::den * R2::den."
and every thing is OK (See below the replaced code)
I'm doing something wrong?
No, you're doing something right by investigating this mystery. :-) I've lost the link to the code you're working with. Could you post it? The original implementation of ratio_subtract (thank you for including it below) is designed to be equivalent to your substitution, but less susceptible to overflow, by performing exact division as soon as possible (get integers as low as possible, as soon as possible). I'm not sure where your example of computing speed from distance and time involves subtraction. But I'm interested to help you get to the bottom of it. -Howard
Best, _____________________ Vicente Juan Botet Escribá
template <class R1, class R2> struct ratio_subtract { private: #if 1 typedef ratio<R1::num * R2::den - R2::num * R1::den,R1::den * R2::den> aux_type; #else static const boost::intmax_t gcd_n1_n2 = detail::static_gcd<R1::num, R2::num>::value; static const boost::intmax_t gcd_d1_d2 = detail::static_gcd<R1::den, R2::den>::value;#endif public: //The nested typedef type shall be a synonym for ratio<T1, T2> where T1 has the value // R1::num *R2::den - R2::num * R1::den and T2 has the value R1::den * R2::den. #if 1 typedef ratio<aux_type::num ,aux_type::den > type; #else typedef typename ratio_multiply < ratio<gcd_n1_n2, R1::den / gcd_d1_d2>, ratio < detail::ll_sub < detail::ll_mul<R1::num / gcd_n1_n2, R2::den / gcd_d1_d2>::value, detail::ll_mul<R2::num / gcd_n1_n2, R1::den / gcd_d1_d2>::value
::value, R2::den
::type type; #endif };
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost