Re: Implementing a templated "round" function?

From: Jef Driesen (jefdriesen_at_nospam.hotmail.com)
Date: 09/30/04


Date: Thu, 30 Sep 2004 12:24:24 +0200


"Siemel Naran" <SiemelNaran@REMOVE.att.net> wrote in message
news:CSP6d.458905$OB3.112056@bgtnsc05-news.ops.worldnet.att.net...
> "Jef Driesen" <jefdriesen@nospam.hotmail.com> wrote in message
> news:cjgg07$cvj$1@ikaria.belnet.be...
>
> > I need to implement a function to implement the rounding of floating
point
> > values. At the moment i have two different implementations, depending on
> the
> > type of the return value (integer or double).
> >
> > // Integer calculation (fast)
> > int iround(const double x) {
> > return (x>=0 ? static_cast<int>(x + 0.5) : static_cast<int>(x + 0.5)
> > }
> > // Floating point calculation (slow)
> > double dround(const double x) {
> > return (x>=0 ? floor(x + 0.5) : ceil(x + 0.5)
> > }
>
> The first function looks suspect because it loses precision.

IIRC the floating point representation of integer numbers is exact. If you
are talking about a possible under/overflow in the conversion from double to
int, you are correct. In the final code I will probably add code to prevent
under/overflows:

   const R minimum = std::numeric_limits<int>::min();
   const R maximum = std::numeric_limits<int>::max();
   if (x < minimum)
      return minimum;
   else if (x > maximum)
      return maximum;

> Anyway, if the true and false clauses of operator ? are the same,
> you can avoid the comparison.

This is a typo. The last "+0.5" should become "-0.5" in both functions.

> Anyway, have you measured the time difference?

Yes I did and dround is (1.89 times) faster than iround, unless I
static_cast the result of dround to int (factor 0.73).

>
> > But then I have 2 different functions for the same functionality. To
solve
> > this, I created a template function with 2 specialisations:
> >
> > template <typename T> T round(const double x);
> > template <>
> > int round(const double x) {
> > return iround(x);
> > }
>
> Should that be
>
> template <>
> int round<int>(const double x) {

Another typo. But it don't think my syntax was incorrect.

> > template <>
> > double round<double>(const double x) {
> > return dround(x);
> > }
> >
> > I can add specialisations for the other data types (float, long, short,
> > char, signed/unsigned,...) as well. I did not add a 'default'
> > specialisation, because the round function is only usefull for numeric
> > types. At this time my function accepts only double precision floating
> point
> > values, and I would like to have equivalent functions for float, double
> and
> > long double. I did add a second template parameter S for the source
type:
> >
> > template <typename T, typename S>
> > T round(const S x) {
> > ...
> > }
> >
> > The problem is now how do I implement this function?
> >
> > I could add a specialisation for every combination of S and T, but this
is
> a
> > lot of work, and there are only 4 usefull implementations possible:
> > - S and T are floating point type -> implementation using floor/ceil
> > (dround)
> > - S is a floating point type and T an integer type -> implementation
using
> > static_cast (iround)
> > - S is an integer type and T is an integer or floating point type ->
> simply
> > static_cast to T
> > - otherwise no implementation is necessary (should not compile if this
is
> > possible, to prevent e.g. round<double>(std::complex) )
> >
> > I was thinking of using only one 'default' specialisation and using
> > std::numeric_limits:
> >
> > template <typename T, typename S>
> > T round(const S x)
> > {
> > if (std::numeric_limits<S>::is_integer)
> > // Integer type needs no rounding.
> > return static_cast<T>(x);
> >
> > // Find rounding error.
> > const S round_error = std::numeric_limits<S>::round_error();
> >
> > if (std::numeric_limits<T>::is_integer) {
> > // Integer calculation (fastest).
> > return (x>=0 ? static_cast<T>(x + round_error) : static_cast<T>(x
+
> > round_error)
> > } else {
> > // Floating point calculation (slower).
> > return (x>=0 ? floor(x + round_error) : ceil(x + round_error)
> > }
> > }
> >
> > But this will results in a performance degradation if the compiler is
> unable
> > to optimize (eliminate) the 'if' statements. And the function has also
an
> > implementation for data types other then integer and floating point
types.
> > Any advice on this problem?
>
> It's worthwhile to check the assembly to see if your compiler does the
> optimization.

MSVC7.1 does the optimization. I don't know about other compilers.

> Anyway, you can put the numeric_limits::is_integer into the function or
> class template argument list. Here is the idea:
>
> template <typename T, typename S>
> inline
> T round(const S x) {
> return generic_round<T, S,T::is_integer>(x);
> }
>
> template <typename T, typename S, bool is_integer>
> inline
> T generic_round(const S x);
>
> template <typename T, typename S>
> inline
> T generic_round<T,S,true>(const S x) {
> const S round_error = std::numeric_limits<S>::round_error();
> return T(x + round_error);
> }
>
> etc
>

Looks interesting to me.



Relevant Pages

  • Re: IIR Filter Realizations
    ... This works very well for DF1 as rb-j suggests. ... floating point implementations do not benefit from the DF1 structure. ... Most floating point implementations use DF2 or DF2 transpose. ...
    (comp.dsp)
  • Re: double money
    ... Floating point types can use *any* integer base greater or equal to two. ... intention to implement decimal floating point in hardware. ... but not in standard C implementations (and without hardware ... Dan Pop ...
    (comp.lang.c)
  • Re: Fixed vs Float ?
    ... I think that the added complexity of floating point in an FPGA will ... Fixed point implementations are often better than floating point ... filter structure that takes advantage of the long result. ... floating-point computations can be just as fast as fixed-point. ...
    (comp.arch.fpga)
  • Re: Floating point multiplication on Spartan3 device
    ... I apologize that my question was not clean. ... Both of floating and fixed point implementations are allowed. ...
    (comp.arch.fpga)
  • Re: inline objects <-> floating objects
    ... I'm using Word 2000 terminology re inline vs floating. ... status of the wrapping style of all the graphics objects, ... -- floating objects are a disaster when it comes to captions (and the table ...
    (microsoft.public.word.drawing.graphics)