1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
19da2e3ebdSchin *                   Phong Vo <kpv@research.att.com>                    *
20da2e3ebdSchin *                                                                      *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #pragma prototyped
23da2e3ebdSchin 
24da2e3ebdSchin /*
25da2e3ebdSchin  * frexp/ldexp implementation
26da2e3ebdSchin  */
27da2e3ebdSchin 
28da2e3ebdSchin #include <ast.h>
29da2e3ebdSchin 
30da2e3ebdSchin #include "FEATURE/float"
31da2e3ebdSchin 
32da2e3ebdSchin #if _lib_frexp && _lib_ldexp
33da2e3ebdSchin 
34da2e3ebdSchin NoN(frexp)
35da2e3ebdSchin 
36da2e3ebdSchin #else
37da2e3ebdSchin 
38da2e3ebdSchin #if defined(_ast_dbl_exp_index) && defined(_ast_dbl_exp_shift)
39da2e3ebdSchin 
40da2e3ebdSchin #define INIT()		_ast_dbl_exp_t _pow_
41da2e3ebdSchin #define pow2(i)		(_pow_.f=1,_pow_.e[_ast_dbl_exp_index]+=((i)<<_ast_dbl_exp_shift),_pow_.f)
42da2e3ebdSchin 
43da2e3ebdSchin #else
44da2e3ebdSchin 
45da2e3ebdSchin static double		pow2tab[DBL_MAX_EXP + 1];
46da2e3ebdSchin 
47da2e3ebdSchin static int
48da2e3ebdSchin init(void)
49da2e3ebdSchin {
50da2e3ebdSchin 	register int	x;
51da2e3ebdSchin 	double		g;
52da2e3ebdSchin 
53da2e3ebdSchin 	g = 1;
54da2e3ebdSchin 	for (x = 0; x < elementsof(pow2tab); x++)
55da2e3ebdSchin 	{
56da2e3ebdSchin 		pow2tab[x] = g;
57da2e3ebdSchin 		g *= 2;
58da2e3ebdSchin 	}
59da2e3ebdSchin 	return 0;
60da2e3ebdSchin }
61da2e3ebdSchin 
62da2e3ebdSchin #define INIT()		(pow2tab[0]?0:init())
63da2e3ebdSchin 
64da2e3ebdSchin #define pow2(i)		pow2tab[i]
65da2e3ebdSchin 
66da2e3ebdSchin #endif
67da2e3ebdSchin 
68da2e3ebdSchin #if !_lib_frexp
69da2e3ebdSchin 
70da2e3ebdSchin extern double
71da2e3ebdSchin frexp(double f, int* p)
72da2e3ebdSchin {
73da2e3ebdSchin 	register int	k;
74da2e3ebdSchin 	register int	x;
75da2e3ebdSchin 	double		g;
76da2e3ebdSchin 
77da2e3ebdSchin 	INIT();
78da2e3ebdSchin 
79da2e3ebdSchin 	/*
80da2e3ebdSchin 	 * normalize
81da2e3ebdSchin 	 */
82da2e3ebdSchin 
83da2e3ebdSchin 	x = k = DBL_MAX_EXP / 2;
84da2e3ebdSchin 	if (f < 1)
85da2e3ebdSchin 	{
86da2e3ebdSchin 		g = 1.0L / f;
87da2e3ebdSchin 		for (;;)
88da2e3ebdSchin 		{
89da2e3ebdSchin 			k = (k + 1) / 2;
90da2e3ebdSchin 			if (g < pow2(x))
91da2e3ebdSchin 				x -= k;
92da2e3ebdSchin 			else if (k == 1 && g < pow2(x+1))
93da2e3ebdSchin 				break;
94da2e3ebdSchin 			else
95da2e3ebdSchin 				x += k;
96da2e3ebdSchin 		}
97da2e3ebdSchin 		if (g == pow2(x))
98da2e3ebdSchin 			x--;
99da2e3ebdSchin 		x = -x;
100da2e3ebdSchin 	}
101da2e3ebdSchin 	else if (f > 1)
102da2e3ebdSchin 	{
103da2e3ebdSchin 		for (;;)
104da2e3ebdSchin 		{
105da2e3ebdSchin 			k = (k + 1) / 2;
106da2e3ebdSchin 			if (f > pow2(x))
107da2e3ebdSchin 				x += k;
108da2e3ebdSchin 			else if (k == 1 && f > pow2(x-1))
109da2e3ebdSchin 				break;
110da2e3ebdSchin 			else
111da2e3ebdSchin 				x -= k;
112da2e3ebdSchin 		}
113da2e3ebdSchin 		if (f == pow2(x))
114da2e3ebdSchin 			x++;
115da2e3ebdSchin 	}
116da2e3ebdSchin 	else
117da2e3ebdSchin 		x = 1;
118da2e3ebdSchin 	*p = x;
119da2e3ebdSchin 
120da2e3ebdSchin 	/*
121da2e3ebdSchin 	 * shift
122da2e3ebdSchin 	 */
123da2e3ebdSchin 
124da2e3ebdSchin 	x = -x;
125da2e3ebdSchin 	if (x < 0)
126da2e3ebdSchin 		f /= pow2(-x);
127da2e3ebdSchin 	else if (x < DBL_MAX_EXP)
128da2e3ebdSchin 		f *= pow2(x);
129da2e3ebdSchin 	else
130da2e3ebdSchin 		f = (f * pow2(DBL_MAX_EXP - 1)) * pow2(x - (DBL_MAX_EXP - 1));
131da2e3ebdSchin 	return f;
132da2e3ebdSchin }
133da2e3ebdSchin 
134da2e3ebdSchin #endif
135da2e3ebdSchin 
136da2e3ebdSchin #if !_lib_ldexp
137da2e3ebdSchin 
138da2e3ebdSchin extern double
139da2e3ebdSchin ldexp(double f, register int x)
140da2e3ebdSchin {
141da2e3ebdSchin 	INIT();
142da2e3ebdSchin 	if (x < 0)
143da2e3ebdSchin 		f /= pow2(-x);
144da2e3ebdSchin 	else if (x < DBL_MAX_EXP)
145da2e3ebdSchin 		f *= pow2(x);
146da2e3ebdSchin 	else
147da2e3ebdSchin 		f = (f * pow2(DBL_MAX_EXP - 1)) * pow2(x - (DBL_MAX_EXP - 1));
148da2e3ebdSchin 	return f;
149da2e3ebdSchin }
150da2e3ebdSchin 
151da2e3ebdSchin #endif
152da2e3ebdSchin 
153da2e3ebdSchin #endif
154