Boost logo

Boost :

From: Paul A. Bristow (boost_at_[hidden])
Date: 2003-01-27 09:08:29


> -----Original Message-----
> From: boost-bounces_at_[hidden]
> [mailto:boost-bounces_at_[hidden]]On Behalf Of Joerg Walter
> Sent: Friday, January 24, 2003 9:06 PM
> To: Boost mailing list
> Subject: Re: [boost] RE: math constant - generic function circle_area
> example.
>
>
> [snip]
>
> I've again tried to compile this with GCC 3.2.1. Here are the diagnostics:
>
> In file included from test_circle_area.cpp:12:
> function_constants.hpp:83: uninitialized const `
> boost::math::float_constants::pi
>
> The following workaround (applied to all constants) heals this
>
> namespace float_constants
> {
> #ifndef __GNUC__
> constant< float, pi_tag > const pi;
> #else
> constant< float, pi_tag > const pi = constant< float, pi_tag >();
> #endif
> }

This may be better for all platforms? I'll think about this.

> The preprocessor symbol __TIMESTAMP__ seems to be platform specific.
Agreed - but I personally find it useful so tend to use it. I should bracket
with #ifdef MSVC ...
>
> Ok, back to my earlier question. If I understand you correctly, we better
> should write
>
> return boost::math::constant< T, boost::math::pi_tag >() * radius * radius;
>
> instead of something like
>
> return boost::math::constant< T >::pi() * radius * radius;
>
> in generic code? I'll have to think about this.

It depends if Boosters decide to accept this fancy presentation of pi.

If not, then going back to the macro (long double)

 #define PI 3.141592653589793238462643383279502884197L

and using the compiler to convert to type T

template <typename T>
T circle_area(const T& radius)
{
 // Usage example: circle_area<double>( 2.) // Explicit type double.
 // or circle_area(2.F) // Implicit type float.
        return T(PI) * radius * radius;
}

*_probably yields_* the same end result
(as will the appropriate function of float pi(), double pi(), long double pi()).

But if you want the exactly representable value for interval arithmetic,
then I think the form

return boost::math::constant< T, boost::math::pi_tag >() * radius * radius;

will always give the exact value for pi.

(But, to confuse the matter further, is it not going to be more accurate, if
less portable, to calculate PI * radius * radius using long double before a
final rounding to type T? So we are choosing portability over accuracy here,
rightly in my view. Anyone who wants maximum accuracy will have to do their own
thing with the 40 decimal digit macro value for pi, and probably only wants long
double type anyway.)

Paul


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk