Boost logo

Boost :

From: Joerg Walter (jhr.walter_at_[hidden])
Date: 2003-01-24 16:05:49


Hi Paul,

you wrote:

> Please send me your amended code. I had thought that the Kenniston stuff
was
> included in the zip uploaded, but I will check. Apologies if not.

OK. I've just learned that the file function_constants.hpp attached to your
last posting is an updated version of the same file in the
math_constants3.zip at groups.yahoo.com.

[snip]

> > > Attached is an example using Michael Kenniston's Kunning Function
> > constants.
> > >
> > > Briefly
> > >
> > > 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 boost::math::constant< T, boost::math::pi_tag >() * radius *
> > radius;
> > > }

[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'
function_constants.hpp:87: uninitialized const `
   boost::math::double_constants::pi'
function_constants.hpp:91: uninitialized const `
   boost::math::long_double_constants::pi'
function_constants.hpp:122: uninitialized const `
   boost::math::float_constants::sqrt2'
function_constants.hpp:126: uninitialized const `
   boost::math::double_constants::sqrt2'
function_constants.hpp:130: uninitialized const `
   boost::math::long_double_constants::sqrt2'
function_constants.hpp:150: uninitialized const `
   boost::math::float_constants::e'
function_constants.hpp:154: uninitialized const `
   boost::math::double_constants::e'
function_constants.hpp:158: uninitialized const `
   boost::math::long_double_constants::e'
test_circle_area.cpp: In function `int main()':
test_circle_area.cpp:34: `__TIMESTAMP__' undeclared (first use this
function)
test_circle_area.cpp:34: (Each undeclared identifier is reported only once
for
   each function it appears in.)

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
  }

The preprocessor symbol __TIMESTAMP__ seems to be platform specific.

> > > It compiles with MSVC 7.0 (but not 6 - see MK's original example for
why
> > not).
> > > (long double == double for MSVC, so long double not fully
> > testable/useful).
> > >
> > > It seems to do the trick, without too many surprises. I have
displayed
> > the
> > > output using the 17 significant digits for double so one can see the
> > difference
> > > between a float pi 3.1415927410125732 and a double pi
3.1415926535897931
> > (even
> > > though only 9 are really significant for float).
> > >
> > > cout << "circle_area<float>(1.) = " << circle_area<float>(1.) <<
endl; //
> > > Explicit type float.
> > > cout << "circle_area<double>(1.) = " << circle_area<double>(1.) <<
endl;
> > //
> > > Explicit type double.
> > > cout << "circle_area(1.F) = " << circle_area(1.F) << endl; //
Implicit
> > type
> > > float.
> > > cout << "circle_area(1.) = " << circle_area(1.) << endl; // Implicit
type
> > > double.
> > > cout << "circle_area(1.L) = " << circle_area(1.L) << endl; //
implicit
> > type
> > > long double.
> > > cout << "circle_area<double>(1.F) = " << circle_area<double>(1.F) <<
> > endl; //
> > > Explicit over-rides implicit.
> > >
> > > And silly types like int fail helpfully.
> > > // cout << "circle_area(1) = " << circle_area(1)<< endl; //
Implicit
> > int -
> > > does not link!
> > > // cout << "circle_area<int>(1.) = " << circle_area<int>(1.)<<
endl; //
> > > Explicit int - does not compile!
> > >
> > > Output is
> > >
> > > Test test_circle_area.cpp Thu Jan 23 00:06:28 2003
> > > float pi = 3.14159274
> > > double pi = 3.1415926535897931
> > > float pi = 3.1415927410125732
> > > circle_area<float>(1.) = 3.1415927410125732
> > > circle_area<double>(1.) = 3.1415926535897931
> > > circle_area(1.F) = 3.1415927410125732
> > > circle_area(1.) = 3.1415926535897931
> > > circle_area(1.L) = 3.1415926535897931
> > > circle_area<double>(1.F) = 3.1415926535897931
> > > circle_area<long double>(1.) = 3.1415926535897931
> > > circle_area<float>(2.) = 12.566370964050293
> > > circle_area<double>(2.) = 12.566370614359172
> > > circle_area(2.F) = 12.566370964050293
> > > circle_area(2.) = 12.566370614359172
> > > circle_area(2.L) = 12.566370614359172
> > > circle_area<double>(2.F) = 12.566370614359172
> > > boost::math::constant< float, boost::math::pi_tag >()
3.1415927410125732
> > >
> > > I haven't looked at any assembler to check on efficiency, but
believe/hope
> > from
> > > previous examples that it will be optimal if inlined.
> > >
> > > Does this look sensible/useful?
> >
> > Only if I learn to see the relation to your latest upload (which I'm
> > assuming your review request is related to).

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.

Thanks,

Joerg


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