This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: PowerPC floating point little-endian [4 of 15]
- From: Alan Modra <amodra at gmail dot com>
- To: Adhemerval Zanella <azanella at linux dot vnet dot ibm dot com>
- Cc: libc-alpha at sourceware dot org
- Date: Thu, 3 Oct 2013 16:58:00 +0930
- Subject: Re: PowerPC floating point little-endian [4 of 15]
- Authentication-results: sourceware.org; auth=none
- References: <20130710012435 dot GN2602 at bubble dot grove dot modra dot org> <20130710012622 dot GQ2602 at bubble dot grove dot modra dot org> <20130809044210 dot GU3294 at bubble dot grove dot modra dot org> <524C2AE9 dot 1030809 at linux dot vnet dot ibm dot com>
On Wed, Oct 02, 2013 at 11:17:13AM -0300, Adhemerval Zanella wrote:
> > if(__builtin_expect(hx<=hy,0)) {
> > - if((hx<hy)||(lx<ly)) return x; /* |x|<|y| return x */
> > - if(lx==ly)
> > - return Zero[(u_int64_t)sx>>63]; /* |x|=|y| return x*0*/
> > + if (hx < hy
> > + || (((ly ^ sy) & 0x8000000000000000LL) == 0
> > + && (int64_t) (lx ^ sx) < (int64_t) (ly ^ sy))
> > + || (((lx ^ sx) & 0x8000000000000000LL) != 0
> > + && (int64_t) (lx ^ sx) > (int64_t) (ly ^ sy)))
> > + return x; /* |x|<|y| return x */
> > + if ((lx ^ sx) == (ly ^ sy))
> > + return Zero[(uint64_t)sx>>63]; /* |x|=|y| return x*0*/
>
> These bitwise operations are kinda crypt at first sign, care to add a comment
> for the need of less than and greater than comparison expressing the need
> to check the magnitudes?
You're right, the code was a little cryptic, especially the last
magnitude test which would need uint64_t casts to handle the same sign
y doubles. This is how I'll commit it.
- if(__builtin_expect(hx<=hy,0)) {
- if((hx<hy)||(lx<ly)) return x; /* |x|<|y| return x */
- if(lx==ly)
- return Zero[(u_int64_t)sx>>63]; /* |x|=|y| return x*0*/
+ if (__builtin_expect (hx <= hy, 0))
+ {
+ /* If |x| < |y| return x. */
+ if (hx < hy)
+ return x;
+ /* At this point the absolute value of the high doubles of
+ x and y must be equal. */
+ /* If the low double of y is the same sign as the high
+ double of y (ie. the low double increases |y|)... */
+ if (((ly ^ sy) & 0x8000000000000000LL) == 0
+ /* ... then a different sign low double to high double
+ for x or same sign but lower magnitude... */
+ && (int64_t) (lx ^ sx) < (int64_t) (ly ^ sy))
+ /* ... means |x| < |y|. */
+ return x;
+ /* If the low double of x differs in sign to the high
+ double of x (ie. the low double decreases |x|)... */
+ if (((lx ^ sx) & 0x8000000000000000LL) != 0
+ /* ... then a different sign low double to high double
+ for y with lower magnitude (we've already caught
+ the same sign for y case above)... */
+ && (int64_t) (lx ^ sx) > (int64_t) (ly ^ sy))
+ /* ... means |x| < |y|. */
+ return x;
+ /* If |x| == |y| return x*0. */
+ if ((lx ^ sx) == (ly ^ sy))
+ return Zero[(uint64_t) sx >> 63];
}
--
Alan Modra
Australia Development Lab, IBM