From 08b11a02f49da5ca0e4e58a32fa853df0c5e0214 Mon Sep 17 00:00:00 2001 From: Mattias EngdegÄrd Date: Mon, 1 Mar 2021 20:52:39 +0100 Subject: Fix multiple Calc defmath errors (bug#46750) Fix incorrect variable scoping in `let*`, `for` and `foreach`. Fix loop variable value in `foreach` (should be element, not tail). Fix function quoting, as in ('cons x y) -- didn't work at all. Reported by Stephan Neuhaus. * lisp/calc/calc-prog.el (math-define-exp, math-handle-foreach): * test/lisp/calc/calc-tests.el: (var-g, test1, test2, test3, test4) (test5, test6, test7, calc-defmath): Test various defmath forms. --- test/lisp/calc/calc-tests.el | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) (limited to 'test/lisp/calc/calc-tests.el') diff --git a/test/lisp/calc/calc-tests.el b/test/lisp/calc/calc-tests.el index bdcf78e020a..c5aa5a31eb2 100644 --- a/test/lisp/calc/calc-tests.el +++ b/test/lisp/calc/calc-tests.el @@ -707,6 +707,82 @@ An existing calc stack is reused, otherwise a new one is created." (var c var-c)))))) (calc-set-language nil))) +(defvar var-g) + +;; Test `let'. +(defmath test1 (x) + (let ((x (+ x 1)) + (y (+ x 3))) + (let ((z (+ y 6))) + (* x y z g)))) + +;; Test `let*'. +(defmath test2 (x) + (let* ((y (+ x 1)) + (z (+ y 3))) + (let* ((u (+ z 6))) + (* x y z u g)))) + +;; Test `for'. +(defmath test3 (x) + (let ((s 0)) + (for ((ii 1 x) + (jj 1 ii)) + (setq s (+ s (* ii jj)))) + s)) + +;; Test `for' with non-unit stride. +(defmath test4 (x) + (let ((l nil)) + (for ((ii 1 x 1) + (jj 1 10 ii)) + (setq l ('cons jj l))) ; Use Lisp `cons', not `calcFunc-cons'. + (reverse l))) + +;; Test `foreach'. +(defmath test5 (x) + (let ((s 0)) + (foreach ((a x) + (b a)) + (setq s (+ s b))) + s)) + +;; Test `break'. +(defmath test6 (x) + (let ((a (for ((ii 1 10)) + (when (= ii x) + (break (* ii 2))))) + (b (foreach ((e '(9 3 6))) + (when (= e x) + (break (- e 1)))))) + (* a b))) + +;; Test `return' from `for'. +(defmath test7 (x) + (for ((ii 1 10)) + (when (= ii x) + (return (* ii 2)))) + 5) + +(ert-deftest calc-defmath () + (let ((var-g 17)) + (should (equal (calcFunc-test1 2) (* 3 5 11 17))) + (should (equal (calcFunc-test2 2) (* 2 3 6 12 17)))) + (should (equal (calcFunc-test3 3) + (+ (* 1 1) + (* 2 1) (* 2 2) + (* 3 1) (* 3 2) (* 3 3)))) + (should (equal (calcFunc-test4 5) + '( 1 2 3 4 5 6 7 8 9 10 + 1 3 5 7 9 + 1 4 7 10 + 1 5 9 + 1 6))) + (should (equal (calcFunc-test5 '((2 3) (5) (7 11 13))) + (+ 2 3 5 7 11 13))) + (should (equal (calcFunc-test6 3) (* (* 3 2) (- 3 1)))) + (should (equal (calcFunc-test7 3) (* 3 2)))) + (provide 'calc-tests) ;;; calc-tests.el ends here -- cgit v1.2.3 From 7133a67dcdb68fc16d71c3d45323baba8ac5afe9 Mon Sep 17 00:00:00 2001 From: Mattias EngdegÄrd Date: Tue, 27 Apr 2021 17:36:15 +0200 Subject: Calc: control digits after decimal point (bug#47302) Calc normally displays a trailing decimal point for floats with no fractional part, like '12.'. Some uses require at least one digit after the point; add the governing variable calc-digit-after-point. * lisp/calc/calc.el (calc-digit-after-point): New variable. (math-format-number): Use it. * test/lisp/calc/calc-tests.el (calc-display-digit-after-point): New test. --- lisp/calc/calc.el | 14 +++++++++++--- test/lisp/calc/calc-tests.el | 27 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) (limited to 'test/lisp/calc/calc-tests.el') diff --git a/lisp/calc/calc.el b/lisp/calc/calc.el index ec09abb34c4..1e7d5e7766c 100644 --- a/lisp/calc/calc.el +++ b/lisp/calc/calc.el @@ -483,6 +483,11 @@ current precision are displayed in scientific notation in calc-mode.") "Floating-point numbers with this negative exponent or lower are displayed scientific notation in calc-mode.") +(defvar calc-digit-after-point nil + "If t, display at least one digit after the decimal point, as in `12.0'. +If nil, the decimal point may come last in a number, as in `12.'. +This setting only applies to floats in normal display mode.") + (defvar calc-other-modes nil "List of used-defined strings to append to Calculator mode line.") @@ -3184,7 +3189,8 @@ the United States." exp (- exp adj))))) (setq str (int-to-string mant)) (let* ((len (length str)) - (dpos (+ exp len))) + (dpos (+ exp len)) + (trailing-0 (and calc-digit-after-point "0"))) (if (and (eq fmt 'float) (<= dpos (+ calc-internal-prec calc-display-sci-high)) (>= dpos (+ calc-display-sci-low 2))) @@ -3194,9 +3200,11 @@ the United States." (setq str (concat "0" point str))) ((and (<= exp 0) (> dpos 0)) (setq str (concat (substring str 0 dpos) point - (substring str dpos)))) + (substring str dpos) + (and (>= dpos len) trailing-0)))) ((> exp 0) - (setq str (concat str (make-string exp ?0) point))) + (setq str (concat str (make-string exp ?0) + point trailing-0))) (t ; (< dpos 0) (setq str (concat "0" point (make-string (- dpos) ?0) str)))) diff --git a/test/lisp/calc/calc-tests.el b/test/lisp/calc/calc-tests.el index c5aa5a31eb2..13dd228d3b3 100644 --- a/test/lisp/calc/calc-tests.el +++ b/test/lisp/calc/calc-tests.el @@ -191,6 +191,33 @@ An existing calc stack is reused, otherwise a new one is created." (let ((calc-number-radix 36)) (should (equal (math-format-number 12345678901) "36#5,O6A,QT1"))))) +(ert-deftest calc-digit-after-point () + "Test display of trailing 0 after decimal point (bug#47302)." + (let ((calc-digit-after-point nil)) + ;; Integral floats have no digits after the decimal point (default). + (should (equal (math-format-number '(float 0 0)) "0.")) + (should (equal (math-format-number '(float 5 0)) "5.")) + (should (equal (math-format-number '(float 3 1)) "30.")) + (should (equal (math-format-number '(float 23 0)) "23.")) + (should (equal (math-format-number '(float 123 0)) "123.")) + (should (equal (math-format-number '(float 1 -1)) "0.1")) + (should (equal (math-format-number '(float 54 -1)) "5.4")) + (should (equal (math-format-number '(float 1 -4)) "1e-4")) + (should (equal (math-format-number '(float 1 14)) "1e14")) + (should (equal (math-format-number 12) "12"))) + (let ((calc-digit-after-point t)) + ;; Integral floats have at least one digit after the decimal point. + (should (equal (math-format-number '(float 0 0)) "0.0")) + (should (equal (math-format-number '(float 5 0)) "5.0")) + (should (equal (math-format-number '(float 3 1)) "30.0")) + (should (equal (math-format-number '(float 23 0)) "23.0")) + (should (equal (math-format-number '(float 123 0)) "123.0")) + (should (equal (math-format-number '(float 1 -1)) "0.1")) + (should (equal (math-format-number '(float 54 -1)) "5.4")) + (should (equal (math-format-number '(float 1 -4)) "1e-4")) + (should (equal (math-format-number '(float 1 14)) "1e14")) + (should (equal (math-format-number 12) "12")))) + (ert-deftest calc-calendar () "Test calendar conversions (bug#36822)." (should (equal (calcFunc-julian (math-parse-date "2019-07-27")) 2458692)) -- cgit v1.2.3