|
Boost : |
From: Daniel Frey (d.frey_at_[hidden])
Date: 2003-10-17 16:11:41
Hi Boosters,
during the last weeks I developed a framework to represent
constants. Due to my lack of time, I haven't had the time to work on
all the details and ideas that might be important, but Paul Bristow
kindly reminded me that something should be shown "Real Soon Now" :)
Also, I was trying to make this a CUJ article, but since they ignore
me for two months now, I'll no longer wait for them...
As I agree that it's better to have something than to have nothing at
all, I would like to ask for comments, help, discussion etc. with the code
I have. The code can be found in the files section, here's a link:
<http://groups.yahoo.com/group/boost/files/MathConstants/>
Current features include:
- Separation of framework and constants
The framework to provide and handle constants is separated from the
definition of constants itself. The definition is reduced to a
straight forward and easy syntax. One framework can be used for
different sets of constants, e.g. mathematical constants, physical
constants, etc.
- No brackets for constants
A constant is accessed as 'pi', not 'pi()'.
- Explicit type selection
You can use static_cast to convert a constant to a given type. Nice
for generic programming.
- Implicit type selection
Combining a constant with a non-constant automatically converts the
constant to the non-constant's type. Should IMHO match most people's
expectations. Example: 'pi * 2.' selects the 'double'-version of
'pi'. Also works for other uses like 'double d = pi;'.
- Composed constants
You can define 'pi * pi' as a single constant. The user needn't
remember a special naming convention for it like 'pi2', 'pi_squared'
or 'squared_pi'. No run-time multiplication of loss of precision
involved. One drawback: 'srqt( two )' is required instead of
'sqrt( 2 )' as 2 is always of type integer, not constant<...>, so it
cannot be detected as a constant.
- On demand extension for composed constants
If you need special constants that are not predefined by the
library, you can add them without touching the library itself. As
this is an optimization, it's invisible from the outside and you can
ignore it during development. Well, you do need to use an indirect
include, though. (More on that later...)
- Lazy type selection
const double d = 1.;
const double d2 = sqrt( pi ) * d;
In this example, sqrt( pi ) is either a composed constant or it's
type is selected by 'd'. Works for complex expressions like
const double d = sqrt( sqrt( pi + pi ) / pi );
- Few operators
Unlike several other frameworks, no operators or function overloads
are define pre-constant. Should help to keep the compiler in trim :)
- No required pessimisations
The framework itself allows compilers to produce code which is as
good as hand-written code. Of course, not all compilers make use of
these opportunities. I tested the GCC and the Intel compiler, the
latter can produce optimal code, the former has some problems,
though. Last tested: GCC 3.3, maybe this has improved since, further
testing is definitly needed. To be fair, I should also mention that
Paul Bristow tried the run the code through the VC++, which
failed. The code seems to be a bit challanging, but I haven't given
up hope. If you can make it work for the VC++, please let me know :)
OK, so much for the advertising section. The code I placed in the
files section is a single source which contains everything needed and
doesn't require boost. I hope this is convenient for everybody. I
called it M1 for Milestone 1 as I think it will need more work before
a formal review can be approached. My personal roadmap is only a quick
hack and comments on it are appreciated - as are comments on the code
itself :)
M1: See if anyone's interested :)
Get comments about big picture issues
M2: Support VC++ if possible
More features as needed
M3: Stabilize the code, start boostification
Add mathematical constants as separate part (Paul, would you mind
or even like doing this? :)
Add preliminary documentation
Benchmarks?
M4: Complete documentation, ask for formal review
Each milestone might have several versions. No time shedule is given
since this is only a hobby and my time is very limited, so I try not
to promise anything I can't keep. If you would like to speed things
up, just start helping me :o)
Some ideas I had which are not yet included in the code:
- Generic types
Today, adding a new type means you have to provide all variables
for the new type. As a default, I think it might make sense to
provide a function which can either convert this type from another
type if the precision and efficiency is sufficient (should actually
be easy), or we could provide a special function which returns a
string with the requested length which in turn can be used to
initialized the new type's constant. See the code with the
Roguewave-type as a example for a type where this would make
sense. Algorithms to provide 'pi' with the required precision are
usually available, although it's a lot of work :)
- Better syntax through a language extension
This is probably unrealistic, but why can't I overload functions on
integral constant expressions? sqrt(2) reads so much nicer than
sqrt(two). The syntax for these overloads could look like this:
template< int I > result_type sqrt( int I ) { /* I is an ICE here */ }
template<> result_type sqrt( int 2 ) { /* Specialization for I=2 */ }
result_type sqrt( int i ) { /* only used for non-ICEs */ }
OK, this is probably not important for now, just an idea. It could
even be used for other things but that should be discussed
separately if there is interest.
Regards, Daniel
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk