slouken@2758: /* @(#)s_floor.c 5.1 93/09/24 */ slouken@2758: /* slouken@2758: * ==================================================== slouken@2758: * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. slouken@2758: * slouken@2758: * Developed at SunPro, a Sun Microsystems, Inc. business. slouken@2758: * Permission to use, copy, modify, and distribute this slouken@2758: * software is freely granted, provided that this notice slouken@2758: * is preserved. slouken@2758: * ==================================================== slouken@2758: */ slouken@2758: slouken@2758: #if defined(LIBM_SCCS) && !defined(lint) slouken@2758: static char rcsid[] = slouken@2758: "$NetBSD: s_floor.c,v 1.8 1995/05/10 20:47:20 jtc Exp $"; slouken@2758: #endif slouken@2758: slouken@2758: /* slouken@2758: * floor(x) slouken@2758: * Return x rounded toward -inf to integral value slouken@2758: * Method: slouken@2758: * Bit twiddling. slouken@2758: * Exception: slouken@2758: * Inexact flag raised if x not equal to floor(x). slouken@2758: */ slouken@2758: slouken@2758: #include "math.h" slouken@2758: #include "math_private.h" slouken@2758: slouken@2758: #ifdef __STDC__ slouken@2758: static const double huge = 1.0e300; slouken@2758: #else slouken@2758: static double huge = 1.0e300; slouken@2758: #endif slouken@2758: slouken@2758: libm_hidden_proto(floor) slouken@2758: #ifdef __STDC__ slouken@2758: double floor(double x) slouken@2758: #else slouken@2758: double floor(x) slouken@2758: double x; slouken@2758: #endif slouken@2758: { slouken@2758: int32_t i0, i1, j0; slouken@2758: u_int32_t i, j; slouken@2758: EXTRACT_WORDS(i0, i1, x); slouken@2758: j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; slouken@2758: if (j0 < 20) { slouken@2758: if (j0 < 0) { /* raise inexact if x != 0 */ slouken@2758: if (huge + x > 0.0) { /* return 0*sign(x) if |x|<1 */ slouken@2758: if (i0 >= 0) { slouken@2758: i0 = i1 = 0; slouken@2758: } else if (((i0 & 0x7fffffff) | i1) != 0) { slouken@2758: i0 = 0xbff00000; slouken@2758: i1 = 0; slouken@2758: } slouken@2758: } slouken@2758: } else { slouken@2758: i = (0x000fffff) >> j0; slouken@2758: if (((i0 & i) | i1) == 0) slouken@2758: return x; /* x is integral */ slouken@2758: if (huge + x > 0.0) { /* raise inexact flag */ slouken@2758: if (i0 < 0) slouken@2758: i0 += (0x00100000) >> j0; slouken@2758: i0 &= (~i); slouken@2758: i1 = 0; slouken@2758: } slouken@2758: } slouken@2758: } else if (j0 > 51) { slouken@2758: if (j0 == 0x400) slouken@2758: return x + x; /* inf or NaN */ slouken@2758: else slouken@2758: return x; /* x is integral */ slouken@2758: } else { slouken@2758: i = ((u_int32_t) (0xffffffff)) >> (j0 - 20); slouken@2758: if ((i1 & i) == 0) slouken@2758: return x; /* x is integral */ slouken@2758: if (huge + x > 0.0) { /* raise inexact flag */ slouken@2758: if (i0 < 0) { slouken@2758: if (j0 == 20) slouken@2758: i0 += 1; slouken@2758: else { slouken@2758: j = i1 + (1 << (52 - j0)); slouken@2758: if (j < i1) slouken@2758: i0 += 1; /* got a carry */ slouken@2758: i1 = j; slouken@2758: } slouken@2758: } slouken@2758: i1 &= (~i); slouken@2758: } slouken@2758: } slouken@2758: INSERT_WORDS(x, i0, i1); slouken@2758: return x; slouken@2758: } slouken@2758: slouken@2758: libm_hidden_def(floor)