| ... |
... |
@@ -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))
|