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 Schultztruncl(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