about summary refs log tree commit diff
path: root/sysdeps/generic/s_nexttowardf.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1999-07-14 00:54:57 +0000
committerUlrich Drepper <drepper@redhat.com>1999-07-14 00:54:57 +0000
commitabfbdde177c3a7155070dda1b2cdc8292054cc26 (patch)
treee021306b596381fbf8311d2b7eb294e918ff17c8 /sysdeps/generic/s_nexttowardf.c
parent86421aa57ecfd70963ae66848bd6a6dd3b8e0fe6 (diff)
downloadglibc-abfbdde177c3a7155070dda1b2cdc8292054cc26.tar.gz
glibc-abfbdde177c3a7155070dda1b2cdc8292054cc26.tar.xz
glibc-abfbdde177c3a7155070dda1b2cdc8292054cc26.zip
Update.
Diffstat (limited to 'sysdeps/generic/s_nexttowardf.c')
-rw-r--r--sysdeps/generic/s_nexttowardf.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/sysdeps/generic/s_nexttowardf.c b/sysdeps/generic/s_nexttowardf.c
new file mode 100644
index 0000000000..f4cf18d06e
--- /dev/null
+++ b/sysdeps/generic/s_nexttowardf.c
@@ -0,0 +1,79 @@
+/* Single precision version of nexttoward.c.
+   Conversion to IEEE single float by Jakub Jelinek, jj@ultra.linux.cz. */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* IEEE functions
+ *	nexttowardf(x,y)
+ *	return the next machine floating-point number of x in the
+ *	direction toward y.
+ * This is for machines which use the same binary type for double and
+ * long double.
+ *   Special cases:
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __STDC__
+	float __nexttowardf(float x, long double y)
+#else
+	float __nexttowardf(x,y)
+	float x;
+	long double y;
+#endif
+{
+	int32_t hx,hy,ix,iy;
+	u_int32_t ly;
+
+	GET_FLOAT_WORD(hx,x);
+	EXTRACT_WORDS(hy,ly,y);
+	ix = hx&0x7fffffff;		/* |x| */
+	iy = hy&0x7fffffff;		/* |y| */
+
+	if(((ix>=0x7f800000) ||				    /* x is nan */
+	   ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0))     /* y is nan */
+	   return x+y;
+	if((long double) x==y) return y;	/* x=y, return y */
+	if(ix==0) {				/* x == 0 */
+	    float x2;
+	    SET_FLOAT_WORD(x,(u_int32_t)((hy>>32)&0x80000000)|1);/* return +-minsub*/
+	    x2 = x*x;
+	    if(x2==x) return x2; else return x; /* raise underflow flag */
+	}
+	if(hx>=0) {				/* x > 0 */
+	    if(hy<0||(ix>>23)>(iy>>20)-0x380
+	       || ((ix>>23)==(iy>>20)-0x380
+		   && (ix&0x7fffff)>((hy<<3)|(ly>>29))&0x7fffff))	/* x > y, x -= ulp */
+		hx -= 1;
+	    else				/* x < y, x += ulp */
+		hx += 1;
+	} else {				/* x < 0 */
+	    if(hy>=0||(ix>>23)>(iy>>20)-0x380
+	       || ((ix>>23)==(iy>>20)-0x380
+		   && (ix&0x7fffff)>((hy<<3)|(ly>>29))&0x7fffff))	/* x < y, x -= ulp */
+		hx -= 1;
+	    else				/* x > y, x += ulp */
+		hx += 1;
+	}
+	hy = hx&0x7f800000;
+	if(hy>=0x7f800000) return x+x;	/* overflow  */
+	if(hy<0x00800000) {		/* underflow */
+	    float x2 = x*x;
+	    if(x2!=x) {		/* raise underflow flag */
+		SET_FLOAT_WORD(x2,hx);
+		return x2;
+	    }
+	}
+	SET_FLOAT_WORD(x,hx);
+	return x;
+}
+weak_alias (__nexttowardf, nexttowardf)