Back to index

glibc  2.9
s_nexttowardf.c
Go to the documentation of this file.
00001 /* s_nexttowardf.c -- float version of s_nextafter.c.
00002  * Special i387 version.
00003  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@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 #include "math.h"
00022 #include <math_private.h>
00023 #include <float.h>
00024 
00025 #ifdef __STDC__
00026        float __nexttowardf(float x, long double y)
00027 #else
00028        float __nexttowardf(x,y)
00029        float x;
00030        long double y;
00031 #endif
00032 {
00033        int32_t hx,ix,iy;
00034        u_int32_t hy,ly,esy;
00035 
00036        GET_FLOAT_WORD(hx,x);
00037        GET_LDOUBLE_WORDS(esy,hy,ly,y);
00038        ix = hx&0x7fffffff;         /* |x| */
00039        iy = esy&0x7fff;            /* |y| */
00040 
00041        /* Intel's extended format has the normally implicit 1 explicit
00042           present.  Sigh!  */
00043        if((ix>0x7f800000) ||                     /* x is nan */
00044           (iy>=0x7fff&&(((hy&0x7fffffff)|ly)!=0))) /* y is nan */
00045           return x+y;
00046        if((long double) x==y) return y;   /* x=y, return y */
00047        if(ix==0) {                        /* x == 0 */
00048            float u;
00049            SET_FLOAT_WORD(x,((esy&0x8000)<<16)|1);/* return +-minsub*/
00050            u = math_opt_barrier (x);
00051            u = u * u;
00052            math_force_eval (u);           /* raise underflow flag */
00053            return x;
00054        }
00055        if(hx>=0) {                        /* x > 0 */
00056            if(esy>=0x8000||((ix>>23)&0xff)>iy-0x3f80
00057               || (((ix>>23)&0xff)==iy-0x3f80
00058                  && ((ix&0x7fffff)<<8)>(hy&0x7fffffff))) {/* x > y, x -= ulp */
00059               hx -= 1;
00060            } else {                       /* x < y, x += ulp */
00061               hx += 1;
00062            }
00063        } else {                           /* x < 0 */
00064            if(esy<0x8000||((ix>>23)&0xff)>iy-0x3f80
00065               || (((ix>>23)&0xff)==iy-0x3f80
00066                  && ((ix&0x7fffff)<<8)>(hy&0x7fffffff))) {/* x < y, x -= ulp */
00067               hx -= 1;
00068            } else {                       /* x > y, x += ulp */
00069               hx += 1;
00070            }
00071        }
00072        hy = hx&0x7f800000;
00073        if(hy>=0x7f800000) {
00074          x = x+x;    /* overflow  */
00075          if (FLT_EVAL_METHOD != 0)
00076            /* Force conversion to float.  */
00077            asm ("" : "+m"(x));
00078          return x;
00079        }
00080        if(hy<0x00800000) {
00081            float u = x*x;                 /* underflow */
00082            math_force_eval (u);           /* raise underflow flag */
00083        }
00084        SET_FLOAT_WORD(x,hx);
00085        return x;
00086 }
00087 weak_alias (__nexttowardf, nexttowardf)