Boost logo

Boost :

From: Ed Brey (edbrey_at_[hidden])
Date: 2001-10-22 16:43:39


From: "Paul A. Bristow" <boost_at_[hidden]>
> >
> > The current version in the vault has several files
> > (float_constants.h, double_constants.h, long_constants.h) that
> > each define identical names in the global namespace. This is
> > certainly not acceptable for a boost library. Now, if the
> > objective is just to show that the constants can be partitioned
> > into multiple headers, that is fine. However, one should never
> > count on the user just including only one of multiple headers,
> > since any given library may include any given header in a .hpp
> > file (perhaps because a constant is needed in inlined code).
>
> I naively envisaged that only one would be #included.
> Are you suggesting instead naming them piF, pi and piL?
> (This could be done quite easily - but it fixes the float size in user code,
> and I wonder if this is a good idea?).

Providing different names is a good idea, but as you point out, making the names unique by mangling fixes the size in the user code. A more flexable method is to make the names unique by qualification. Names would look like this float_constants::pi, double_constants::pi, etc. End user (non-library) code would tend to look like this:

// implementation.cpp:
#include <boost/math/constants.hpp>
using namespace boost::math::double_constants;
double my_function() {return pi;}
float my_little_function() {
    // Override default for this translation unit.
    return boost::math::float_constants::pi;
}

Library code would look like this, taking advantage of the fact that it has its own namespace:

// library_config.hpp:
#include <boost/math/constants.hpp>
namespace lib {
    using namespace boost::math::double_constants;
}

// library_header.hpp:
#include "library_config.hpp"
namespace lib {
    inline double my_inlined_function() {return pi;}
}

// library_implementation.cpp:
#include "library_header.hpp"
namespace lib {
    double my_function() {return 2 * pi * my_inlined_function();}
}

The using directives can also be used in individual functions or specific constants can be typedefed into a particular class. These patterns are valuable for programs that make light usage of the constants.

The above assumes it is OK to pull all constants into the current namespace. If this is not OK for a particular program, specific using declarations would be used instead.

> > What didn't make sense is why the compiler would generate code
> > for unused constant classes. Fortunately is that the answer is
> > due to a simple (arguable) bug in the library. The constant
> > class has a superfluous constructor. If you remove the
> > constructor, then the compiler generates code only for what is
> > used, and optimally efficient code at that. ("The compiler" here
> > is VC6.) If there was ever a poster child for not littering
> > classes with do-nothing constructors, this is it.
>
> I don't understood you here.
>
> Removing the constructor thus doesn't compile.
>
> namespace float_constants
> {
> // constant<pi_tag, float> const pi;
> }
> namespace double_constants
> {
> // constant<pi_tag, double> const pi;
> }
> namespace long_double_constants
> {
> // constant<pi_tag, long double> const pi;
> }

These aren't constructors, but rather variable definitions. The constructor is boost::math::constant::constant. The line to remove is:
  constant() {} // Returns the value of the constant.

> > It seems that there is good potential for providing a simple,
> > single interface to regular end users: just use
> > boost::math::double_constants::pi.
>
> Users will not take kindly (ie won't use it!!) to having to write
>
> area = boost::math::double_constants::pi * r * r;
>
> but writing using boost::math::double_constants;
>
> allows
>
> area = pi * r * r;

I complete agree. My point wasn't that they'd use the fully qualified forms, just that the contents of function_constants.hpp is all that's needed.

> > I don't really have the background to know what values are
> > appropriate. My only view would be to stick to primitives,
> > avoiding pi/2 syndrome, since I'm afraid the pollution vs. value
> > curve will likely not have a knee.
>
> 2. * pi and p /2. are special in that there is no loss of accuracy,
> 3/2 * pi may lose accuracy.
> I hope the cost of completeness is small enough for some like this.

Perhaps. I don't know how to begin determining what "complete" is, much less the cost of completeness. If we can come up with systemic reasoning why one constant, say 3/2*pi should be included but another, say 3/4*pi, should not, we have something to evaluate. If it comes down to just guessing, I'd say that the accuracy gained by precomputing the constant has better be pretty significant.

Personally, I'd start from the accuracy standpoint. It is clearly more accurate to provide precomputed constants. But will it ever be more than an extremely rare case when it makes a meaningful difference in the end result?

> > I think that having the user copy and paste values is
> > unacceptable except in cases where a user needs extremely high
> > precision and they are pasting a value out of a book or
> > generation output for a constant not provided by Boost. All
> > constants provided by Boost should be placed in a single
> > ready-to-go header.
>
> Ideally I agree with this,
> but it must not cost - hence the simple float, double, log files.

I agree that the template method only makes sense if it costs the same or less than simple constants. Try out function_constants without the construct or your platform(s) and let me know what you find.

> > Finally, the static copyright variable needs to go. Personally,
> > I would like to see the generated .hpp file placed into the
> > public domain. The generator, of course, would remain copyrighted.
>
> I am happy for it all to go into the public domain with Boost's
> choice of licence terms.

My understanding is that public domain means there are no licensing terms.


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