about summary refs log tree commit diff
path: root/REORG.TODO/sysdeps/ieee754/dbl-64/mpexp.c
diff options
context:
space:
mode:
Diffstat (limited to 'REORG.TODO/sysdeps/ieee754/dbl-64/mpexp.c')
-rw-r--r--REORG.TODO/sysdeps/ieee754/dbl-64/mpexp.c163
1 files changed, 163 insertions, 0 deletions
diff --git a/REORG.TODO/sysdeps/ieee754/dbl-64/mpexp.c b/REORG.TODO/sysdeps/ieee754/dbl-64/mpexp.c
new file mode 100644
index 0000000000..e08f424133
--- /dev/null
+++ b/REORG.TODO/sysdeps/ieee754/dbl-64/mpexp.c
@@ -0,0 +1,163 @@
+/*
+ * IBM Accurate Mathematical Library
+ * written by International Business Machines Corp.
+ * Copyright (C) 2001-2017 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU  Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+/*************************************************************************/
+/*   MODULE_NAME:mpexp.c                                                 */
+/*                                                                       */
+/*   FUNCTIONS: mpexp                                                    */
+/*                                                                       */
+/*   FILES NEEDED: mpa.h endian.h mpexp.h                                */
+/*                 mpa.c                                                 */
+/*                                                                       */
+/* Multi-Precision exponential function subroutine                       */
+/*   (  for p >= 4, 2**(-55) <= abs(x) <= 1024     ).                    */
+/*************************************************************************/
+
+#include "endian.h"
+#include "mpa.h"
+#include <assert.h>
+
+#ifndef SECTION
+# define SECTION
+#endif
+
+/* Multi-Precision exponential function subroutine (for p >= 4,
+   2**(-55) <= abs(x) <= 1024).  */
+void
+SECTION
+__mpexp (mp_no *x, mp_no *y, int p)
+{
+  int i, j, k, m, m1, m2, n;
+  mantissa_t b;
+  static const int np[33] =
+    {
+      0, 0, 0, 0, 3, 3, 4, 4, 5, 4, 4, 5, 5, 5, 6, 6, 6, 6, 6, 6,
+      6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8
+    };
+
+  static const int m1p[33] =
+    {
+      0, 0, 0, 0,
+      17, 23, 23, 28,
+      27, 38, 42, 39,
+      43, 47, 43, 47,
+      50, 54, 57, 60,
+      64, 67, 71, 74,
+      68, 71, 74, 77,
+      70, 73, 76, 78,
+      81
+    };
+  static const int m1np[7][18] =
+    {
+      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+      {0, 0, 0, 0, 36, 48, 60, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+      {0, 0, 0, 0, 24, 32, 40, 48, 56, 64, 72, 0, 0, 0, 0, 0, 0, 0},
+      {0, 0, 0, 0, 17, 23, 29, 35, 41, 47, 53, 59, 65, 0, 0, 0, 0, 0},
+      {0, 0, 0, 0, 0, 0, 23, 28, 33, 38, 42, 47, 52, 57, 62, 66, 0, 0},
+      {0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 39, 43, 47, 51, 55, 59, 63},
+      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 47, 50, 54}
+    };
+  mp_no mps, mpk, mpt1, mpt2;
+
+  /* Choose m,n and compute a=2**(-m).  */
+  n = np[p];
+  m1 = m1p[p];
+  b = X[1];
+  m2 = 24 * EX;
+  for (; b < HALFRAD; m2--)
+    b *= 2;
+  if (b == HALFRAD)
+    {
+      for (i = 2; i <= p; i++)
+	{
+	  if (X[i] != 0)
+	    break;
+	}
+      if (i == p + 1)
+	m2--;
+    }
+
+  m = m1 + m2;
+  if (__glibc_unlikely (m <= 0))
+    {
+      /* The m1np array which is used to determine if we can reduce the
+	 polynomial expansion iterations, has only 18 elements.  Besides,
+	 numbers smaller than those required by p >= 18 should not come here
+	 at all since the fast phase of exp returns 1.0 for anything less
+	 than 2^-55.  */
+      assert (p < 18);
+      m = 0;
+      for (i = n - 1; i > 0; i--, n--)
+	if (m1np[i][p] + m2 > 0)
+	  break;
+    }
+
+  /* Compute s=x*2**(-m). Put result in mps.  This is the range-reduced input
+     that we will use to compute e^s.  For the final result, simply raise it
+     to 2^m.  */
+  __pow_mp (-m, &mpt1, p);
+  __mul (x, &mpt1, &mps, p);
+
+  /* Compute the Taylor series for e^s:
+
+         1 + x/1! + x^2/2! + x^3/3! ...
+
+     for N iterations.  We compute this as:
+
+         e^x = 1 + (x * n!/1! + x^2 * n!/2! + x^3 * n!/3!) / n!
+             = 1 + (x * (n!/1! + x * (n!/2! + x * (n!/3! + x ...)))) / n!
+
+     k! is computed on the fly as KF and at the end of the polynomial loop, KF
+     is n!, which can be used directly.  */
+  __cpy (&mps, &mpt2, p);
+
+  double kf = 1.0;
+
+  /* Evaluate the rest.  The result will be in mpt2.  */
+  for (k = n - 1; k > 0; k--)
+    {
+      /* n! / k! = n * (n - 1) ... * (n - k + 1) */
+      kf *= k + 1;
+
+      __dbl_mp (kf, &mpk, p);
+      __add (&mpt2, &mpk, &mpt1, p);
+      __mul (&mps, &mpt1, &mpt2, p);
+    }
+  __dbl_mp (kf, &mpk, p);
+  __dvd (&mpt2, &mpk, &mpt1, p);
+  __add (&__mpone, &mpt1, &mpt2, p);
+
+  /* Raise polynomial value to the power of 2**m. Put result in y.  */
+  for (k = 0, j = 0; k < m;)
+    {
+      __sqr (&mpt2, &mpt1, p);
+      k++;
+      if (k == m)
+	{
+	  j = 1;
+	  break;
+	}
+      __sqr (&mpt1, &mpt2, p);
+      k++;
+    }
+  if (j)
+    __cpy (&mpt1, y, p);
+  else
+    __cpy (&mpt2, y, p);
+  return;
+}