1*6232589aSDavid Schultz /* @(#)s_modf.c 5.1 93/09/24 */ 2*6232589aSDavid Schultz /* 3*6232589aSDavid Schultz * ==================================================== 4*6232589aSDavid Schultz * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 5*6232589aSDavid Schultz * 6*6232589aSDavid Schultz * Developed at SunPro, a Sun Microsystems, Inc. business. 7*6232589aSDavid Schultz * Permission to use, copy, modify, and distribute this 8*6232589aSDavid Schultz * software is freely granted, provided that this notice 9*6232589aSDavid Schultz * is preserved. 10*6232589aSDavid Schultz * ==================================================== 11*6232589aSDavid Schultz */ 12*6232589aSDavid Schultz 13*6232589aSDavid Schultz #include <sys/cdefs.h> 14*6232589aSDavid Schultz __FBSDID("$FreeBSD$"); 15*6232589aSDavid Schultz 16*6232589aSDavid Schultz /* 17*6232589aSDavid Schultz * modf(double x, double *iptr) 18*6232589aSDavid Schultz * return fraction part of x, and return x's integral part in *iptr. 19*6232589aSDavid Schultz * Method: 20*6232589aSDavid Schultz * Bit twiddling. 21*6232589aSDavid Schultz * 22*6232589aSDavid Schultz * Exception: 23*6232589aSDavid Schultz * No exception. 24*6232589aSDavid Schultz */ 25*6232589aSDavid Schultz 26*6232589aSDavid Schultz #include <sys/types.h> 27*6232589aSDavid Schultz #include <machine/endian.h> 28*6232589aSDavid Schultz #include <math.h> 29*6232589aSDavid Schultz 30*6232589aSDavid Schultz /* Bit fiddling routines copied from msun/src/math_private.h,v 1.15 */ 31*6232589aSDavid Schultz 32*6232589aSDavid Schultz #if BYTE_ORDER == BIG_ENDIAN 33*6232589aSDavid Schultz 34*6232589aSDavid Schultz typedef union 35*6232589aSDavid Schultz { 36*6232589aSDavid Schultz double value; 37*6232589aSDavid Schultz struct 38*6232589aSDavid Schultz { 39*6232589aSDavid Schultz u_int32_t msw; 40*6232589aSDavid Schultz u_int32_t lsw; 41*6232589aSDavid Schultz } parts; 42*6232589aSDavid Schultz } ieee_double_shape_type; 43*6232589aSDavid Schultz 44*6232589aSDavid Schultz #endif 45*6232589aSDavid Schultz 46*6232589aSDavid Schultz #if BYTE_ORDER == LITTLE_ENDIAN 47*6232589aSDavid Schultz 48*6232589aSDavid Schultz typedef union 49*6232589aSDavid Schultz { 50*6232589aSDavid Schultz double value; 51*6232589aSDavid Schultz struct 52*6232589aSDavid Schultz { 53*6232589aSDavid Schultz u_int32_t lsw; 54*6232589aSDavid Schultz u_int32_t msw; 55*6232589aSDavid Schultz } parts; 56*6232589aSDavid Schultz } ieee_double_shape_type; 57*6232589aSDavid Schultz 58*6232589aSDavid Schultz #endif 59*6232589aSDavid Schultz 60*6232589aSDavid Schultz /* Get two 32 bit ints from a double. */ 61*6232589aSDavid Schultz 62*6232589aSDavid Schultz #define EXTRACT_WORDS(ix0,ix1,d) \ 63*6232589aSDavid Schultz do { \ 64*6232589aSDavid Schultz ieee_double_shape_type ew_u; \ 65*6232589aSDavid Schultz ew_u.value = (d); \ 66*6232589aSDavid Schultz (ix0) = ew_u.parts.msw; \ 67*6232589aSDavid Schultz (ix1) = ew_u.parts.lsw; \ 68*6232589aSDavid Schultz } while (0) 69*6232589aSDavid Schultz 70*6232589aSDavid Schultz /* Get the more significant 32 bit int from a double. */ 71*6232589aSDavid Schultz 72*6232589aSDavid Schultz #define GET_HIGH_WORD(i,d) \ 73*6232589aSDavid Schultz do { \ 74*6232589aSDavid Schultz ieee_double_shape_type gh_u; \ 75*6232589aSDavid Schultz gh_u.value = (d); \ 76*6232589aSDavid Schultz (i) = gh_u.parts.msw; \ 77*6232589aSDavid Schultz } while (0) 78*6232589aSDavid Schultz 79*6232589aSDavid Schultz /* Set a double from two 32 bit ints. */ 80*6232589aSDavid Schultz 81*6232589aSDavid Schultz #define INSERT_WORDS(d,ix0,ix1) \ 82*6232589aSDavid Schultz do { \ 83*6232589aSDavid Schultz ieee_double_shape_type iw_u; \ 84*6232589aSDavid Schultz iw_u.parts.msw = (ix0); \ 85*6232589aSDavid Schultz iw_u.parts.lsw = (ix1); \ 86*6232589aSDavid Schultz (d) = iw_u.value; \ 87*6232589aSDavid Schultz } while (0) 88*6232589aSDavid Schultz 89*6232589aSDavid Schultz static const double one = 1.0; 90*6232589aSDavid Schultz 91*6232589aSDavid Schultz double 92*6232589aSDavid Schultz modf(double x, double *iptr) 93*6232589aSDavid Schultz { 94*6232589aSDavid Schultz int32_t i0,i1,j0; 95*6232589aSDavid Schultz u_int32_t i; 96*6232589aSDavid Schultz EXTRACT_WORDS(i0,i1,x); 97*6232589aSDavid Schultz j0 = ((i0>>20)&0x7ff)-0x3ff; /* exponent of x */ 98*6232589aSDavid Schultz if(j0<20) { /* integer part in high x */ 99*6232589aSDavid Schultz if(j0<0) { /* |x|<1 */ 100*6232589aSDavid Schultz INSERT_WORDS(*iptr,i0&0x80000000,0); /* *iptr = +-0 */ 101*6232589aSDavid Schultz return x; 102*6232589aSDavid Schultz } else { 103*6232589aSDavid Schultz i = (0x000fffff)>>j0; 104*6232589aSDavid Schultz if(((i0&i)|i1)==0) { /* x is integral */ 105*6232589aSDavid Schultz u_int32_t high; 106*6232589aSDavid Schultz *iptr = x; 107*6232589aSDavid Schultz GET_HIGH_WORD(high,x); 108*6232589aSDavid Schultz INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */ 109*6232589aSDavid Schultz return x; 110*6232589aSDavid Schultz } else { 111*6232589aSDavid Schultz INSERT_WORDS(*iptr,i0&(~i),0); 112*6232589aSDavid Schultz return x - *iptr; 113*6232589aSDavid Schultz } 114*6232589aSDavid Schultz } 115*6232589aSDavid Schultz } else if (j0>51) { /* no fraction part */ 116*6232589aSDavid Schultz u_int32_t high; 117*6232589aSDavid Schultz if (j0 == 0x400) { /* inf/NaN */ 118*6232589aSDavid Schultz *iptr = x; 119*6232589aSDavid Schultz return 0.0 / x; 120*6232589aSDavid Schultz } 121*6232589aSDavid Schultz *iptr = x*one; 122*6232589aSDavid Schultz GET_HIGH_WORD(high,x); 123*6232589aSDavid Schultz INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */ 124*6232589aSDavid Schultz return x; 125*6232589aSDavid Schultz } else { /* fraction part in low x */ 126*6232589aSDavid Schultz i = ((u_int32_t)(0xffffffff))>>(j0-20); 127*6232589aSDavid Schultz if((i1&i)==0) { /* x is integral */ 128*6232589aSDavid Schultz u_int32_t high; 129*6232589aSDavid Schultz *iptr = x; 130*6232589aSDavid Schultz GET_HIGH_WORD(high,x); 131*6232589aSDavid Schultz INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */ 132*6232589aSDavid Schultz return x; 133*6232589aSDavid Schultz } else { 134*6232589aSDavid Schultz INSERT_WORDS(*iptr,i0,i1&(~i)); 135*6232589aSDavid Schultz return x - *iptr; 136*6232589aSDavid Schultz } 137*6232589aSDavid Schultz } 138*6232589aSDavid Schultz } 139