mirror of
				https://sourceware.org/git/glibc.git
				synced 2025-10-30 10:45:40 +03:00 
			
		
		
		
	This patch adds a new macro, libm_alias_finite, to define all _finite symbol. It sets all _finite symbol as compat symbol based on its first version (obtained from the definition at built generated first-versions.h). The <fn>f128_finite symbols were introduced in GLIBC 2.26 and so need special treatment in code that is shared between long double and float128. It is done by adding a list, similar to internal symbol redifinition, on sysdeps/ieee754/float128/float128_private.h. Alpha also needs some tricky changes to ensure we still emit 2 compat symbols for sqrt(f). Passes buildmanyglibc. Co-authored-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
		
			
				
	
	
		
			151 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* e_fmodl.c -- long double version of e_fmod.c.
 | |
|  * Conversion to IEEE quad long double by Jakub Jelinek, jj@ultra.linux.cz.
 | |
|  */
 | |
| /*
 | |
|  * ====================================================
 | |
|  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
 | |
|  *
 | |
|  * Developed at SunPro, a Sun Microsystems, Inc. business.
 | |
|  * Permission to use, copy, modify, and distribute this
 | |
|  * software is freely granted, provided that this notice
 | |
|  * is preserved.
 | |
|  * ====================================================
 | |
|  */
 | |
| 
 | |
| /*
 | |
|  * __ieee754_fmodl(x,y)
 | |
|  * Return x mod y in exact arithmetic
 | |
|  * Method: shift and subtract
 | |
|  */
 | |
| 
 | |
| #include <math.h>
 | |
| #include <math_private.h>
 | |
| #include <ieee754.h>
 | |
| #include <libm-alias-finite.h>
 | |
| 
 | |
| static const long double one = 1.0, Zero[] = {0.0, -0.0,};
 | |
| 
 | |
| long double
 | |
| __ieee754_fmodl (long double x, long double y)
 | |
| {
 | |
| 	int64_t hx, hy, hz, sx, sy;
 | |
| 	uint64_t lx, ly, lz;
 | |
| 	int n, ix, iy;
 | |
| 	double xhi, xlo, yhi, ylo;
 | |
| 
 | |
| 	ldbl_unpack (x, &xhi, &xlo);
 | |
| 	EXTRACT_WORDS64 (hx, xhi);
 | |
| 	EXTRACT_WORDS64 (lx, xlo);
 | |
| 	ldbl_unpack (y, &yhi, &ylo);
 | |
| 	EXTRACT_WORDS64 (hy, yhi);
 | |
| 	EXTRACT_WORDS64 (ly, ylo);
 | |
| 	sx = hx&0x8000000000000000ULL;		/* sign of x */
 | |
| 	hx ^= sx;				/* |x| */
 | |
| 	sy = hy&0x8000000000000000ULL;		/* sign of y */
 | |
| 	hy ^= sy;				/* |y| */
 | |
| 
 | |
|     /* purge off exception values */
 | |
| 	if(__builtin_expect(hy==0 ||
 | |
| 			    (hx>=0x7ff0000000000000LL)|| /* y=0,or x not finite */
 | |
| 			    (hy>0x7ff0000000000000LL),0))	/* or y is NaN */
 | |
| 	    return (x*y)/(x*y);
 | |
| 	if (__glibc_unlikely (hx <= hy))
 | |
| 	  {
 | |
| 	    /* If |x| < |y| return x.  */
 | |
| 	    if (hx < hy)
 | |
| 	      return x;
 | |
| 	    /* At this point the absolute value of the high doubles of
 | |
| 	       x and y must be equal.  */
 | |
| 	    if ((lx & 0x7fffffffffffffffLL) == 0
 | |
| 		&& (ly & 0x7fffffffffffffffLL) == 0)
 | |
| 	      /* Both low parts are zero.  The result should be an
 | |
| 		 appropriately signed zero, but the subsequent logic
 | |
| 		 could treat them as unequal, depending on the signs
 | |
| 		 of the low parts.  */
 | |
| 	      return Zero[(uint64_t) sx >> 63];
 | |
| 	    /* If the low double of y is the same sign as the high
 | |
| 	       double of y (ie. the low double increases |y|)...  */
 | |
| 	    if (((ly ^ sy) & 0x8000000000000000LL) == 0
 | |
| 		/* ... then a different sign low double to high double
 | |
| 		   for x or same sign but lower magnitude...  */
 | |
| 		&& (int64_t) (lx ^ sx) < (int64_t) (ly ^ sy))
 | |
| 	      /* ... means |x| < |y|.  */
 | |
| 	      return x;
 | |
| 	    /* If the low double of x differs in sign to the high
 | |
| 	       double of x (ie. the low double decreases |x|)...  */
 | |
| 	    if (((lx ^ sx) & 0x8000000000000000LL) != 0
 | |
| 		/* ... then a different sign low double to high double
 | |
| 		   for y with lower magnitude (we've already caught
 | |
| 		   the same sign for y case above)...  */
 | |
| 		&& (int64_t) (lx ^ sx) > (int64_t) (ly ^ sy))
 | |
| 	      /* ... means |x| < |y|.  */
 | |
| 	      return x;
 | |
| 	    /* If |x| == |y| return x*0.  */
 | |
| 	    if ((lx ^ sx) == (ly ^ sy))
 | |
| 	      return Zero[(uint64_t) sx >> 63];
 | |
| 	}
 | |
| 
 | |
|     /* Make the IBM extended format 105 bit mantissa look like the ieee854 112
 | |
|        bit mantissa so the following operations will give the correct
 | |
|        result.  */
 | |
| 	ldbl_extract_mantissa(&hx, &lx, &ix, x);
 | |
| 	ldbl_extract_mantissa(&hy, &ly, &iy, y);
 | |
| 
 | |
| 	if (__glibc_unlikely (ix == -IEEE754_DOUBLE_BIAS))
 | |
| 	  {
 | |
| 	    /* subnormal x, shift x to normal.  */
 | |
| 	    while ((hx & (1LL << 48)) == 0)
 | |
| 	      {
 | |
| 		hx = (hx << 1) | (lx >> 63);
 | |
| 		lx = lx << 1;
 | |
| 		ix -= 1;
 | |
| 	      }
 | |
| 	  }
 | |
| 
 | |
| 	if (__glibc_unlikely (iy == -IEEE754_DOUBLE_BIAS))
 | |
| 	  {
 | |
| 	    /* subnormal y, shift y to normal.  */
 | |
| 	    while ((hy & (1LL << 48)) == 0)
 | |
| 	      {
 | |
| 		hy = (hy << 1) | (ly >> 63);
 | |
| 		ly = ly << 1;
 | |
| 		iy -= 1;
 | |
| 	      }
 | |
| 	  }
 | |
| 
 | |
|     /* fix point fmod */
 | |
| 	n = ix - iy;
 | |
| 	while(n--) {
 | |
| 	    hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
 | |
| 	    if(hz<0){hx = hx+hx+(lx>>63); lx = lx+lx;}
 | |
| 	    else {
 | |
| 		if((hz|lz)==0)		/* return sign(x)*0 */
 | |
| 		    return Zero[(uint64_t)sx>>63];
 | |
| 		hx = hz+hz+(lz>>63); lx = lz+lz;
 | |
| 	    }
 | |
| 	}
 | |
| 	hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
 | |
| 	if(hz>=0) {hx=hz;lx=lz;}
 | |
| 
 | |
|     /* convert back to floating value and restore the sign */
 | |
| 	if((hx|lx)==0)			/* return sign(x)*0 */
 | |
| 	    return Zero[(uint64_t)sx>>63];
 | |
| 	while(hx<0x0001000000000000LL) {	/* normalize x */
 | |
| 	    hx = hx+hx+(lx>>63); lx = lx+lx;
 | |
| 	    iy -= 1;
 | |
| 	}
 | |
| 	if(__builtin_expect(iy>= -1022,0)) {	/* normalize output */
 | |
| 	    x = ldbl_insert_mantissa((sx>>63), iy, hx, lx);
 | |
| 	} else {		/* subnormal output */
 | |
| 	    n = -1022 - iy;
 | |
| 	    /* We know 1 <= N <= 52, and that there are no nonzero
 | |
| 	       bits in places below 2^-1074.  */
 | |
| 	    lx = (lx >> n) | ((uint64_t) hx << (64 - n));
 | |
| 	    hx >>= n;
 | |
| 	    x = ldbl_insert_mantissa((sx>>63), -1023, hx, lx);
 | |
| 	    x *= one;		/* create necessary signal */
 | |
| 	}
 | |
| 	return x;		/* exact output */
 | |
| }
 | |
| libm_alias_finite (__ieee754_fmodl, __fmodl)
 |