Module Name:    src
Committed By:   isaki
Date:           Sat Apr 20 03:06:20 UTC 2013

Modified Files:
        src/sys/arch/m68k/fpe: fpu_exp.c

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/m68k/fpe/fpu_exp.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/m68k/fpe/fpu_exp.c
diff -u src/sys/arch/m68k/fpe/fpu_exp.c:1.5 src/sys/arch/m68k/fpe/fpu_exp.c:1.6
--- src/sys/arch/m68k/fpe/fpu_exp.c:1.5	Mon Jul 18 07:44:30 2011
+++ src/sys/arch/m68k/fpe/fpu_exp.c	Sat Apr 20 03:06:19 2013
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: fpu_exp.c,v 
  * fpu_exp.c: defines fpu_etox(), fpu_etoxm1(), fpu_tentox(), and fpu_twotox();
  */
 
+/*
+ *                  x^2   x^3   x^4
+ * exp(x) = 1 + x + --- + --- + --- + ...
+ *                   2!    3!    4!
+ */
+static struct fpn *
+fpu_etox_taylor(struct fpemu *fe)
+{
+	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);
+
+		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)
 {
-	/* stub */
-	return &fe->fe_f2;
+	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)
 {
-	/* stub */
-	return &fe->fe_f2;
+	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);
 }

Reply via email to