s_truncl.c revision 176245
1145170Sdas/* 2145170Sdas * ==================================================== 3145170Sdas * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 4145170Sdas * 5145170Sdas * Developed at SunPro, a Sun Microsystems, Inc. business. 6145170Sdas * Permission to use, copy, modify, and distribute this 7145170Sdas * software is freely granted, provided that this notice 8145170Sdas * is preserved. 9145170Sdas * ==================================================== 10145170Sdas * 11145170Sdas * From: @(#)s_floor.c 5.1 93/09/24 12145170Sdas */ 13145170Sdas 14176245Sbde#include <sys/cdefs.h> 15176245Sbde__FBSDID("$FreeBSD: head/lib/msun/src/s_truncl.c 176245 2008-02-13 17:38:16Z bde $"); 16145170Sdas 17145170Sdas/* 18145170Sdas * truncl(x) 19145170Sdas * Return x rounded toward 0 to integral value 20145170Sdas * Method: 21145170Sdas * Bit twiddling. 22145170Sdas * Exception: 23145170Sdas * Inexact flag raised if x not equal to truncl(x). 24145170Sdas */ 25145170Sdas 26145170Sdas#include <float.h> 27145170Sdas#include <math.h> 28145170Sdas#include <stdint.h> 29145170Sdas 30145170Sdas#include "fpmath.h" 31145170Sdas 32145170Sdas#ifdef LDBL_IMPLICIT_NBIT 33145170Sdas#define MANH_SIZE (LDBL_MANH_SIZE + 1) 34145170Sdas#else 35145170Sdas#define MANH_SIZE LDBL_MANH_SIZE 36145170Sdas#endif 37145170Sdas 38145637Sstefanfstatic const long double huge = 1.0e300; 39176102Sbdestatic const float zero[] = { 0.0, -0.0 }; 40145394Sstefanf 41145170Sdaslong double 42145170Sdastruncl(long double x) 43145170Sdas{ 44145170Sdas union IEEEl2bits u = { .e = x }; 45145170Sdas int e = u.bits.exp - LDBL_MAX_EXP + 1; 46145170Sdas 47145170Sdas if (e < MANH_SIZE - 1) { 48145170Sdas if (e < 0) { /* raise inexact if x != 0 */ 49145637Sstefanf if (huge + x > 0.0) 50176102Sbde u.e = zero[u.bits.sign]; 51145170Sdas } else { 52145170Sdas uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1); 53145170Sdas if (((u.bits.manh & m) | u.bits.manl) == 0) 54145170Sdas return (x); /* x is integral */ 55145637Sstefanf if (huge + x > 0.0) { /* raise inexact flag */ 56145394Sstefanf u.bits.manh &= ~m; 57145394Sstefanf u.bits.manl = 0; 58145394Sstefanf } 59145170Sdas } 60145170Sdas } else if (e < LDBL_MANT_DIG - 1) { 61145170Sdas uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1); 62145170Sdas if ((u.bits.manl & m) == 0) 63145170Sdas return (x); /* x is integral */ 64145637Sstefanf if (huge + x > 0.0) /* raise inexact flag */ 65145394Sstefanf u.bits.manl &= ~m; 66145170Sdas } 67145170Sdas return (u.e); 68145170Sdas} 69176243Sbde 70176243Sbde#if LDBL_MANT_DIG == 53 71176243Sbde__weak_reference(trunc, truncl); 72176243Sbde#endif 73