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

Commits:

3 changed files:

Changes:

  • src/code/ryu-print.lisp
    ... ... @@ -489,10 +489,11 @@
    489 489
        d2fixed and write it right-justified in a field of width W.  At
    
    490 490
        least one fractional digit is always shown: if FRAC is 0 the
    
    491 491
        rounded value is integral and a single \"0\" is appended after the
    
    492
    -   decimal point (CLHS 22.3.3.1).  The optional leading zero before
    
    493
    -   the decimal point is dropped when the field would otherwise
    
    494
    -   overflow W.  Used by the free-format ~F path when the shortest
    
    495
    -   representation does not fit in W."
    
    492
    +   decimal point (CLHS 22.3.3.1).  The leading zero before the
    
    493
    +   decimal point is kept when the field fits in W (FORMAT.F.47) and
    
    494
    +   dropped when keeping it would overflow W (FORMAT.F.46).  Used by
    
    495
    +   the free-format ~F path when the shortest representation does not
    
    496
    +   fit in W."
    
    496 497
       (declare (type (or single-float double-float) value)
    
    497 498
     	   (type (integer 0 *) frac))
    
    498 499
       (let* ((rounded   (d2fixed (float (abs value) 1d0) frac))
    
    ... ... @@ -510,7 +511,7 @@
    510 511
     	 (sign-len   (if (or is-negative-p at-sign-p) 1 0))
    
    511 512
     	 ;; The leading "0." may be shortened to "." when the magnitude
    
    512 513
     	 ;; is < 1 (integer part is the single digit "0") and nonzero,
    
    513
    -	 ;; and the full field would not fit in W.
    
    514
    +	 ;; and only when the full field would not fit in W.
    
    514 515
     	 (lpoint-droppable
    
    515 516
     	   (and (= int-end 1)
    
    516 517
     		(char= (char rounded 0) #\0)
    
    ... ... @@ -544,23 +545,14 @@
    544 545
                  (int-len     (max 1 (1+ exponent)))
    
    545 546
                  (shortest-d  (max 0 (- digit-count 1 exponent)))
    
    546 547
                  (sign-len    (if (or is-negative-p at-sign-p) 1 0))
    
    547
    -             (d-fit       (and w (- w sign-len int-len 1)))
    
    548
    -	     ;; When the magnitude is < 1 the integer part is a single
    
    549
    -	     ;; "0" that may be dropped (the leading zero is optional),
    
    550
    -	     ;; freeing one more slot for a fractional digit.  Compute
    
    551
    -	     ;; the fractional-digit count that exactly fills W under
    
    552
    -	     ;; that rule.
    
    553
    -	     (frac-fit (and w
    
    554
    -			    (if (plusp (1+ exponent))
    
    555
    -				(- w sign-len int-len 1)	; "[int]."
    
    556
    -				(- w sign-len 1)))))		; ".[frac]"
    
    548
    +             (d-fit       (and w (- w sign-len int-len 1))))
    
    557 549
     	(cond
    
    558 550
               ((or (null w) (>= d-fit shortest-d))
    
    559 551
     	   ;; No width, or the shortest round-trip form already fits
    
    560 552
     	   ;; within a field width of W.  Emit it directly.
    
    561 553
                (emit-shortest stream mantissa exponent is-negative-p w
    
    562 554
                               overflowchar padchar at-sign-p))
    
    563
    -	  ((and overflowchar (minusp frac-fit))
    
    555
    +	  ((and overflowchar (minusp d-fit))
    
    564 556
     	   ;; Not even the integer part and decimal point fit, and an
    
    565 557
     	   ;; overflow character was supplied: fill the field.
    
    566 558
     	   (loop repeat w
    
    ... ... @@ -568,12 +560,12 @@
    568 560
     	  (t
    
    569 561
     	   ;; The shortest form does not fit in W.  D was not specified,
    
    570 562
     	   ;; so round the value to the largest number of fractional
    
    571
    -	   ;; digits FRAC-FIT that fits, then display it.  Per CLHS
    
    572
    -	   ;; 22.3.3.1, if the fraction rounds away to nothing a single
    
    573
    -	   ;; zero digit must still appear after the decimal point.  We
    
    574
    -	   ;; therefore round at FRAC-FIT places (which may be 0) but
    
    575
    -	   ;; always show at least one fractional digit.
    
    576
    -	   (emit-rounded-to-width stream value (max 0 frac-fit)
    
    563
    +	   ;; digits D-FIT that fits, then display it.  Per CLHS 22.3.3.1,
    
    564
    +	   ;; if the fraction rounds away to nothing a single zero digit
    
    565
    +	   ;; must still appear after the decimal point.  EMIT-ROUNDED-TO-
    
    566
    +	   ;; WIDTH may drop the leading "0" before the dot if keeping it
    
    567
    +	   ;; would still overflow W.
    
    568
    +	   (emit-rounded-to-width stream value (max 0 d-fit)
    
    577 569
     				  is-negative-p w
    
    578 570
     				  overflowchar padchar at-sign-p)))))))
    
    579 571
     
    

  • src/i18n/locale/cmucl.pot
    No preview for this file type
  • tests/ryu.lisp
    ... ... @@ -767,18 +767,24 @@
    767 767
     
    
    768 768
     (define-test format-f.d-nil-rounds-to-width-with-forced-zero
    
    769 769
       (:tag :format-f)
    
    770
    -  ;; ANSI FORMAT.F.45/F.47: ~F with unspecified d rounds the value to
    
    771
    -  ;; the fractional digits that fit in W, but always shows at least one
    
    772
    -  ;; fractional digit (a single "0" if the fraction rounds away).  The
    
    773
    -  ;; field expands past W when even that minimum doesn't fit and no
    
    774
    -  ;; overflow char is given.
    
    775
    -  ;; ~2f of 1.1 and 1.9 round to integers, forced ".0", overflow to 3.
    
    770
    +  ;; ANSI FORMAT.F.45/F.46/F.47: ~F with unspecified d rounds the
    
    771
    +  ;; value to the fractional digits that fit in W, always shows at
    
    772
    +  ;; least one fractional digit (a single "0" if the fraction rounds
    
    773
    +  ;; away), and drops the leading "0." -> "." only when keeping it
    
    774
    +  ;; would overflow W.
    
    775
    +  ;; ~2f of 1.1 and 1.9 round to integers, forced ".0", overflow to 3
    
    776
    +  ;; (FORMAT.F.45).
    
    776 777
       (assert-equal "1.0" (lisp::format-f 1.1f0 2 nil 0 nil nil nil))
    
    777 778
       (assert-equal "2.0" (lisp::format-f 1.9f0 2 nil 0 nil nil nil))
    
    778
    -  ;; ~3f of 1e-6: rounds to .00 (leading zero dropped to fit width 3).
    
    779
    -  (assert-equal ".00" (lisp::format-f 1.0f-6 3 nil 0 nil nil nil))
    
    780
    -  ;; ~4f of 1e-6: .000.
    
    781
    -  (assert-equal ".000" (lisp::format-f 1.0f-6 4 nil 0 nil nil nil)))
    
    779
    +  ;; ~3f of 1e-6: "0.0" fits w=3 exactly, leading zero kept
    
    780
    +  ;; (FORMAT.F.47).
    
    781
    +  (assert-equal "0.0" (lisp::format-f 1.0f-6 3 nil 0 nil nil nil))
    
    782
    +  ;; ~4f of 1e-6: "0.00" fits w=4 exactly.
    
    783
    +  (assert-equal "0.00" (lisp::format-f 1.0f-6 4 nil 0 nil nil nil))
    
    784
    +  ;; ~2f, ~1f, ~0f of 0.01: leading zero dropped to ".0" (FORMAT.F.46).
    
    785
    +  (assert-equal ".0" (lisp::format-f 0.01f0 2 nil 0 nil nil nil))
    
    786
    +  (assert-equal ".0" (lisp::format-f 0.01f0 1 nil 0 nil nil nil))
    
    787
    +  (assert-equal ".0" (lisp::format-f 0.01f0 0 nil 0 nil nil nil)))
    
    782 788
     
    
    783 789
     (define-test format-f.single-narrow-width-with-overflow-char
    
    784 790
       (:tag :format-f :single-float)