Back to index

glibc  2.9
s_nextafterl.c
Go to the documentation of this file.
00001 /* s_nextafterl.c -- long double version of s_nextafter.c.
00002  * Conversion to long double by Ulrich Drepper,
00003  * Cygnus Support, drepper@cygnus.com.
00004  */
00005 
00006 /*
00007  * ====================================================
00008  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
00009  *
00010  * Developed at SunPro, a Sun Microsystems, Inc. business.
00011  * Permission to use, copy, modify, and distribute this
00012  * software is freely granted, provided that this notice
00013  * is preserved.
00014  * ====================================================
00015  */
00016 
00017 #if defined(LIBM_SCCS) && !defined(lint)
00018 static char rcsid[] = "$NetBSD: $";
00019 #endif
00020 
00021 /* IEEE functions
00022  *     nextafterl(x,y)
00023  *     return the next machine floating-point number of x in the
00024  *     direction toward y.
00025  *   Special cases:
00026  */
00027 
00028 #include "math.h"
00029 #include <math_private.h>
00030 
00031 #ifdef __STDC__
00032        long double __nextafterl(long double x, long double y)
00033 #else
00034        long double __nextafterl(x,y)
00035        long double x,y;
00036 #endif
00037 {
00038        int32_t hx,hy,ix,iy;
00039        u_int32_t lx,ly,esx,esy;
00040 
00041        GET_LDOUBLE_WORDS(esx,hx,lx,x);
00042        GET_LDOUBLE_WORDS(esy,hy,ly,y);
00043        ix = esx&0x7fff;            /* |x| */
00044        iy = esy&0x7fff;            /* |y| */
00045 
00046        if (((ix==0x7fff)&&((hx|lx)!=0)) ||   /* x is nan */
00047            ((iy==0x7fff)&&((hy|ly)!=0)))     /* y is nan */
00048           return x+y;
00049        if(x==y) return y;          /* x=y, return y */
00050        if((ix|hx|lx)==0) {                /* x == 0 */
00051            long double u;
00052            SET_LDOUBLE_WORDS(x,esy&0x8000,0,1);/* return +-minsubnormal */
00053            u = math_opt_barrier (x);
00054            u = u * u;
00055            math_force_eval (u);           /* raise underflow flag */
00056            return x;
00057        }
00058        if(esx<0x8000) {                   /* x > 0 */
00059            if(ix>iy||((ix==iy) && (hx>hy||((hx==hy)&&(lx>ly))))) {
00060              /* x > y, x -= ulp */
00061               if(lx==0) {
00062                   if (hx==0) esx -= 1;
00063                   hx -= 1;
00064               }
00065               lx -= 1;
00066            } else {                       /* x < y, x += ulp */
00067               lx += 1;
00068               if(lx==0) {
00069                   hx += 1;
00070                   if (hx==0)
00071                      esx += 1;
00072               }
00073            }
00074        } else {                           /* x < 0 */
00075            if(esy>=0||(ix>iy||((ix==iy)&&(hx>hy||((hx==hy)&&(lx>ly)))))){
00076              /* x < y, x -= ulp */
00077               if(lx==0) {
00078                   if (hx==0) esx -= 1;
00079                   hx -= 1;
00080               }
00081               lx -= 1;
00082            } else {                       /* x > y, x += ulp */
00083               lx += 1;
00084               if(lx==0) {
00085                   hx += 1;
00086                   if (hx==0) esx += 1;
00087               }
00088            }
00089        }
00090        esy = esx&0x7fff;
00091        if(esy==0x7fff) return x+x;        /* overflow  */
00092        if(esy==0) {
00093            long double u = x*x;           /* underflow */
00094            math_force_eval (u);           /* raise underflow flag */
00095        }
00096        SET_LDOUBLE_WORDS(x,esx,hx,lx);
00097        return x;
00098 }
00099 weak_alias (__nextafterl, nextafterl)
00100 strong_alias (__nextafterl, __nexttowardl)
00101 weak_alias (__nextafterl, nexttowardl)