| | |
| | | /* @(#)s_floor.c 5.1 93/09/24 */ |
| | | /* |
| | | * ==================================================== |
| | | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
| | |
| | | * ==================================================== |
| | | */ |
| | | |
| | | #if defined(LIBM_SCCS) && !defined(lint) |
| | | static const char rcsid[] = |
| | | "$NetBSD: s_floor.c,v 1.8 1995/05/10 20:47:20 jtc Exp $"; |
| | | #endif |
| | | |
| | | /* |
| | | * floor(x) |
| | | * Return x rounded toward -inf to integral value |
| | |
| | | * Inexact flag raised if x not equal to floor(x). |
| | | */ |
| | | |
| | | /*#include <features.h>*/ |
| | | /* Prevent math.h from defining a colliding inline */ |
| | | #undef __USE_EXTERN_INLINES |
| | | #include "math_libm.h" |
| | | #include "math_private.h" |
| | | |
| | | #ifdef __STDC__ |
| | | static const double huge_val = 1.0e300; |
| | | #else |
| | | static double huge_val = 1.0e300; |
| | | #endif |
| | | static const double huge = 1.0e300; |
| | | |
| | | libm_hidden_proto(floor) |
| | | #ifdef __STDC__ |
| | | double floor(double x) |
| | | #else |
| | | double floor(x) |
| | | double x; |
| | | #endif |
| | | double floor(double x) |
| | | { |
| | | int32_t i0, i1, j0; |
| | | u_int32_t i, j; |
| | | EXTRACT_WORDS(i0, i1, x); |
| | | j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; |
| | | if (j0 < 20) { |
| | | if (j0 < 0) { /* raise inexact if x != 0 */ |
| | | if (huge_val + x > 0.0) { /* return 0*sign(x) if |x|<1 */ |
| | | if (i0 >= 0) { |
| | | i0 = i1 = 0; |
| | | } else if (((i0 & 0x7fffffff) | i1) != 0) { |
| | | i0 = 0xbff00000; |
| | | i1 = 0; |
| | | } |
| | | } |
| | | } else { |
| | | i = (0x000fffff) >> j0; |
| | | if (((i0 & i) | i1) == 0) |
| | | return x; /* x is integral */ |
| | | if (huge_val + x > 0.0) { /* raise inexact flag */ |
| | | if (i0 < 0) |
| | | i0 += (0x00100000) >> j0; |
| | | i0 &= (~i); |
| | | i1 = 0; |
| | | } |
| | | } |
| | | } else if (j0 > 51) { |
| | | if (j0 == 0x400) |
| | | return x + x; /* inf or NaN */ |
| | | else |
| | | return x; /* x is integral */ |
| | | } else { |
| | | i = ((u_int32_t) (0xffffffff)) >> (j0 - 20); |
| | | if ((i1 & i) == 0) |
| | | return x; /* x is integral */ |
| | | if (huge_val + x > 0.0) { /* raise inexact flag */ |
| | | if (i0 < 0) { |
| | | if (j0 == 20) |
| | | i0 += 1; |
| | | else { |
| | | j = i1 + (1 << (52 - j0)); |
| | | if (j < (u_int32_t) i1) |
| | | i0 += 1; /* got a carry */ |
| | | i1 = j; |
| | | } |
| | | } |
| | | i1 &= (~i); |
| | | } |
| | | } |
| | | INSERT_WORDS(x, i0, i1); |
| | | return x; |
| | | int32_t i0,i1,j0; |
| | | u_int32_t i,j; |
| | | EXTRACT_WORDS(i0,i1,x); |
| | | j0 = ((i0>>20)&0x7ff)-0x3ff; |
| | | if(j0<20) { |
| | | if(j0<0) { /* raise inexact if x != 0 */ |
| | | if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ |
| | | if(i0>=0) {i0=i1=0;} |
| | | else if(((i0&0x7fffffff)|i1)!=0) |
| | | { i0=0xbff00000;i1=0;} |
| | | } |
| | | } else { |
| | | i = (0x000fffff)>>j0; |
| | | if(((i0&i)|i1)==0) return x; /* x is integral */ |
| | | if(huge+x>0.0) { /* raise inexact flag */ |
| | | if(i0<0) i0 += (0x00100000)>>j0; |
| | | i0 &= (~i); i1=0; |
| | | } |
| | | } |
| | | } else if (j0>51) { |
| | | if(j0==0x400) return x+x; /* inf or NaN */ |
| | | else return x; /* x is integral */ |
| | | } else { |
| | | i = ((u_int32_t)(0xffffffff))>>(j0-20); |
| | | if((i1&i)==0) return x; /* x is integral */ |
| | | if(huge+x>0.0) { /* raise inexact flag */ |
| | | if(i0<0) { |
| | | if(j0==20) i0+=1; |
| | | else { |
| | | j = i1+(1<<(52-j0)); |
| | | if(j<(u_int32_t)i1) i0 +=1 ; /* got a carry */ |
| | | i1=j; |
| | | } |
| | | } |
| | | i1 &= (~i); |
| | | } |
| | | } |
| | | INSERT_WORDS(x,i0,i1); |
| | | return x; |
| | | } |
| | | |
| | | libm_hidden_def(floor) |