xref: /reactos/sdk/lib/crt/math/s_modf.c (revision c2c66aff)
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