|
Boost : |
From: Daniel Frey (d.frey_at_[hidden])
Date: 2003-06-08 15:53:34
On Sun, 08 Jun 2003 16:56:53 +0200, Paul A Bristow wrote:
> You can seen an example of extending to a 'new' constant 'gamma' in the
> examples testFunctionConstants/gamma_function_constants.hpp.
Either I don't understand the example or we are talking past each other. I
don't meant to extend the framework with new constants, but with
definitions of existing constants for new types. Maybe the attached
example of a small experiment of mine clarifies what I was thinking about.
Look at the "Roguewave"-extension for pi. If I imagine to use
"boost/math_constants.hpp" in the company I work, it would be encapsulated
into another header "base/math_constants.h" and it would provide all
constants for Roguewawve's decimal type, too. I already used the
lambda-library and tought it about the decimal type, which worked very
smooth and I was really happy to see that the library designers didn't
limited it to build-in types. A key-feature for me!
> defining the constant as a 40 decimal digit string.
Roguewave's types can be used with precisions up to 1024 bits - probably
more. I don't think that a one-size-fits-all approach can work in the area
of numeric computations.
> If Boosters agree that this scheme is an acceptable way to go, the the
> example and guidance could be made more helpful to provide the
> encouragement you rightly say is needed.
>
> But first the overall strategy needs agreement.
Indeed. So if I still missed that the constants can be provided by the
user for their types, please let me know. Otherwise, we should find a
consensus whether such a feature is needed. I personally think it is, but
if the majority thinks it's not that important... :)
Note that the attached file is not meant to offend you in any way. It way
just a toy example and maybe you can take some ideas out of it. It's not
meant to replace your code as I think you have put a lot of ideas in it
and provide features I don't even know of :)
Regards, Daniel
--- #include <iostream> using namespace std; namespace math { // Generic base class for all constants template< typename T, template< class > class F > struct constant { // A cast-to-anything-operator :) template< typename U > operator U() const { return F< U >()(); } #define ADD_OPERATOR( OP ) \ template< typename U > friend U operator OP( const T& lhs, const U& rhs ) \ { U nrv( static_cast< U >( lhs ) ); nrv OP##= rhs; return nrv; } \ template< typename U > friend U operator OP( const U& lhs, const T& rhs ) \ { U nrv( lhs ); nrv OP##= static_cast< U >( rhs ); return nrv; } ADD_OPERATOR( + ); ADD_OPERATOR( - ); ADD_OPERATOR( * ); ADD_OPERATOR( / ); #undef ADD_OPERATOR }; // Here's the definition for pi for all types (can be extended by UDTs): template< typename T > struct pi_value; template<> struct pi_value< float > { float operator()() const { return 3.14; } }; template<> struct pi_value< double > { double operator()() const { return 3.1416; } }; template<> struct pi_value< long double > { long double operator()() const { return 3.1415927; } }; /* // For expensive constructions, maybe this is an option: template<> struct pi_value< RWDecimal< RWMP3Int > > { const RWDecimal< RWMP3Int >& operator()() const { static const RWDecimal< RWMP3Int > value( "3.1415926535897932384626433832" ); return value; } }; */ // Here's the single line to create a useful interface struct pi_t : constant< pi_t, pi_value > {} pi; // Another one: template< typename T > struct pi2_value; template<> struct pi2_value< float > { float operator()() const { return 9.87; } }; template<> struct pi2_value< double > { double operator()() const { return 9.8696; } }; template<> struct pi2_value< long double > { long double operator()() const { return 9.8696044; } }; struct pi2_t : constant< pi2_t, pi2_value > {} pi2; // And their relationship: pi2_t operator*( const pi_t&, const pi_t& ) { return pi2_t(); } // Some obvious (?) constants: #define CONSTANT_VALUE( name, value ) \ template< typename T > struct name##_value { T operator()() const { return value; } }; \ struct name##_t : constant< name##_t, name##_value > {} name; CONSTANT_VALUE( minus_one, -1 ); CONSTANT_VALUE( zero, 0 ); CONSTANT_VALUE( one, 1 ); CONSTANT_VALUE( two, 2 ); CONSTANT_VALUE( three, 3 ); CONSTANT_VALUE( ten, 10 ); #undef CONSTANT_VALUE minus_one_t operator-( const one_t& ) { return minus_one_t(); } one_t operator-( const minus_one_t& ) { return one_t(); } zero_t operator-( const zero_t& ) { return zero_t(); } // Another one: template< typename T > struct half_pi_value; template<> struct half_pi_value< float > { float operator()() const { return 1.57; } }; template<> struct half_pi_value< double > { double operator()() const { return 1.5708; } }; template<> struct half_pi_value< long double > { long double operator()() const { return 1.5707963; } }; struct half_pi_t : constant< half_pi_t, half_pi_value > {} half_pi; // And their relationship: // The user can now write 'pi / two' and needn't remember // whether it was 'half_pi' or 'pi_by_2' or whatever... half_pi_t operator/( const pi_t&, const two_t& ) { return half_pi_t(); } // An example for another optimization type // to solve the naming dilemma, this time providing 'sin( pi )' template< typename T > T sin( const T& v ) { return std::sin( v ); } zero_t sin( const pi_t& ) { return zero_t(); } one_t sin( const half_pi_t& ) { return one_t(); } } int main() { // Usage example: using namespace math; const float f = 1.; const double d = 1.; const long double ld = 1.; cout << pi * f * f << endl; cout << pi * d * d << endl; cout << pi * ld * ld << endl; cout << static_cast< double >( pi ) << endl; cout << static_cast< float >( pi ) * d * d << endl; cout << pi * pi * f << endl; cout << pi * pi * d << endl; cout << pi * pi * ld << endl; cout << d * -sin( pi / two ) << endl; cout << d * -sin( pi / 2. ) << endl; long double r = 0; for( int i = 0; i < 10000000; ++i ) r = d * -sin( pi / 2. ); // try replacing the "2." by "two" - makes this test program 100x faster! cout << r << endl; }
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk