Boost logo

Boost :

From: Daniel Spangenberg (dsp_at_[hidden])
Date: 2003-07-22 03:33:44


Hello Boosters!

Some time ago, I developed three class templates emulating some
Fortran90 features, known
as SELECTED_REAL_KIND and SELECTED_INT_KIND. For those who don't know
about Fortran90 "kind" values: In C++ they correspond to a "type-value"
mapping.

In short the template class declarations are:

template <int Precision, int Range = -1>
class selected_real;

Precision: Minimum number of decimal digits, this real type should
provide.
It corresponds to std::numeric_limits<real_type>::digits10.

Range: Minimum decimal exponent range, this real type should provide.
The definition of Range corresponds to
min(abs(std::numeric_limits<real_type>::min_exponent10),
abs(std::numeric_limits<real_type>::max_exponent10))

The default template parameter effectively means, that the type
selection does not depend on this
criterium.

template <int Range>
class selected_int;

Range: Minimum **decimal** exponent range, so that the integer data type
is capable of representing
all values n in the range of values -10^R < n < 10^R

template <int Range>
class selected_uint;
(This is a personal extension compared to Fortran90)

Range: Minimum **decimal** exponent range, so that the integer data type
is capable of representing
all values n in the range of values 0 <= n < 10^R

Example of usage:

#include <iostream>
#include <typeinfo>

#include "selected_types.hpp"

int main()
{
  using namespace std;
  using namespace boost;

  // Ask for a floating-point variable which provides at least a
precision of
  // 6 decimal digits and an exponent range between -10^3000 - 10^3000:
  typedef selected_real<60, 3000> MyReal;

  // Ask for a floating-point variable which provides at least a
precision of
  // 3 decimal digits:
  typedef selected_real<3> MyReal_2;

  // Ask for a floating-point variable which provides at least an
exponent range
  // between -10^400 - 10^400:
  typedef selected_real<-1, 400> MyReal_3;

  typedef selected_int<9> MyInt;
  typedef selected_uint<10> MyUInt;

  BOOST_STATIC_ASSERT(MyReal::is_provided); // Most systems will choke
here,
 // because the compiler can not provide this type

  // MyReal::type aReal; // Should not compile on most systems
  MyInt::type aInt; // Should be OK
  // MyUInt::type aUInt; // Might not compile, because the compiler
can't provide
                      // such an unsigned integer type.

  cout << "My selected real has kind value " << int(MyReal::kind) <<
          " and type <" << typeid(MyReal::type).name() << '>' << endl;

  cout << "Effective decimal precision: " << MyReal::precision << endl;
  cout << "Effective decimal range: " << MyReal::range << endl;

  cout << "My selected int has kind value " << int(MyInt::kind) <<
          " and type <" << typeid(MyInt::type).name() << '>' << endl;

  cout << "Effective decimal range: " << MyInt::range << endl;

  cout << "My selected uint has kind value " << int(MyUInt::kind) <<
          " and type <" << typeid(MyUInt::type).name() << '>' << endl;

  cout << "Effective decimal range: " << MyUInt::range << endl;

  return 0;
}

As you see, these classes have some similarities to the templates
provided by
boost/integer.hpp. There are some fundamental differences, yet:

1) Typedefs are compilable, even if the demanded type is not available
(This
corresponds to Fortran and might not be C++'ish), but the compiler
should choke
on any declaration of such a type. This is easy to change, if necessary.

2) The current implementation even provides the Fortran'esque "kind"
values (
implementation defined integer values describing the actual type), which
are most
probably useless for C++ (Since we can directly get types). But they
also provide
further information:
     -1 if the precision is not available
     -2 if the exponent range is not available
     -3 if neither is available
The kind value is guaranteed to be non-negative, if all requirements are
fullfilled

3) The point of view is momentarily decimal orientated, but this is not
a necessary
constraint.
It is easy to provide similar characteristics as integer.hpp provides
(possibly minimum
constraints on the precision and range based on radix, or exact bit
constraints like
32 bit, 64 bit, 80 bit, or 128 bit floating point types)

4) If you think that the selected_int and selected_uint class templates
are redundant
because of the capabilities that are provided by the class templates
inside boost/integer.hpp,
I think, that at least selected_real could be a base for the missing
"boost/floating_point.hpp"
header. If you like, I would prepare an implementation even for that.

Before I invest more time in a reviewable implementation (The version I
have needs
perhabs one day), I would like to hear your general opinion.

Thanks,

Daniel Spangenberg


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