| ... |
... |
@@ -147,6 +147,16 @@ |
|
147
|
147
|
((< n 100) 2)
|
|
148
|
148
|
(t 3)))
|
|
149
|
149
|
|
|
|
150
|
+(declaim (inline exponent-digit-count))
|
|
|
151
|
+(defun exponent-digit-count (e actual-exp)
|
|
|
152
|
+ "Number of decimal digits needed to display the ACTUAL-EXP in a width
|
|
|
153
|
+ of E. If E is NIL, the actual number of digits is returned.
|
|
|
154
|
+ Otherwise, the max of E and the number of digits is returned."
|
|
|
155
|
+ (declare (type (or fixnum null) e)
|
|
|
156
|
+ (fixnum actual-exp))
|
|
|
157
|
+ (max (or e 1)
|
|
|
158
|
+ (count-decimal-digits (abs actual-exp))))
|
|
|
159
|
+
|
|
150
|
160
|
(defun compute-d-for-width (w e k actual-exp is-negative-p at-sign-p)
|
|
151
|
161
|
"Find the largest d (precision) value that fits in width W given the
|
|
152
|
162
|
actual exponent (adjusted by k), and whether signs are printed or
|
| ... |
... |
@@ -155,8 +165,7 @@ |
|
155
|
165
|
Returns NIL if no width d can fit in a field of length w."
|
|
156
|
166
|
(declare (fixnum k actual-exp))
|
|
157
|
167
|
(let* ((sign-len (if (or is-negative-p at-sign-p) 1 0))
|
|
158
|
|
- (exp-digits (max (or e 1)
|
|
159
|
|
- (count-decimal-digits (abs actual-exp))))
|
|
|
168
|
+ (exp-digits (exponent-digit-count e actual-exp))
|
|
160
|
169
|
;; The min output includes the leading sign, and the length
|
|
161
|
170
|
;; of the exponent. If k > 0, we have a leading digit, a
|
|
162
|
171
|
;; dot, the exponent marker and exponent sign for 4 extra.
|
| ... |
... |
@@ -187,8 +196,7 @@ |
|
187
|
196
|
(fixnum actual-exp k)
|
|
188
|
197
|
(type (or null fixnum) e))
|
|
189
|
198
|
(let* ((sign-len (if (or is-negative-p at-sign-p) 1 0))
|
|
190
|
|
- (exp-digits (max (or e 1)
|
|
191
|
|
- (count-decimal-digits (abs actual-exp))))
|
|
|
199
|
+ (exp-digits (exponent-digit-count e actual-exp))
|
|
192
|
200
|
(raw-digits (mantissa-digit-count mantissa))
|
|
193
|
201
|
(mantissa-len
|
|
194
|
202
|
(cond
|
| ... |
... |
@@ -328,6 +336,21 @@ |
|
328
|
336
|
;; d - |k| - 1 digits after the decimal point.
|
|
329
|
337
|
(max (+ d k -1) 0))))
|
|
330
|
338
|
|
|
|
339
|
+(defun write-exponent (stream shown-exp e exponentchar)
|
|
|
340
|
+ "Write the ~E exponent tail \"[marker][sign][digits]\" to STREAM.
|
|
|
341
|
+ E is the minimum exponent-digit count (zero-padded if shorter);
|
|
|
342
|
+ EXPONENTCHAR overrides the marker (default #\\d)."
|
|
|
343
|
+ (declare (fixnum shown-exp)
|
|
|
344
|
+ (type (or null fixnum) e))
|
|
|
345
|
+ (let* ((exp-abs (abs shown-exp))
|
|
|
346
|
+ (exp-digits (count-decimal-digits exp-abs))
|
|
|
347
|
+ (exp-width (max (or e 1) exp-digits)))
|
|
|
348
|
+ (write-char (or exponentchar #\d) stream)
|
|
|
349
|
+ (write-char (if (minusp shown-exp) #\- #\+) stream)
|
|
|
350
|
+ (loop repeat (- exp-width exp-digits)
|
|
|
351
|
+ do (write-char #\0 stream))
|
|
|
352
|
+ (princ exp-abs stream)))
|
|
|
353
|
+
|
|
331
|
354
|
(defun format-e-string (stream mantissa exponent is-negative-p w e k
|
|
332
|
355
|
overflowchar padchar exponentchar at-sign-p
|
|
333
|
356
|
drop-leading-zero-p)
|
| ... |
... |
@@ -342,32 +365,14 @@ |
|
342
|
365
|
(declare (type simple-string mantissa)
|
|
343
|
366
|
(fixnum exponent k))
|
|
344
|
367
|
(let* ((shown-exp (- exponent (1- k)))
|
|
345
|
|
- (exp-sign (if (minusp shown-exp)
|
|
346
|
|
- #\- #\+))
|
|
347
|
|
- (exp-abs (abs shown-exp))
|
|
348
|
|
- (exp-marker (or exponentchar #\d))
|
|
349
|
|
- (exp-digits (count-decimal-digits exp-abs))
|
|
350
|
|
- (exp-width (max (or e 1)
|
|
351
|
|
- exp-digits))
|
|
352
|
|
- ;; Full output length: sign + reshaped + marker + exp-sign +
|
|
353
|
|
- ;; exp-width. compute-exp-output-length gives reshape + exp
|
|
354
|
|
- ;; body (marker + exp-sign + max(e, exp-digits)), but it also
|
|
355
|
|
- ;; includes sign, so use it directly. Wait, it doesn't
|
|
356
|
|
- ;; account for drop-leading-zero, so we use it carefully.
|
|
357
|
368
|
(field-len (compute-exp-output-length mantissa shown-exp k e
|
|
358
|
369
|
is-negative-p at-sign-p
|
|
359
|
370
|
drop-leading-zero-p)))
|
|
360
|
371
|
(flet ((write-field ()
|
|
361
|
|
- (cond (is-negative-p
|
|
362
|
|
- (write-char #\- stream))
|
|
363
|
|
- (at-sign-p
|
|
364
|
|
- (write-char #\+ stream)))
|
|
|
372
|
+ (cond (is-negative-p (write-char #\- stream))
|
|
|
373
|
+ (at-sign-p (write-char #\+ stream)))
|
|
365
|
374
|
(scale-mantissa stream mantissa k drop-leading-zero-p)
|
|
366
|
|
- (write-char exp-marker stream)
|
|
367
|
|
- (write-char exp-sign stream)
|
|
368
|
|
- (loop repeat (- exp-width exp-digits)
|
|
369
|
|
- do (write-char #\0 stream))
|
|
370
|
|
- (princ exp-abs stream)))
|
|
|
375
|
+ (write-exponent stream shown-exp e exponentchar)))
|
|
371
|
376
|
(declare (dynamic-extent #'write-field))
|
|
372
|
377
|
(pad-overflow stream field-len w overflowchar padchar #'write-field))))
|
|
373
|
378
|
|
| ... |
... |
@@ -385,11 +390,7 @@ |
|
385
|
390
|
(let* ((dotpos (position #\. mantissa))
|
|
386
|
391
|
(mant-len (length mantissa))
|
|
387
|
392
|
(sig-digits (mantissa-digit-count mantissa))
|
|
388
|
|
- (exp-sign (if (minusp shown-exp) #\- #\+))
|
|
389
|
|
- (exp-abs (abs shown-exp))
|
|
390
|
|
- (exp-digits (count-decimal-digits exp-abs))
|
|
391
|
|
- (exp-width (max (or e 1) exp-digits))
|
|
392
|
|
- (exp-marker (or exponentchar #\d))
|
|
|
393
|
+ (exp-width (exponent-digit-count e shown-exp))
|
|
393
|
394
|
(sign-len (if (or is-negative-p at-sign-p) 1 0))
|
|
394
|
395
|
;; sign + int + dot + marker + exp-sign + exp-width
|
|
395
|
396
|
(field-len (+ sign-len int-digits 3 exp-width)))
|
| ... |
... |
@@ -411,11 +412,7 @@ |
|
411
|
412
|
(loop repeat (- int-digits sig-digits)
|
|
412
|
413
|
do (write-char #\0 stream))
|
|
413
|
414
|
(write-char #\. stream)
|
|
414
|
|
- (write-char exp-marker stream)
|
|
415
|
|
- (write-char exp-sign stream)
|
|
416
|
|
- (loop repeat (- exp-width exp-digits)
|
|
417
|
|
- do (write-char #\0 stream))
|
|
418
|
|
- (princ exp-abs stream)))
|
|
|
415
|
+ (write-exponent stream shown-exp e exponentchar)))
|
|
419
|
416
|
(declare (dynamic-extent #'write-field))
|
|
420
|
417
|
(pad-overflow stream field-len w overflowchar padchar #'write-field))))
|
|
421
|
418
|
|