Re: [boost] Boost.Math and Math Constants

On Wed, 7 Dec 2011 15:33:21 Paul A. Bristow wrote:
John Maddock has now added a new cunning feature that allows the vast majority of users who just want a built-in double to get the constants quickly as plain variables. So in non-template code, users can write
using boost::math::double_constants; double area = pi * r * r;
and users can read the equations easily.
(Float and long double are similarly available in their own namespaces).
It's a little bit of work up front, but if you define a custom type with separate overloads for each arithmetic operator/operand type combination (i.e. *(float), *(double), +(float), +(double), etc.) you should be able to offer a single namespace with constants that auto-promote (or demote) to the right type in expressions. That's also easily extensible to user-defined storage classes such as an extended precision float, and I think it's more maintainable since the using declaration (which is now untyped) can't get out of sync with the usage context. To prevent ambiguous overloads (in contexts where the constant itself is supplied as an argument to a polymorphic function, not in expressions), you can leave just one type (perhaps double) as implicitly castable-to, with explicit casts for the others. That seems more Boost-y to me, at any rate.

On Thu, Dec 08, 2011 at 03:23:07AM +0000, Brent Spillner wrote:
On Wed, 7 Dec 2011 15:33:21 Paul A. Bristow wrote:
John Maddock has now added a new cunning feature that allows the vast majority of users who just want a built-in double to get the constants quickly as plain variables. So in non-template code, users can write
using boost::math::double_constants; double area = pi * r * r;
and users can read the equations easily.
(Float and long double are similarly available in their own namespaces).
It's a little bit of work up front, but if you define a custom type with separate overloads for each arithmetic operator/operand type combination (i.e. *(float), *(double), +(float), +(double), etc.) you should be able to offer a single namespace with constants that auto-promote (or demote) to the right type in expressions. That's also easily extensible to user-defined storage classes such as an extended precision float, and I think it's more maintainable since the using declaration (which is now untyped) can't get out of sync with the usage context. To prevent ambiguous overloads (in contexts where the constant itself is supplied as an argument to a polymorphic function, not in expressions), you can leave just one type (perhaps double) as implicitly castable-to, with explicit casts for the others.
A fundamental problem with proxies and things that try to rely on correct usage of conversion is that the conversion won't kick in when dealing with templates, as they do not matter when deducing template parameters. It's very easy to taint your types in such a way that a lot of machinery goes very very wrong. -- Lars Viklund | zao@acc.umu.se

It's a little bit of work up front, but if you define a custom type with separate overloads for each arithmetic operator/operand type combination (i.e. *(float), *(double), +(float), +(double), etc.) you should be able to offer a single namespace with constants that auto-promote (or demote) to the right type in expressions. That's also easily extensible to user-defined storage classes such as an extended precision float, and I think it's more maintainable since the using declaration (which is now untyped) can't get out of sync with the usage context. To prevent ambiguous overloads (in contexts where the constant itself is supplied as an argument to a polymorphic function, not in expressions), you can leave just one type (perhaps double) as implicitly castable-to, with explicit casts for the others.
A fundamental problem with proxies and things that try to rely on correct usage of conversion is that the conversion won't kick in when dealing with templates, as they do not matter when deducing template parameters. It's very easy to taint your types in such a way that a lot of machinery goes very very wrong.
Nod. There was some work on this I seem to remember after Paul's previous constant-lib review failed, but it never really fully worked well enough... John.

AMDG On 12/07/2011 07:23 PM, Brent Spillner wrote:
On Wed, 7 Dec 2011 15:33:21 Paul A. Bristow wrote:
John Maddock has now added a new cunning feature that allows the vast majority of users who just want a built-in double to get the constants quickly as plain variables. So in non-template code, users can write
using boost::math::double_constants; double area = pi * r * r;
and users can read the equations easily.
(Float and long double are similarly available in their own namespaces).
It's a little bit of work up front, but if you define a custom type with separate overloads for each arithmetic operator/operand type combination (i.e. *(float), *(double), +(float), +(double), etc.) you should be able to offer a single namespace with constants that auto-promote (or demote) to the right type in expressions. That's also easily extensible to user-defined storage classes such as an extended precision float, and I think it's more maintainable since the using declaration (which is now untyped) can't get out of sync with the usage context. To prevent ambiguous overloads (in contexts where the constant itself is supplied as an argument to a polymorphic function, not in expressions), you can leave just one type (perhaps double) as implicitly castable-to, with explicit casts for the others.
That seems more Boost-y to me, at any rate.
Don't go that route please. We did it in the Units library, and it causes way too many problems, because it's too clever. The only thing that acts exactly like a double is a double. When your custom type fails to act like a double it's going to cause surprises. In Christ, Steven Watanabe
participants (4)
-
Brent Spillner
-
John Maddock
-
Lars Viklund
-
Steven Watanabe