Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/m68k/fpe Implement exponential and power functions.



details:   https://anonhg.NetBSD.org/src/rev/05c9bba64747
branches:  trunk
changeset: 786210:05c9bba64747
user:      isaki <isaki%NetBSD.org@localhost>
date:      Sat Apr 20 03:06:19 2013 +0000

description:
Implement exponential and power functions.
o FETOX   .. exp(x)
o FETOXM1 .. exp(x) - 1
o FTENTOX .. 10^x
o FTWOTOX .. 2^x
At last all mathematics functions of FPE were implemented.
Thanks to Yosuke Sugahara.

diffstat:

 sys/arch/m68k/fpe/fpu_exp.c |  146 +++++++++++++++++++++++++++++++++++++++----
 1 files changed, 131 insertions(+), 15 deletions(-)

diffs (178 lines):

diff -r 243c0ecc0762 -r 05c9bba64747 sys/arch/m68k/fpe/fpu_exp.c
--- a/sys/arch/m68k/fpe/fpu_exp.c       Sat Apr 20 01:48:20 2013 +0000
+++ b/sys/arch/m68k/fpe/fpu_exp.c       Sat Apr 20 03:06:19 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fpu_exp.c,v 1.5 2011/07/18 07:44:30 isaki Exp $        */
+/*     $NetBSD: fpu_exp.c,v 1.6 2013/04/20 03:06:19 isaki Exp $        */
 
 /*
  * Copyright (c) 1995  Ken Nakata
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu_exp.c,v 1.5 2011/07/18 07:44:30 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu_exp.c,v 1.6 2013/04/20 03:06:19 isaki Exp $");
 
 #include "fpu_emulate.h"
 
@@ -40,30 +40,146 @@
  * fpu_exp.c: defines fpu_etox(), fpu_etoxm1(), fpu_tentox(), and fpu_twotox();
  */
 
-struct fpn *
-fpu_etox(struct fpemu *fe)
+/*
+ *                  x^2   x^3   x^4
+ * exp(x) = 1 + x + --- + --- + --- + ...
+ *                   2!    3!    4!
+ */
+static struct fpn *
+fpu_etox_taylor(struct fpemu *fe)
 {
-       /* stub */
-       return &fe->fe_f2;
-}
+       struct fpn res;
+       struct fpn x;
+       struct fpn s0;
+       struct fpn *s1;
+       struct fpn *r;
+       uint32_t k;
+
+       CPYFPN(&x, &fe->fe_f2);
+       CPYFPN(&s0, &fe->fe_f2);
+
+       /* res := 1 + x */
+       fpu_const(&fe->fe_f1, FPU_CONST_1);
+       r = fpu_add(fe);
+       CPYFPN(&res, r);
+
+       k = 2;
+       for (;; k++) {
+               /* s1 = s0 * x / k */
+               CPYFPN(&fe->fe_f1, &s0);
+               CPYFPN(&fe->fe_f2, &x);
+               r = fpu_mul(fe);
 
-struct fpn *
-fpu_etoxm1(struct fpemu *fe)
-{
-       /* stub */
+               CPYFPN(&fe->fe_f1, r);
+               fpu_explode(fe, &fe->fe_f2, FTYPE_LNG, &k);
+               s1 = fpu_div(fe);
+
+               /* break if s1 is enough small */
+               if (ISZERO(s1))
+                       break;
+               if (res.fp_exp - s1->fp_exp >= FP_NMANT)
+                       break;
+
+               /* s0 := s1 for next loop */
+               CPYFPN(&s0, s1);
+
+               /* res += s1 */
+               CPYFPN(&fe->fe_f2, s1);
+               CPYFPN(&fe->fe_f1, &res);
+               r = fpu_add(fe);
+               CPYFPN(&res, r);
+       }
+
+       CPYFPN(&fe->fe_f2, &res);
        return &fe->fe_f2;
 }
 
+/*
+ * exp(x)
+ */
+struct fpn *
+fpu_etox(struct fpemu *fe)
+{
+       struct fpn *fp;
+
+       if (ISNAN(&fe->fe_f2))
+               return &fe->fe_f2;
+       if (ISINF(&fe->fe_f2)) {
+               if (fe->fe_f2.fp_sign)
+                       fpu_const(&fe->fe_f2, FPU_CONST_0);
+               return &fe->fe_f2;
+       }
+
+       if (fe->fe_f2.fp_sign == 0) {
+               /* exp(x) */
+               fp = fpu_etox_taylor(fe);
+       } else {
+               /* 1/exp(-x) */
+               fe->fe_f2.fp_sign = 0;
+               fp = fpu_etox_taylor(fe);
+
+               CPYFPN(&fe->fe_f2, fp);
+               fpu_const(&fe->fe_f1, FPU_CONST_1);
+               fp = fpu_div(fe);
+       }
+       
+       return fp;
+}
+
+/*
+ * exp(x) - 1
+ */
+struct fpn *
+fpu_etoxm1(struct fpemu *fe)
+{
+       struct fpn *fp;
+
+       fp = fpu_etox(fe);
+
+       CPYFPN(&fe->fe_f1, fp);
+       /* build a 1.0 */
+       fp = fpu_const(&fe->fe_f2, FPU_CONST_1);
+       fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign;
+       /* fp = f2 - 1.0 */
+       fp = fpu_add(fe);
+
+       return fp;
+}
+
+/*
+ * 10^x = exp(x * ln10)
+ */
 struct fpn *
 fpu_tentox(struct fpemu *fe)
 {
-       /* stub */
-       return &fe->fe_f2;
+       struct fpn *fp;
+
+       /* build a ln10 */
+       fp = fpu_const(&fe->fe_f1, FPU_CONST_LN_10);
+       /* fp = ln10 * f2 */
+       fp = fpu_mul(fe);
+
+       /* copy the result to the src opr */
+       CPYFPN(&fe->fe_f2, fp);
+
+       return fpu_etox(fe);
 }
 
+/*
+ * 2^x = exp(x * ln2)
+ */
 struct fpn *
 fpu_twotox(struct fpemu *fe)
 {
-       /* stub */
-       return &fe->fe_f2;
+       struct fpn *fp;
+
+       /* build a ln2 */
+       fp = fpu_const(&fe->fe_f1, FPU_CONST_LN_2);
+       /* fp = ln2 * f2 */
+       fp = fpu_mul(fe);
+
+       /* copy the result to the src opr */
+       CPYFPN(&fe->fe_f2, fp);
+
+       return fpu_etox(fe);
 }



Home | Main Index | Thread Index | Old Index