[chrono] type_traits/common_type and integer/ratio

Hi, I'm looking on how to continue with the Boost.Chrono library and I would like to know if * Boost.TypeTraits could take care of the common_type class template. * Boost.Integer could take care of the ratio class template. In this way Boost.Chrono will contain only the time related facilities, duration, time_point and Clocks. In order to minimize the task and been able to purpose as soon as possible the library for review I would like to concentrate on the implementation of the standard proposal and let for a future release the facilities Beman added as * Class template timer, with typedefs: * `system_timer` * `monotonic_timer` * `high_resolution_timer` * Process clocks and timers: * `process_clock`, capturing real, user-CPU, and system-CPU times. * `process_timer`, capturing elapsed real, user-CPU, and system-CPU times. * `run_timer`, convenient reporting of process_timer results. What do you think about this approach? Best, Vicente -- View this message in context: http://old.nabble.com/-chrono--type_traits-common_type-and-integer-ratio-tp2... Sent from the Boost - Dev mailing list archive at Nabble.com.

I'm looking on how to continue with the Boost.Chrono library and I would like to know if
* Boost.TypeTraits could take care of the common_type class template. * Boost.Integer could take care of the ratio class template.
Can you summarize what these templates are? Are they generally useful? Thanks, John.

John Maddock wrote:
I'm looking on how to continue with the Boost.Chrono library and I would like to know if
* Boost.TypeTraits could take care of the common_type class template. * Boost.Integer could take care of the ratio class template.
Can you summarize what these templates are? Are they generally useful?
Thanks, John. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Hi, You can see [http://www.open-std.org/jtc1/sc22/wg21 [*N2661 - A Foundation to Sleep On]] which is very informative and provides motivation for key design decisions for `common_type`, ratio and chrono. I really think they are very useful and the standard group also, as both are in N3000. Here there are some extracts "In a nutshell, `common_type` is a trait that takes 1 or more types, and returns a type which all of the types will convert to. The default definition demands this conversion be implicit. However the trait can be specialized for user-defined types which want to limit their inter-type conversions to explicit, and yet still want to interoperate with the `common_type` facility. Example: template <class T, class U> typename common_type<complex<T>, complex<U> >::type operator+(complex<T>, complex<U>); In the above example, "mixed-mode" complex arithmetic is allowed. The return type is described by `common_type`. For example the resulting type of adding a `complex<int>` and `complex<double>` might be a `complex<double>`." and "`ratio` is a general purpose utility inspired by Walter Brown allowing one to easily and safely compute rational values at compile time. The `ratio` class catches all errors (such as divide by zero and overflow) at compile time. It is used in the `duration` and `time_point` classes to efficiently create units of time. It can also be used in other "quantity" libraries (both std-defined and user-defined), or anywhere there is a rational constant which is known at compile time. The use of this utility can greatly reduce the chances of run time overflow because the `ratio` (and any ratios resulting from `ratio` arithmetic) are always reduced to lowest terms. `ratio` is a template taking two intmax_ts, with the second defaulted to 1. It only has two public members, both of which are static const intmax_t. One is the numerator of the `ratio` and the other is the denominator. The `ratio` is always normalized such that it is expressed in lowest terms, and the denominator is always positive. When the numerator is 0, the denominator is always 1. [*Example:] typedef ratio<5, 3> five_thirds; // five_thirds::num == 5, five_thirds::den == 3 typedef ratio<25, 15> also_five_thirds; // also_five_thirds::num == 5, also_five_thirds::den == 3 typedef ratio_divide<five_thirds, also_five_thirds>::type one; // one::num == 1, one::den == 1 " You can find prototypes implementation on the sandbox /chrono/boost/type_trais/common_type.hpp and /chrono/boost/ratio.hpp. Thanks for your interest, Vicente -- View this message in context: http://old.nabble.com/-chrono--type_traits-common_type-and-integer-ratio-tp2... Sent from the Boost - Dev mailing list archive at Nabble.com.

You can see [http://www.open-std.org/jtc1/sc22/wg21 [*N2661 - A Foundation to Sleep On]] which is very informative and provides motivation for key design decisions for `common_type`, ratio and chrono.
I really think they are very useful and the standard group also, as both are in N3000.
Here there are some extracts
"In a nutshell, `common_type` is a trait that takes 1 or more types, and returns a type which all of the types will convert to. The default definition demands this conversion be implicit. However the trait can be specialized for user-defined types which want to limit their inter-type conversions to explicit, and yet still want to interoperate with the `common_type` facility.
Example:
template <class T, class U> typename common_type<complex<T>, complex<U> >::type operator+(complex<T>, complex<U>);
In the above example, "mixed-mode" complex arithmetic is allowed. The return type is described by `common_type`. For example the resulting type of adding a `complex<int>` and `complex<double>` might be a `complex<double>`."
OK, looking into that a bit more, I think that would be a reasonably uncontrovercial addition to type_traits - but do you have a test suite and docs?
"`ratio` is a general purpose utility inspired by Walter Brown allowing one to easily and safely compute rational values at compile time. The `ratio` class catches all errors (such as divide by zero and overflow) at compile time. It is used in the `duration` and `time_point` classes to efficiently create units of time. It can also be used in other "quantity" libraries (both std-defined and user-defined), or anywhere there is a rational constant which is known at compile time. The use of this utility can greatly reduce the chances of run time overflow because the `ratio` (and any ratios resulting from `ratio` arithmetic) are always reduced to lowest terms.
This one's quite a bit of an addition - almost a little mini-library in it's own right. I think you're correct that it should be locatable as a utility in it's own right, and yes under boost/integer I guess. My suggestion is that you ask for a review for ratio separately from chrono. BTW the utilities here http://www.boost.org/doc/libs/1_41_0/libs/math/doc/gcd/html/index.html might be useful for the implementation of this one, rather than re-inventing your own. HTH, John.

Hi Johm, John Maddock wrote:
You can see [http://www.open-std.org/jtc1/sc22/wg21 [*N2661 - A Foundation to Sleep On]] which is very informative and provides motivation for key design decisions for `common_type`, ratio and chrono.
I really think they are very useful and the standard group also, as both are in N3000.
OK, looking into that a bit more, I think that would be a reasonably uncontrovercial addition to type_traits - but do you have a test suite and docs?
I'm reworking the Beman documentation using quickbook. I'll add it to the vault as soon as possible. Concerning tests, currently there is much more examples using chrono and ratio than common_type. You can take a look at the Beman version on the Sandbox. I hope you could adopt this utility.
This one's quite a bit of an addition - almost a little mini-library in it's own right.
I think you're correct that it should be locatable as a utility in it's own right, and yes under boost/integer I guess. My suggestion is that you ask for a review for ratio separately from chrono. BTW the utilities here http://www.boost.org/doc/libs/1_41_0/libs/math/doc/gcd/html/index.html might be useful for the implementation of this one, rather than re-inventing your own.
Ok, I'm going to separate the comom_type, the ratio and the chono documentation and test to make eaisier separated reviews. Thanks for the pointer. I'll see how math/gdc can be used to refactor the use of gdc in the class ratio. Best, Vicente -- View this message in context: http://old.nabble.com/-chrono--type_traits-common_type-and-integer-ratio-tp2... Sent from the Boost - Dev mailing list archive at Nabble.com.

----- Original Message ----- From: "Vicente Botet Escriba" <vicente.botet@wanadoo.fr> To: <boost@lists.boost.org> Sent: Thursday, December 03, 2009 4:17 AM Subject: Re: [boost] [chrono] type_traits/common_type and integer/ratio
Hi Johm,
John Maddock wrote:
This one's quite a bit of an addition - almost a little mini-library in it's own right.
I think you're correct that it should be locatable as a utility in it's own right, and yes under boost/integer I guess. My suggestion is that you ask for a review for ratio separately from chrono. BTW the utilities here http://www.boost.org/doc/libs/1_41_0/libs/math/doc/gcd/html/index.html might be useful for the implementation of this one, rather than re-inventing your own.
Thanks for the pointer. I'll see how math/gdc can be used to refactor the use of gdc in the class ratio.
Hi, I hav refactored boost/ratio;hpp to use math::static_gcd instead of the internal detail::static_gcd, and this is working now. In the detail implementation there was also the following metafunctions template <boost::intmax_t X> struct static_abs { static const boost::intmax_t value = X < 0 ? -X : X; }; template <boost::intmax_t X> struct static_sign { static const boost::intmax_t value = X == 0 ? 0 : (X < 0 ? -1 : 1); }; Is there something similar in Boost.Math or elsewhere? Thanks, Vicente

I hav refactored boost/ratio;hpp to use math::static_gcd instead of the internal detail::static_gcd, and this is working now. In the detail implementation there was also the following metafunctions
template <boost::intmax_t X> struct static_abs { static const boost::intmax_t value = X < 0 ? -X : X; };
template <boost::intmax_t X> struct static_sign { static const boost::intmax_t value = X == 0 ? 0 : (X < 0 ? -1 : 1); };
Is there something similar in Boost.Math or elsewhere?
Nope, but they might make reasonable additions... or maybe they would be better in Boost.Integer I don't know? John.

John Maddock wrote:
Nope, but they might make reasonable additions... or maybe they would be better in Boost.Integer I don't know? couldbe nice if they used mpl::integral_c so it can be used easily as MPL meta-functions
-- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

joel falcou wrote:
could be nice if they used mpl::integral_c so it can be used easily as MPL meta-functions forgot the code obv. :
namespace mpl { template<class X> struct abs : integral_c< typename X::value_type, (X < 0 ? -X : X)> {}; } etc -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

----- Original Message ----- From: "joel falcou" <joel.falcou@lri.fr> To: <boost@lists.boost.org> Sent: Sunday, December 06, 2009 10:57 AM Subject: Re: [boost] [chrono] type_traits/common_type and integer/ratio
joel falcou wrote:
could be nice if they used mpl::integral_c so it can be used easily as MPL meta-functions forgot the code obv. :
namespace mpl { template<class X> struct abs : integral_c< typename X::value_type, (X < 0 ? -X : X)> {}; }
etc
--
Hi Joel, even if template <boost::intmax_t X> struct static_abs { static const boost::intmax_t value = X < 0 ? -X : X; }; don't use mpl::integral_c, it is a valid mpl metafunction. I don't think it is worth adding a dependency to Boost.MPL. Best, Vicente

vicente.botet wrote:
template <boost::intmax_t X> struct static_abs { static const boost::intmax_t value = X < 0 ? -X : X; };
don't use mpl::integral_c, it is a valid mpl metafunction. I don't think it is worth adding a dependency to Boost.MPL You're right, it just need the value_type typedef.
-- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

On Mon, Nov 30, 2009 at 7:25 AM, Vicente Botet Escriba <vicente.botet@wanadoo.fr> wrote:
"In a nutshell, `common_type` is a trait that takes 1 or more types, and returns a type which all of the types will convert to. The default definition demands this conversion be implicit. However the trait can be specialized for user-defined types which want to limit their inter-type conversions to explicit, and yet still want to interoperate with the `common_type` facility.
Example:
template <class T, class U> typename common_type<complex<T>, complex<U> >::type operator+(complex<T>, complex<U>);
In the above example, "mixed-mode" complex arithmetic is allowed. The return type is described by `common_type`. For example the resulting type of adding a `complex<int>` and `complex<double>` might be a `complex<double>`."
I've needed this feature many times. Can you explain the pros/cons of common_type against Boost.Typeof? Thanks, --Michael Fawcett

Michael Fawcett wrote:
On Mon, Nov 30, 2009 at 7:25 AM, Vicente Botet Escriba <vicente.botet@wanadoo.fr> wrote:
"In a nutshell, `common_type` is a trait that takes 1 or more types, and returns a type which all of the types will convert to. The default definition demands this conversion be implicit. However the trait can be specialized for user-defined types which want to limit their inter-type conversions to explicit, and yet still want to interoperate with the `common_type` facility.
Example:
template <class T, class U> typename common_type<complex<T>, complex<U> >::type operator+(complex<T>, complex<U>);
In the above example, "mixed-mode" complex arithmetic is allowed. The return type is described by `common_type`. For example the resulting type of adding a `complex<int>` and `complex<double>` might be a `complex<double>`."
I've needed this feature many times. Can you explain the pros/cons of common_type against Boost.Typeof?
Thanks,
--Michael Fawcett _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Hi, Happy to hear you could find a use for this class. Even if in a first look they sound to be close, common_type and typeof have different purposes. You use typeof to get the type of an expression, while you use common_type to set explicitly the type returned of a template function. Both are complementary. For example with the preceding declaration and the needed Typeof registrations, you can do complex<int> ic; complex<double> id; BOOST_AUTO(icd, ic+id); Surely others would give a better explanation, Regards, Vicente -- View this message in context: http://old.nabble.com/-chrono--type_traits-common_type-and-integer-ratio-tp2... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Dec 1, 2009, at 1:15 PM, Michael Fawcett wrote:
On Mon, Nov 30, 2009 at 7:25 AM, Vicente Botet Escriba <vicente.botet@wanadoo.fr> wrote:
"In a nutshell, `common_type` is a trait that takes 1 or more types, and returns a type which all of the types will convert to. The default definition demands this conversion be implicit. However the trait can be specialized for user-defined types which want to limit their inter-type conversions to explicit, and yet still want to interoperate with the `common_type` facility.
Example:
template <class T, class U> typename common_type<complex<T>, complex<U> >::type operator+(complex<T>, complex<U>);
In the above example, "mixed-mode" complex arithmetic is allowed. The return type is described by `common_type`. For example the resulting type of adding a `complex<int>` and `complex<double>` might be a `complex<double>`."
I've needed this feature many times. Can you explain the pros/cons of common_type against Boost.Typeof?
common_type is closer in nature to promote_args<class ...T> in boost/math/tools/promotion.hpp than it is to Boost.Typeof, though it is not exactly the same as promote_args either. common_type<T1, T2>::type simply represents the result of some operation on T1 and T2, and defaults to the type obtained by putting T1 and T2 into a conditional statement. It is meant to be customizable (via specialization) if this default is not appropriate. Here is a link to the D version of the same tool: http://www.digitalmars.com/d/2.0/phobos/std_traits.html#CommonType -Howard

On Wed, Dec 2, 2009 at 10:33 AM, Howard Hinnant <howard.hinnant@gmail.com> wrote:
On Dec 1, 2009, at 1:15 PM, Michael Fawcett wrote:
I've needed this feature many times. Can you explain the pros/cons of common_type against Boost.Typeof?
common_type is closer in nature to promote_args<class ...T> in boost/math/tools/promotion.hpp than it is to Boost.Typeof, though it is not exactly the same as promote_args either. common_type<T1, T2>::type simply represents the result of some operation on T1 and T2, and defaults to the type obtained by putting T1 and T2 into a conditional statement.
It is meant to be customizable (via specialization) if this default is not appropriate. Here is a link to the D version of the same tool:
http://www.digitalmars.com/d/2.0/phobos/std_traits.html#CommonType
I'm replying here, but thank you, Vicente, for your explanation as well. I'm trying to figure out what the best tool for the job is and it appears I have 3 choices, Typeof, common_type, and promote_args. Suppose I have a mixed type vector2 class with a magnitude_squared function defined as: template <typename X, typename Y> BOOST_TYPEOF_TPL(X() * X() + Y() * Y()) magnitude_squared(const vector2<X, Y> &v) { return v.x * v.x + v.y * v.y; } Typeof works, but I'm wondering if it's overkill and that perhaps common_type is much more lightweight and appropriate. promote_args doesn't do quite what I need here, but thank you for pointing that facility out to me. Regardless, the original post was about how to proceed, and I definitely see reason to break those components out of Boost.Chrono. I didn't mean to hijack the thread ;) --Michael Fawcett

Michael Fawcett wrote:
template <typename X, typename Y> BOOST_TYPEOF_TPL(X() * X() + Y() * Y()) magnitude_squared(const vector2<X, Y> &v) { return v.x * v.x + v.y * v.y; }
Typeof works, but I'm wondering if it's overkill and that perhaps common_type is much more lightweight and appropriate. promote_args doesn't do quite what I need here, but thank you for pointing that facility out to me.
Regardless, the original post was about how to proceed, and I definitely see reason to break those components out of Boost.Chrono. I didn't mean to hijack the thread ;)
Why not having a proper polymorphic function object that performs the computation and hide the potential uglyness of the type computation ? struct magnitude_squared_ { template<class Sig> struct result; template<class This,class X, class Y> struct result<This(vector2<X,Y>)> { typedef BOOST_TYPEOF_TPL(X() * X() + Y() * Y()) type; }; template<class X,class Y> typename result<magnitude_squared_(vector2<X,Y>)>::type operator()( vector2<X,Y> const& v ) { return v.x*v.x + v.y*v.y; } }; magnitude_squared_ const magnitude_square = {}; or template<class X,class Y> typename boost::result_of<magnitude_squared_(vector2<X,Y>)>::type magnitude_squared( vector2<X,Y> const& v ) { magnitude_squared_ callee; return callee(v); } Bonus is that you can ask the return type of an arbitrary magnitude_squared call in other template function if neede using boost::result_of. -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

On Wed, Dec 2, 2009 at 12:46 PM, joel falcou <joel.falcou@lri.fr> wrote:
Michael Fawcett wrote:
template <typename X, typename Y> BOOST_TYPEOF_TPL(X() * X() + Y() * Y()) magnitude_squared(const vector2<X, Y> &v) { return v.x * v.x + v.y * v.y; }
Typeof works, but I'm wondering if it's overkill and that perhaps common_type is much more lightweight and appropriate. promote_args doesn't do quite what I need here, but thank you for pointing that facility out to me.
Regardless, the original post was about how to proceed, and I definitely see reason to break those components out of Boost.Chrono. I didn't mean to hijack the thread ;)
Why not having a proper polymorphic function object that performs the computation and hide the potential uglyness of the type computation ?
struct magnitude_squared_ { template<class Sig> struct result; template<class This,class X, class Y> struct result<This(vector2<X,Y>)> { typedef BOOST_TYPEOF_TPL(X() * X() + Y() * Y()) type; };
template<class X,class Y> typename result<magnitude_squared_(vector2<X,Y>)>::type operator()( vector2<X,Y> const& v ) { return v.x*v.x + v.y*v.y; } };
magnitude_squared_ const magnitude_square = {};
or
template<class X,class Y> typename boost::result_of<magnitude_squared_(vector2<X,Y>)>::type magnitude_squared( vector2<X,Y> const& v ) { magnitude_squared_ callee; return callee(v); }
Bonus is that you can ask the return type of an arbitrary magnitude_squared call in other template function if neede using boost::result_of.
I'll look into this. It certainly sounds attractive! I went down a similar path once, but I didn't like how I had to do this for every free function - dot_product, cross_product, magnitude, normalize, etc. Maybe it's just a one time cost that pays off in the end with usability. Thanks, --Michael Fawcett

Michael Fawcett wrote:
I'll look into this. It certainly sounds attractive!
I went down a similar path once, but I didn't like how I had to do this for every free function - dot_product, cross_product, magnitude, normalize, etc. Maybe it's just a one time cost that pays off in the end with usability I did that for my HPC library and well, managing 457 such functiosn is a bit of a daunting task, but in the end it pays. At some point you can factor out recurrent result into external class and just have your actual PFO using them etc... Other nice thign is that turning this into a phoenix lambda is trivial, as for applying them to fusion tuples etc...
-- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

Typeof works, but I'm wondering if it's overkill and that perhaps common_type is much more lightweight and appropriate. promote_args doesn't do quite what I need here, but thank you for pointing that facility out to me.
The only version of common_type I've seen uses typeof internally, so doesn't actually differ from your existing implementation - other than having a cute interface. Just my 2c, John.

John Maddock wrote:
Typeof works, but I'm wondering if it's overkill and that perhaps common_type is much more lightweight and appropriate. promote_args doesn't do quite what I need here, but thank you for pointing that facility out to me.
The only version of common_type I've seen uses typeof internally, so doesn't actually differ from your existing implementation - other than having a cute interface.
Just my 2c, John.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Hi, IMO the typeof of X() * X() + Y() * Y() use the declarations of the operators * and +. These operator could need common_type if the operators * and + are able to combine different types. Thus the uses of typeof and comon_type are orthogonal. Best, Vicente -- View this message in context: http://old.nabble.com/-chrono--type_traits-common_type-and-integer-ratio-tp2... Sent from the Boost - Dev mailing list archive at Nabble.com.
participants (6)
-
Howard Hinnant
-
joel falcou
-
John Maddock
-
Michael Fawcett
-
Vicente Botet Escriba
-
vicente.botet