1 2 3 /* @(#)s_modf.c 5.1 93/09/24 */ 4 /* 5 * ==================================================== 6 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 7 * 8 * Developed at SunPro, a Sun Microsystems, Inc. business. 9 * Permission to use, copy, modify, and distribute this 10 * software is freely granted, provided that this notice 11 * is preserved. 12 * ==================================================== 13 */ 14 15 /* 16 FUNCTION 17 <<modf>>, <<modff>>---split fractional and integer parts 18 19 INDEX 20 modf 21 INDEX 22 modff 23 24 ANSI_SYNOPSIS 25 #include <math.h> 26 double modf(double <[val]>, double *<[ipart]>); 27 float modff(float <[val]>, float *<[ipart]>); 28 29 TRAD_SYNOPSIS 30 #include <math.h> 31 double modf(<[val]>, <[ipart]>) 32 double <[val]>; 33 double *<[ipart]>; 34 35 float modff(<[val]>, <[ipart]>) 36 float <[val]>; 37 float *<[ipart]>; 38 39 DESCRIPTION 40 <<modf>> splits the double <[val]> apart into an integer part 41 and a fractional part, returning the fractional part and 42 storing the integer part in <<*<[ipart]>>>. No rounding 43 whatsoever is done; the sum of the integer and fractional 44 parts is guaranteed to be exactly equal to <[val]>. That 45 is, if . <[realpart]> = modf(<[val]>, &<[intpart]>); then 46 `<<<[realpart]>+<[intpart]>>>' is the same as <[val]>. 47 <<modff>> is identical, save that it takes and returns 48 <<float>> rather than <<double>> values. 49 50 RETURNS 51 The fractional part is returned. Each result has the same 52 sign as the supplied argument <[val]>. 53 54 PORTABILITY 55 <<modf>> is ANSI C. <<modff>> is an extension. 56 57 QUICKREF 58 modf ansi pure 59 modff - pure 60 61 */ 62 63 /* 64 * modf(double x, double *iptr) 65 * return fraction part of x, and return x's integral part in *iptr. 66 * Method: 67 * Bit twiddling. 68 * 69 * Exception: 70 * No exception. 71 */ 72 73 74 static const double one = 1.0; 75 76 #define __int32_t long 77 #define __uint32_t unsigned long 78 #define __IEEE_LITTLE_ENDIAN 79 80 #ifdef __IEEE_BIG_ENDIAN 81 82 typedef union 83 { 84 struct 85 { 86 __uint32_t msw; 87 __uint32_t lsw; 88 } parts; 89 double value; 90 } ieee_double_shape_type; 91 92 #endif 93 94 #ifdef __IEEE_LITTLE_ENDIAN 95 96 typedef union 97 { 98 struct 99 { 100 __uint32_t lsw; 101 __uint32_t msw; 102 } parts; 103 double value; 104 } ieee_double_shape_type; 105 106 #endif 107 108 109 /* Get two 32 bit ints from a double. */ 110 111 #define EXTRACT_WORDS(ix0,ix1,d) \ 112 do { \ 113 ieee_double_shape_type ew_u; \ 114 ew_u.value = (d); \ 115 (ix0) = ew_u.parts.msw; \ 116 (ix1) = ew_u.parts.lsw; \ 117 } while (0) 118 119 /* Get the more significant 32 bit int from a double. */ 120 121 #define GET_HIGH_WORD(i,d) \ 122 do { \ 123 ieee_double_shape_type gh_u; \ 124 gh_u.value = (d); \ 125 (i) = gh_u.parts.msw; \ 126 } while (0) 127 128 /* Get the less significant 32 bit int from a double. */ 129 130 #define GET_LOW_WORD(i,d) \ 131 do { \ 132 ieee_double_shape_type gl_u; \ 133 gl_u.value = (d); \ 134 (i) = gl_u.parts.lsw; \ 135 } while (0) 136 137 /* Set a double from two 32 bit ints. */ 138 139 #define INSERT_WORDS(d,ix0,ix1) \ 140 do { \ 141 ieee_double_shape_type iw_u; \ 142 iw_u.parts.msw = (ix0); \ 143 iw_u.parts.lsw = (ix1); \ 144 (d) = iw_u.value; \ 145 } while (0) 146 147 148 149 150 double modf(double x, double *iptr) 151 { 152 __int32_t i0,i1,j_0; 153 __uint32_t i; 154 EXTRACT_WORDS(i0,i1,x); 155 j_0 = ((i0>>20)&0x7ff)-0x3ff; /* exponent of x */ 156 if(j_0<20) { /* integer part in high x */ 157 if(j_0<0) { /* |x|<1 */ 158 INSERT_WORDS(*iptr,i0&0x80000000U,0); /* *iptr = +-0 */ 159 return x; 160 } else { 161 i = (0x000fffff)>>j_0; 162 if(((i0&i)|i1)==0) { /* x is integral */ 163 __uint32_t high; 164 *iptr = x; 165 GET_HIGH_WORD(high,x); 166 INSERT_WORDS(x,high&0x80000000U,0); /* return +-0 */ 167 return x; 168 } else { 169 INSERT_WORDS(*iptr,i0&(~i),0); 170 return x - *iptr; 171 } 172 } 173 } else if (j_0>51) { /* no fraction part */ 174 __uint32_t high; 175 *iptr = x*one; 176 GET_HIGH_WORD(high,x); 177 INSERT_WORDS(x,high&0x80000000U,0); /* return +-0 */ 178 return x; 179 } else { /* fraction part in low x */ 180 i = ((__uint32_t)(0xffffffffU))>>(j_0-20); 181 if((i1&i)==0) { /* x is integral */ 182 __uint32_t high; 183 *iptr = x; 184 GET_HIGH_WORD(high,x); 185 INSERT_WORDS(x,high&0x80000000U,0); /* return +-0 */ 186 return x; 187 } else { 188 INSERT_WORDS(*iptr,i0,i1&(~i)); 189 return x - *iptr; 190 } 191 } 192 } 193 194 //#endif /* _DOUBLE_IS_32BITS */ 195