Raymond Toy pushed to branch rtoy-ryu-printf at cmucl / cmucl

Commits:

1 changed file:

Changes:

  • src/code/print.lisp
    ... ... @@ -2107,7 +2107,8 @@ radix-R. If you have a power-list then pass it in as PL."
    2107 2107
             ((< n 100) 2)
    
    2108 2108
             (t         3)))
    
    2109 2109
     
    
    2110
    -(defun compute-exp-output-length (mantissa actual-exp k e is-negative-p at-sign-p drop-leading-zero-p)
    
    2110
    +(defun compute-exp-output-length (mantissa actual-exp k e is-negative-p at-sign-p
    
    2111
    +				  drop-leading-zero-p)
    
    2111 2112
       ;; Compute length of the ~E result with the given parameters, but
    
    2112 2113
       ;; don't build the string.  MANTISSA is "d[.dddd]" from d2exp or d2s.
    
    2113 2114
       ;; ACTUAL-EXP is the exponent with scaling factor applied.  If
    
    ... ... @@ -2138,77 +2139,6 @@ radix-R. If you have a power-list then pass it in as PL."
    2138 2139
         ;; +2 for the exponent marker and sign
    
    2139 2140
         (+ sign-len mantissa-len exp-digits 2)))
    
    2140 2141
     
    
    2141
    -#+nil
    
    2142
    -(defun reshape-format-e (mantissa-text k drop-leading-zero-p)
    
    2143
    -  "Reshape MANTISSA-TEXT of the form 'd[.dddd]Eee' from d2s or d2exp into
    
    2144
    -  the displayed mantissa for ~E with scale factor K.  If
    
    2145
    -  DROP-LEADING-ZERO-P is non-NIL, the leading 0 that would have been
    
    2146
    -  printed is dropped."
    
    2147
    -  (declare (type simple-string mantissa-text)
    
    2148
    -           (fixnum k))
    
    2149
    -  ;; Fast path: K=1 covers the overwhelmingly common case since K=1 is
    
    2150
    -  ;; the default.
    
    2151
    -  (when (= k 1)
    
    2152
    -    (return-from reshape-format-e
    
    2153
    -      (cond
    
    2154
    -        ((find #\. mantissa-text)
    
    2155
    -         mantissa-text)                                      ; verbatim
    
    2156
    -        (t
    
    2157
    -         (concatenate 'string mantissa-text ".0")))))         ; single digit -> "D.0"
    
    2158
    -  (let* ((has-dot     (find #\. mantissa-text))
    
    2159
    -         (lead-char   (char mantissa-text 0))
    
    2160
    -	 ;; Where the stuff after the dot starts
    
    2161
    -         (tail-start  (if has-dot 2 1))
    
    2162
    -         (tail-len    (- (length mantissa-text) tail-start))
    
    2163
    -         (digit-count (1+ tail-len)))
    
    2164
    -    ;; Several cases to consider:
    
    2165
    -    ;;
    
    2166
    -    ;; * k is negative so the new dot preceeds the mantissa.  Pad with
    
    2167
    -    ;;   zeroes.
    
    2168
    -    ;; * k is so large that the dot is past the rightmost part of the
    
    2169
    -    ;;   mantissa.  Append enough zeroes and then add ".0"
    
    2170
    -    ;; * k is somewhere in the mantissa.  Handling of this case
    
    2171
    -    ;;   depends on if the new dot is to the left or to the right of
    
    2172
    -    ;;   the original dot.
    
    2173
    -    (with-output-to-string (s)
    
    2174
    -      (cond
    
    2175
    -        ;; Case 2: new dot at or before position 0.
    
    2176
    -        ((<= k 0)
    
    2177
    -         (unless drop-leading-zero-p
    
    2178
    -	   (write-char #\0 s))
    
    2179
    -         (write-char #\. s)
    
    2180
    -	 ;; Insert zeros after the decimal but before the mantissa.
    
    2181
    -         (loop repeat (- k)
    
    2182
    -	       do (write-char #\0 s))
    
    2183
    -	 ;; Insert the mantissa, skipping the existing dot.
    
    2184
    -         (write-char lead-char s)
    
    2185
    -         (when (plusp tail-len)
    
    2186
    -           (write-string mantissa-text s :start tail-start)))
    
    2187
    -        ;; Case 1b: 1 < k < digit-count.  Move dot right by (k-1).
    
    2188
    -        ((< k digit-count)
    
    2189
    -	 ;; Output the original mantissa up to the original dot.
    
    2190
    -         (write-char lead-char s)
    
    2191
    -         (write-string mantissa-text s
    
    2192
    -                       :start tail-start
    
    2193
    -                       :end (+ tail-start k -1))
    
    2194
    -	 ;; Output the new dot.
    
    2195
    -         (write-char #\. s)
    
    2196
    -	 ;; Output everything after the original dot.
    
    2197
    -         (write-string mantissa-text s
    
    2198
    -		       :start (+ tail-start k -1)))
    
    2199
    -        ;; Case 3: k >= digit-count.  Pad with zeros, force ".0".
    
    2200
    -        (t
    
    2201
    -	 ;; Output the original mantissa, then everything after the
    
    2202
    -	 ;; dot (if there was one).
    
    2203
    -         (write-char lead-char s)
    
    2204
    -         (when (plusp tail-len)
    
    2205
    -           (write-string mantissa-text s :start tail-start))
    
    2206
    -	 ;; Pad with 0's
    
    2207
    -         (loop repeat (- k digit-count)
    
    2208
    -	       do (write-char #\0 s))
    
    2209
    -	 ;; Finish with ".0".
    
    2210
    -         (write-string ".0" s))))))
    
    2211
    -
    
    2212 2142
     (defun scale-mantissa (stream mantissa-text k drop-leading-zero-p)
    
    2213 2143
       "Write MANTISSA-TEXT to STREAM, shifting the decimal point so that
    
    2214 2144
        the new dot lands K digits in from the start of the digit string.
    
    ... ... @@ -2292,56 +2222,6 @@ radix-R. If you have a power-list then pass it in as PL."
    2292 2222
     	 ;; d - |k| - 1 digits after the decimal point.
    
    2293 2223
     	 (max (+ d k -1) 0))))
    
    2294 2224
     		  
    
    2295
    -#+nil
    
    2296
    -(defun format-e-string (mantissa exponent is-negative-p w e k
    
    2297
    -                        overflowchar padchar exponentchar at-sign-p
    
    2298
    -                        drop-leading-zero-p)
    
    2299
    -  (declare (type simple-string mantissa)
    
    2300
    -           (fixnum exponent k))
    
    2301
    -  (let* ((shown-exp (- exponent (1- k)))
    
    2302
    -         (exp-sign (if (minusp shown-exp) #\- #\+))
    
    2303
    -         (exp-abs (abs shown-exp))
    
    2304
    -         (exp-marker (or exponentchar #\d))
    
    2305
    -         (exp-string
    
    2306
    -           (with-output-to-string (s)
    
    2307
    -             (write-char exp-marker s)
    
    2308
    -             (write-char exp-sign s)
    
    2309
    -	     #+nil
    
    2310
    -             (let ((digits (princ-to-string exp-abs)))
    
    2311
    -               (when e
    
    2312
    -                 (loop repeat (- e (length digits))
    
    2313
    -                       do (write-char #\0 s)))
    
    2314
    -               (write-string digits s))
    
    2315
    -	     (let ((d (count-decimal-digits exp-abs)))
    
    2316
    -	       (when e
    
    2317
    -                 (loop repeat (- e d)
    
    2318
    -                       do (write-char #\0 s)))
    
    2319
    -	       (princ exp-abs s))))
    
    2320
    -         (sign-mantissa (cond (is-negative-p "-")
    
    2321
    -                              (at-sign-p "+")
    
    2322
    -                              (t "")))
    
    2323
    -         ;; Reshape once, reuse everywhere.
    
    2324
    -         (reshaped (reshape-format-e mantissa k drop-leading-zero-p))
    
    2325
    -         (field-len (+ (length sign-mantissa)
    
    2326
    -                       (length reshaped)
    
    2327
    -                       (length exp-string))))
    
    2328
    -    (flet ((write-field (s)
    
    2329
    -             (write-string sign-mantissa s)
    
    2330
    -             (write-string reshaped s)
    
    2331
    -             (write-string exp-string s)))
    
    2332
    -      (with-output-to-string (s)
    
    2333
    -        (cond
    
    2334
    -          ((null w)
    
    2335
    -           (write-field s))
    
    2336
    -          ((> field-len w)
    
    2337
    -           (if overflowchar
    
    2338
    -               (loop repeat w do (write-char overflowchar s))
    
    2339
    -               (write-field s)))
    
    2340
    -          (t
    
    2341
    -           (let ((pad-char (or padchar #\Space)))
    
    2342
    -             (loop repeat (- w field-len) do (write-char pad-char s))
    
    2343
    -             (write-field s))))))))
    
    2344
    -
    
    2345 2225
     (defun format-e-string (stream mantissa exponent is-negative-p w e k
    
    2346 2226
                             overflowchar padchar exponentchar at-sign-p
    
    2347 2227
                             drop-leading-zero-p)
    
    ... ... @@ -2379,64 +2259,6 @@ radix-R. If you have a power-list then pass it in as PL."
    2379 2259
           (declare (dynamic-extent #'write-field))
    
    2380 2260
           (pad-overflow stream field-len w overflowchar padchar #'write-field))))
    
    2381 2261
     
    
    2382
    -#+nil
    
    2383
    -(defun format-e (value w d e k overflowchar padchar exponentchar at-sign-p)
    
    2384
    -  (declare (double-float value)
    
    2385
    -	   (fixnum k)
    
    2386
    -	   (type (or null (and unsigned-byte fixnum)) w d e)
    
    2387
    -	   (optimize (speed 3)))
    
    2388
    -  (let* ((is-negative-p (minusp (float-sign value)))
    
    2389
    -	 (abs-value (abs value)))
    
    2390
    -    (cond
    
    2391
    -      (d
    
    2392
    -       ;; Fixed precision path.  Leading 0 is kept.
    
    2393
    -       (multiple-value-bind (mantissa exponent)
    
    2394
    -	   (parsed-exp-form (d2exp abs-value (d2exp-precision d k)))
    
    2395
    -	 (format-e-string mantissa exponent is-negative-p
    
    2396
    -			  w e k overflowchar padchar exponentchar at-sign-p nil)))
    
    2397
    -      (t
    
    2398
    -       ;; Free-format path.  Use d2s to find the shortest result.  If
    
    2399
    -       ;; it won't fit in the given format parameters, compute a new d
    
    2400
    -       ;; value to make it fit in the given width if possible.
    
    2401
    -       ;; Otherwise, overflow.
    
    2402
    -       (multiple-value-bind (mantissa exponent)
    
    2403
    -	   (parsed-exp-form (d2s abs-value))
    
    2404
    -	 (let* ((actual-exp (- exponent (1- k)))
    
    2405
    -		(full-len (compute-exp-output-length mantissa actual-exp k e is-negative-p at-sign-p
    
    2406
    -						    nil)))
    
    2407
    -	   #+nil
    
    2408
    -	   (format t "mantissa = ~A exponent = ~D actual-exp = ~D full-len = ~D w = ~D~%"
    
    2409
    -		   mantissa exponent actual-exp full-len w)
    
    2410
    -	   (cond
    
    2411
    -	     ((or (null w) (<= full-len w))
    
    2412
    -	      ;; Shortest fits.  Emit it.  Drop the leading 0 whenever
    
    2413
    -	      ;; k <= 0 so the actual emitted legnth matches the
    
    2414
    -	      ;; predicted one.
    
    2415
    -	      (format-e-string mantissa exponent is-negative-p
    
    2416
    -			       w e k overflowchar padchar exponentchar at-sign-p
    
    2417
    -			       (not (plusp k))))
    
    2418
    -	     (t
    
    2419
    -	      ;; Doesn't fit.  Compute the largest fitting d and
    
    2420
    -	      ;; recompute the result via d2exp.  For backwards
    
    2421
    -	      ;; compatibility, drop the leading 0 when k <= 0 to
    
    2422
    -	      ;; maximize d, the number of digits shown.
    
    2423
    -	      (let* ((d-fit (compute-d-for-width w e k actual-exp is-negative-p at-sign-p))
    
    2424
    -		     (drop-zero-p (and d-fit (<= k 0))))
    
    2425
    -		#+nil
    
    2426
    -		(format t "d-fit = ~A, drop = ~A~%" d-fit drop-zero-p)
    
    2427
    -		(if d-fit
    
    2428
    -		    (multiple-value-bind (mantissa exponent)
    
    2429
    -			(parsed-exp-form (d2exp abs-value (d2exp-precision d-fit k)))
    
    2430
    -		      (format-e-string mantissa exponent is-negative-p
    
    2431
    -				       w e k overflowchar padchar exponentchar at-sign-p
    
    2432
    -				       drop-zero-p))
    
    2433
    -		    ;; Even with d = 0, the result won't fit.  Let
    
    2434
    -		    ;; FORMAT-E-STRING overflow with the overflow
    
    2435
    -		    ;; character.
    
    2436
    -		    (format-e-string mantissa exponent is-negative-p
    
    2437
    -				     w e k overflowchar padchar exponentchar at-sign-p
    
    2438
    -				     nil)))))))))))
    
    2439
    -
    
    2440 2262
     (defun format-e (value w d e k overflowchar padchar exponentchar at-sign-p)
    
    2441 2263
       (declare (double-float value)
    
    2442 2264
                (fixnum k)
    
    ... ... @@ -2478,23 +2300,6 @@ radix-R. If you have a power-list then pass it in as PL."
    2478 2300
                                            nil))))))))))))
    
    2479 2301
     
    
    2480 2302
     ;;; Ryu ~F
    
    2481
    -#+nil
    
    2482
    -(defun format-f-fixed (stream abs-value is-negative-p w d overflowchar padchar at-sign-p)
    
    2483
    -  (let* ((raw-string (let ((f (d2fixed abs-value d)))
    
    2484
    -		       ;; If precision = 0, d2fixed doesn't have a
    
    2485
    -		       ;; dot.  We need it.
    
    2486
    -		       (if (zerop d)
    
    2487
    -			   (concatenate 'string f ".")
    
    2488
    -			   f)))
    
    2489
    -	 (field
    
    2490
    -	   (with-output-to-string (s)
    
    2491
    -	     (cond (is-negative-p
    
    2492
    -		    (write-char #\- s))
    
    2493
    -		   (at-sign-p
    
    2494
    -		    (write-char #\+ s)))
    
    2495
    -	     (write-string raw-string s))))
    
    2496
    -    (format-f-pad-overflow field w overflowchar padchar)))
    
    2497
    -
    
    2498 2303
     (declaim (inline pad-overflow))
    
    2499 2304
     (defun pad-overflow (stream field-len w overflowchar padchar field-writer)
    
    2500 2305
       "Apply width/pad/overflow rules.  FIELD-WRITER is a thunk of zero
    
    ... ... @@ -2565,34 +2370,6 @@ radix-R. If you have a power-list then pass it in as PL."
    2565 2370
           (declare (dynamic-extent #'write-field))
    
    2566 2371
           (pad-overflow stream field-len w overflowchar padchar #'write-field))))
    
    2567 2372
     	 
    
    2568
    -#+nil
    
    2569
    -(defun format-f-free (abs-value is-negative-p w overflowchar padchar at-sign-p)
    
    2570
    -  ;; We need to call d2s to get the shortest.
    
    2571
    -  (multiple-value-bind (mantissa exponent)
    
    2572
    -      (parsed-exp-form (d2s abs-value))
    
    2573
    -    (let* ((has-dot (find #\. mantissa))
    
    2574
    -           (digit-count (if has-dot (1- (length mantissa)) (length mantissa)))
    
    2575
    -           (int-len (max 1 (1+ exponent)))
    
    2576
    -           (shortest-d (max 0 (- digit-count 1 exponent)))
    
    2577
    -           (sign-len (if (or is-negative-p at-sign-p) 1 0))
    
    2578
    -           (d-fit (and w (- w sign-len int-len 1))))
    
    2579
    -      (cond
    
    2580
    -	((or (null w)
    
    2581
    -	     (>= d-fit shortest-d))
    
    2582
    -	 ;; Shortest fits or no width bound
    
    2583
    -	 (emit-shortest mantissa exponent is-negative-p w overflowchar padchar at-sign-p))
    
    2584
    -	((minusp d-fit)
    
    2585
    -	 ;; Integer part alone exceeds w--overflow path
    
    2586
    -	 (if overflowchar
    
    2587
    -	     (make-string w :initial-element overflowchar)
    
    2588
    -	     ;; No overflow; emit shortest at natural width, overflow w.
    
    2589
    -	     (emit-shortest mantissa exponent is-negative-p
    
    2590
    -			    w overflowchar padchar at-sign-p)))
    
    2591
    -	(t
    
    2592
    -	 ;; d-fit between 0 and shortest-d.  Shrink via d2fixed.
    
    2593
    -	 (format-f-fixed abs-value is-negative-p
    
    2594
    -			 w d-fit overflowchar padchar at-sign-p))))))
    
    2595
    -
    
    2596 2373
     (defun format-f-free (stream abs-value is-negative-p w
    
    2597 2374
                           overflowchar padchar at-sign-p)
    
    2598 2375
       (multiple-value-bind (mantissa exponent)