From f50347a91b5dd8172c7975a3d1f85c6949d964dd Mon Sep 17 00:00:00 2001 From: Jay Belanger Date: Wed, 4 Jul 2007 04:20:35 +0000 Subject: [PATCH] (calculator-expt, calculator-integer-p): New functions. (calculator-fact): Check to see if the factorial will be too large before computing it. (calculator-initial-operators): Use `calculator-expt' to compute "^". (calculator-mode): Mention that results which are too large will return inf. --- lisp/ChangeLog | 11 +++++++++++ lisp/calculator.el | 45 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 9c8bb573e80..e7ab6ae52d9 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,14 @@ +2007-07-03 Jay Belanger + + * calculator.el (calculator-expt, calculator-integer-p): + New functions. + (calculator-fact): Check to see if the factorial will be too + large before computing it. + (calculator-initial-operators): Use `calculator-expt' to + compute "^". + (calculator-mode): Mention that results which are too large + will return inf. + 2007-07-03 David Kastrup * shell.el: On request of the authors, remove their addresses for diff --git a/lisp/calculator.el b/lisp/calculator.el index 53a3c96d948..c1e0edb6276 100644 --- a/lisp/calculator.el +++ b/lisp/calculator.el @@ -278,7 +278,7 @@ Examples: ("IC" acos (D (acos X)) x 6) ("IT" atan (D (atan X)) x 6) ("Q" sqrt sqrt x 7) - ("^" ^ expt 2 7) + ("^" ^ calculator-expt 2 7) ("!" ! calculator-fact x 7) (";" 1/ (/ 1 X) 1 7) ("_" - - 1 8) @@ -596,7 +596,8 @@ specified, then it is fixed, otherwise it depends on this variable). `+' and `-' can be used as either binary operators or prefix unary operators. Numbers can be entered with exponential notation using `e', except when using a non-decimal radix mode for input (in this case `e' -will be the hexadecimal digit). +will be the hexadecimal digit). If the result of a calculation is too +large (out of range for Emacs), the value of \"inf\" is returned. Here are the editing keys: * `RET' `=' evaluate the current expression @@ -1779,13 +1780,43 @@ To use this, apply a binary operator (evaluate it), then call this." (car calculator-last-opXY) (nth 1 calculator-last-opXY) x)) x)) +(defun calculator-integer-p (x) + "Non-nil if X is equal to an integer." + (condition-case nil + (= x (ftruncate x)) + (error nil))) + +(defun calculator-expt (x y) + "Compute X^Y, dealing with errors appropriately." + (condition-case + nil + (expt x y) + (domain-error 0.0e+NaN) + (range-error + (if (> y 0) + (if (and + (< x 0) + (= y (truncate y)) + (oddp (truncate y))) + -1.0e+INF + 1.0e+INF) + 0.0)) + (error 0.0e+NaN))) + (defun calculator-fact (x) "Simple factorial of X." - (let ((r (if (<= x 10) 1 1.0))) - (while (> x 0) - (setq r (* r (truncate x))) - (setq x (1- x))) - (+ 0.0 r))) + (if (and (>= x 0) + (calculator-integer-p x)) + (if (= (calculator-expt (/ x 3.0) x) 1.0e+INF) + 1.0e+INF + (let ((r (if (<= x 10) 1 1.0))) + (while (> x 0) + (setq r (* r (truncate x))) + (setq x (1- x))) + (+ 0.0 r))) + (if (= x 1.0e+INF) + x + 0.0e+NaN))) (defun calculator-truncate (n) "Truncate N, return 0 in case of overflow." -- 2.39.2