Home | History | Annotate | Line # | Download | only in src
      1 /* s_rintf.c -- float version of s_rint.c.
      2  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian (at) cygnus.com.
      3  */
      4 
      5 /*
      6  * ====================================================
      7  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
      8  *
      9  * Developed at SunPro, a Sun Microsystems, Inc. business.
     10  * Permission to use, copy, modify, and distribute this
     11  * software is freely granted, provided that this notice
     12  * is preserved.
     13  * ====================================================
     14  */
     15 
     16 #include <sys/cdefs.h>
     17 #if defined(LIBM_SCCS) && !defined(lint)
     18 __RCSID("$NetBSD: s_rintf.c,v 1.9 2008/04/25 22:21:53 christos Exp $");
     19 #endif
     20 
     21 #include "math.h"
     22 #include "math_private.h"
     23 
     24 static const float
     25 TWO23[2]={
     26   8.3886080000e+06, /* 0x4b000000 */
     27  -8.3886080000e+06, /* 0xcb000000 */
     28 };
     29 
     30 float
     31 rintf(float x)
     32 {
     33 	int32_t i0,jj0,sx;
     34 	u_int32_t i,i1;
     35 #ifdef __i386__ /* XXX gcc4 will omit the rounding otherwise */
     36 	volatile
     37 #endif
     38 		float w;
     39 	float t;
     40 	GET_FLOAT_WORD(i0,x);
     41 	sx = (i0>>31)&1;
     42 	jj0 = ((i0>>23)&0xff)-0x7f;
     43 	if(jj0<23) {
     44 	    if(jj0<0) {
     45 		if((i0&0x7fffffff)==0) return x;
     46 		i1 = (i0&0x07fffff);
     47 		i0 &= 0xfff00000;
     48 		i0 |= ((i1|-i1)>>9)&0x400000;
     49 		SET_FLOAT_WORD(x,i0);
     50 	        w = TWO23[sx]+x;
     51 	        t =  w-TWO23[sx];
     52 		GET_FLOAT_WORD(i0,t);
     53 		SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31));
     54 	        return t;
     55 	    } else {
     56 		i = (0x007fffff)>>jj0;
     57 		if((i0&i)==0) return x; /* x is integral */
     58 		i>>=1;
     59 		if((i0&i)!=0) i0 = (i0&(~i))|((0x100000)>>jj0);
     60 	    }
     61 	} else {
     62 	    if(jj0==0x80) return x+x;	/* inf or NaN */
     63 	    else return x;		/* x is integral */
     64 	}
     65 	SET_FLOAT_WORD(x,i0);
     66 	w = TWO23[sx]+x;
     67 	return w-TWO23[sx];
     68 }
     69