xref: /freebsd/lib/msun/src/s_truncl.c (revision 0dd5a5603e7a33d976f8e6015620bbc79839c609)
12f2ee27dSDavid Schultz /*
22f2ee27dSDavid Schultz  * ====================================================
32f2ee27dSDavid Schultz  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
42f2ee27dSDavid Schultz  *
52f2ee27dSDavid Schultz  * Developed at SunPro, a Sun Microsystems, Inc. business.
62f2ee27dSDavid Schultz  * Permission to use, copy, modify, and distribute this
72f2ee27dSDavid Schultz  * software is freely granted, provided that this notice
82f2ee27dSDavid Schultz  * is preserved.
92f2ee27dSDavid Schultz  * ====================================================
102f2ee27dSDavid Schultz  */
112f2ee27dSDavid Schultz 
122f2ee27dSDavid Schultz /*
132f2ee27dSDavid Schultz  * truncl(x)
142f2ee27dSDavid Schultz  * Return x rounded toward 0 to integral value
152f2ee27dSDavid Schultz  * Method:
162f2ee27dSDavid Schultz  *	Bit twiddling.
172f2ee27dSDavid Schultz  * Exception:
182f2ee27dSDavid Schultz  *	Inexact flag raised if x not equal to truncl(x).
192f2ee27dSDavid Schultz  */
202f2ee27dSDavid Schultz 
212f2ee27dSDavid Schultz #include <float.h>
222f2ee27dSDavid Schultz #include <math.h>
232f2ee27dSDavid Schultz #include <stdint.h>
242f2ee27dSDavid Schultz 
252f2ee27dSDavid Schultz #include "fpmath.h"
262f2ee27dSDavid Schultz 
272f2ee27dSDavid Schultz #ifdef LDBL_IMPLICIT_NBIT
282f2ee27dSDavid Schultz #define	MANH_SIZE	(LDBL_MANH_SIZE + 1)
292f2ee27dSDavid Schultz #else
302f2ee27dSDavid Schultz #define	MANH_SIZE	LDBL_MANH_SIZE
312f2ee27dSDavid Schultz #endif
322f2ee27dSDavid Schultz 
3366116c07SStefan Farfeleder static const long double huge = 1.0e300;
34fbe8fb4dSBruce Evans static const float zero[] = { 0.0, -0.0 };
359eb30792SStefan Farfeleder 
362f2ee27dSDavid Schultz long double
truncl(long double x)372f2ee27dSDavid Schultz truncl(long double x)
382f2ee27dSDavid Schultz {
392f2ee27dSDavid Schultz 	union IEEEl2bits u = { .e = x };
402f2ee27dSDavid Schultz 	int e = u.bits.exp - LDBL_MAX_EXP + 1;
412f2ee27dSDavid Schultz 
422f2ee27dSDavid Schultz 	if (e < MANH_SIZE - 1) {
432f2ee27dSDavid Schultz 		if (e < 0) {			/* raise inexact if x != 0 */
4466116c07SStefan Farfeleder 			if (huge + x > 0.0)
45fbe8fb4dSBruce Evans 				u.e = zero[u.bits.sign];
462f2ee27dSDavid Schultz 		} else {
472f2ee27dSDavid Schultz 			uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
482f2ee27dSDavid Schultz 			if (((u.bits.manh & m) | u.bits.manl) == 0)
492f2ee27dSDavid Schultz 				return (x);	/* x is integral */
5066116c07SStefan Farfeleder 			if (huge + x > 0.0) {	/* raise inexact flag */
512f2ee27dSDavid Schultz 				u.bits.manh &= ~m;
522f2ee27dSDavid Schultz 				u.bits.manl = 0;
532f2ee27dSDavid Schultz 			}
549eb30792SStefan Farfeleder 		}
552f2ee27dSDavid Schultz 	} else if (e < LDBL_MANT_DIG - 1) {
562f2ee27dSDavid Schultz 		uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
572f2ee27dSDavid Schultz 		if ((u.bits.manl & m) == 0)
582f2ee27dSDavid Schultz 			return (x);	/* x is integral */
5966116c07SStefan Farfeleder 		if (huge + x > 0.0)		/* raise inexact flag */
602f2ee27dSDavid Schultz 			u.bits.manl &= ~m;
612f2ee27dSDavid Schultz 	}
622f2ee27dSDavid Schultz 	return (u.e);
632f2ee27dSDavid Schultz }
64