|
Boost : |
From: Paul A. Bristow (boost_at_[hidden])
Date: 2003-01-22 19:24:06
> [snip]
>
> I've been looking into an earlier version of the proposed math constants
> before and asked myself how to implement a generic function like
>
> template<class T>
> T circle_area (const T &radius) {
> return math_constants<T>::pi * radius * radius;
> }
>
> How should this be done?
>
> Thanks,
>
> Joerg
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;
}
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?
Paul
Paul A Bristow, Prizet Farmhouse, Kendal, Cumbria, LA8 8AB UK
+44 1539 561830 Mobile +44 7714 33 02 04
Mobile mailto:pabristow_at_[hidden]
mailto:pbristow_at_[hidden]
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk