summaryrefslogtreecommitdiff
path: root/regress/lib/libc/cephes/epow.c
diff options
context:
space:
mode:
Diffstat (limited to 'regress/lib/libc/cephes/epow.c')
-rw-r--r--regress/lib/libc/cephes/epow.c187
1 files changed, 187 insertions, 0 deletions
diff --git a/regress/lib/libc/cephes/epow.c b/regress/lib/libc/cephes/epow.c
new file mode 100644
index 00000000000..646268fce7c
--- /dev/null
+++ b/regress/lib/libc/cephes/epow.c
@@ -0,0 +1,187 @@
+/* $OpenBSD: epow.c,v 1.1 2011/07/02 18:11:01 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* epow.c */
+/* power function: z = x**y */
+/* by Stephen L. Moshier. */
+
+
+#include "ehead.h"
+
+extern int rndprc;
+void epowi();
+
+void epow( x, y, z )
+unsigned short *x, *y, *z;
+{
+unsigned short w[NE];
+int rndsav;
+long li;
+
+efloor( y, w );
+if( ecmp(y,w) == 0 )
+ {
+ eifrac( y, &li, w );
+ if( li < 0 )
+ li = -li;
+ if( (li < 0x7fffffff) && (li != 0x80000000) )
+ {
+ epowi( x, y, z );
+ return;
+ }
+ }
+/* z = exp( y * log(x) ) */
+rndsav = rndprc;
+rndprc = NBITS;
+elog( x, w );
+emul( y, w, w );
+eexp( w, z );
+rndprc = rndsav;
+emul( eone, z, z );
+}
+
+
+/* y is integer valued. */
+
+void epowi( x, y, z )
+unsigned short x[], y[], z[];
+{
+unsigned short w[NE];
+long li, lx;
+unsigned long lu;
+int rndsav;
+unsigned short signx;
+/* unsigned short signy; */
+
+rndsav = rndprc;
+eifrac( y, &li, w );
+if( li < 0 )
+ lx = -li;
+else
+ lx = li;
+
+if( (lx == 0x7fffffff) || (lx == 0x80000000) )
+ {
+ epow( x, y, z );
+ goto done;
+ }
+
+if( (x[NE-1] & (unsigned short )0x7fff) == 0 )
+ {
+ if( li == 0 )
+ {
+ emov( eone, z );
+ return;
+ }
+ else if( li < 0 )
+ {
+ einfin( z );
+ return;
+ }
+ else
+ {
+ eclear( z );
+ return;
+ }
+ }
+
+if( li == 0L )
+ {
+ emov( eone, z );
+ return;
+ }
+
+emov( x, w );
+signx = w[NE-1] & (unsigned short )0x8000;
+w[NE-1] &= (unsigned short )0x7fff;
+
+/* Overflow detection */
+/*
+lx = li * (w[NE-1] - 0x3fff);
+if( lx > 16385L )
+ {
+ einfin( z );
+ mtherr( "epowi", OVERFLOW );
+ goto done;
+ }
+if( lx < -16450L )
+ {
+ eclear( z );
+ return;
+ }
+*/
+rndprc = NBITS;
+
+if( li < 0 )
+ {
+ lu = (unsigned int )( -li );
+/* signy = 0xffff;*/
+ ediv( w, eone, w );
+ }
+else
+ {
+ lu = (unsigned int )li;
+/* signy = 0;*/
+ }
+
+/* First bit of the power */
+if( lu & 1 )
+ {
+ emov( w, z );
+ }
+else
+ {
+ emov( eone, z );
+ signx = 0;
+ }
+
+
+lu >>= 1;
+while( lu != 0L )
+ {
+ emul( w, w, w ); /* arg to the 2-to-the-kth power */
+ if( lu & 1L ) /* if that bit is set, then include in product */
+ emul( w, z, z );
+ lu >>= 1;
+ }
+
+
+done:
+
+if( signx )
+ eneg( z ); /* odd power of negative number */
+
+/*
+if( signy )
+ {
+ if( ecmp( z, ezero ) != 0 )
+ {
+ ediv( z, eone, z );
+ }
+ else
+ {
+ einfin( z );
+ printf( "epowi OVERFLOW\n" );
+ }
+ }
+*/
+rndprc = rndsav;
+emul( eone, z, z );
+}
+
+