(root)/
glibc-2.38/
sysdeps/
ieee754/
ldbl-128/
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  
      26  float __nexttowardf(float x, _Float128 y)
      27  {
      28  	int32_t hx,ix;
      29  	int64_t hy,iy;
      30  	uint64_t ly;
      31  
      32  	GET_FLOAT_WORD(hx,x);
      33  	GET_LDOUBLE_WORDS64(hy,ly,y);
      34  	ix = hx&0x7fffffff;		/* |x| */
      35  	iy = hy&0x7fffffffffffffffLL;	/* |y| */
      36  
      37  	if((ix>0x7f800000) ||   /* x is nan */
      38  	   ((iy>=0x7fff000000000000LL)&&((iy-0x7fff000000000000LL)|ly)!=0))
      39  				/* y is nan */
      40  	   return x+y;
      41  	if((_Float128) x==y) return y;		/* x=y, return y */
      42  	if(ix==0) {				/* x == 0 */
      43  	    float u;
      44  	    SET_FLOAT_WORD(x,(uint32_t)((hy>>32)&0x80000000)|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 < 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)