
Folks, someone's just filed a feature request asking for more numeric constants to be added to Boost.Math (these are currently an implementation detail, albeit a semi-documented one: http://www.boost.org/doc/libs/1_37_0/libs/math/doc/sf_and_dist/html/math_too...), but we know what troubles we had agreeing on anything last time this came up for review! Even so it appears to be time to fearlessly open up this particular can of worms again ;-) So, it appears that there is still interest, but as you know last time we tried this there was no agreement on interface, some folks felt a template interface was essential: template <class T> T pi(); leading to: template <class T> T circumference(T r) { return 2 * boost::math::constants::pi<T>() * r; } While others were absolutely adament that they wouldn't use a syntax other than: template <class T> T circumference(T r) { return 2 * pi * r; } Various attempts were made to solve this conundrum via expression templates and/or overloaded operators, but all introduced their own new issues as well, and IMO none were wholly satisfactory (not least due to the complexity introduced, a complexity that becomes all too apparent to the user if they do get a compiler error due to an unsupported use case). So.... here's what I think Paul Bristow and I might be persuaded to submit: * A library based on the existing Boost.Math code, with pi<T>() as the main interface / use case. * Possibly add constants of specific precision in alternative namespaces, so we could have: double circumference(double r) { using namspace boost::math::double_constants; return 2 * pi * r; } And that's pretty much it: no overly complex stuff, just a really simple library with a few constants in it, that makes it really easy to add new constants when required. Thoughts? Regards, John.

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of John Maddock Sent: 30 January 2009 10:35 To: boost@lists.boost.org Subject: [boost] Numeric constants
Folks, someone's just filed a feature request asking for more numeric constants to be added to Boost.Math (these are currently an implementation detail, albeit a semi-documented one:
kit/internals1/constants.html), but we know what troubles we had agreeing on anything last time this came up for review! Even so it appears to be time to fearlessly open up this particular can of worms again ;-)
So, it appears that there is still interest, but as you know last time we tried this there was no agreement on interface, some folks felt a template interface was essential:
template <class T> T pi();
leading to:
template <class T> T circumference(T r) { return 2 * boost::math::constants::pi<T>() * r; }
While others were absolutely adament that they wouldn't use a syntax other than:
template <class T> T circumference(T r) { return 2 * pi * r; }
Various attempts were made to solve this conundrum via expression templates and/or overloaded operators, but all introduced their own new issues as well, and IMO none were wholly satisfactory (not least due to the complexity introduced, a complexity that becomes all too apparent to the user if they do get a compiler error due to an unsupported use case).
So.... here's what I think Paul Bristow and I might be persuaded to submit:
* A library based on the existing Boost.Math code, with pi<T>() as the
http://www.boost.org/doc/libs/1_37_0/libs/math/doc/sf_and_dist/html/math_too lkit/tool main
interface / use case. * Possibly add constants of specific precision in alternative namespaces, so we could have:
double circumference(double r) { using namspace boost::math::double_constants; return 2 * pi * r; }
And that's pretty much it: no overly complex stuff, just a really simple library with a few constants in it, that makes it really easy to add new constants when required.
Thoughts?
Well - obviously I am entirely in agreement with John's suggestion. I was very disappointed that we got bogged down in the presentation issue. I still have the collection of constants in the vault and I don't think any of them have changed since 2003 ;-) Since more than 95% of the use will be people wanting doubles, I think John's proposal to have specific doubles namespace is a really good idea. One question I have is the precision needed. My current set are 50 decimal digits, more than enough for any foreseeable floating point hardware. John's current code in the Boost.Math package allows much more, and the constants now defined are to 100 decimal digits. This allows really accurate computation using an arbitrary precision system like Victor Shoup's NTL (GPL License) (or a Boost equivalent if we can produce one - a GSoC project?). My question is - what precision would be useful? Paul --- Paul A. Bristow Prizet Farmhouse Kendal, UK LA8 8AB +44 1539 561830, mobile +44 7714330204 pbristow@hetp.u-net.com

One question I have is the precision needed. My current set are 50 decimal digits, more than enough for any foreseeable floating point hardware. John's current code in the Boost.Math package allows much more, and the constants now defined are to 100 decimal digits. This allows really accurate computation using an arbitrary precision system like Victor Shoup's NTL (GPL License) (or a Boost equivalent if we can produce one - a GSoC project?).
My question is - what precision would be useful?
Not sure, but I guess if we got organised (Ha!), we could generate them programatically using arbitrary precision arithmetic and just tweek the precision as required? John.

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of John Maddock Sent: 30 January 2009 11:09 To: boost@lists.boost.org Subject: Re: [boost] Numeric constants
One question I have is the precision needed. My current set are 50 decimal digits, more than enough for any foreseeable floating point hardware. John's current code in the Boost.Math package allows much more, and the constants now defined are to 100 decimal digits. This allows really accurate computation using an arbitrary precision system like Victor Shoup's NTL (GPL License) (or a Boost equivalent if we can produce one - a GSoC project?).
My question is - what precision would be useful?
Not sure, but I guess if we got organised (Ha!), we could generate them programatically using arbitrary precision arithmetic and just tweek the precision as required?
Well I have part of that already to generate the stuff I produced before. But for the Boost release, I would hope we can settle for 50 (or 100) decimal digits. Paul --- Paul A. Bristow Prizet Farmhouse Kendal, UK LA8 8AB +44 1539 561830, mobile +44 7714330204 pbristow@hetp.u-net.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Thorsten Ottosen Sent: 30 January 2009 12:34 To: boost@lists.boost.org Subject: Re: [boost] Numeric constants
Paul A. Bristow skrev:
My question is - what precision would be useful?
I assume float, double and long double will be supported? These seems to be the ones we need for the new bounded_float class from the ContrainedValue lib recently reviewed.
Yes by having three extra namespaces: namespace boost::math::float_constants; namespace boost::math::double_constants; namespace boost::math::long_double_constants; used like this: float circumference(float r) { using namespace boost::math::float_constants; return 2 * pi * r; } and double circumference(double r) { using namespace boost::math::double_constants; return 2 * pi * r; } Similarly long double. Would this fit with the new bounded_float classes from the ContrainedValue library? But I was asking about the maximum possible precision for the underlying constants - that you might want to use with an arbitrary precision type, 'BigFloats' like NTL, GMP etc. As John has shown with the Math library, there are times when you need this to generate reference values, more accurate than built-in types, to be sure that you get exactly the right built-in value. Paul --- Paul A. Bristow Prizet Farmhouse Kendal, UK LA8 8AB +44 1539 561830, mobile +44 7714330204 pbristow@hetp.u-net.com

So.... here's what I think Paul Bristow and I might be persuaded to submit:
* A library based on the existing Boost.Math code, with pi<T>() as the
John Maddock wrote: main
interface / use case. * Possibly add constants of specific precision in alternative namespaces, so we could have:
+1

Thomas Klimpel skrev:
So.... here's what I think Paul Bristow and I might be persuaded to submit: * A library based on the existing Boost.Math code, with pi<T>() as the
John Maddock wrote: main
interface / use case. * Possibly add constants of specific precision in alternative namespaces, so we could have:
+1
+1 -Thorsten

John Maddock wrote:
template <class T> T pi();
I have a fixed-point class. What actually happens when I call pi<fixed>() ? Presumably the implementation just does "return 3.1415...", so fixed::fixed(double) gets called. Yes my fixed class has a constructor that takes a double, and if I'm really lucky it may do the conversion at compile time - but more likely it will happen at run time. I would get the same code if you just declared "const double pi = 3.1415" (or #defined it). My 64-bit fixed point type can store more digits of PI than a 64-bit floating point value. But I'm not aware of any way of filling those extra digits [ignoring the existence of long double]. Similarly if I had an arbitrary precision (i.e. variable length) type, how would it be constructed from the 100-digit constants that you mention without support from the language (or maybe macros)? (As for the actual constants, the only ones I find myself using are pi and the approximate radius of the earth.) Cheers, Phil.

I was wondering what kind of constants this would include. Physical constants, or just mathematical ones? And what about constants with multiple expressions depending on units? For example, H_bar = 6.626e-34 J-s = 4.135e-15 eV-s.

I was wondering what kind of constants this would include. Physical constants, or just mathematical ones? And what about constants with multiple expressions depending on units? For example, H_bar = 6.626e-34 J-s = 4.135e-15 eV-s.
In the first instance I think we'll stick to well defined non-controvercial numerical constants, the example you give being a good reason to do so ;-) *If* we can get agreement on the interface, then a later submission of more physical constants would seem to be in order - perhaps this would be a good use for Boost.Units? John.

AMDG John Maddock wrote:
I was wondering what kind of constants this would include. Physical constants, or just mathematical ones? And what about constants with multiple expressions depending on units? For example, H_bar = 6.626e-34 J-s = 4.135e-15 eV-s.
In the first instance I think we'll stick to well defined non-controvercial numerical constants, the example you give being a good reason to do so ;-)
*If* we can get agreement on the interface, then a later submission of more physical constants would seem to be in order - perhaps this would be a good use for Boost.Units?
We already have a number of physical constants in SI units using doubles only. Actually, the template<class T> T H_bar(); interface would work pretty well, because it allows T to contain the unit information. In Christ, Steven Watanabe

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Ross Levine Sent: 30 January 2009 16:09 To: boost@lists.boost.org Subject: Re: [boost] Numeric constants
I was wondering what kind of constants this would include. Physical constants, or just mathematical ones? And what about constants with multiple expressions depending on units? For example, H_bar = 6.626e-34 J-s = 4.135e-15 eV-s.
I think we are limiting ourselves to Math constants in the Boost.Math library. The units library might include physical 'not-so-constant' constants ;-) Paul --- Paul A. Bristow Prizet Farmhouse Kendal, UK LA8 8AB +44 1539 561830, mobile +44 7714330204 pbristow@hetp.u-net.com

I was wondering what kind of constants this would include. Physical constants, or just mathematical ones? And what about constants with multiple expressions depending on units? For example, H_bar = 6.626e-34 J-s = 4.135e-15 eV-s.
IMO, We should definitely use SI. B/Rgds Max

Max wrote:
I was wondering what kind of constants this would include. Physical constants, or just mathematical ones? And what about constants with multiple expressions depending on units? For example, H_bar = 6.626e-34 J-s = 4.135e-15 eV-s.
IMO, We should definitely use SI.
B/Rgds Max
What units to use is strictly a function of what you are simulating. I'm a big fan of SI units in education and many problems, but in some settings they are not a good choice. (Consider a particle physics program, as an example.) In physical calculations, you should always choose your units based on what calculations you are doing, not on some rigid belief in what system people "should" use. This has some flexibility based on what units users of the program will expect to see, but none based on pure dogma. John

IMO, We should definitely use SI.
What units to use is strictly a function of what you are simulating. I'm a big fan of SI units in education and many problems, but in some settings they are not a good choice. (Consider a particle physics program, as an example.) In physical calculations, you should always choose your units based on what calculations you are doing, not on some rigid belief in what system people "should" use.
This has some flexibility based on what units users of the program will expect to see, but none based on pure dogma.
:-) with my face getting red for a while. B/Rgds Max

template <class T> T pi();
I have a fixed-point class. What actually happens when I call pi<fixed>() ? Presumably the implementation just does "return 3.1415...", so fixed::fixed(double) gets called. Yes my fixed class has a constructor that takes a double, and if I'm really lucky it may do the conversion at compile time - but more likely it will happen at run time. I would get the same code if you just declared "const double pi = 3.1415" (or #defined it).
My 64-bit fixed point type can store more digits of PI than a 64-bit floating point value. But I'm not aware of any way of filling those extra digits [ignoring the existence of long double]. Similarly if I had an arbitrary precision (i.e. variable length) type, how would it be constructed from the 100-digit constants that you mention without support from the language (or maybe macros)?
(As for the actual constants, the only ones I find myself using are pi and the approximate radius of the earth.)
Currently with Boost.Math if you call: pi<my_UDT>() then internally it does a lexical_cast from a string containing ~100 decimal digits to my_UDT. The resulting value is cached for performance reasons, but of course that's not thread safe, although it could be made so (still on the TODO list though). So unless my_UDT supports an unfeasably large number of digits, you should get pi to the full precision of your type. We currently use this with both NTL::RR and mpfr_class (2 arbitrary precision types), and it works very well. Obviously there are float/double/long double specialisations that just return the numeric constant directly (with appropriate suffix). And finally don't forget that you could add user-defined full specialisations of the templates for my_UDT if my_UDT provides it's own interfaces to various constants. John.

John Maddock wrote:
template <class T> T pi();
I have a fixed-point class. What actually happens when I call pi<fixed>() ?
Currently with Boost.Math if you call:
pi<my_UDT>()
then internally it does a lexical_cast from a string containing ~100 decimal digits to my_UDT.
OK, I suppose that makes sense in general. My fixed class doesn't have operator<<,>> unfortunately, since I've never needed them for anything else.
And finally don't forget that you could add user-defined full specialisations of the templates for my_UDT if my_UDT provides its own interfaces to various constants.
Can I specialise all_constants<my_type> to cast from double without having to write out all of the constants individually? Phil.

Phil Endecott a écrit :
John Maddock wrote:
template <class T> T pi();
I have a fixed-point class. What actually happens when I call pi<fixed>() ? Presumably the implementation just does "return 3.1415...", so fixed::fixed(double) gets called. Yes my fixed class has a constructor that takes a double, and if I'm really lucky it may do the conversion at compile time - but more likely it will happen at run time. I would get the same code if you just declared "const double pi = 3.1415" (or #defined it).
My 64-bit fixed point type can store more digits of PI than a 64-bit floating point value. But I'm not aware of any way of filling those extra digits [ignoring the existence of long double]. Similarly if I had an arbitrary precision (i.e. variable length) type, how would it be constructed from the 100-digit constants that you mention without support from the language (or maybe macros)?
(As for the actual constants, the only ones I find myself using are pi and the approximate radius of the earth.)
Sorry if i soem up with a bad or already proposed solution. I had to handle such named constant in soem code with the same ste of constraints (usability and casting to user-defined type). What I did was to have class of constants that are build based on a constant ID and expose a tempalte operator T: template<class ID> class constant { template<class T> operator T() const { return cast<T>(ID::Value()); } // proper unary operator and so on }; ID class are the one containing the actual consatnt value and a "default type" : class pi_id { typedef long double type; static inline Value() { return 3.1415........; } }; The T() operator call a cast function which is in fact a polymorphic function object that uses tag dispatching to either just perform a cast or to call a user-defined casting operation. Those user defined operator can be overloaded on the constant id if needed (for example if you have special algorithm to compute pi with fixed representation but use a cast for other constant). Those constant are then statically defined as POD constant : constant<pi_id> pi_ = {}; How to use those constant ? It rather simple. Things like double k = pi_; int u = ten_; works as intended by auto-casting the valeu to the destination type. You can force a constant to be of a given type : abs( float(log2_) ); Alternatively, the basic operator (+,-,*,/,unary -, ~, ! and comparison) are overlaod to autocast the constant into a proper type when used like : double k,v; k = v + pi_; bool test = x > log10_; A set of result_of enabled traits also allows to computes the correct type of a constant when used in a complex expression. Most constant type-cast is performed at compile-time, unless if you use a user-defined type-casting overload. I am overthinking it or could this be viable ? -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

How to use those constant ? It rather simple. Things like double k = pi_; int u = ten_; works as intended by auto-casting the valeu to the destination type.
You can force a constant to be of a given type : abs( float(log2_) ); Alternatively, the basic operator (+,-,*,/,unary -, ~, ! and comparison) are overlaod to autocast the constant into a proper type when used like :
double k,v; k = v + pi_; bool test = x > log10_;
A set of result_of enabled traits also allows to computes the correct type of a constant when used in a complex expression. Most constant type-cast is performed at compile-time, unless if you use a user-defined type-casting overload.
I am overthinking it or could this be viable ?
Well.... this is one of those "complex" solutions that was suggested last time this was discussed that I've been trying to avoid ;-) Off the top of my head, the main problems I see are: * What is the result of 2 * pi? How about 2 * pi * r where r is a real? * If you mistakenly call a function passing a constant as argument, for example foo(2.0, pi), then if foo is a template you will likely get an inscutable failure very deep inside foo's body (or worse some other function that foo calls). * In order to avoid ODR violations I presume the constants have to be defined in an anonymous namespace? Does this cause code bloat simply by #including the constants header? Now I suspect that all of these issues are probably solvable to some degree, it's a question of whether it's worth the hassle, and/or whether the resulting code is likely to turn into a problem to maintain. Cheers, John.

John Maddock a écrit :
Well.... this is one of those "complex" solutions that was suggested last time this was discussed that I've been trying to avoid ;-) I was unable to retrieve the "original" thread about the numeric consatnt so I can't find the roots of the discussion but I guessed it was problematic.
Off the top of my head, the main problems I see are:
* What is the result of 2 * pi? How about 2 * pi * r where r is a real? What I did was assigning to each constant a conversion policy. 2*pi is prolly a double by default, while 2*pi*r is the greatest common real type between double and type of r. * If you mistakenly call a function passing a constant as argument, for example foo(2.0, pi), then if foo is a template you will likely get an inscutable failure very deep inside foo's body (or worse some other function that foo calls). Yes that's the main problem of this solution I think. In my case, the consatnts are alwasy used with "constant" aware function so the problem doesn't appear. * In order to avoid ODR violations I presume the constants have to be defined in an anonymous namespace? Does this cause code bloat simply by #including the constants header? I don't get how ODR if violated in this case. Now I suspect that all of these issues are probably solvable to some degree, it's a question of whether it's worth the hassle, and/or whether the resulting code is likely to turn into a problem to maintain. Yes, as said above I *thought* it was discussed somewhere but wasn't able to retrieve the actual discussion. So everything perfectly fine now that thigns ahve been cleared out ;)
-- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

From: "John Maddock" <john@johnmaddock.co.uk> Currently with Boost.Math if you call:
pi<my_UDT>()
then internally it does a lexical_cast from a string containing ~100 decimal digits to my_UDT. The resulting value is cached for performance reasons, but of course that's not thread safe, although it could be made so (still on the TODO list though). So unless my_UDT supports an unfeasably large number of digits, you should get pi to the full precision of your type. We currently use this with both NTL::RR and mpfr_class (2 arbitrary precision types), and it works very well. Obviously there are float/double/long double specialisations that just return the numeric constant directly (with appropriate suffix). And finally don't forget that you could add user-defined full specialisations of the templates for my_UDT if my_UDT provides it's own interfaces to various constants.
John.
I played around with this type of idea in the geometry code I've been working on. In my case I wanted to support any kind of type as well as rational types (for which even a 100 decimal pi might be considered poor resolution?). I've never really worked in a domain requiring this high of a precision for pi.. but figured it was fun to give it a whirl. One use case for such a thing would be if you are using integral types for defining the geometry but still need to work with some constants like PI (in very high precisions). So for an example I had a specialization say for an arbitrary big int type (with a traits specialization to limit the precision to something .... mortal): template <> struct constants<my_big_int> { typedef my_big_int int_type; typedef rational_promotion_traits< int_type >::rational_type rational_type; //! \brief Calculate the required digits of pi for type my_big_int. static inline rational_type pi() { //! Calculate PI to the required precision using a spigot algorithm. static rational_type _pi = detail::calculate_pi< rational_type, numeric_traits< int_type >::precision
::pi(); return _pi; } };
And voila, I had a means to use a tailor fit approximation of PI with my integral geometry types. I always figured this really didn't belong to the geometry code.. and that it should be factored out and into a more general numeric library (but there wasn't one that I saw at the time). Would Boost.Math already have a facility covering this use case? Cheers, Brandon

I played around with this type of idea in the geometry code I've been working on. In my case I wanted to support any kind of type as well as rational types (for which even a 100 decimal pi might be considered poor resolution?). I've never really worked in a domain requiring this high of a precision for pi.. but figured it was fun to give it a whirl.
One use case for such a thing would be if you are using integral types for defining the geometry but still need to work with some constants like PI (in very high precisions).
So for an example I had a specialization say for an arbitrary big int type (with a traits specialization to limit the precision to something .... mortal):
template <> struct constants<my_big_int> { typedef my_big_int int_type; typedef rational_promotion_traits< int_type >::rational_type rational_type;
//! \brief Calculate the required digits of pi for type my_big_int. static inline rational_type pi() { //! Calculate PI to the required precision using a spigot algorithm. static rational_type _pi = detail::calculate_pi< rational_type, numeric_traits< int_type >::precision
::pi(); return _pi; } };
And voila, I had a means to use a tailor fit approximation of PI with my integral geometry types. I always figured this really didn't belong to the geometry code.. and that it should be factored out and into a more general numeric library (but there wasn't one that I saw at the time). Would Boost.Math already have a facility covering this use case?
Sort of, you would specialize boost::math::constants::pi: namespace boost{ namespace math{ namespace constants{ template<> inline rational_type pi<rational_type>() { //! Calculate PI to the required precision using a spigot algorithm. static rational_type _pi = detail::calculate_pi< rational_type, numeric_traits< int_type >::precision
::pi(); return _pi; } };
}}} // namespaces And then you can write generic code involving PI that functions the same for your rational type as it does for say double or float. Is that what you were looking for? John.

John Maddock wrote:
Folks, someone's just filed a feature request asking for more numeric constants to be added to Boost.Math (these are currently an implementation detail, albeit a semi-documented one: http://www.boost.org/doc/libs/1_37_0/libs/math/doc/sf_and_dist/html/math_too...), but we know what troubles we had agreeing on anything last time this came up for review! Even so it appears to be time to fearlessly open up this particular can of worms again ;-) <snip> And that's pretty much it: no overly complex stuff, just a really simple library with a few constants in it, that makes it really easy to add new constants when required.
Thoughts?
Regards, John.
Another +1 John

Is that what you were looking for?
John.
Indeed it does do the trick nicely. In what I wrote I diverged slightly from the clean path by using a rational promotion trait type. I think the main difference is that it really doesn't make sense to define PI for a plain integral type (3...) so I added type promotion to a rational into the mix. This allows me to simply ask for a value of pi given whatever type I'm currently working with and let the generative machinery crank out the details such as a promotion to rational if required. Then using something like auto or typeof I can abstract number types from these details and carry on with the work in the problem space without having to worry about whether the type returned can actually be properly represented/approximated. I guess the argument then becomes whether it's more correct to simply return the whole number approximation of a constant under the specialized type or to attempt to adapt it into a more useful type. Maybe both via a modified alternate path? Perhaps this is something worth a bit of discussion, as there is the Boost.Rational library (which is nice.. but underutilized I suspect due to a lack of a Boost arbitrary integer.) Kevin Sopp has been working on such an integral type which seems to be coming along nicely. I also have a lazy_exact type which I've been using with Boost.Rational, Kevin's integer and some extension code to the rational I have written which allows for construction from floating point types and some other useful conversions. These ingredients are one way to manage writing geometry algorithms which are fraught with precision issues when performed under floating point. They ultimately form a suboptimal solution as lazy floating point filtered types are still very slow.. but sometimes there is little alternative. So even though it's not the fastest way to go (GMP beats this paradigm every time) I think it might be useful if Boost.Math (or something similar) supported these modes of use when accessing values for constants. Cheers, Brandon
participants (11)
-
Brandon Kohn
-
Joel Falcou
-
John Maddock
-
John Phillips
-
Max
-
Paul A. Bristow
-
Phil Endecott
-
Ross Levine
-
Steven Watanabe
-
Thomas Klimpel
-
Thorsten Ottosen