xref: /openbsd-src/lib/libm/src/s_trunc.c (revision 2f2c00629eff6a304ebffb255fc56f4fa7a1833b)
155dfb921Sbrad /* @(#)s_floor.c 5.1 93/09/24 */
255dfb921Sbrad /*
355dfb921Sbrad  * ====================================================
455dfb921Sbrad  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
555dfb921Sbrad  *
655dfb921Sbrad  * Developed at SunPro, a Sun Microsystems, Inc. business.
755dfb921Sbrad  * Permission to use, copy, modify, and distribute this
855dfb921Sbrad  * software is freely granted, provided that this notice
955dfb921Sbrad  * is preserved.
1055dfb921Sbrad  * ====================================================
1155dfb921Sbrad  */
1255dfb921Sbrad 
1355dfb921Sbrad /*
1455dfb921Sbrad  * trunc(x)
1555dfb921Sbrad  * Return x rounded toward 0 to integral value
1655dfb921Sbrad  * Method:
1755dfb921Sbrad  *	Bit twiddling.
1855dfb921Sbrad  * Exception:
1955dfb921Sbrad  *	Inexact flag raised if x not equal to trunc(x).
2055dfb921Sbrad  */
2155dfb921Sbrad 
2249393c00Smartynas #include <float.h>
2349393c00Smartynas #include <math.h>
2449393c00Smartynas 
2555dfb921Sbrad #include "math_private.h"
2655dfb921Sbrad 
2755dfb921Sbrad static const double huge = 1.0e300;
2855dfb921Sbrad 
2955dfb921Sbrad double
trunc(double x)3055dfb921Sbrad trunc(double x)
3155dfb921Sbrad {
3255fa043fSotto 	int32_t i0,i1,jj0;
3371324c4cSotto 	u_int32_t i;
3455dfb921Sbrad 	EXTRACT_WORDS(i0,i1,x);
3555fa043fSotto 	jj0 = ((i0>>20)&0x7ff)-0x3ff;
3655fa043fSotto 	if(jj0<20) {
3755fa043fSotto 	    if(jj0<0) { 	/* raise inexact if x != 0 */
3855dfb921Sbrad 		if(huge+x>0.0) {/* |x|<1, so return 0*sign(x) */
3955dfb921Sbrad 		    i0 &= 0x80000000U;
4055dfb921Sbrad 		    i1 = 0;
4155dfb921Sbrad 		}
4255dfb921Sbrad 	    } else {
4355fa043fSotto 		i = (0x000fffff)>>jj0;
4455dfb921Sbrad 		if(((i0&i)|i1)==0) return x; /* x is integral */
4555dfb921Sbrad 		if(huge+x>0.0) {	/* raise inexact flag */
4655dfb921Sbrad 		    i0 &= (~i); i1=0;
4755dfb921Sbrad 		}
4855dfb921Sbrad 	    }
4955fa043fSotto 	} else if (jj0>51) {
5055fa043fSotto 	    if(jj0==0x400) return x+x;	/* inf or NaN */
5155dfb921Sbrad 	    else return x;		/* x is integral */
5255dfb921Sbrad 	} else {
5355fa043fSotto 	    i = ((u_int32_t)(0xffffffff))>>(jj0-20);
5455dfb921Sbrad 	    if((i1&i)==0) return x;	/* x is integral */
5555dfb921Sbrad 	    if(huge+x>0.0)		/* raise inexact flag */
5655dfb921Sbrad 		i1 &= (~i);
5755dfb921Sbrad 	}
5855dfb921Sbrad 	INSERT_WORDS(x,i0,i1);
5955dfb921Sbrad 	return x;
6055dfb921Sbrad }
61*2f2c0062Sguenther DEF_STD(trunc);
62*2f2c0062Sguenther LDBL_MAYBE_UNUSED_CLONE(trunc);
63