| ... |
... |
@@ -2096,7 +2096,10 @@ radix-R. If you have a power-list then pass it in as PL." |
|
2096
|
2096
|
raw-string))
|
|
2097
|
2097
|
(mantissa (subseq raw-string 0 e-pos))
|
|
2098
|
2098
|
(exp (parse-integer raw-string :start (1+ e-pos))))
|
|
2099
|
|
- (values mantissa exp)))
|
|
|
2099
|
+ ;; The exponent from a double-float is in the range of [-324,
|
|
|
2100
|
+ ;; 308]. Just declare the exponent as a (signed-byte 11).
|
|
|
2101
|
+ (values mantissa
|
|
|
2102
|
+ (truly-the (signed-byte 11) exp))))
|
|
2100
|
2103
|
|
|
2101
|
2104
|
(defun compute-d-for-width (w e k actual-exp is-negative-p at-sign-p)
|
|
2102
|
2105
|
;; Find the largest d (precision) value that fits in width W given
|
| ... |
... |
@@ -2138,6 +2141,9 @@ radix-R. If you have a power-list then pass it in as PL." |
|
2138
|
2141
|
|
|
2139
|
2142
|
(defun compute-exp-output-length (mantissa actual-exp k e is-negative-p at-sign-p
|
|
2140
|
2143
|
drop-leading-zero-p)
|
|
|
2144
|
+ (declare (type simple-string mantissa)
|
|
|
2145
|
+ (fixnum actual-exp k)
|
|
|
2146
|
+ (type (or null fixnum) e))
|
|
2141
|
2147
|
;; Compute length of the ~E result with the given parameters, but
|
|
2142
|
2148
|
;; don't build the string. MANTISSA is "d[.dddd]" from d2exp or d2s.
|
|
2143
|
2149
|
;; ACTUAL-EXP is the exponent with scaling factor applied. If
|
| ... |
... |
@@ -2154,19 +2160,20 @@ radix-R. If you have a power-list then pass it in as PL." |
|
2154
|
2160
|
((plusp k)
|
|
2155
|
2161
|
(cond
|
|
2156
|
2162
|
((> raw-digits k)
|
|
2157
|
|
- (1+ raw-digits)) ; "D.DDDD"
|
|
|
2163
|
+ (1+ raw-digits)) ; "D.DDDD"
|
|
2158
|
2164
|
((and (= k 1) (= raw-digits 1))
|
|
2159
|
|
- 3) ; "D.0" forced
|
|
|
2165
|
+ 3) ; "D.0" forced
|
|
2160
|
2166
|
(t
|
|
2161
|
|
- (max raw-digits k)))) ; "DDDD"
|
|
|
2167
|
+ (max raw-digits k)))) ; "DDDD"
|
|
2162
|
2168
|
(t
|
|
2163
|
2169
|
;; "0.000DDD" or ".000DDD"
|
|
2164
|
2170
|
(+ (if drop-leading-zero-p 0 1)
|
|
2165
|
|
- 1 ; the dot
|
|
2166
|
|
- (- k) ; leading zeros after the dot
|
|
|
2171
|
+ 1 ; the dot
|
|
|
2172
|
+ (- k) ; leading zeros after the dot
|
|
2167
|
2173
|
raw-digits)))))
|
|
2168
|
2174
|
;; +2 for the exponent marker and sign
|
|
2169
|
|
- (+ sign-len mantissa-len exp-digits 2)))
|
|
|
2175
|
+ (the (and unsigned-byte fixnum)
|
|
|
2176
|
+ (+ sign-len mantissa-len exp-digits 2))))
|
|
2170
|
2177
|
|
|
2171
|
2178
|
(defun scale-mantissa (stream mantissa-text k drop-leading-zero-p)
|
|
2172
|
2179
|
"Write MANTISSA-TEXT to STREAM, shifting the decimal point so that
|
| ... |
... |
@@ -2240,7 +2247,9 @@ radix-R. If you have a power-list then pass it in as PL." |
|
2240
|
2247
|
(defun pad-overflow (stream field-len w overflowchar padchar field-writer)
|
|
2241
|
2248
|
"Apply width/pad/overflow rules. FIELD-WRITER is a thunk of zero
|
|
2242
|
2249
|
arguments that writes the field characters to STREAM."
|
|
2243
|
|
- (declare (function field-writer))
|
|
|
2250
|
+ (declare (fixnum field-len)
|
|
|
2251
|
+ (type (or null fixnum) w)
|
|
|
2252
|
+ (function field-writer))
|
|
2244
|
2253
|
(cond
|
|
2245
|
2254
|
((null w)
|
|
2246
|
2255
|
(funcall field-writer))
|
| ... |
... |
@@ -2267,7 +2276,7 @@ radix-R. If you have a power-list then pass it in as PL." |
|
2267
|
2276
|
(abs value)))
|
|
2268
|
2277
|
(single-float
|
|
2269
|
2278
|
(values (minusp (float-sign value))
|
|
2270
|
|
- (abs (float (value 1d0)))))))
|
|
|
2279
|
+ (abs (float value 1d0))))))
|
|
2271
|
2280
|
|
|
2272
|
2281
|
(defun d2exp-precision (d k)
|
|
2273
|
2282
|
;; Compute precision for d2exp when CL requests D digits and the
|
| ... |
... |
@@ -2297,8 +2306,6 @@ radix-R. If you have a power-list then pass it in as PL." |
|
2297
|
2306
|
(exp-digits (count-decimal-digits exp-abs))
|
|
2298
|
2307
|
(exp-width (max (or e 1)
|
|
2299
|
2308
|
exp-digits))
|
|
2300
|
|
- (sign-len (if (or is-negative-p at-sign-p)
|
|
2301
|
|
- 1 0))
|
|
2302
|
2309
|
;; Full output length: sign + reshaped + marker + exp-sign +
|
|
2303
|
2310
|
;; exp-width. compute-exp-output-length gives reshape + exp
|
|
2304
|
2311
|
;; body (marker + exp-sign + max(e, exp-digits)), but it also
|
| ... |
... |
@@ -2364,23 +2371,33 @@ radix-R. If you have a power-list then pass it in as PL." |
|
2364
|
2371
|
nil))))))))))))
|
|
2365
|
2372
|
|
|
2366
|
2373
|
;;; Ryu ~F
|
|
2367
|
|
-(defun format-f-fixed (stream abs-value is-negative-p w d
|
|
|
2374
|
+(defun format-f-fixed (stream value w d
|
|
2368
|
2375
|
overflowchar padchar at-sign-p)
|
|
2369
|
|
- (declare (double-float abs-value))
|
|
2370
|
|
- (let* ((raw-string (d2fixed abs-value d))
|
|
2371
|
|
- (raw-len (length raw-string))
|
|
2372
|
|
- (sign-len (if (or is-negative-p at-sign-p) 1 0))
|
|
2373
|
|
- (need-dot (zerop d))
|
|
2374
|
|
- (field-len (+ sign-len raw-len (if need-dot 1 0))))
|
|
2375
|
|
- (flet ((write-field ()
|
|
2376
|
|
- (cond (is-negative-p (write-char #\- stream))
|
|
2377
|
|
- (at-sign-p (write-char #\+ stream)))
|
|
2378
|
|
- (write-string raw-string stream)
|
|
2379
|
|
- (when need-dot (write-char #\. stream))))
|
|
2380
|
|
- (declare (dynamic-extent #'write-field))
|
|
2381
|
|
- (pad-overflow stream field-len w overflowchar padchar #'write-field))))
|
|
2382
|
|
-
|
|
|
2376
|
+ (declare (type (or single-float double-float) value))
|
|
|
2377
|
+ (multiple-value-bind (is-negative-p abs-value)
|
|
|
2378
|
+ (get-sign-and-absolute-value value)
|
|
|
2379
|
+ (let* ((raw-string (d2fixed abs-value d))
|
|
|
2380
|
+ (raw-len (length raw-string))
|
|
|
2381
|
+ (sign-len (if (or is-negative-p at-sign-p) 1 0))
|
|
|
2382
|
+ (need-dot (zerop d))
|
|
|
2383
|
+ (field-len (+ sign-len raw-len (if need-dot 1 0))))
|
|
|
2384
|
+ (flet ((write-field ()
|
|
|
2385
|
+ (cond (is-negative-p (write-char #\- stream))
|
|
|
2386
|
+ (at-sign-p (write-char #\+ stream)))
|
|
|
2387
|
+ (write-string raw-string stream)
|
|
|
2388
|
+ (when need-dot (write-char #\. stream))))
|
|
|
2389
|
+ (declare (dynamic-extent #'write-field))
|
|
|
2390
|
+ (pad-overflow stream field-len w overflowchar padchar #'write-field)))))
|
|
|
2391
|
+
|
|
2383
|
2392
|
(defun reshape-fixed-length (digit-count exponent)
|
|
|
2393
|
+ ;; DIGIT-COUNT is the number of digits returned by d2s/f2s. That no
|
|
|
2394
|
+ ;; more than 20. EXPONENT is teh power of 10 for a double-float. A
|
|
|
2395
|
+ ;; signed-byte 10 is large enough to hold this.
|
|
|
2396
|
+ ;;
|
|
|
2397
|
+ ;; We don't need to be super-precise here; we just need to be close
|
|
|
2398
|
+ ;; enough so as not to use bignums.
|
|
|
2399
|
+ (declare (type (integer 1 20) digit-count)
|
|
|
2400
|
+ (type (signed-byte 10) exponent))
|
|
2384
|
2401
|
(let ((k (1+ exponent)))
|
|
2385
|
2402
|
(cond ((zerop exponent)
|
|
2386
|
2403
|
;; Fast path
|
| ... |
... |
@@ -2399,6 +2416,8 @@ radix-R. If you have a power-list then pass it in as PL." |
|
2399
|
2416
|
|
|
2400
|
2417
|
(defun emit-shortest (stream mantissa exponent is-negative-p w
|
|
2401
|
2418
|
overflowchar padchar at-sign-p)
|
|
|
2419
|
+ (declare (type simple-string mantissa)
|
|
|
2420
|
+ (type (signed-byte 10) exponent))
|
|
2402
|
2421
|
(let* ((has-dot (find #\. mantissa))
|
|
2403
|
2422
|
;; Number of digits, not including the decimal point.
|
|
2404
|
2423
|
(digit-count (- (length mantissa)
|
| ... |
... |
@@ -2415,53 +2434,52 @@ radix-R. If you have a power-list then pass it in as PL." |
|
2415
|
2434
|
(declare (dynamic-extent #'write-field))
|
|
2416
|
2435
|
(pad-overflow stream field-len w overflowchar padchar #'write-field))))
|
|
2417
|
2436
|
|
|
2418
|
|
-(defun format-f-free (stream value is-negative-p w
|
|
|
2437
|
+(defun format-f-free (stream value w
|
|
2419
|
2438
|
overflowchar padchar at-sign-p)
|
|
2420
|
2439
|
(declare (type (or single-float double-float) value))
|
|
2421
|
|
- (multiple-value-bind (mantissa exponent)
|
|
2422
|
|
- (parsed-exp-form (float-to-string value))
|
|
2423
|
|
- (let* ((has-dot (find #\. mantissa))
|
|
2424
|
|
- (digit-count (if has-dot (1- (length mantissa)) (length mantissa)))
|
|
2425
|
|
- (int-len (max 1 (1+ exponent)))
|
|
2426
|
|
- (shortest-d (max 0 (- digit-count 1 exponent)))
|
|
2427
|
|
- (sign-len (if (or is-negative-p at-sign-p) 1 0))
|
|
2428
|
|
- (d-fit (and w (- w sign-len int-len 1))))
|
|
2429
|
|
- (cond
|
|
2430
|
|
- ((or (null w) (>= d-fit shortest-d))
|
|
2431
|
|
- (emit-shortest stream mantissa exponent is-negative-p w
|
|
2432
|
|
- overflowchar padchar at-sign-p))
|
|
2433
|
|
- ((minusp d-fit)
|
|
2434
|
|
- (cond (overflowchar
|
|
2435
|
|
- (loop repeat w do (write-char overflowchar stream)))
|
|
2436
|
|
- (t
|
|
2437
|
|
- (emit-shortest stream mantissa exponent is-negative-p w
|
|
2438
|
|
- overflowchar padchar at-sign-p))))
|
|
2439
|
|
- (t
|
|
2440
|
|
- (multiple-value-bind (is-negative-p abs-value)
|
|
2441
|
|
- (get-sign-and-absolute-value value)
|
|
2442
|
|
- (format-f-fixed stream abs-value is-negative-p w d-fit
|
|
|
2440
|
+ (multiple-value-bind (is-negative-p abs-value)
|
|
|
2441
|
+ (get-sign-and-absolute-value value)
|
|
|
2442
|
+ (declare (ignore abs-value))
|
|
|
2443
|
+ (multiple-value-bind (mantissa exponent)
|
|
|
2444
|
+ (parsed-exp-form (float-to-string value))
|
|
|
2445
|
+ (let* ((has-dot (find #\. mantissa))
|
|
|
2446
|
+ (digit-count (if has-dot (1- (length mantissa)) (length mantissa)))
|
|
|
2447
|
+ (int-len (max 1 (1+ exponent)))
|
|
|
2448
|
+ (shortest-d (max 0 (- digit-count 1 exponent)))
|
|
|
2449
|
+ (sign-len (if (or is-negative-p at-sign-p) 1 0))
|
|
|
2450
|
+ (d-fit (and w (- w sign-len int-len 1))))
|
|
|
2451
|
+ (cond
|
|
|
2452
|
+ ((or (null w) (>= d-fit shortest-d))
|
|
|
2453
|
+ (emit-shortest stream mantissa exponent is-negative-p w
|
|
|
2454
|
+ overflowchar padchar at-sign-p))
|
|
|
2455
|
+ ((minusp d-fit)
|
|
|
2456
|
+ (cond (overflowchar
|
|
|
2457
|
+ (loop repeat w do (write-char overflowchar stream)))
|
|
|
2458
|
+ (t
|
|
|
2459
|
+ (emit-shortest stream mantissa exponent is-negative-p w
|
|
|
2460
|
+ overflowchar padchar at-sign-p))))
|
|
|
2461
|
+ (t
|
|
|
2462
|
+ (format-f-fixed stream value w d-fit
|
|
2443
|
2463
|
overflowchar padchar at-sign-p)))))))
|
|
2444
|
2464
|
|
|
2445
|
2465
|
(defun format-f (value w d k overflowchar padchar at-sign-p)
|
|
2446
|
2466
|
(declare (type (or single-float double-float) value)
|
|
2447
|
2467
|
(fixnum k)
|
|
2448
|
2468
|
(type (or null (and unsigned-byte fixnum)) w d))
|
|
2449
|
|
- (multiple-value-bind (is-negative-p abs-value)
|
|
2450
|
|
- (get-sign-and-absolute-value value)
|
|
2451
|
|
- (with-output-to-string (s)
|
|
2452
|
|
- (cond ((not (zerop k))
|
|
2453
|
|
- ;; Complex case that doesn't fit with what d2s and d2fixed
|
|
2454
|
|
- ;; returns. Especially when d+k is negative so that some
|
|
2455
|
|
- ;; digits are shifted right past the desired precision.
|
|
2456
|
|
- ;; We'd have to round the result. Just use our existing
|
|
2457
|
|
- ;; code to handle this case with the correct rounding.
|
|
2458
|
|
- (format::format-fixed-aux s value w d k overflowchar padchar at-sign-p))
|
|
2459
|
|
- (d
|
|
2460
|
|
- (format-f-fixed s abs-value is-negative-p w d overflowchar padchar at-sign-p))
|
|
2461
|
|
- (t
|
|
2462
|
|
- ;; No d, so use d2s to get the shortest digits; convert by
|
|
2463
|
|
- ;; placing the decimal poin at the right spot.
|
|
2464
|
|
- (format-f-free s value is-negative-p w overflowchar padchar at-sign-p))))))
|
|
|
2469
|
+ (with-output-to-string (s)
|
|
|
2470
|
+ (cond ((not (zerop k))
|
|
|
2471
|
+ ;; Complex case that doesn't fit with what d2s and d2fixed
|
|
|
2472
|
+ ;; returns. Especially when d+k is negative so that some
|
|
|
2473
|
+ ;; digits are shifted right past the desired precision.
|
|
|
2474
|
+ ;; We'd have to round the result. Just use our existing
|
|
|
2475
|
+ ;; code to handle this case with the correct rounding.
|
|
|
2476
|
+ (format::format-fixed-aux s value w d k overflowchar padchar at-sign-p))
|
|
|
2477
|
+ (d
|
|
|
2478
|
+ (format-f-fixed s value w d overflowchar padchar at-sign-p))
|
|
|
2479
|
+ (t
|
|
|
2480
|
+ ;; No d, so use d2s to get the shortest digits; convert by
|
|
|
2481
|
+ ;; placing the decimal poin at the right spot.
|
|
|
2482
|
+ (format-f-free s value w overflowchar padchar at-sign-p)))))
|
|
2465
|
2483
|
|
|
2466
|
2484
|
;;; Ryu ~G
|
|
2467
|
2485
|
(defun format-g (value w d e k overflowchar padchar exponentchar at-sign-p)
|
| ... |
... |
@@ -2470,7 +2488,9 @@ radix-R. If you have a power-list then pass it in as PL." |
|
2470
|
2488
|
(type (or null (and unsigned-byte fixnum)) w d e))
|
|
2471
|
2489
|
(multiple-value-bind (mantissa exponent)
|
|
2472
|
2490
|
(parsed-exp-form (float-to-string value))
|
|
2473
|
|
- (let* ((digit-count (length (remove #\. mantissa)))
|
|
|
2491
|
+ (let* ((digit-count (- (length mantissa)
|
|
|
2492
|
+ (if (find #\. mantissa)
|
|
|
2493
|
+ 1 0)))
|
|
2474
|
2494
|
(n (1+ exponent))
|
|
2475
|
2495
|
(effective-d (or d (max digit-count (min n 7))))
|
|
2476
|
2496
|
(ee (if e (+ e 2) 4))
|