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