12116Sjkh/* @(#)s_modf.c 5.1 93/09/24 */
22116Sjkh/*
32116Sjkh * ====================================================
42116Sjkh * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
52116Sjkh *
62116Sjkh * Developed at SunPro, a Sun Microsystems, Inc. business.
72116Sjkh * Permission to use, copy, modify, and distribute this
88870Srgrimes * software is freely granted, provided that this notice
92116Sjkh * is preserved.
102116Sjkh * ====================================================
112116Sjkh */
122116Sjkh
132116Sjkh#ifndef lint
1450476Speterstatic char rcsid[] = "$FreeBSD$";
152116Sjkh#endif
162116Sjkh
172116Sjkh/*
188870Srgrimes * modf(double x, double *iptr)
192116Sjkh * return fraction part of x, and return x's integral part in *iptr.
202116Sjkh * Method:
212116Sjkh *	Bit twiddling.
222116Sjkh *
232116Sjkh * Exception:
242116Sjkh *	No exception.
252116Sjkh */
262116Sjkh
272116Sjkh#include "math.h"
282116Sjkh#include "math_private.h"
292116Sjkh
302116Sjkhstatic const double one = 1.0;
312116Sjkh
3297413Salfreddouble
3397413Salfredmodf(double x, double *iptr)
342116Sjkh{
352116Sjkh	int32_t i0,i1,j0;
362116Sjkh	u_int32_t i;
372116Sjkh	EXTRACT_WORDS(i0,i1,x);
382116Sjkh	j0 = ((i0>>20)&0x7ff)-0x3ff;	/* exponent of x */
392116Sjkh	if(j0<20) {			/* integer part in high x */
402116Sjkh	    if(j0<0) {			/* |x|<1 */
412116Sjkh	        INSERT_WORDS(*iptr,i0&0x80000000,0);	/* *iptr = +-0 */
422116Sjkh		return x;
432116Sjkh	    } else {
442116Sjkh		i = (0x000fffff)>>j0;
452116Sjkh		if(((i0&i)|i1)==0) {		/* x is integral */
462116Sjkh		    u_int32_t high;
472116Sjkh		    *iptr = x;
482116Sjkh		    GET_HIGH_WORD(high,x);
492116Sjkh		    INSERT_WORDS(x,high&0x80000000,0);	/* return +-0 */
502116Sjkh		    return x;
512116Sjkh		} else {
522116Sjkh		    INSERT_WORDS(*iptr,i0&(~i),0);
532116Sjkh		    return x - *iptr;
542116Sjkh		}
552116Sjkh	    }
562116Sjkh	} else if (j0>51) {		/* no fraction part */
572116Sjkh	    u_int32_t high;
58165838Sdas	    if (j0 == 0x400) {		/* inf/NaN */
59165838Sdas		*iptr = x;
60165838Sdas		return 0.0 / x;
61165838Sdas	    }
622116Sjkh	    *iptr = x*one;
632116Sjkh	    GET_HIGH_WORD(high,x);
642116Sjkh	    INSERT_WORDS(x,high&0x80000000,0);	/* return +-0 */
652116Sjkh	    return x;
662116Sjkh	} else {			/* fraction part in low x */
672116Sjkh	    i = ((u_int32_t)(0xffffffff))>>(j0-20);
682116Sjkh	    if((i1&i)==0) { 		/* x is integral */
692116Sjkh	        u_int32_t high;
702116Sjkh		*iptr = x;
712116Sjkh		GET_HIGH_WORD(high,x);
722116Sjkh		INSERT_WORDS(x,high&0x80000000,0);	/* return +-0 */
732116Sjkh		return x;
742116Sjkh	    } else {
752116Sjkh	        INSERT_WORDS(*iptr,i0,i1&(~i));
762116Sjkh		return x - *iptr;
772116Sjkh	    }
782116Sjkh	}
792116Sjkh}
80