Back to index

glibc  2.9
s_nextafter.c
Go to the documentation of this file.
00001 /* @(#)s_nextafter.c 5.1 93/09/24 */
00002 /*
00003  * ====================================================
00004  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
00005  *
00006  * Developed at SunPro, a Sun Microsystems, Inc. business.
00007  * Permission to use, copy, modify, and distribute this
00008  * software is freely granted, provided that this notice
00009  * is preserved.
00010  * ====================================================
00011  */
00012 
00013 #if defined(LIBM_SCCS) && !defined(lint)
00014 static char rcsid[] = "$NetBSD: s_nextafter.c,v 1.8 1995/05/10 20:47:58 jtc Exp $";
00015 #endif
00016 
00017 /* IEEE functions
00018  *     nextafter(x,y)
00019  *     return the next machine floating-point number of x in the
00020  *     direction toward y.
00021  *   Special cases:
00022  */
00023 
00024 /* Ugly hack so that the aliasing works.  */
00025 #define __nexttoward __internal___nexttoward
00026 #define nexttoward __internal_nexttoward
00027 
00028 #include <math.h>
00029 #include <math_private.h>
00030 #include <float.h>
00031 
00032 #ifdef __STDC__
00033        double __nextafter(double x, double y)
00034 #else
00035        double __nextafter(x,y)
00036        double x,y;
00037 #endif
00038 {
00039        int32_t hx,hy,ix,iy;
00040        u_int32_t lx,ly;
00041 
00042        EXTRACT_WORDS(hx,lx,x);
00043        EXTRACT_WORDS(hy,ly,y);
00044        ix = hx&0x7fffffff;         /* |x| */
00045        iy = hy&0x7fffffff;         /* |y| */
00046 
00047        if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) ||   /* x is nan */
00048           ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0))     /* y is nan */
00049           return x+y;
00050        if(x==y) return y;          /* x=y, return y */
00051        if((ix|lx)==0) {                   /* x == 0 */
00052            double u;
00053            INSERT_WORDS(x,hy&0x80000000,1);      /* return +-minsubnormal */
00054            u = math_opt_barrier (x);
00055            u = u*u;
00056            math_force_eval (u);           /* raise underflow flag */
00057            return x;
00058        }
00059        if(hx>=0) {                        /* x > 0 */
00060            if(hx>hy||((hx==hy)&&(lx>ly))) {      /* x > y, x -= ulp */
00061               if(lx==0) hx -= 1;
00062               lx -= 1;
00063            } else {                       /* x < y, x += ulp */
00064               lx += 1;
00065               if(lx==0) hx += 1;
00066            }
00067        } else {                           /* x < 0 */
00068            if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */
00069               if(lx==0) hx -= 1;
00070               lx -= 1;
00071            } else {                       /* x > y, x += ulp */
00072               lx += 1;
00073               if(lx==0) hx += 1;
00074            }
00075        }
00076        hy = hx&0x7ff00000;
00077        if(hy>=0x7ff00000) {
00078          x = x+x;    /* overflow  */
00079          if (FLT_EVAL_METHOD != 0 && FLT_EVAL_METHOD != 1)
00080            asm ("" : "+m"(x));
00081          return x;   /* overflow  */
00082        }
00083        if(hy<0x00100000) {
00084            double u = x*x;                /* underflow */
00085            math_force_eval (u);           /* raise underflow flag */
00086        }
00087        INSERT_WORDS(x,hx,lx);
00088        return x;
00089 }
00090 weak_alias (__nextafter, nextafter)
00091 #ifdef NO_LONG_DOUBLE
00092 strong_alias (__nextafter, __nextafterl)
00093 weak_alias (__nextafter, nextafterl)
00094 strong_alias (__nextafter, __nexttowardl)
00095 weak_alias (__nexttowardl, nexttowardl)
00096 #undef __nexttoward
00097 strong_alias (__nextafter, __nexttoward)
00098 #undef nexttoward
00099 weak_alias (__nextafter, nexttoward)
00100 #endif