(root)/
glibc-2.38/
sysdeps/
ieee754/
ldbl-128ibm/
s_nexttowardf.c
       1  /* s_nexttowardf.c -- float version of s_nextafter.c.
       2   * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com
       3   * and Jakub Jelinek, jj@ultra.linux.cz.
       4   */
       5  
       6  /*
       7   * ====================================================
       8   * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
       9   *
      10   * Developed at SunPro, a Sun Microsystems, Inc. business.
      11   * Permission to use, copy, modify, and distribute this
      12   * software is freely granted, provided that this notice
      13   * is preserved.
      14   * ====================================================
      15   */
      16  
      17  #if defined(LIBM_SCCS) && !defined(lint)
      18  static char rcsid[] = "$NetBSD: $";
      19  #endif
      20  
      21  #include <errno.h>
      22  #include <math.h>
      23  #include <math-barriers.h>
      24  #include <math_private.h>
      25  #include <math_ldbl_opt.h>
      26  #include <float.h>
      27  
      28  float __nexttowardf(float x, long double y)
      29  {
      30  	int32_t hx,ix;
      31  	int64_t hy,iy;
      32  	double yhi;
      33  
      34  	GET_FLOAT_WORD(hx,x);
      35  	yhi = ldbl_high (y);
      36  	EXTRACT_WORDS64 (hy, yhi);
      37  	ix = hx&0x7fffffff;		/* |x| */
      38  	iy = hy&0x7fffffffffffffffLL;	/* |y| */
      39  
      40  	if((ix>0x7f800000) ||   /* x is nan */
      41  	   (iy>0x7ff0000000000000LL))
      42  				/* y is nan */
      43  	   return x+y;
      44  	if((long double) x==y) return y;	/* x=y, return y */
      45  	if(ix==0) {				/* x == 0 */
      46  	    float u;
      47  	    SET_FLOAT_WORD(x,(uint32_t)((hy>>32)&0x80000000)|1);/* return +-minsub*/
      48  	    u = math_opt_barrier (x);
      49  	    u = u * u;
      50  	    math_force_eval (u);		/* raise underflow flag */
      51  	    return x;
      52  	}
      53  	if(hx>=0) {				/* x > 0 */
      54  	    if(x > y) {				/* x -= ulp */
      55  		hx -= 1;
      56  	    } else {				/* x < y, x += ulp */
      57  		hx += 1;
      58  	    }
      59  	} else {				/* x < 0 */
      60  	    if(x < y) {				/* x -= ulp */
      61  		hx -= 1;
      62  	    } else {				/* x > y, x += ulp */
      63  		hx += 1;
      64  	    }
      65  	}
      66  	hy = hx&0x7f800000;
      67  	if(hy>=0x7f800000) {
      68  	  float u = x+x;		/* overflow  */
      69  	  math_force_eval (u);
      70  	  __set_errno (ERANGE);
      71  	}
      72  	if(hy<0x00800000) {		/* underflow */
      73  	    float u = x*x;
      74  	    math_force_eval (u);	/* raise underflow flag */
      75  	    __set_errno (ERANGE);
      76  	}
      77  	SET_FLOAT_WORD(x,hx);
      78  	return x;
      79  }
      80  long_double_symbol (libm, __nexttowardf, nexttowardf);