Re: [boost] Re: Re: Math Constants Formal Review

2003-06-22 Thread Terje Slettebø
>From: "Daniel Frey" <[EMAIL PROTECTED]>

> On Sun, 22 Jun 2003 22:01:19 +0200, Terje Slettebø wrote:
> >
> > Another thing, are the ADD_OPERATOR macro in your code necessary? It
> > compiles fine without it on Intel C++ 7.1.
>
> The GCC doesn't work without the operators, as it doesn't implicitly tries
> to satisfy float*pi_t by casting pi_t to float to use float*float. I
> think this is OK as the language can go for two ways:
>
> a) define float*float and use a promotion/conversion for, say, float*int.
> b) define several operators float*float, float*int, ...
>
> if it's b), the compiler cannot cast pi_t to float as it doesn't know
> whether to select float*float or float*int, thus it fails. Maybe a
> question for the language lawyers over at csc++ to find out what's
> correct.

It's an odd thing, anyway. Both g++ 3.2 and MSVC 7.1 complains that there's
no matching operator*.

> >> Also, I'm not sure whether it's standard compliant code.
> >
> > I think it is. It specialises a member. What could be the problem with
> > this? As you say, errors are caught at link time.
>
> I think that you have to declare the specialization in the class'
> definition, not just outside. But I may be wrong here and I haven't
> checked it.

I don't think so. I tried that, and it gave the error: "error: explicit
specialization is not allowed in the current scope"


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


[boost] Re: Re: Math Constants Formal Review

2003-06-22 Thread Daniel Frey
On Sun, 22 Jun 2003 22:01:19 +0200, Terje Slettebø wrote:

> Ok. So maybe an extra level of indirection, as in your code (and
> Kenniston's) may be preferable. I was wondering what was the point with
> it. :)
> 
> Another thing, are the ADD_OPERATOR macro in your code necessary? It
> compiles fine without it on Intel C++ 7.1.

The GCC doesn't work without the operators, as it doesn't implicitly tries
to satisfy float*pi_t by casting pi_t to float to use float*float. I
think this is OK as the language can go for two ways:

a) define float*float and use a promotion/conversion for, say, float*int.
b) define several operators float*float, float*int, ...

if it's b), the compiler cannot cast pi_t to float as it doesn't know
whether to select float*float or float*int, thus it fails. Maybe a
question for the language lawyers over at csc++ to find out what's
correct.

>> Also, I'm not sure whether it's standard compliant code.
> 
> I think it is. It specialises a member. What could be the problem with
> this? As you say, errors are caught at link time.

I think that you have to declare the specialization in the class'
definition, not just outside. But I may be wrong here and I haven't
checked it. Note I didn't say it's illegal, just that *I* am not sure it's
legal ;)

Regards, Daniel

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


RE: [boost] Re: Re: Math Constants Formal Review - usingnamespacestoselectfloat size is simpler?

2003-06-20 Thread Paul A Bristow
|  -Original Message-
|  From: [EMAIL PROTECTED] 
|  [mailto:[EMAIL PROTECTED] On Behalf Of Ken Hagan
|  Sent: 20 June 2003 11:27
|  To: [EMAIL PROTECTED]
|  Subject: [boost] Re: Re: Math Constants Formal Review - 
|  using namespacestoselectfloat size is simpler?
|  
|  Paul A Bristow wrote:
|  > This scheme may offer more surprises to the many naive 
|  users (like me) 
|  > than an explicit (and convenient 'global') choice, for example:
|  >
|  > using boost::math::double_constants;
|  >
|  > to ensure that the expected size is used.
|  >
|  > One can make the compiler warn you about size conversions, 
|  whereas I 
|  > have the impression that these rules will mean that you 
|  won't get any 
|  > warnings.
|  
|  AFAICT, you will either get exactly the type that the 
|  context requires, or a diagnostic from the compiler saying 
|  that it is ambiguous. (This assumes that a selection of 
|  possible types are available for each
|  constant.) I don't think it is possible to get a quiet conversion.
|  
|  In contrast, "using boost::math::double_constants" does 
|  allow you to get an implicit size conversion, where the 
|  context requires one. Compilers will warn, but only if users 
|  haven't disabled the warning.
|  
|  So, with the "clever" approach, all users will find 
|  themselves writing a few explicit conversions to avoid 
|  ambiguities. With the "simple" approach, only users who have 
|  their warning level right up will need to write explicit 
|  conversions, and then only to silence the compiler.
|  
|  Listening to compiler warnings is something the community 
|  might want to encourage (so the simple approach would then 
|  have no advantages), but it isn't the job of a language 
|  standard to mandate "good" programming practices. (In the 
|  absence of such constraints, the definition of "good" tends 
|  to change with time.)

I am grateful for this reassurance that conversions not expected,
though I hope the compiler writers know the rules -
as Michael Caine would have said "Not a lot of people know that" :-) 

Thanks too for your accurate summing up of pros and cons.
My slight preference for the 'simple' approach 
perhaps came from always setting the compiler to warn about
conversions and carefully 'casting them all away'.
Alas Microsoft have not chosen this as their default
and it is not obvious how to ensure that
all files are compiled with the right warning option.
(After getting some helpful hints, I previously posted guidance
on how to modify common.js to achieve this).

But I am persuaded that the 'casting' method is OK.

Paul



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


[boost] Re: Re: Math Constants Formal Review - using namespacestoselectfloat size is simpler?

2003-06-20 Thread Ken Hagan
Paul A Bristow wrote:
> This scheme may offer more surprises to the many naive users (like me)
> than an explicit (and convenient 'global') choice, for example:
>
> using boost::math::double_constants;
>
> to ensure that the expected size is used.
>
> One can make the compiler warn you about size conversions,
> whereas I have the impression that these rules will mean
> that you won't get any warnings.

AFAICT, you will either get exactly the type that the context requires,
or a diagnostic from the compiler saying that it is ambiguous. (This
assumes that a selection of possible types are available for each
constant.) I don't think it is possible to get a quiet conversion.

In contrast, "using boost::math::double_constants" does allow you
to get an implicit size conversion, where the context requires one.
Compilers will warn, but only if users haven't disabled the warning.

So, with the "clever" approach, all users will find themselves
writing a few explicit conversions to avoid ambiguities. With
the "simple" approach, only users who have their warning level
right up will need to write explicit conversions, and then only
to silence the compiler.

Listening to compiler warnings is something the community might
want to encourage (so the simple approach would then have no
advantages), but it isn't the job of a language standard to
mandate "good" programming practices. (In the absence of such
constraints, the definition of "good" tends to change with time.)



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


RE: [boost] RE: Re: Math Constants Formal Review - ()s are a keyissue.

2003-06-17 Thread Paul A Bristow
In previous discussions, the main issues debated were:

1 Control of precision is essential,
and some users wanted to be able to use
float, double and long double at the same time.

2  Avoiding paying for what you don't use, which leads to

2a  MACROS provide a simple way of avoiding some cost for 
constants you don't use, (Although some Boosters were opposed 
to MACROs because they pollute the global namespace).

So, even if other presentations are provided,
I strongly believe macros should be published.
If you don't like them, don't use them!

2b Splitting the constants into several groups of files: essential,
common, esoteric...

3 Efficiency

Some compilers can generate better code 
from functions like "double pi() { return 3.1459;}"
but that this implies writing "pi()" instead of plain "pi".

4 Appearance

BUT Users extremely strongly prefer to write "float area = pi * r * r;"

So the ()s remain a MAJOR issue.

Michael Kenniston produced a 'presentation'
which allows 'novice' users to write "pi" but
get the effect of "pi()" without too many precision surprises.
Yet it still allows the 'expert' to write "pi()" and control precision 
explicitly.

I see nothing wrong with your suggestions and examples,
but I don't yet understand
how your proposal helps to meet this last 'requirement'.

Paul


Paul A Bristow, Prizet Farmhouse, Kendal, Cumbria LA8 8AB  UK
+44 1539 561830
[EMAIL PROTECTED]

|  -Original Message-
|  From: [EMAIL PROTECTED]
|  [mailto:[EMAIL PROTECTED] On Behalf Of Daniel Frey
|  Sent: 14 June 2003 20:48
|  To: [EMAIL PROTECTED]
|  Subject: [boost] RE: Re: Math Constants Formal Review - is 
|  extensible.
|  
|  
|  On Wed, 11 Jun 2003 15:49:05 +0200, Paul A. Bristow wrote:
|  
|  > The proposal is for several header files each containing the same
|  > constants, only one of which would be used for any 
|  compilation. (Users 
|  > have been warned against using more than one! Nobody has 
|  suggested a 
|  > way to guard against this mistake, but I think that it would be 
|  > apparent pretty soon, probably at compile time, and at 
|  link time if 
|  > not.)  The macros constants header is the simplest and 
|  could be used 
|  > to provide the appropiate value(s) above.
|  
|  The difference IMHO is, that this is not a generic approach.
|  It's a bit like replacing templates with macros. I haven't 
|  seen any convincing arguments against the code I showed, 
|  which *is* generic IMHO, but as I don't have the background 
|  of the "long saga" you mentioned, I think I'm not the right 
|  one to say what's the best way to go.
|  
|  Regards, Daniel
|  
|  ___
|  Unsubscribe & other changes:
|  http://lists.boost.org/mailman/listinfo.cgi/b|  oost
|  
|  


___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


RE: [boost] RE: Re: Math Constants Formal Review - is extensible.

2003-06-16 Thread Paul A Bristow
I understand that this is not normal, but in this case there
is a lot of work to do to create the files and I am reluctant to
do this if the result is not ultimately going to be accepted.

So I'd prefer agreement in principle first to the way of presenting the
constants,
and to the actual constants, their names and their values in the C macro
files.

There has already been much dicussion of all these items, but until the
MSVC 7.1 compiler was out, the Kenniston presentation format was only
sensible on other compilers.  Now this has proved to be workable and
efficient,
it seemed timely to re-review the issue.

Paul


|  I'm a bit surprised, that we currently are reviewing some 
|  ideas instead of a library as far as I understood.
|  
|  Regards,
|  Joerg

 
Paul A Bristow, Prizet Farmhouse, Kendal, Cumbria LA8 8AB  UK
+44 1539 561830
[EMAIL PROTECTED] 


___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] RE: Re: Math Constants Formal Review - is extensible.

2003-06-14 Thread Joerg Walter

- Original Message -
From: "Daniel Frey" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Saturday, June 14, 2003 9:47 PM
Subject: [boost] RE: Re: Math Constants Formal Review - is extensible.


> On Wed, 11 Jun 2003 15:49:05 +0200, Paul A. Bristow wrote:
>
> > The proposal is for several header files each containing the same
> > constants, only one of which would be used for any compilation. (Users
> > have been warned against using more than one! Nobody has suggested a way
> > to guard against this mistake, but I think that it would be apparent
> > pretty soon, probably at compile time, and at link time if not.)  The
> > macros constants header is the simplest and could be used to provide the
> > appropiate value(s) above.
>
> The difference IMHO is, that this is not a generic approach.

During my last discussion with Paul I realized that math_constants<>
probably isn't the same as numeric_limits<> (nevertheless I'd try to write
them based upon the supplied constants ;-).

> It's a bit
> like replacing templates with macros. I haven't seen any convincing
> arguments against the code I showed, which *is* generic

I like that code.

> IMHO, but as I
> don't have the background of the "long saga" you mentioned, I think I'm
> not the right one to say what's the best way to go.

I'm a bit surprised, that we currently are reviewing some ideas instead of a
library as far as I understood.

Regards,
Joerg


___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


[boost] RE: Re: Math Constants Formal Review - is extensible.

2003-06-14 Thread Daniel Frey
On Wed, 11 Jun 2003 15:49:05 +0200, Paul A. Bristow wrote:

> The proposal is for several header files each containing the same
> constants, only one of which would be used for any compilation. (Users
> have been warned against using more than one! Nobody has suggested a way
> to guard against this mistake, but I think that it would be apparent
> pretty soon, probably at compile time, and at link time if not.)  The
> macros constants header is the simplest and could be used to provide the
> appropiate value(s) above.

The difference IMHO is, that this is not a generic approach. It's a bit
like replacing templates with macros. I haven't seen any convincing
arguments against the code I showed, which *is* generic IMHO, but as I
don't have the background of the "long saga" you mentioned, I think I'm
not the right one to say what's the best way to go.

Regards, Daniel

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


RE: [boost] RE: RE: Math Constants Formal Review - is extensible.

2003-06-10 Thread Paul A. Bristow
Sorry I have misunderstood your wish - for existing constants in different types
rather than new constants in existing types.

Your example is interesting.  I think that providing a Macro value allows this
sort of UDT extensions code (very like Michael Kenniston's examples).

My thesis that 40 decimal digits are enough is because it is enough for all
existing floating point hardware, up to 128 significands.  I believe that anyone
wanting more is likely to be using a separate 'unlimited' precision package
anyway.

There is also an example of a UDT _interval_ - a 128-bit quad_float type, used
by Victor Shoup's NTL package. But it does require using the NTL generator
program to create the exactly representable values.  (See test_quad_float.cpp
example).
I believe that interval constants are an important feature - and quite novel.

Paul

Paul A Bristow, Prizet Farmhouse, Kendal, Cumbria, LA8 8AB  UK
+44 1539 561830   Mobile +44 7714 33 02 04
Mobile mailto:[EMAIL PROTECTED]
mailto:[EMAIL PROTECTED]


| -Original Message-
| From: [EMAIL PROTECTED]
| [mailto:[EMAIL PROTECTED] Behalf Of Daniel Frey
| Sent: Sunday, June 08, 2003 9:54 PM
| To: [EMAIL PROTECTED]
| Subject: [boost] RE: RE: Math Constants Formal Review - is extensible.
|
|
| 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 
| 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()

RE: [boost] Re: RE: Math Constants Formal Review - recap & summary

2003-06-10 Thread Paul A. Bristow


| -Original Message-
| From: [EMAIL PROTECTED]
| [mailto:[EMAIL PROTECTED] Behalf Of Ed Brey
| Sent: Monday, June 09, 2003 2:57 PM
| To: [EMAIL PROTECTED]
| Subject: [boost] Re: RE: Math Constants Formal Review - recap & summary
|
|
| Paul A Bristow wrote:
| > A Mini-recapitulation of the _long_ saga so far:
| >
| > 7  There are dozens of constants that some users rate 'essential'.
| > Splitting into several #include files still risks violating the
| > "don't pay for what you don't use" principle.
|
| > 10 There is evidence that some compilers can generate better code
| > from functions like "double pi() { return 3.1459;}"
| > but that this implies writing pi() instead of plain "long double pi".
| > So the ()s remain a major issue.
|
| These two points are based on observations that compilers don't
| optimally handle constants defined like this:
|
| double const d1 = 1.2;
|
| It would be useful to record exactly which compilers have which
| troubles, so that as compilers improve, constraints can be dropped.
|
| For example, VC 7.1 discards d1 if it is not referenced, so there is
| no issue with paying for what you don't use when using that method on
| that compiler.

This is good news. What optimisation did you chose?

|  It would be useful to know what compilers do retain
| unused constants.

But is tiresome to find out, and will keep changing.  (and if the scheme becomes
widely used, compiler writers will have a strong incentive to make sure it is
optimised away.

| The FAQ entry "Why are functions like double pi() which return
| constants provided?" has a start to the idea of documenting specific
| compiler limitations.  I'd recommend adding this elaboration on VC 7
| (others can help with other compilers):
|
| - Static constants are referenced via a pointer, which leads to
| smaller code if the constant is used more than once, but often to slower code.
|
| (I would take out the blurb about MSVC 7 Standard edition.  Does
| anyone who needs to professional-grade execution speed really buy the
| standard, rather than professional edition?  The professional edition
| inlines properly according to the standard-specified "inline" keyword hint.)

Agreed.  I think this problem looks likely to go away, as I hoped - which is why
I waited until 7.1 before this review.

Paul

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


[boost] Re: RE: Math Constants Formal Review - recap & summary

2003-06-09 Thread Ed Brey
Paul A Bristow wrote:
> A Mini-recapitulation of the _long_ saga so far:
> 
> 7  There are dozens of constants that some users rate 'essential'.
> Splitting into several #include files still risks violating the
> "don't pay for what you don't use" principle.

> 10 There is evidence that some compilers can generate better code
> from functions like "double pi() { return 3.1459;}"
> but that this implies writing pi() instead of plain "long double pi".
> So the ()s remain a major issue.

These two points are based on observations that compilers don't optimally handle 
constants defined like this:

double const d1 = 1.2;

It would be useful to record exactly which compilers have which troubles, so that as 
compilers improve, constraints can be dropped.

For example, VC 7.1 discards d1 if it is not referenced, so there is no issue with 
paying for what you don't use when using that method on that compiler.  It would be 
useful to know what compilers do retain unused constants.

The FAQ entry "Why are functions like double pi() which return constants provided?" 
has a start to the idea of documenting specific compiler limitations.  I'd recommend 
adding this elaboration on VC 7 (others can help with other compilers):

- Static constants are referenced via a pointer, which leads to smaller code if the 
constant is used more than once, but often to slower code.

(I would take out the blurb about MSVC 7 Standard edition.  Does anyone who needs to 
professional-grade execution speed really buy the standard, rather than professional 
edition?  The professional edition inlines properly according to the 
standard-specified "inline" keyword hint.)


___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


[boost] RE: RE: Math Constants Formal Review - is extensible.

2003-06-08 Thread Daniel Frey
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 
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<>