# [PATCH wayland 4/5] Add support for signed 24.8 decimal numbers

Bill Spitzak spitzak at gmail.com
Wed May 2 08:30:26 PDT 2012

```On 05/02/2012 04:57 AM, Pekka Paalanen wrote:
> On Tue,  1 May 2012 20:30:15 +0100
> Daniel Stone<daniel at fooishbar.org>  wrote:

>> +			u = trunc(d);
>> +			*p = u<<  8;
>> +			*p |= (uint32_t) (trunc((fabs(d - u)) * (1<<  8)))&  0xff;
>
> Hmm, any reason for not doing this instead?
> 	*p = (int32_t)trunc(d * 256.0)

The sample code certainly looks wrong, especially if d is negative.

It is also much faster to just calculate the integer in floating point
and then do the conversion to int. On most processors this will also
translate out-of-range to max/min int.

> Also, any rationale in choosing trunc() instead of round() or
> ceil/floor?

I would use floor() for all graphics. Otherwise you get weird behavior
when the locations of things goes negative, because they will often
shift by 1 pixel over. Another way to look at it is that if you drew 50%
on the pixel identified by f/2 for all integers, you expect every pixel
to be drawn twice. This will happen if the pixel is floor(f/2). But if
trunc(f/2) is done pixel '0' is drawn 3 times.

The main reason you will often see shift in graphics code is because of
the desire for floor(). "i>>1" will divide by 2 but turns -3 into -2.

Of course it is an unfortunate historical accident that floating point
was designed to compile 1950's Fortran where modulus arithmetic was not
used. Otherwise I'm sure rounding would be done by floor and a%b would
have the sign of b, not a.

PS: there are also well-known tricks for converting from float->24.8
that avoid the slow fpu converter. This involves multiplying a double by
a large enough constant that all values in range have the same exponent
and the lower 32 bits are equal to the desired integer. You can check
the upper 32 bits to see if they are the correct value to detect
out-of-range. I'm not sure if these are faster on modern processors
however, and it is difficult to control the rounding.
```