(root)/
glibc-2.38/
sysdeps/
i386/
fpu/
s_nexttowardf.c
       1  /* s_nexttowardf.c -- float version of s_nextafter.c.
       2   * Special i387 version.
       3   */
       4  
       5  /*
       6   * ====================================================
       7   * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
       8   *
       9   * Developed at SunPro, a Sun Microsystems, Inc. business.
      10   * Permission to use, copy, modify, and distribute this
      11   * software is freely granted, provided that this notice
      12   * is preserved.
      13   * ====================================================
      14   */
      15  
      16  #if defined(LIBM_SCCS) && !defined(lint)
      17  static char rcsid[] = "$NetBSD: $";
      18  #endif
      19  
      20  #include <errno.h>
      21  #include <math.h>
      22  #include <math-barriers.h>
      23  #include <math_private.h>
      24  #include <float.h>
      25  
      26  float __nexttowardf(float x, long double y)
      27  {
      28  	int32_t hx,ix,iy;
      29  	uint32_t hy,ly,esy;
      30  
      31  	GET_FLOAT_WORD(hx,x);
      32  	GET_LDOUBLE_WORDS(esy,hy,ly,y);
      33  	ix = hx&0x7fffffff;		/* |x| */
      34  	iy = esy&0x7fff;		/* |y| */
      35  
      36  	/* Intel's extended format has the normally implicit 1 explicit
      37  	   present.  Sigh!  */
      38  	if((ix>0x7f800000) ||			/* x is nan */
      39  	   (iy>=0x7fff&&(((hy&0x7fffffff)|ly)!=0))) /* y is nan */
      40  	   return x+y;
      41  	if((long double) x==y) return y;	/* x=y, return y */
      42  	if(ix==0) {				/* x == 0 */
      43  	    float u;
      44  	    SET_FLOAT_WORD(x,((esy&0x8000)<<16)|1);/* return +-minsub*/
      45  	    u = math_opt_barrier (x);
      46  	    u = u * u;
      47  	    math_force_eval (u);		/* raise underflow flag */
      48  	    return x;
      49  	}
      50  	if(hx>=0) {				/* x > 0 */
      51  	    if(x > y) {				/* x -= ulp */
      52  		hx -= 1;
      53  	    } else {				/* x < y, x += ulp */
      54  		hx += 1;
      55  	    }
      56  	} else {				/* x < 0 */
      57  	    if(x < y) {				/* x -= ulp */
      58  		hx -= 1;
      59  	    } else {				/* x > y, x += ulp */
      60  		hx += 1;
      61  	    }
      62  	}
      63  	hy = hx&0x7f800000;
      64  	if(hy>=0x7f800000) {
      65  	  float u = x+x;			/* overflow  */
      66  	  math_force_eval (u);
      67  	  __set_errno (ERANGE);
      68  	}
      69  	if(hy<0x00800000) {
      70  	    float u = x*x;			/* underflow */
      71  	    math_force_eval (u);		/* raise underflow flag */
      72  	    __set_errno (ERANGE);
      73  	}
      74  	SET_FLOAT_WORD(x,hx);
      75  	return x;
      76  }
      77  weak_alias (__nexttowardf, nexttowardf)