OSDN Git Service

Merge branch 'master' of git://github.com/monaka/binutils
[pf3gnuchains/pf3gnuchains3x.git] / newlib / libm / common / s_modf.c
1
2 /* @(#)s_modf.c 5.1 93/09/24 */
3 /*
4  * ====================================================
5  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
6  *
7  * Developed at SunPro, a Sun Microsystems, Inc. business.
8  * Permission to use, copy, modify, and distribute this
9  * software is freely granted, provided that this notice 
10  * is preserved.
11  * ====================================================
12  */
13
14 /*
15 FUNCTION
16        <<modf>>, <<modff>>---split fractional and integer parts
17
18 INDEX
19         modf
20 INDEX
21         modff
22
23 ANSI_SYNOPSIS
24         #include <math.h>
25         double modf(double <[val]>, double *<[ipart]>);
26         float modff(float <[val]>, float *<[ipart]>);
27
28 TRAD_SYNOPSIS
29         #include <math.h>
30         double modf(<[val]>, <[ipart]>)
31         double <[val]>;
32         double *<[ipart]>;
33
34         float modff(<[val]>, <[ipart]>)
35         float <[val]>;
36         float *<[ipart]>;
37
38 DESCRIPTION
39         <<modf>> splits the double <[val]> apart into an integer part
40         and a fractional part, returning the fractional part and
41         storing the integer part in <<*<[ipart]>>>.  No rounding
42         whatsoever is done; the sum of the integer and fractional
43         parts is guaranteed to be exactly  equal to <[val]>.   That
44         is, if <[realpart]> = modf(<[val]>, &<[intpart]>); then
45         `<<<[realpart]>+<[intpart]>>>' is the same as <[val]>.
46         <<modff>> is identical, save that it takes and returns
47         <<float>> rather than <<double>> values. 
48
49 RETURNS
50         The fractional part is returned.  Each result has the same
51         sign as the supplied argument <[val]>.
52
53 PORTABILITY
54         <<modf>> is ANSI C. <<modff>> is an extension.
55
56 QUICKREF
57         modf  ansi pure 
58         modff - pure
59
60 */
61
62 /*
63  * modf(double x, double *iptr) 
64  * return fraction part of x, and return x's integral part in *iptr.
65  * Method:
66  *      Bit twiddling.
67  *
68  * Exception:
69  *      No exception.
70  */
71
72 #include "fdlibm.h"
73
74 #ifndef _DOUBLE_IS_32BITS
75
76 #ifdef __STDC__
77 static const double one = 1.0;
78 #else
79 static double one = 1.0;
80 #endif
81
82 #ifdef __STDC__
83         double modf(double x, double *iptr)
84 #else
85         double modf(x, iptr)
86         double x,*iptr;
87 #endif
88 {
89         __int32_t i0,i1,j0;
90         __uint32_t i;
91         EXTRACT_WORDS(i0,i1,x);
92         j0 = ((i0>>20)&0x7ff)-0x3ff;    /* exponent of x */
93         if(j0<20) {                     /* integer part in high x */
94             if(j0<0) {                  /* |x|<1 */
95                 INSERT_WORDS(*iptr,i0&0x80000000,0);    /* *iptr = +-0 */
96                 return x;
97             } else {
98                 i = (0x000fffff)>>j0;
99                 if(((i0&i)|i1)==0) {            /* x is integral */
100                     __uint32_t high;
101                     *iptr = x;
102                     GET_HIGH_WORD(high,x);
103                     INSERT_WORDS(x,high&0x80000000,0);  /* return +-0 */
104                     return x;
105                 } else {
106                     INSERT_WORDS(*iptr,i0&(~i),0);
107                     return x - *iptr;
108                 }
109             }
110         } else if (j0>51) {             /* no fraction part */
111             __uint32_t high;
112             *iptr = x*one;
113             GET_HIGH_WORD(high,x);
114             INSERT_WORDS(x,high&0x80000000,0);  /* return +-0 */
115             return x;
116         } else {                        /* fraction part in low x */
117             i = ((__uint32_t)(0xffffffff))>>(j0-20);
118             if((i1&i)==0) {             /* x is integral */
119                 __uint32_t high;
120                 *iptr = x;
121                 GET_HIGH_WORD(high,x);
122                 INSERT_WORDS(x,high&0x80000000,0);      /* return +-0 */
123                 return x;
124             } else {
125                 INSERT_WORDS(*iptr,i0,i1&(~i));
126                 return x - *iptr;
127             }
128         }
129 }
130
131 #endif /* _DOUBLE_IS_32BITS */