s_truncl.c revision 145394
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 14145170Sdas#ifndef lint 15145170Sdasstatic char rcsid[] = "$FreeBSD: head/lib/msun/src/s_truncl.c 145394 2005-04-22 08:30:33Z stefanf $"; 16145170Sdas#endif 17145170Sdas 18145170Sdas/* 19145170Sdas * truncl(x) 20145170Sdas * Return x rounded toward 0 to integral value 21145170Sdas * Method: 22145170Sdas * Bit twiddling. 23145170Sdas * Exception: 24145170Sdas * Inexact flag raised if x not equal to truncl(x). 25145170Sdas */ 26145170Sdas 27145170Sdas#include <float.h> 28145170Sdas#include <math.h> 29145170Sdas#include <stdint.h> 30145170Sdas 31145170Sdas#include "fpmath.h" 32145170Sdas 33145170Sdas#ifdef LDBL_IMPLICIT_NBIT 34145170Sdas#define MANH_SIZE (LDBL_MANH_SIZE + 1) 35145170Sdas#else 36145170Sdas#define MANH_SIZE LDBL_MANH_SIZE 37145170Sdas#endif 38145170Sdas 39145394Sstefanfstatic const long double huge = 1.0e300; 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 */ 49145394Sstefanf if (huge + x > 0.0) 50145394Sstefanf u.e = 0.0; 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 */ 55145394Sstefanf 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 */ 64145394Sstefanf if (huge + x > 0.0) /* raise inexact flag */ 65145394Sstefanf u.bits.manl &= ~m; 66145170Sdas } 67145170Sdas return (u.e); 68145170Sdas} 69