This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Signed division with rounding towards -infinity (and floating point rounding)


Tim Prince wrote:
> Christopher Key wrote:
>
>   
>> I have some code that needs to perform signed division by a power of two
>> with rounding towards minus infinity, i.e. it requires an arithmetic
>> right shift.  Now in the C specification, right shifting a signed
>> integer is implementation defined. 
>>     
> Because C may be compiled for ints other than 2's complement.  Perhaps
> you could use pre-processing to specialize for 2's complement for most
> of your targets.
>   
Indeed so.  It's presumably quite simple to implement a preprocessor
macro to detect whether the target system is 2's complement or not. 
Does this guarantee however that a right shift on a signed value will be
implemented as a arithmetic shift?
>   
>> On a similar point, is there a good way get floats rounded to the
>> nearest integer value rather than truncated.  The following give the
>> correct rounding behaviour (I'm only interested in +ve values),
>>
>> x = (int) (f + 0.5)
>>
>>     
> I don't see how this is similar, unless you are harking back to the
> early days of BASIC when there were 2's complement floating point
> implementations.  IEEE standards ruled that out over 20 years ago.  Even
> among those 2's complement implementations which did exist, the results
> varied for -1. < f < -.5.  If you use this only for positive f, the case
>  for which most people would consider this wrong is where f takes odd
> integral values, so your code will increment the result.  But you said
> this is OK, so where is the problem?
>
> Why not use the lrint() and related C intrinsics?
>   
Sorry, perhaps didn't make myself clear.

In both case, I want behaviour that can expressed very tersely in
assembler, but not equivalently so in c.  What I was wanting to write is
code that will do as intended under any c(99) implementation, but that
gcc can see as being equivalent to its terse assembler implementation.

The first case is slightly different in that I can express what I want
(i.e. y = x>>d) and have it compile to suitable assembler, but the code
isn't guaranteed to behave as desired on an arbitrary compiler.

using rint() is an alternative, although I was put off for one reason. 
As this is library code, I don't want to change the global execution
state (is this the correct term) without restoring it afterwards, and I
didn't really want to add fegetround() and fesetround() wrappers around
various bits of code.

Regards,

Chris


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]