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