| /* |
| * inspired by glibc-2.0.6/sysdeps/libm-ieee754/s_nextafterf.c |
| * |
| * gcc -O2 -S -DOP=+ gives faddp %st(1),%st |
| * gcc -O2 -S -DOP=* gives fmulp %st(1),%st |
| * gcc -O2 -S -DOP=- gives fsubrp %st(1),%st |
| * gcc -O2 -S -DOP=/ gives fdivrp %st(1),%st |
| */ |
| |
| #ifndef OP |
| #define OP * |
| #endif |
| |
| typedef int int32_t __attribute__ ((__mode__ ( __SI__ ))) ; |
| typedef unsigned int u_int32_t __attribute__ ((__mode__ ( __SI__ ))) ; |
| |
| typedef union |
| { |
| float value; |
| u_int32_t word; |
| } ieee_float_shape_type; |
| |
| float __nextafterf(float x, float y) |
| { |
| int32_t hx,hy,ix,iy; |
| |
| { |
| ieee_float_shape_type gf_u; |
| gf_u.value = x; |
| hx = gf_u.word; |
| } |
| { |
| ieee_float_shape_type gf_u; |
| gf_u.value = y; |
| hy = gf_u.word; |
| } |
| ix = hx&0x7fffffff; |
| iy = hy&0x7fffffff; |
| |
| if ( ix > 0x7f800000 || iy > 0x7f800000 ) |
| return x+y; |
| if (x == y) return x; |
| if (ix == 0) |
| { |
| { |
| ieee_float_shape_type sf_u; |
| sf_u.word = (hy&0x80000000) | 1; |
| x = sf_u.value; |
| } |
| y = x*x; |
| if (y == x) return y; else return x; |
| } |
| if (hx >= 0) |
| { |
| if (hx > hy) |
| hx -= 1; |
| else |
| hx += 1; |
| } |
| else |
| { |
| if (hy >= 0 || hx > hy) |
| hx -= 1; |
| else |
| hx += 1; |
| } |
| hy = hx & 0x7f800000; |
| if (hy >= 0x7f800000) |
| return x+x; |
| if (hy < 0x00800000) |
| { |
| y = x OP x; |
| if (y != x) |
| { |
| ieee_float_shape_type sf_u; |
| sf_u.word = hx; |
| y = sf_u.value; |
| return y; |
| } |
| } |
| { |
| ieee_float_shape_type sf_u; |
| sf_u.word = hx; |
| x = sf_u.value; |
| } |
| return x; |
| } |
| |
| |