1/* s_nexttowardf.c -- float version of s_nextafter.c. 2 * Special i387 version. 3 * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. 4 */ 5 6/* 7 * ==================================================== 8 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 9 * 10 * Developed at SunPro, a Sun Microsystems, Inc. business. 11 * Permission to use, copy, modify, and distribute this 12 * software is freely granted, provided that this notice 13 * is preserved. 14 * ==================================================== 15 */ 16 17#if defined(LIBM_SCCS) && !defined(lint) 18static char rcsid[] = "$NetBSD: $"; 19#endif 20 21#include "math.h" 22#include "math_private.h" 23 24#ifdef __STDC__ 25 float __nexttowardf(float x, long double y) 26#else 27 float __nexttowardf(x,y) 28 float x; 29 long double y; 30#endif 31{ 32 int32_t hx,ix,iy; 33 u_int32_t hy,ly,esy; 34 35 GET_FLOAT_WORD(hx,x); 36 GET_LDOUBLE_WORDS(esy,hy,ly,y); 37 ix = hx&0x7fffffff; /* |x| */ 38 iy = esy&0x7fff; /* |y| */ 39 40 /* Intel's extended format has the normally implicit 1 explicit 41 present. Sigh! */ 42 if((ix>0x7f800000) || /* x is nan */ 43 (iy>=0x7fff&&(((hy&0x7fffffff)|ly)!=0))) /* y is nan */ 44 return x+y; 45 if((long double) x==y) return y; /* x=y, return y */ 46 if(ix==0) { /* x == 0 */ 47 float x2; 48 SET_FLOAT_WORD(x,((esy&0x8000)<<16)|1);/* return +-minsub*/ 49 x2 = x*x; 50 if(x2==x) return x2; else return x; /* raise underflow flag */ 51 } 52 if(hx>=0) { /* x > 0 */ 53 if(esy>=0x8000||((ix>>23)&0xff)>iy-0x3f80 54 || (((ix>>23)&0xff)==iy-0x3f80 55 && ((ix&0x7fffff)<<8)>(hy&0x7fffffff))) {/* x > y, x -= ulp */ 56 hx -= 1; 57 } else { /* x < y, x += ulp */ 58 hx += 1; 59 } 60 } else { /* x < 0 */ 61 if(esy<0x8000||((ix>>23)&0xff)>iy-0x3f80 62 || (((ix>>23)&0xff)==iy-0x3f80 63 && ((ix&0x7fffff)<<8)>(hy&0x7fffffff))) {/* x < y, x -= ulp */ 64 hx -= 1; 65 } else { /* x > y, x += ulp */ 66 hx += 1; 67 } 68 } 69 hy = hx&0x7f800000; 70 if(hy>=0x7f800000) { 71 x = x+x; /* overflow */ 72 /* Force conversion to float. */ 73 asm ("" : "=m"(x) : "m"(x)); 74 return x; 75 } 76 if(hy<0x00800000) { /* underflow */ 77 float x2 = x*x; 78 if(x2!=x) { /* raise underflow flag */ 79 SET_FLOAT_WORD(x2,hx); 80 return x2; 81 } 82 } 83 SET_FLOAT_WORD(x,hx); 84 return x; 85} 86weak_alias (__nexttowardf, nexttowardf) 87