From f3b73541a4918c50abdc17da4164113e40fa6036 Mon Sep 17 00:00:00 2001
From: Raymond Toy <toy.raymond@gmail.com>
Date: Fri, 1 Jan 2016 09:30:18 -0800
Subject: [PATCH] Add special case for (expt 0 power)

We know the result of (expt 0 power) so return it immediately without
first checking if the power exceeds the limit.

Also took the opportunity to add a better message to the
intexp-limit-error condition to make it more explicit what is being
computed and why it's failing.

Tests added too.
---
 src/code/irrat.lisp |  7 +++++++
 tests/irrat.lisp    | 20 ++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/src/code/irrat.lisp b/src/code/irrat.lisp
index b21b92fbc..a3af4bb74 100644
--- a/src/code/irrat.lisp
+++ b/src/code/irrat.lisp
@@ -252,6 +252,13 @@
     (return-from intexp base))
   (when (eql base -1)
     (return-from intexp (if (oddp power) -1 1)))
+
+  ;; Handle 0 raised to a power.  Return 0 if the power is
+  ;; non-negative or signal a divide-by-zero if the power is negative.
+  (when (zerop base)
+    (if (minusp power)
+	(error 'division-by-zero)
+	(return-from intexp base)))
   
   (when (> (abs power) *intexp-maximum-exponent*)
     ;; Allow user the option to continue with calculation, possibly
diff --git a/tests/irrat.lisp b/tests/irrat.lisp
index 14db13eeb..bc3f31cba 100644
--- a/tests/irrat.lisp
+++ b/tests/irrat.lisp
@@ -152,3 +152,23 @@
 	for logx = (kernel::dd-%log2 x)
 	for log1/x = (kernel::dd-%log2 (/ x))
 	do (assert-true (<= (abs (+ logx log1/x)) (* 1 double-float-epsilon)))))
+
+(define-test expt-integer
+  (let ((power (1+ kernel::*intexp-maximum-exponent*)))
+    ;; Make sure we error out in the usual case with the power too
+    ;; large.
+    (assert-error 'kernel::intexp-limit-error
+		  (expt 2 power))
+    (assert-error 'kernel::intexp-limit-error
+		  (expt 2 (- power)))
+    ;; But raising 0 or 1 to a power shouldn't signal anything, except
+    ;; the obvious division-by-zero.
+    (assert-eql 1 (expt 1 power))
+    (cond ((evenp power)
+	   (assert-eql 1 (expt -1 power))
+	   (assert-eql -1 (expt -1 (1+ power))))
+	  (t
+	   (assert-eql -1 (expt -1 power))
+	   (assert-eql 1 (expt -1 (1+ power)))))
+    (assert-eql 0 (expt 0 power))
+    (assert-error 'division-by-zero (expt 0 (- power)))))
-- 
GitLab