Skip to content

October 31, 2007

2

Fixed point math in pure CPP

NOTE
This post has been previously published on 2007/Oct/31: due to my move to another server i’m now in the process to manually recover the comments for this article.
Fixed!

Some time ago i was asked to publish my implementation of fixed-point math, mainly regarding embedded architectures where IEEE floating point computations have really bad performances. What i want to give you here is a pure-c++, template-based implementation of a fixed-point datatype: this thing is more of a test in order to see how much an object-oriented implementation can perform, being in contrast to a more traditional implementation. As expected, operator overloading and temporary object creation overhead are the main issues with a full-oo implementation as this one, anyway, its a damn nice way to exercise yourself in writing c++ policy-based templated code ;)


Big thank you goes to Kurt for having a great discussion with me on c++, math and for recommending me the most wonderful book on computer arithmetic as Hacker’s Delight delivers it in spades!
Back to the fp stuff: usage of this code in testing environments is advised, since it could contain rounding errors and sometimes explicit casts are needed to get it to work correctly; as i said, this was some sort of test, i abandoned the O-O idea when i ack the performances’ gap between OO vs. traditional implementation was remarkable (at least on embedded devices).
Before showing some usage guidelines, i should say that using this datatype on a desktop machine hasn’t much sense: nowadays floating-point math is faster than the integer’s one!
The class itself predefines a 24.8 and a 16.16:

typedef AquaFixed< 8, LowPrecision,  LowPrecision> fixed8_t;
typedef AquaFixed<16, HighPrecision, HighPrecision> fixed16_t;

An usage example could be a generic, datatype-unaware Matrix implementation as this one:

template<class Number>
class matrix {
private:
Number m[4][4];
public:
matrix();

// matrix indexing
inline Number&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; operator()(const int,const int);

// matrix operations
matrix<Number> operator*(const matrix<Number>);
matrix<Number> operator/(const matrix<Number>);
};

Doing it this way, you should be able to declare a Matrix as here and perform your own tests:

matrix<float_t> float_matrix;
matrix<fixed16_t> fixed_matrix;

NOTE! The AquaFixed class comes out straight from my framework, so you’ll have to define basic datatypes such as int32_t/int64_t for yourself, but that shouldn’t be a problem.

Get the code here and let me know of your tests!

Read more from c++, dev
2 Comments Post a comment
  1. Dec 3 2007

    I am the “Kurt” referenced in the article. My experience is that fixed-point costs about 15% more than integer math, and is about twice as fast as floating point math on Intel Pentium-4 processors, and using Microsoft visual c++ versions from 6 to .Net-2005.

    In evaluating the performance of fixed point arithmetic routines, it is important to compile a “release” build. On debug builds, the compiler creates function calls for all your template functions. Function call overhead eats the performance gains from using fixed point.

  2. Manuel
    Dec 5 2007

    Thank you for your feedback Kurt: i performed various test at the time on a desktop machine, obviously with a release build, but on a Pentium D i didn’t notice improvements at all, floating point was showily faster than anything else.
    It may be possible that my tests weren’t exhaustive as they should, i used a matrix-based test and a 3d rasterizer: both tests showed up big fixed point improvements on mobile platforms but none on the desktop.
    I’ll try to search my old tests, too bad i don’t think i still have what i used at the time..
    Have you played with compiling/linking options and stuff like that?

Share your thoughts, post a comment.

(required)
(required)

Note: HTML is allowed. Your email address will never be published.

Subscribe to comments