Boost logo

Boost :

Subject: Re: [boost] [ratio] metafunction ratio_subtract
From: vicente.botet (vicente.botet_at_[hidden])
Date: 2009-12-07 06:42:10

----- Original Message -----
From: "Howard Hinnant" <howard.hinnant_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Monday, December 07, 2009 12:18 AM
Subject: Re: [boost] [ratio] metafunction ratio_subtract

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.


It is from the example related to Type-safe "physics" code interoperating with std::chrono::duration types and taking advantage of the std::ratio infrastructure and design philosophy. sandbox/chrono/libs/chrono/test/ratio_test.cpp

The code I'm testing is derived from the one in the sandbox/chrono. I have modified something the implementation as the code didn't compiled on my environment (cygwin/gcc 3.4), most of them related to the fact that even on POSIX, the CLOCK_MONOTONIC is optionally defined. Please, could you check the unmodified code on the sandbox, if needed I can send you a patch this evening (french time).

Thanks a lot,

Boost list run by bdawes at, gregod at, cpdaniel at, john at