xref: /titanic_41/usr/src/lib/libast/common/comp/frexpl.c (revision 3e14f97f673e8a630f076077de35afdd43dc1587)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*3e14f97fSRoger A. Faulkner *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6da2e3ebdSchin *                  Common Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10da2e3ebdSchin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11da2e3ebdSchin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
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  * frexpl/ldexpl implementation
26da2e3ebdSchin  */
27da2e3ebdSchin 
28da2e3ebdSchin #include <ast.h>
29da2e3ebdSchin 
30da2e3ebdSchin #include "FEATURE/float"
31da2e3ebdSchin 
32da2e3ebdSchin #if _lib_frexpl && _lib_ldexpl
33da2e3ebdSchin 
34da2e3ebdSchin NoN(frexpl)
35da2e3ebdSchin 
36da2e3ebdSchin #else
37da2e3ebdSchin 
38da2e3ebdSchin #ifndef LDBL_MAX_EXP
39da2e3ebdSchin #define LDBL_MAX_EXP	DBL_MAX_EXP
40da2e3ebdSchin #endif
41da2e3ebdSchin 
42da2e3ebdSchin #if defined(_ast_fltmax_exp_index) && defined(_ast_fltmax_exp_shift)
43da2e3ebdSchin 
44da2e3ebdSchin #define INIT()		_ast_fltmax_exp_t _pow_
45da2e3ebdSchin #define pow2(i)		(_pow_.f=1,_pow_.e[_ast_fltmax_exp_index]+=((i)<<_ast_fltmax_exp_shift),_pow_.f)
46da2e3ebdSchin 
47da2e3ebdSchin #else
48da2e3ebdSchin 
49da2e3ebdSchin static _ast_fltmax_t	pow2tab[LDBL_MAX_EXP + 1];
50da2e3ebdSchin 
51da2e3ebdSchin static int
52da2e3ebdSchin init(void)
53da2e3ebdSchin {
54da2e3ebdSchin 	register int		x;
55da2e3ebdSchin 	_ast_fltmax_t		g;
56da2e3ebdSchin 
57da2e3ebdSchin 	g = 1;
58da2e3ebdSchin 	for (x = 0; x < elementsof(pow2tab); x++)
59da2e3ebdSchin 	{
60da2e3ebdSchin 		pow2tab[x] = g;
61da2e3ebdSchin 		g *= 2;
62da2e3ebdSchin 	}
63da2e3ebdSchin 	return 0;
64da2e3ebdSchin }
65da2e3ebdSchin 
66da2e3ebdSchin #define INIT()		(pow2tab[0]?0:init())
67da2e3ebdSchin 
68da2e3ebdSchin #define pow2(i)		(pow2tab[i])
69da2e3ebdSchin 
70da2e3ebdSchin #endif
71da2e3ebdSchin 
72da2e3ebdSchin #if !_lib_frexpl
73da2e3ebdSchin 
74da2e3ebdSchin #undef	frexpl
75da2e3ebdSchin 
76da2e3ebdSchin extern _ast_fltmax_t
77da2e3ebdSchin frexpl(_ast_fltmax_t f, int* p)
78da2e3ebdSchin {
79da2e3ebdSchin 	register int		k;
80da2e3ebdSchin 	register int		x;
81da2e3ebdSchin 	_ast_fltmax_t		g;
82da2e3ebdSchin 
83da2e3ebdSchin 	INIT();
84da2e3ebdSchin 
85da2e3ebdSchin 	/*
86da2e3ebdSchin 	 * normalize
87da2e3ebdSchin 	 */
88da2e3ebdSchin 
89da2e3ebdSchin 	x = k = LDBL_MAX_EXP / 2;
90da2e3ebdSchin 	if (f < 1)
91da2e3ebdSchin 	{
92da2e3ebdSchin 		g = 1.0L / f;
93da2e3ebdSchin 		for (;;)
94da2e3ebdSchin 		{
95da2e3ebdSchin 			k = (k + 1) / 2;
96da2e3ebdSchin 			if (g < pow2(x))
97da2e3ebdSchin 				x -= k;
98da2e3ebdSchin 			else if (k == 1 && g < pow2(x+1))
99da2e3ebdSchin 				break;
100da2e3ebdSchin 			else
101da2e3ebdSchin 				x += k;
102da2e3ebdSchin 		}
103da2e3ebdSchin 		if (g == pow2(x))
104da2e3ebdSchin 			x--;
105da2e3ebdSchin 		x = -x;
106da2e3ebdSchin 	}
107da2e3ebdSchin 	else if (f > 1)
108da2e3ebdSchin 	{
109da2e3ebdSchin 		for (;;)
110da2e3ebdSchin 		{
111da2e3ebdSchin 			k = (k + 1) / 2;
112da2e3ebdSchin 			if (f > pow2(x))
113da2e3ebdSchin 				x += k;
114da2e3ebdSchin 			else if (k == 1 && f > pow2(x-1))
115da2e3ebdSchin 				break;
116da2e3ebdSchin 			else
117da2e3ebdSchin 				x -= k;
118da2e3ebdSchin 		}
119da2e3ebdSchin 		if (f == pow2(x))
120da2e3ebdSchin 			x++;
121da2e3ebdSchin 	}
122da2e3ebdSchin 	else
123da2e3ebdSchin 		x = 1;
124da2e3ebdSchin 	*p = x;
125da2e3ebdSchin 
126da2e3ebdSchin 	/*
127da2e3ebdSchin 	 * shift
128da2e3ebdSchin 	 */
129da2e3ebdSchin 
130da2e3ebdSchin 	x = -x;
131da2e3ebdSchin 	if (x < 0)
132da2e3ebdSchin 		f /= pow2(-x);
133da2e3ebdSchin 	else if (x < LDBL_MAX_EXP)
134da2e3ebdSchin 		f *= pow2(x);
135da2e3ebdSchin 	else
136da2e3ebdSchin 		f = (f * pow2(LDBL_MAX_EXP - 1)) * pow2(x - (LDBL_MAX_EXP - 1));
137da2e3ebdSchin 	return f;
138da2e3ebdSchin }
139da2e3ebdSchin 
140da2e3ebdSchin #endif
141da2e3ebdSchin 
142da2e3ebdSchin #if !_lib_ldexpl
143da2e3ebdSchin 
144da2e3ebdSchin #undef	ldexpl
145da2e3ebdSchin 
146da2e3ebdSchin extern _ast_fltmax_t
147da2e3ebdSchin ldexpl(_ast_fltmax_t f, register int x)
148da2e3ebdSchin {
149da2e3ebdSchin 	INIT();
150da2e3ebdSchin 	if (x < 0)
151da2e3ebdSchin 		f /= pow2(-x);
152da2e3ebdSchin 	else if (x < LDBL_MAX_EXP)
153da2e3ebdSchin 		f *= pow2(x);
154da2e3ebdSchin 	else
155da2e3ebdSchin 		f = (f * pow2(LDBL_MAX_EXP - 1)) * pow2(x - (LDBL_MAX_EXP - 1));
156da2e3ebdSchin 	return f;
157da2e3ebdSchin }
158da2e3ebdSchin 
159da2e3ebdSchin #endif
160da2e3ebdSchin 
161da2e3ebdSchin #endif
162