| ... |
... |
@@ -2440,11 +2440,79 @@ radix-R. If you have a power-list then pass it in as PL." |
|
2440
|
2440
|
do (write-char #\0 s))
|
|
2441
|
2441
|
(write-string raw-digits s))))))
|
|
2442
|
2442
|
|
|
|
2443
|
+#+nil
|
|
2443
|
2444
|
(defun reshape-fixed (mantissa-text exponent)
|
|
2444
|
2445
|
(declare (type simple-string mantissa-text)
|
|
2445
|
2446
|
(fixnum exponent))
|
|
2446
|
2447
|
(reshape-format-e mantissa-text (1+ exponent) nil))
|
|
2447
|
2448
|
|
|
|
2449
|
+(defun reshape-fixed (stream mantissa-text exponent)
|
|
|
2450
|
+ "Adjust MANTISSA-TEXT is scaled exactly by 10^{EXPONENT} by moving the
|
|
|
2451
|
+ decimal point. MANTISSA-TEXT is of the form 'd[.dddd]' from d2exp
|
|
|
2452
|
+ or d2s. The scaled value is written to STREAM."
|
|
|
2453
|
+ (declare (type simple-string mantissa-text)
|
|
|
2454
|
+ (fixnum exponent))
|
|
|
2455
|
+ (let ((k (1+ exponent)))
|
|
|
2456
|
+ ;; If exponent = 0, the mantissa is already the right value, but
|
|
|
2457
|
+ ;; we need to append ".0" if there's not dot in the mantissa.
|
|
|
2458
|
+ ;; This happens when d2s is given a small exact integral value.
|
|
|
2459
|
+ (when (zerop exponent)
|
|
|
2460
|
+ (write-string mantissa-text stream)
|
|
|
2461
|
+ (unless (find #\. mantissa-text)
|
|
|
2462
|
+ (write-string ".0" stream))
|
|
|
2463
|
+ (return-from reshape-fixed))
|
|
|
2464
|
+ (let* ((has-dot (find #\. mantissa-text))
|
|
|
2465
|
+ (lead-char (char mantissa-text 0))
|
|
|
2466
|
+ ;; Where the stuff after the dot starts
|
|
|
2467
|
+ (tail-start (if has-dot 2 1))
|
|
|
2468
|
+ (tail-len (- (length mantissa-text) tail-start))
|
|
|
2469
|
+ (digit-count (1+ tail-len)))
|
|
|
2470
|
+ ;; Several cases to consider:
|
|
|
2471
|
+ ;;
|
|
|
2472
|
+ ;; * k is negative so the new dot preceeds the mantissa. Pad with
|
|
|
2473
|
+ ;; zeroes.
|
|
|
2474
|
+ ;; * k is so large that the dot is past the rightmost part of the
|
|
|
2475
|
+ ;; mantissa. Append enough zeroes and then add ".0"
|
|
|
2476
|
+ ;; * k is somewhere in the mantissa. Handling of this case
|
|
|
2477
|
+ ;; depends on if the new dot is to the left or to the right of
|
|
|
2478
|
+ ;; the original dot.
|
|
|
2479
|
+ (cond
|
|
|
2480
|
+ ;; Case 2: new dot at or before position 0.
|
|
|
2481
|
+ ((<= k 0)
|
|
|
2482
|
+ (write-string "0." stream)
|
|
|
2483
|
+ ;; Insert zeros after the decimal but before the mantissa.
|
|
|
2484
|
+ (loop repeat (- k)
|
|
|
2485
|
+ do (write-char #\0 stream))
|
|
|
2486
|
+ ;; Insert the mantissa, skipping the existing dot.
|
|
|
2487
|
+ (write-char lead-char stream)
|
|
|
2488
|
+ (when (plusp tail-len)
|
|
|
2489
|
+ (write-string mantissa-text stream :start tail-start)))
|
|
|
2490
|
+ ;; Case 1b: 1 < k < digit-count. Move dot right by (k-1).
|
|
|
2491
|
+ ((< k digit-count)
|
|
|
2492
|
+ ;; Output the original mantissa up to the original dot.
|
|
|
2493
|
+ (write-char lead-char stream)
|
|
|
2494
|
+ (write-string mantissa-text stream
|
|
|
2495
|
+ :start tail-start
|
|
|
2496
|
+ :end (+ tail-start k -1))
|
|
|
2497
|
+ ;; Output the new dot.
|
|
|
2498
|
+ (write-char #\. stream)
|
|
|
2499
|
+ ;; Output everything after the original dot.
|
|
|
2500
|
+ (write-string mantissa-text stream
|
|
|
2501
|
+ :start (+ tail-start k -1)))
|
|
|
2502
|
+ ;; Case 3: k >= digit-count. Pad with zeros, force ".0".
|
|
|
2503
|
+ (t
|
|
|
2504
|
+ ;; Output the original mantissa, then everything after the
|
|
|
2505
|
+ ;; dot (if there was one).
|
|
|
2506
|
+ (write-char lead-char stream)
|
|
|
2507
|
+ (when (plusp tail-len)
|
|
|
2508
|
+ (write-string mantissa-text stream :start tail-start))
|
|
|
2509
|
+ ;; Pad with 0's
|
|
|
2510
|
+ (loop repeat (- k digit-count)
|
|
|
2511
|
+ do (write-char #\0 stream))
|
|
|
2512
|
+ ;; Finish with ".0".
|
|
|
2513
|
+ (write-string ".0" stream))))))
|
|
|
2514
|
+
|
|
|
2515
|
+
|
|
2448
|
2516
|
#+nil
|
|
2449
|
2517
|
(defun emit-shortest (mantissa-text exponent is-negative-p w overflowchar padchar at-sign-p)
|
|
2450
|
2518
|
(let* ((reshaped (reshape-fixed mantissa-text exponent))
|
| ... |
... |
@@ -2454,15 +2522,36 @@ radix-R. If you have a power-list then pass it in as PL." |
|
2454
|
2522
|
(field (concatenate 'string sign-text reshaped)))
|
|
2455
|
2523
|
(format-f-pad-overflow field w overflowchar padchar)))
|
|
2456
|
2524
|
|
|
|
2525
|
+(defun reshape-fixed-length (digit-count exponent)
|
|
|
2526
|
+ (let ((k (1+ exponent)))
|
|
|
2527
|
+ (cond ((zerop exponent)
|
|
|
2528
|
+ ;; Fast path
|
|
|
2529
|
+ (if (= digit-count 1)
|
|
|
2530
|
+ 3
|
|
|
2531
|
+ (1+ digit-count)))
|
|
|
2532
|
+ ((<= k 0)
|
|
|
2533
|
+ ;; "0." + |k| zeros + digits
|
|
|
2534
|
+ (+ 2 (- k) digit-count))
|
|
|
2535
|
+ ((< k digit-count)
|
|
|
2536
|
+ ;; "ddd.ddd"; add one for the dot.
|
|
|
2537
|
+ (1+ digit-count))
|
|
|
2538
|
+ (t
|
|
|
2539
|
+ ;; "ddddd.0"; k digits + ".0"
|
|
|
2540
|
+ (+ k 2)))))
|
|
|
2541
|
+
|
|
2457
|
2542
|
(defun emit-shortest (stream mantissa exponent is-negative-p w
|
|
2458
|
2543
|
overflowchar padchar at-sign-p)
|
|
2459
|
|
- (let* ((reshaped (reshape-fixed mantissa exponent))
|
|
|
2544
|
+ (let* ((has-dot (find #\. mantissa))
|
|
|
2545
|
+ ;; Number of digits, not including the decimal point.
|
|
|
2546
|
+ (digit-count (- (length mantissa)
|
|
|
2547
|
+ (if has-dot 1 0)))
|
|
2460
|
2548
|
(sign-len (if (or is-negative-p at-sign-p) 1 0))
|
|
2461
|
|
- (field-len (+ sign-len (length reshaped))))
|
|
|
2549
|
+ (reshaped-len (reshape-fixed-length digit-count exponent))
|
|
|
2550
|
+ (field-len (+ sign-len reshaped-len)))
|
|
2462
|
2551
|
(flet ((write-field ()
|
|
2463
|
2552
|
(cond (is-negative-p (write-char #\- stream))
|
|
2464
|
2553
|
(at-sign-p (write-char #\+ stream)))
|
|
2465
|
|
- (write-string reshaped stream)))
|
|
|
2554
|
+ (reshape-fixed stream mantissa exponent)))
|
|
2466
|
2555
|
(declare (dynamic-extent #'write-field))
|
|
2467
|
2556
|
(pad-overflow stream field-len w overflowchar padchar #'write-field))))
|
|
2468
|
2557
|
|