xref: /openbsd-src/regress/lib/libc/cephes/epow.c (revision b7275c8844bfe6dc0cf95984cd963da8316ddba7)
1*b7275c88Smartynas /*	$OpenBSD: epow.c,v 1.1 2011/07/02 18:11:01 martynas Exp $	*/
2*b7275c88Smartynas 
3*b7275c88Smartynas /*
4*b7275c88Smartynas  * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
5*b7275c88Smartynas  *
6*b7275c88Smartynas  * Permission to use, copy, modify, and distribute this software for any
7*b7275c88Smartynas  * purpose with or without fee is hereby granted, provided that the above
8*b7275c88Smartynas  * copyright notice and this permission notice appear in all copies.
9*b7275c88Smartynas  *
10*b7275c88Smartynas  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11*b7275c88Smartynas  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*b7275c88Smartynas  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13*b7275c88Smartynas  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*b7275c88Smartynas  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15*b7275c88Smartynas  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16*b7275c88Smartynas  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*b7275c88Smartynas  */
18*b7275c88Smartynas 
19*b7275c88Smartynas /*						epow.c	*/
20*b7275c88Smartynas /*  power function: z = x**y */
21*b7275c88Smartynas /*  by Stephen L. Moshier. */
22*b7275c88Smartynas 
23*b7275c88Smartynas 
24*b7275c88Smartynas #include "ehead.h"
25*b7275c88Smartynas 
26*b7275c88Smartynas extern int rndprc;
27*b7275c88Smartynas void epowi();
28*b7275c88Smartynas 
epow(x,y,z)29*b7275c88Smartynas void epow( x, y, z )
30*b7275c88Smartynas unsigned short *x, *y, *z;
31*b7275c88Smartynas {
32*b7275c88Smartynas unsigned short w[NE];
33*b7275c88Smartynas int rndsav;
34*b7275c88Smartynas long li;
35*b7275c88Smartynas 
36*b7275c88Smartynas efloor( y, w );
37*b7275c88Smartynas if( ecmp(y,w) == 0 )
38*b7275c88Smartynas 	{
39*b7275c88Smartynas 	eifrac( y, &li, w );
40*b7275c88Smartynas 	if( li < 0 )
41*b7275c88Smartynas 		li = -li;
42*b7275c88Smartynas 	if( (li < 0x7fffffff) && (li != 0x80000000) )
43*b7275c88Smartynas 		{
44*b7275c88Smartynas 		epowi( x, y, z );
45*b7275c88Smartynas 		return;
46*b7275c88Smartynas 		}
47*b7275c88Smartynas 	}
48*b7275c88Smartynas /* z = exp( y * log(x) ) */
49*b7275c88Smartynas rndsav = rndprc;
50*b7275c88Smartynas rndprc = NBITS;
51*b7275c88Smartynas elog( x, w );
52*b7275c88Smartynas emul( y, w, w );
53*b7275c88Smartynas eexp( w, z );
54*b7275c88Smartynas rndprc = rndsav;
55*b7275c88Smartynas emul( eone, z, z );
56*b7275c88Smartynas }
57*b7275c88Smartynas 
58*b7275c88Smartynas 
59*b7275c88Smartynas /* y is integer valued. */
60*b7275c88Smartynas 
epowi(x,y,z)61*b7275c88Smartynas void epowi( x, y, z )
62*b7275c88Smartynas unsigned short x[], y[], z[];
63*b7275c88Smartynas {
64*b7275c88Smartynas unsigned short w[NE];
65*b7275c88Smartynas long li, lx;
66*b7275c88Smartynas unsigned long lu;
67*b7275c88Smartynas int rndsav;
68*b7275c88Smartynas unsigned short signx;
69*b7275c88Smartynas /* unsigned short signy; */
70*b7275c88Smartynas 
71*b7275c88Smartynas rndsav = rndprc;
72*b7275c88Smartynas eifrac( y, &li, w );
73*b7275c88Smartynas if( li < 0 )
74*b7275c88Smartynas 	lx = -li;
75*b7275c88Smartynas else
76*b7275c88Smartynas 	lx = li;
77*b7275c88Smartynas 
78*b7275c88Smartynas if( (lx == 0x7fffffff) || (lx == 0x80000000) )
79*b7275c88Smartynas 	{
80*b7275c88Smartynas 	epow( x, y, z );
81*b7275c88Smartynas 	goto done;
82*b7275c88Smartynas 	}
83*b7275c88Smartynas 
84*b7275c88Smartynas if( (x[NE-1] & (unsigned short )0x7fff) == 0 )
85*b7275c88Smartynas 	{
86*b7275c88Smartynas 	if( li == 0 )
87*b7275c88Smartynas 		{
88*b7275c88Smartynas 		emov( eone, z );
89*b7275c88Smartynas 		return;
90*b7275c88Smartynas 		}
91*b7275c88Smartynas 	else if( li < 0 )
92*b7275c88Smartynas 		{
93*b7275c88Smartynas 		einfin( z );
94*b7275c88Smartynas 		return;
95*b7275c88Smartynas 		}
96*b7275c88Smartynas 	else
97*b7275c88Smartynas 		{
98*b7275c88Smartynas 		eclear( z );
99*b7275c88Smartynas 		return;
100*b7275c88Smartynas 		}
101*b7275c88Smartynas 	}
102*b7275c88Smartynas 
103*b7275c88Smartynas if( li == 0L )
104*b7275c88Smartynas 	{
105*b7275c88Smartynas 	emov( eone, z );
106*b7275c88Smartynas 	return;
107*b7275c88Smartynas 	}
108*b7275c88Smartynas 
109*b7275c88Smartynas emov( x, w );
110*b7275c88Smartynas signx = w[NE-1] & (unsigned short )0x8000;
111*b7275c88Smartynas w[NE-1] &= (unsigned short )0x7fff;
112*b7275c88Smartynas 
113*b7275c88Smartynas /* Overflow detection */
114*b7275c88Smartynas /*
115*b7275c88Smartynas lx = li * (w[NE-1] - 0x3fff);
116*b7275c88Smartynas if( lx > 16385L )
117*b7275c88Smartynas 	{
118*b7275c88Smartynas 	einfin( z );
119*b7275c88Smartynas 	mtherr( "epowi", OVERFLOW );
120*b7275c88Smartynas 	goto done;
121*b7275c88Smartynas 	}
122*b7275c88Smartynas if( lx < -16450L )
123*b7275c88Smartynas 	{
124*b7275c88Smartynas 	eclear( z );
125*b7275c88Smartynas 	return;
126*b7275c88Smartynas 	}
127*b7275c88Smartynas */
128*b7275c88Smartynas rndprc = NBITS;
129*b7275c88Smartynas 
130*b7275c88Smartynas if( li < 0 )
131*b7275c88Smartynas 	{
132*b7275c88Smartynas 	lu = (unsigned int )( -li );
133*b7275c88Smartynas /*	signy = 0xffff;*/
134*b7275c88Smartynas 	ediv( w, eone, w );
135*b7275c88Smartynas 	}
136*b7275c88Smartynas else
137*b7275c88Smartynas 	{
138*b7275c88Smartynas 	lu = (unsigned int )li;
139*b7275c88Smartynas /*	signy = 0;*/
140*b7275c88Smartynas 	}
141*b7275c88Smartynas 
142*b7275c88Smartynas /* First bit of the power */
143*b7275c88Smartynas if( lu & 1 )
144*b7275c88Smartynas 	{
145*b7275c88Smartynas 	emov( w, z );
146*b7275c88Smartynas 	}
147*b7275c88Smartynas else
148*b7275c88Smartynas 	{
149*b7275c88Smartynas 	emov( eone, z );
150*b7275c88Smartynas 	signx = 0;
151*b7275c88Smartynas 	}
152*b7275c88Smartynas 
153*b7275c88Smartynas 
154*b7275c88Smartynas lu >>= 1;
155*b7275c88Smartynas while( lu != 0L )
156*b7275c88Smartynas 	{
157*b7275c88Smartynas 	emul( w, w, w );	/* arg to the 2-to-the-kth power */
158*b7275c88Smartynas 	if( lu & 1L )	/* if that bit is set, then include in product */
159*b7275c88Smartynas 		emul( w, z, z );
160*b7275c88Smartynas 	lu >>= 1;
161*b7275c88Smartynas 	}
162*b7275c88Smartynas 
163*b7275c88Smartynas 
164*b7275c88Smartynas done:
165*b7275c88Smartynas 
166*b7275c88Smartynas if( signx )
167*b7275c88Smartynas 	eneg( z ); /* odd power of negative number */
168*b7275c88Smartynas 
169*b7275c88Smartynas /*
170*b7275c88Smartynas if( signy )
171*b7275c88Smartynas   	{
172*b7275c88Smartynas   	if( ecmp( z, ezero ) != 0 )
173*b7275c88Smartynas  		{
174*b7275c88Smartynas 		ediv( z, eone, z );
175*b7275c88Smartynas 		}
176*b7275c88Smartynas 	else
177*b7275c88Smartynas 		{
178*b7275c88Smartynas 		einfin( z );
179*b7275c88Smartynas 		printf( "epowi OVERFLOW\n" );
180*b7275c88Smartynas 		}
181*b7275c88Smartynas 	}
182*b7275c88Smartynas */
183*b7275c88Smartynas rndprc = rndsav;
184*b7275c88Smartynas emul( eone, z, z );
185*b7275c88Smartynas }
186*b7275c88Smartynas 
187*b7275c88Smartynas 
188