Raymond Toy pushed to branch rtoy-print-using-ryu at cmucl / cmucl

Commits:

2 changed files:

Changes:

  • src/code/ryu-print.lisp
    ... ... @@ -555,6 +555,10 @@
    555 555
     		      (format-f value ww dd 0 overflowchar padchar at-sign-p)
    
    556 556
     		      (make-string ee :initial-element #\space)))
    
    557 557
     	(t
    
    558
    -	 ;; ~E form
    
    559
    -	 (format-e value w effective-d e k overflowchar padchar exponentchar at-sign-p))))))
    
    558
    +	 ;; ~E form.  CLHS 22.3.3.3 specifies the resulting call as
    
    559
    +	 ;; "~w,d,e,k,...,E" -- using the user's original D, not the
    
    560
    +	 ;; EFFECTIVE-D computed for the ~F-vs-~E decision.  When D is
    
    561
    +	 ;; NIL this lets format-e produce its free-format (shortest)
    
    562
    +	 ;; output rather than fixed-precision.
    
    563
    +	 (format-e value w d e k overflowchar padchar exponentchar at-sign-p))))))
    
    560 564
     

  • tests/ryu.lisp
    ... ... @@ -518,11 +518,12 @@
    518 518
     (define-test format-g.large-uses-e
    
    519 519
       (:tag :format-g)
    
    520 520
       ;; Values with n > 7 should fall into ~E form (no trailing spaces).
    
    521
    -  ;; 1d10 has n=11, q=1, effective-d = max(1, 7) = 7, dd = 7-11 = -4.
    
    522
    -  ;; ~E with effective-d = 7: 1.0000000d+10.
    
    523
    -  (assert-equal "1.0000000d+10"
    
    521
    +  ;; Per CLHS 22.3.3.3, when D is unspecified ~G's ~E call also has
    
    522
    +  ;; D unspecified, so ~E uses free-format (shortest) output rather
    
    523
    +  ;; than fixed precision.
    
    524
    +  (assert-equal "1.0d+10"
    
    524 525
                     (lisp::format-g 1d10 nil nil nil 1 nil nil #\d nil))
    
    525
    -  (assert-equal "1.0000000d+100"
    
    526
    +  (assert-equal "1.0d+100"
    
    526 527
                     (lisp::format-g 1d100 nil nil nil 1 nil nil #\d nil)))
    
    527 528
     
    
    528 529
     (define-test format-g.small-uses-e
    
    ... ... @@ -563,8 +564,9 @@
    563 564
       (:tag :format-g)
    
    564 565
       ;; e parameter controls exponent width in the ~E branch and ee in
    
    565 566
       ;; the ~F branch (ee = e + 2).
    
    566
    -  ;; 1d10 with e=3: ~E with 3-digit exponent, "1.0000000d+010".
    
    567
    -  (assert-equal "1.0000000d+010"
    
    567
    +  ;; 1d10 with e=3: ~E with 3-digit exponent.  D is unspecified so
    
    568
    +  ;; ~E uses free-format, giving "1.0d+010".
    
    569
    +  (assert-equal "1.0d+010"
    
    568 570
                     (lisp::format-g 1d10 nil nil 3 1 nil nil #\d nil))
    
    569 571
       ;; 3.14 with e=3: ~F branch, ee = 5 trailing spaces.
    
    570 572
       (assert-equal "3.14     "
    
    ... ... @@ -577,7 +579,7 @@
    577 579
                     (lisp::format-g 3.14d0 nil nil nil 1 nil nil #\d t))
    
    578 580
       (assert-equal "-3.14    "
    
    579 581
                     (lisp::format-g -3.14d0 nil nil nil 1 nil nil #\d t))
    
    580
    -  (assert-equal "+1.0000000d+10"
    
    582
    +  (assert-equal "+1.0d+10"
    
    581 583
                     (lisp::format-g 1d10 nil nil nil 1 nil nil #\d t)))
    
    582 584
     
    
    583 585
     (define-test format-g.boundary-n-7
    
    ... ... @@ -587,10 +589,26 @@
    587 589
       ;; dd = 0 is in [0, d] so ~F path with d=0.  Output: "1000000." + 4 sp.
    
    588 590
       (assert-equal "1000000.    "
    
    589 591
                     (lisp::format-g 1d6 nil nil nil 1 nil nil #\d nil))
    
    590
    -  ;; 1d7 has n=8, dd = 7-8 = -1, falls into ~E.
    
    591
    -  (assert-equal "1.0000000d+7"
    
    592
    +  ;; 1d7 has n=8, dd = 7-8 = -1, falls into ~E.  D is unspecified so
    
    593
    +  ;; ~E uses free-format.
    
    594
    +  (assert-equal "1.0d+7"
    
    592 595
                     (lisp::format-g 1d7 nil nil nil 1 nil nil #\d nil)))
    
    593 596
     
    
    597
    +(define-test format-g.d-nil-routes-to-e-with-d-nil
    
    598
    +  (:tag :format-g)
    
    599
    +  ;; CLHS 22.3.3.3 specifies that when ~G falls through to the ~E
    
    600
    +  ;; branch, the ~E directive is called with the user's original D
    
    601
    +  ;; (per "~w,d,e,k,...,E"), NOT the EFFECTIVE-D that ~G computed for
    
    602
    +  ;; the ~F-vs-~E decision.  This makes a visible difference when D
    
    603
    +  ;; was originally NIL: ~E then produces its free-format (shortest)
    
    604
    +  ;; output rather than the longer fixed-precision form.
    
    605
    +  ;; 1.5d-10 has n=-9, q=2, effective-d=2, dd=11 -> ~E with D=nil.
    
    606
    +  (assert-equal "1.5d-10"
    
    607
    +                (lisp::format-g 1.5d-10 nil nil nil 1 nil nil #\d nil))
    
    608
    +  ;; If we passed effective-d=2 to ~E we'd get "1.50d-10" instead.
    
    609
    +  (assert-false (equal "1.50d-10"
    
    610
    +                       (lisp::format-g 1.5d-10 nil nil nil 1 nil nil #\d nil))))
    
    611
    +
    
    594 612
     (define-test format-g.padchar
    
    595 613
       (:tag :format-g)
    
    596 614
       ;; padchar passed through to whichever sub-formatter fires.