Back to index

glibc  2.9
s_nexttoward.c
Go to the documentation of this file.
00001 /* s_nexttoward.c
00002  * Special i387 version
00003  * Conversion from s_nextafter.c by Ulrich Drepper, Cygnus Support,
00004  * drepper@cygnus.com.
00005  */
00006 
00007 /*
00008  * ====================================================
00009  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
00010  *
00011  * Developed at SunPro, a Sun Microsystems, Inc. business.
00012  * Permission to use, copy, modify, and distribute this
00013  * software is freely granted, provided that this notice
00014  * is preserved.
00015  * ====================================================
00016  */
00017 
00018 #if defined(LIBM_SCCS) && !defined(lint)
00019 static char rcsid[] = "$NetBSD: $";
00020 #endif
00021 
00022 /* IEEE functions
00023  *     nexttoward(x,y)
00024  *     return the next machine floating-point number of x in the
00025  *     direction toward y.
00026  *   Special cases:
00027  */
00028 
00029 #include "math.h"
00030 #include <math_private.h>
00031 #include <float.h>
00032 
00033 #ifdef __STDC__
00034        double __nexttoward(double x, long double y)
00035 #else
00036        double __nexttoward(x,y)
00037        double x;
00038        long double y;
00039 #endif
00040 {
00041        int32_t hx,ix,iy;
00042        u_int32_t lx,hy,ly,esy;
00043 
00044        EXTRACT_WORDS(hx,lx,x);
00045        GET_LDOUBLE_WORDS(esy,hy,ly,y);
00046        ix = hx&0x7fffffff;         /* |x| */
00047        iy = esy&0x7fff;            /* |y| */
00048 
00049        /* Intel's extended format has the normally implicit 1 explicit
00050           present.  Sigh!  */
00051        if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) ||   /* x is nan */
00052           ((iy>=0x7fff)&&((hy&0x7fffffff)|ly)!=0))        /* y is nan */
00053           return x+y;
00054        if((long double) x==y) return y;   /* x=y, return y */
00055        if((ix|lx)==0) {                   /* x == 0 */
00056            double u;
00057            INSERT_WORDS(x,(esy&0x8000)<<16,1); /* return +-minsub */
00058            u = math_opt_barrier (x);
00059            u = u * u;
00060            math_force_eval (u);           /* raise underflow flag */
00061            return x;
00062        }
00063        if(hx>=0) {                        /* x > 0 */
00064            if (esy>=0x8000||((ix>>20)&0x7ff)>iy-0x3c00
00065               || (((ix>>20)&0x7ff)==iy-0x3c00
00066                   && (((hx<<11)|(lx>>21))>(hy&0x7fffffff)
00067                      || (((hx<<11)|(lx>>21))==(hy&0x7fffffff)
00068                          && (lx<<11)>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        } else {                           /* x < 0 */
00076            if (esy<0x8000||((ix>>20)&0x7ff)>iy-0x3c00
00077               || (((ix>>20)&0x7ff)==iy-0x3c00
00078                   && (((hx<<11)|(lx>>21))>(hy&0x7fffffff)
00079                      || (((hx<<11)|(lx>>21))==(hy&0x7fffffff)
00080                          && (lx<<11)>ly))))      {/* x < y, x -= ulp */
00081               if(lx==0) hx -= 1;
00082               lx -= 1;
00083            } else {                       /* x > y, x += ulp */
00084               lx += 1;
00085               if(lx==0) hx += 1;
00086            }
00087        }
00088        hy = hx&0x7ff00000;
00089        if(hy>=0x7ff00000) {
00090          x = x+x;    /* overflow  */
00091          if (FLT_EVAL_METHOD != 0 && FLT_EVAL_METHOD != 1)
00092            /* Force conversion to double.  */
00093            asm ("" : "+m"(x));
00094          return x;
00095        }
00096        if(hy<0x00100000) {
00097            double u = x*x;                /* underflow */
00098            math_force_eval (u);           /* raise underflow flag */
00099        }
00100        INSERT_WORDS(x,hx,lx);
00101        return x;
00102 }
00103 weak_alias (__nexttoward, nexttoward)
00104 #ifdef NO_LONG_DOUBLE
00105 strong_alias (__nexttoward, __nexttowardl)
00106 weak_alias (__nexttoward, nexttowardl)
00107 #endif