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