[cairo] Re: [Librsvg-devel] Porting librsvg to an Embedded Platform

Bill Spitzak spitzak at d2.com
Thu Oct 5 11:37:36 PDT 2006

Carl Worth wrote:

> * Use a much faster method for converting floating-point to
>   fixed-point, (taking advantage of IEEE floating-point representation
>   when possible). There are patches that have been proposed to do
>   this, but none of them yet have the configure-time checks to ensure
>   that the method can reliably be used. There is also some open
>   discussion about which rounding mode we want, but I'm guessing it
>   really won't matter down at the level of the fixed-point sub-pixel
>   grid.

Attached is a fast_rint function that work with GCC 4.0 with full 
optimizations, and with the Intel and Windows compilers. I also attached 
what I believe are converters to 16.16 and 24.8, but these are not tested.

These work by adding a large enough constant that the interesting 
portion of the number is shifted right to a fixed location in the low 
half of the double. The actual rounding these functions do depends on 
the current setting of the floating point processor. It matches, except 
toward-zero will end up acting like floor (due to the large positive 
number added).

It is possible to check for overflow by asserting that the "hi" field 
has the right value after the addition. This value is a constant for 
each of these, sorry I don't know what it is.

Since these conversions involve adding a large positive number, it would 
be possible to merge this into the matrix multiplication by putting the 
constant into the xy offsets, as though a translation is always being 
done to this very large xy location.

// Attached code is released into the public domain by the author, Bill 
// Spitzak. Code may be used for any purpose.
// Warning: we assume long is a 32 bit and double is 64 bit IEEE!

union Double_Long {
   double v;
#if __BIG_ENDIAN__
   long hi, low;
   long low, hi;
   long long big;

/*! Fast version of (int)rint().
    Works for -2147483648.5 .. 2147483647.49975574019
inline long fast_rint(double val) {
   Double_Long v; v.v = val + 68719476736.0*65536.0*1.5;
   return v.low;

/*! Fast converter to 24.8 representation.
     Works for -8388608.00195 to 8388607.99805
inline long fast_24_8(double val) {
   Double_Long v; v.v = val + (68719476736.0*256.0*1.5);
   return v.low;

/*! Fast converter to 16.16 representation.
    Works for -32768.0000076 to 32767.9999924
inline long fast_16_16(double val) {
   Double_Long v; v.v = val + (68719476736.0*1.5);
   return v.low;

More information about the cairo mailing list