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

Commits:

1 changed file:

Changes:

  • src/code/ryu-print.lisp
    ... ... @@ -124,6 +124,15 @@
    124 124
         (values mantissa
    
    125 125
     	    (truly-the (signed-byte 11) exp))))
    
    126 126
     
    
    127
    +(declaim (inline mantissa-digit-count))
    
    128
    +(defun mantissa-digit-count (mantissa)
    
    129
    +  "Return the number of significant digits in MANTISSA, a string of
    
    130
    +   the form \"d\" or \"d.dddd\" (as produced by d2s/d2exp).  The decimal
    
    131
    +   point, if present, is not counted."
    
    132
    +  (declare (type string mantissa))
    
    133
    +  (- (length mantissa)
    
    134
    +     (if (find #\. mantissa) 1 0)))
    
    135
    +
    
    127 136
     (defun compute-d-for-width (w e k actual-exp is-negative-p at-sign-p)
    
    128 137
       ;; Find the largest d (precision) value that fits in width W given
    
    129 138
       ;; the actual exponent (adjusted by k), and whether signs are
    
    ... ... @@ -175,9 +184,7 @@
    175 184
       (let* ((sign-len (if (or is-negative-p at-sign-p) 1 0))
    
    176 185
              (exp-digits (max (or e 1)
    
    177 186
                               (count-decimal-digits (abs actual-exp))))
    
    178
    -         (dotp (find #\. mantissa))
    
    179
    -         (raw-digits (let ((len (length mantissa)))
    
    180
    -                       (if dotp (1- len) len)))
    
    187
    +         (raw-digits (mantissa-digit-count mantissa))
    
    181 188
              (mantissa-len
    
    182 189
                (cond
    
    183 190
                  ((plusp k)
    
    ... ... @@ -462,10 +469,8 @@
    462 469
                           overflowchar padchar at-sign-p)
    
    463 470
       (declare (type simple-string mantissa)
    
    464 471
     	   (type (signed-byte 10) exponent))
    
    465
    -  (let* ((has-dot (find #\. mantissa))
    
    466
    -	 ;; Number of digits, not including the decimal point.
    
    467
    -	 (digit-count (- (length mantissa)
    
    468
    -			 (if has-dot 1 0)))
    
    472
    +  (let* (;; Number of digits, not including the decimal point.
    
    473
    +	 (digit-count (mantissa-digit-count mantissa))
    
    469 474
              (sign-len  (if (or is-negative-p at-sign-p) 1 0))
    
    470 475
     	 (reshaped-len (reshape-fixed-length digit-count exponent))
    
    471 476
              (field-len (+ sign-len reshaped-len)))
    
    ... ... @@ -478,6 +483,55 @@
    478 483
           (declare (dynamic-extent #'write-field))
    
    479 484
           (pad-overflow stream field-len w overflowchar padchar #'write-field))))
    
    480 485
     	 
    
    486
    +(defun emit-rounded-to-width (stream value frac is-negative-p w
    
    487
    +			      overflowchar padchar at-sign-p)
    
    488
    +  "Round (the magnitude of) VALUE to FRAC fractional digits with
    
    489
    +   d2fixed and write it right-justified in a field of width W.  At
    
    490
    +   least one fractional digit is always shown: if FRAC is 0 the
    
    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."
    
    496
    +  (declare (type (or single-float double-float) value)
    
    497
    +	   (type (integer 0 *) frac))
    
    498
    +  (let* ((rounded   (d2fixed (float (abs value) 1d0) frac))
    
    499
    +	 (len       (length rounded))
    
    500
    +	 ;; ROUNDED is "ddd" (frac=0) or "ddd.ddd" (frac>0).  Locate the
    
    501
    +	 ;; decimal point and the integer/fractional digit spans without
    
    502
    +	 ;; allocating substrings.
    
    503
    +	 (dot        (position #\. rounded))
    
    504
    +	 (int-end    (or dot len))
    
    505
    +	 (frac-start (if dot (1+ dot) len))
    
    506
    +	 (frac-len   (- len frac-start))
    
    507
    +	 ;; At least one fractional digit is always shown; when there are
    
    508
    +	 ;; none a single "0" is emitted instead.
    
    509
    +	 (frac-out-len (max 1 frac-len))
    
    510
    +	 (sign-len   (if (or is-negative-p at-sign-p) 1 0))
    
    511
    +	 ;; The leading "0." may be shortened to "." when the magnitude
    
    512
    +	 ;; is < 1 (integer part is the single digit "0") and nonzero,
    
    513
    +	 ;; and the full field would not fit in W.
    
    514
    +	 (lpoint-droppable
    
    515
    +	   (and (= int-end 1)
    
    516
    +		(char= (char rounded 0) #\0)
    
    517
    +		(not (zerop value))))
    
    518
    +	 (full-len   (+ sign-len int-end 1 frac-out-len))
    
    519
    +	 (drop-leading-zero-p
    
    520
    +	   (and lpoint-droppable w (> full-len w)))
    
    521
    +	 (field-len  (if drop-leading-zero-p (1- full-len) full-len)))
    
    522
    +    (flet ((write-field ()
    
    523
    +	     (cond (is-negative-p (write-char #\- stream))
    
    524
    +		   (at-sign-p     (write-char #\+ stream)))
    
    525
    +	     (unless drop-leading-zero-p
    
    526
    +	       (write-string rounded stream :start 0 :end int-end))
    
    527
    +	     (write-char #\. stream)
    
    528
    +	     (cond ((zerop frac-len)
    
    529
    +		    (write-char #\0 stream))
    
    530
    +		   (t
    
    531
    +		    (write-string rounded stream :start frac-start :end len)))))
    
    532
    +      (declare (dynamic-extent #'write-field))
    
    533
    +      (pad-overflow stream field-len w overflowchar padchar #'write-field))))
    
    534
    +
    
    481 535
     (defun format-f-free (stream value w
    
    482 536
                           overflowchar padchar at-sign-p)
    
    483 537
       (declare (type (or single-float double-float) value))
    
    ... ... @@ -486,8 +540,7 @@
    486 540
         (declare (ignore abs-value))
    
    487 541
         (multiple-value-bind (mantissa exponent)
    
    488 542
     	(parsed-exp-form (float-to-string value))
    
    489
    -      (let* ((has-dot     (find #\. mantissa))
    
    490
    -             (digit-count (if has-dot (1- (length mantissa)) (length mantissa)))
    
    543
    +      (let* ((digit-count (mantissa-digit-count mantissa))
    
    491 544
                  (int-len     (max 1 (1+ exponent)))
    
    492 545
                  (shortest-d  (max 0 (- digit-count 1 exponent)))
    
    493 546
                  (sign-len    (if (or is-negative-p at-sign-p) 1 0))
    
    ... ... @@ -524,47 +577,6 @@
    524 577
     				  is-negative-p w
    
    525 578
     				  overflowchar padchar at-sign-p)))))))
    
    526 579
     
    
    527
    -(defun emit-rounded-to-width (stream value frac is-negative-p w
    
    528
    -			      overflowchar padchar at-sign-p)
    
    529
    -  "Round (the magnitude of) VALUE to FRAC fractional digits with
    
    530
    -   d2fixed and write it right-justified in a field of width W.  At
    
    531
    -   least one fractional digit is always shown: if FRAC is 0 the
    
    532
    -   rounded value is integral and a single \"0\" is appended after the
    
    533
    -   decimal point (CLHS 22.3.3.1).  The optional leading zero before
    
    534
    -   the decimal point is dropped when the field would otherwise
    
    535
    -   overflow W.  Used by the free-format ~F path when the shortest
    
    536
    -   representation does not fit in W."
    
    537
    -  (declare (type (or single-float double-float) value)
    
    538
    -	   (type (integer 0 *) frac))
    
    539
    -  (let* ((rounded   (d2fixed (float (abs value) 1d0) frac))
    
    540
    -	 ;; ROUNDED is "ddd" (frac=0) or "ddd.ddd" (frac>0).  Split it
    
    541
    -	 ;; into integer and fractional digit runs.
    
    542
    -	 (dot        (position #\. rounded))
    
    543
    -	 (int-part   (if dot (subseq rounded 0 dot) rounded))
    
    544
    -	 (frac-part  (if dot (subseq rounded (1+ dot)) ""))
    
    545
    -	 ;; Force at least one fractional digit.
    
    546
    -	 (frac-out   (if (zerop (length frac-part)) "0" frac-part))
    
    547
    -	 (sign-len   (if (or is-negative-p at-sign-p) 1 0))
    
    548
    -	 ;; The leading "0." may be shortened to "." when the magnitude
    
    549
    -	 ;; is < 1 (integer part is a single "0") and nonzero, and the
    
    550
    -	 ;; full field would not fit in W.
    
    551
    -	 (lpoint-droppable
    
    552
    -	   (and (string= int-part "0")
    
    553
    -		(not (zerop value))))
    
    554
    -	 (full-len   (+ sign-len (length int-part) 1 (length frac-out)))
    
    555
    -	 (drop-leading-zero-p
    
    556
    -	   (and lpoint-droppable w (> full-len w)))
    
    557
    -	 (field-len  (if drop-leading-zero-p (1- full-len) full-len)))
    
    558
    -    (flet ((write-field ()
    
    559
    -	     (cond (is-negative-p (write-char #\- stream))
    
    560
    -		   (at-sign-p     (write-char #\+ stream)))
    
    561
    -	     (unless drop-leading-zero-p
    
    562
    -	       (write-string int-part stream))
    
    563
    -	     (write-char #\. stream)
    
    564
    -	     (write-string frac-out stream)))
    
    565
    -      (declare (dynamic-extent #'write-field))
    
    566
    -      (pad-overflow stream field-len w overflowchar padchar #'write-field))))
    
    567
    -
    
    568 580
     (defun format-f (value w d k overflowchar padchar at-sign-p)
    
    569 581
       (declare (type (or single-float double-float) value)
    
    570 582
     	   (fixnum k)
    
    ... ... @@ -591,9 +603,7 @@
    591 603
     	   (type (or null (and unsigned-byte fixnum)) w d e))
    
    592 604
       (multiple-value-bind (mantissa exponent)
    
    593 605
           (parsed-exp-form (float-to-string value))
    
    594
    -    (let* ((digit-count (- (length mantissa)
    
    595
    -			   (if (find #\. mantissa)
    
    596
    -			       1 0)))
    
    606
    +    (let* ((digit-count (mantissa-digit-count mantissa))
    
    597 607
     	   (n (1+ exponent))
    
    598 608
     	   (effective-d (or d (max digit-count (min n 7))))
    
    599 609
     	   (ee (if e (+ e 2) 4))