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

Commits:

2 changed files:

Changes:

  • src/code/ryu-print.lisp
    ... ... @@ -142,7 +142,7 @@
    142 142
       (declare (fixnum k actual-exp))
    
    143 143
       (let* ((sign-len (if (or is-negative-p at-sign-p) 1 0))
    
    144 144
     	 (exp-digits (max (or e 1)
    
    145
    -			  (length (princ-to-string (abs actual-exp)))))
    
    145
    +			  (count-decimal-digits (abs actual-exp))))
    
    146 146
     	 ;; The min output includes the leading sign, and the length
    
    147 147
     	 ;; of the exponent.  If k > 0, we have a leading digit, a
    
    148 148
     	 ;; dot, the exponent marker and exponent sign for 4 extra.
    
    ... ... @@ -389,16 +389,48 @@
    389 389
                    (t
    
    390 390
                     (let* ((d-fit (compute-d-for-width w e k actual-exp is-negative-p at-sign-p))
    
    391 391
                            (drop-zero-p (and d-fit (<= k 0))))
    
    392
    -                  (if d-fit
    
    393
    -                      (multiple-value-bind (mantissa exponent)
    
    394
    -                          (parsed-exp-form (d2exp abs-value
    
    392
    +                  (cond
    
    393
    +                    (d-fit
    
    394
    +                     (multiple-value-bind (mantissa exponent)
    
    395
    +                         (parsed-exp-form (d2exp abs-value
    
    395 396
     						  (d2exp-precision d-fit k)))
    
    396
    -                        (format-e-string stream mantissa exponent is-negative-p
    
    397
    -                                         w e k overflowchar padchar exponentchar at-sign-p
    
    398
    -                                         drop-zero-p))
    
    399
    -                      (format-e-string stream mantissa exponent is-negative-p
    
    400
    -                                       w e k overflowchar padchar exponentchar at-sign-p
    
    401
    -                                       nil))))))))))))
    
    397
    +                       (format-e-string stream mantissa exponent is-negative-p
    
    398
    +                                        w e k overflowchar padchar exponentchar at-sign-p
    
    399
    +                                        drop-zero-p)))
    
    400
    +                    (overflowchar
    
    401
    +                     ;; Not even the no-fractional-digit form fits and
    
    402
    +                     ;; an overflow char was supplied: fill W.
    
    403
    +                     (loop repeat w do (write-char overflowchar stream)))
    
    404
    +                    ((= k 1)
    
    405
    +                     ;; No fractional digit fits.  Emit "[d].e[exp]"
    
    406
    +                     ;; directly -- no forced ".0".  CLHS 22.3.3.2
    
    407
    +                     ;; "single zero digit ... if the width w permits";
    
    408
    +                     ;; here it does not, so the field overflows W.
    
    409
    +                     ;; Handled only for k=1 (default); other k values
    
    410
    +                     ;; fall through to the old format-e-string path.
    
    411
    +                     (multiple-value-bind (one-digit shown-exp)
    
    412
    +                         (parsed-exp-form (d2exp abs-value 0))
    
    413
    +                       (let* ((exp-sign  (if (minusp shown-exp) #\- #\+))
    
    414
    +                              (exp-abs   (abs shown-exp))
    
    415
    +                              (exp-digits (count-decimal-digits exp-abs))
    
    416
    +                              (exp-width (max (or e 1) exp-digits))
    
    417
    +                              (exp-marker (or exponentchar #\d)))
    
    418
    +                         (cond (is-negative-p (write-char #\- stream))
    
    419
    +                               (at-sign-p     (write-char #\+ stream)))
    
    420
    +                         (write-string one-digit stream)
    
    421
    +                         (write-char #\. stream)
    
    422
    +                         (write-char exp-marker stream)
    
    423
    +                         (write-char exp-sign stream)
    
    424
    +                         (loop repeat (- exp-width exp-digits)
    
    425
    +                               do (write-char #\0 stream))
    
    426
    +                         (princ exp-abs stream))))
    
    427
    +                    (t
    
    428
    +                     ;; k != 1 and no width fits: fall back to the
    
    429
    +                     ;; shortest form (may still emit a forced ".0";
    
    430
    +                     ;; rare, not yet handled).
    
    431
    +                     (format-e-string stream mantissa exponent is-negative-p
    
    432
    +                                      w e k overflowchar padchar exponentchar at-sign-p
    
    433
    +                                      nil)))))))))))))
    
    402 434
     
    
    403 435
     ;;; Ryu ~F
    
    404 436
     (defun format-f-fixed (stream value w d
    

  • tests/ryu.lisp
    ... ... @@ -288,6 +288,24 @@
    288 288
       (assert-equal "0.0d+0"
    
    289 289
                     (lisp::format-e 0d0 nil nil nil 1 nil nil #\d nil)))
    
    290 290
     
    
    291
    +(define-test format-e.tight-width-no-fraction
    
    292
    +  (:tag :format-e)
    
    293
    +  ;; ANSI FORMAT.E.4/.5/.7/.8/.9: ~Ne with N too small for the
    
    294
    +  ;; "d.0e+0" shortest form drops the fractional digit instead of
    
    295
    +  ;; forcing the ".0", giving "d.e+0" (overflowing W when even that
    
    296
    +  ;; form is wider).  CLHS 22.3.3.2 "single zero digit ... if the
    
    297
    +  ;; width w permits" -- here it does not.
    
    298
    +  (assert-equal "1.e+0"
    
    299
    +                (lisp::format-e 1.0f0 5 nil nil 1 nil nil #\e nil))
    
    300
    +  (assert-equal "1.e+0"
    
    301
    +                (lisp::format-e 1.0f0 4 nil nil 1 nil nil #\e nil))
    
    302
    +  (assert-equal "+1.e+0"
    
    303
    +                (lisp::format-e 1.0f0 6 nil nil 1 nil nil #\e t))
    
    304
    +  (assert-equal "+1.e+0"
    
    305
    +                (lisp::format-e 1.0f0 5 nil nil 1 nil nil #\e t))
    
    306
    +  (assert-equal "-1.e+0"
    
    307
    +                (lisp::format-e -1.0f0 6 nil nil 1 nil nil #\e nil)))
    
    308
    +
    
    291 309
     ;;; ~F tests
    
    292 310
     (define-test format-f.basic
    
    293 311
       (:tag :format-f)