OSDN Git Service

From Steve Papacharalambous:
[uclinux-h8/uClibc.git] / libm / powerpc / classic / s_frexp.c
1 /*******************************************************************************
2 *                                                                              *
3 *      File frexpldexp.c,                                                      *
4 *      Functions frexp(x) and ldexp(x),                                        *
5 *      Implementation of frexp and ldexp functions for the PowerPC.            *
6 *                                                                              *
7 *      Copyright © 1991 Apple Computer, Inc.  All rights reserved.             *
8 *                                                                              *
9 *      Written by Ali Sazegari, started on January 1991,                       *
10 *                                                                              *
11 *      W A R N I N G:  This routine expects a 64 bit double model.             *
12 *                                                                              *
13 *      December03 1992: first rs6000 implementation.                           *
14 *      October 05 1993: added special cases for NaN and ° in frexp.            *
15 *      May     27 1997: improved the performance of frexp by eliminating the   *
16 *                       switch statement.                                      *
17 *        June      13 2001: (ram) rewrote frexp to eliminate calls to scalb and    *
18 *                               logb.                                                                    *
19 *                                                                              *
20 *******************************************************************************/
21
22 #include <limits.h>
23 #include <math.h>
24 #include <endian.h>
25
26 static const double two54 =  1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */
27
28 typedef union
29       {
30       struct {
31 #if (__BYTE_ORDER == __BIG_ENDIAN)
32         unsigned long int hi;
33         unsigned long int lo;
34 #else
35         unsigned long int lo;
36         unsigned long int hi;
37 #endif
38       } words;
39       double dbl;
40       } DblInHex;
41
42 libm_hidden_proto(frexp)
43 double frexp ( double value, int *eptr )
44       {
45       DblInHex argument;
46       unsigned long int valueHead;
47
48       argument.dbl = value;
49       valueHead = argument.words.hi & 0x7fffffffUL; // valueHead <- |x|
50
51       *eptr = 0;
52         if ( valueHead >= 0x7ff00000 || ( valueHead | argument.words.lo ) == 0 )
53                 return value;           // 0, inf, or NaN
54
55         if ( valueHead < 0x00100000 )
56                 {       // denorm
57                 argument.dbl = two54 * value;
58                 valueHead = argument.words.hi &0x7fffffff;
59                 *eptr = -54;
60                 }
61         *eptr += ( valueHead >> 20 ) - 1022;
62         argument.words.hi = ( argument.words.hi & 0x800fffff ) | 0x3fe00000;
63         return argument.dbl;
64         }
65 libm_hidden_def(frexp)