Re: [AD] Borland C++ compilation errors

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


"Eric Botcazou" <ebotcazou@xxxxxxxxxx> writes:

[skipped]
> 
> This gives fceil(0x7FFF0001) = 0x8000, which is inconsistent with the x86
> asm versions and the previous behaviour.

This one should have familiar behaviour:

int
fceil (long v)
{
  if (v > 0x7FFF0000) {
    *allegro_errno = ERANGE;
    return 0x7FFF;
  }
  else if (v < 0)
    return -(int) ((unsigned long) -v >> 16);
  else
    return (int) (((unsigned long) v + 0xFFFF) >> 16);
}

The one below is independent from sizeof(long), or it can be done by
comparing with (long) (((~(unsigned long) 0) >> 1) & ~0xFFFF)

int
fceil (long v)
{
  long t = v + 0xFFFF;
  if ((v > 0) && (t < 0)) {
    *allegro_errno = ERANGE;
    return (int) ((unsigned long) v >> 16); /* or 0x7FFF?  */
  }
  else if (v < 0)
    return -(int) ((unsigned long) -v >> 16);
  else
    return (int) (((unsigned long) t) >> 16);
}

[skipped]
> 
> Ouch !
> Why wouldn't my previous proposal work ? According to my references, it is
> legal to do shifting on signed integers and the vacants bits are always
> filled with zeros for positive ones.

It may not work on computers where negative numbers are made by simply
inverting most significant bit, for example

-0x00010001 -> 0x80010001 -> (~) -> 0x7FFEFFFE -> (>>16) ->
 -> 0x00007FFE -> (~) -> 0xFFFF8001 -> -0x7FFF8001 != -2


I use casts to (int) to shut up overcautious compilers.  IMHO, cast to
(unsigned long) before shifting makes sure that it is simply bitshift
with zero filling (though compilers might have their own ideas).

-- 
Michael Bukin



Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/