Boost logo

Boost :

From: Guillaume Melquiond (gmelquio_at_[hidden])
Date: 2003-05-05 04:19:09


On Mon, 5 May 2003, [iso-8859-1] Terje Slettebø wrote:

> As was said in another posting: And now for something completely different.
>
> The Interval library, which has recently been accepted into Boost, has been
> mentioned regarding the discussion of an SI units/quantity library. I've
> read the docs for this, and it appears that no special support is needed to
> use this with a quantity library, provided the library may use any type as
> the underlying type. In that case, you can just use interval<T> rather than
> T, and you can use it with interval arithmetic.
>
> Interval arithmetic is useful to specify precision, and other cases where
> you're dealing with an interval.
>
> When it comes to the output operator, it displays an interval in the form
> "[<lower>, <upper>]". This is fine as a general output. However, if the

As I explained in a previous mail, interval/io.hpp is only here as a
debugging tool, it is not included by interval.hpp, and each user should
define its own versions of >> and <<. As I suggested before, I am even
ready to suppress this file if it could clear any misunderstanding on its
purpose.

> interval is used to determine precision, it may be more useful to print the
> value, with the number of significant digits, instead. For example:
>
> std::cout << interval<double>(1.231, 1.233); // Prints "1.23"
>
> std::cout << interval<double>(1.2345678911, 1.2345678913); // Prints
> "1.234567891"

It is a nice idea and could probably be useful in some particular
situations.

> Below is an ouput operator which works like this, and an example program
> with output after it.
>
> --- Start ---
>
> #include <boost/interval.hpp>
> #include <boost/io/ios_state.hpp>
> #include <cmath>
>
> namespace boost {
>
> template<class T, class CharType, class CharTraits>
> std::basic_ostream<CharType, CharTraits> &operator<<
> (std::basic_ostream<CharType, CharTraits> &stream, const interval<T>
> &value)
> {
> const T abs_lower=value.lower()>=0 ? value.lower() : -value.lower();
> const T abs_upper=value.upper()>=0 ? value.upper() : -value.upper();
> const T lower_mantissa=value.lower()/std::pow(10,
> static_cast<int>(std::log10(abs_lower)));
> const T upper_mantissa=value.upper()/std::pow(10,
> static_cast<int>(std::log10(abs_upper)));
>
> const T difference=upper_mantissa-lower_mantissa;
>
> const double exponent=std::log10(difference);
>
> boost::io::ios_precision_saver state(stream,-exponent+1);
>
> return stream << (value.upper()+value.lower())/2;
> }
>
> } // namespace boost
>
> // Test program
>
> #include <iostream>
> #include <iomanip>
>
> int main()
> {
> std::cout << std::setprecision(std::numeric_limits<double>::digits10)
> << 1.0/3.0 << '\n'
> << '\n'
> << boost::interval<double>(1.231,1.233) << '\n'
> << boost::interval<double>(-1.233,-1.231) << '\n'
> << boost::interval<double>(1.231e100,1.233e100) << '\n'
> << boost::interval<double>(-1.233e100,-1.231e100) << '\n'
> << '\n'
> << boost::interval<double>(1.2345678911,1.2345678913) << '\n'
> << boost::interval<double>(-1.2345678913,-1.2345678911) << '\n'
> << boost::interval<double>(1.2345678911e100,1.2345678913e100) <<
> '\n'
> << boost::interval<double>(-1.2345678913e100,-1.2345678911e100)
> << '\n';
> }
>
> --- End ---

I have some comments to do about this code. First, the interval library
don't lie anymore in the boost directory, it is in boost/numeric. And
similarly, the class is in the namespace boost::numeric. Maybe you are
using the old version, the one that was in the boost sandbox? This version
is no longer maintained (and furthermore, it is no more in the sandbox).

Next, the signature of the operator should be changed to deal with
interval policies (only the definition need to be changed, the code can
stay as it is):

  template<class T, class Policies, class CharType, class CharTraits>
  std::basic_ostream<CharType, CharTraits> &operator<<
    (std::basic_ostream<CharType, CharTraits> &stream,
     const interval<T, Policies> &value)

Another point: your operator expects the two bounds of the interval to be
of the same sign. If the interval contains 0, the answer won't have a lot
of meaning. Moreover, if one of the bounds is 0, the behavior probably
is undefined.

Finally, there might be a lot of problems with respect to rounding policy.
But I don't really want to speak about them: it is kind of an internal
problem to the library and it would be important only if the users expect
the operators >> and << to behave like the arithmetic operators.

> Output:
>
> 0.333333333333333
>
> 1.23
> -1.23
> 1.23e+100
> -1.23e+100
>
> 1.234567891
> -1.234567891
> 1.234567891e+100
> -1.234567891e+100
>
> Could this be a useful addition to the Interval library?

Yes, it could be. But I am not sure if it is an useful addition to the
headers part, or if it should rather go to the examples part.

> Since there is an output operator in boost/interval/io.hpp, this might be
> called boost/interval/io_precision.hpp.

Supposing it goes to the headers part, I would better create an
interval/io directory and put all the io schemes inside. So the file would
become interval/io/precision.hpp. However, the name "precision" does not
ring any bell to me; am I the only one or should a more explicit name be
found?

> An input operator, working in the same way - determining the interval from
> the number of digits given - might also be provided. It might for example be
> written using Spirit to parse the number.
>
>
> Regards,
>
> Terje

Regards,

Guillaume


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