
Note: With this refactoring, `math/utils' no longer depends on `rackunit'. * (flexp2 x) computes (flexpt 2.0 x) but in about 1/3 the time for integer `x' using a lookup table. Written for exact argument reduction in `fllog2' after discovering that (flexpt 2.0 x) was the main performance bottleneck. * (fllog2 x) computes (/ (fllog x) (fllog 2.0)) with near perfect accuracy. Invented an algorithm to compute it with at least 8 extra bits before final rounding; quite pleased with the result. Needed `fllog2' to ensure (fllogb 2.0 x) would be exact when `x' is a power of two. * (fllogb b x) computes (/ (fllog x) (fllog b)) with better accuracy, and also handles limit values in a way that's consistent with the mathematical limits. When those are ambiguous, it's consistent with `flexpt', which follows IEEE 754 and C99. Otherwise returns +nan.0. See docs for details. * `bflogb' is currently just for testing `fllogb'. * Refactored FPU testing and documented it. So far, the only documented way to do it is by calling `test-floating-point', which runs a comprehensive deterministic+randomized suite of tests and returns a list representing failed tests. I'll document individual tests after I document flonum expansions and result/error functions like `fl+/error'. * Added `fllog2' and `fllogb' to the flonum tests.
49 lines
1.7 KiB
Racket
49 lines
1.7 KiB
Racket
#lang typed/racket/base
|
|
|
|
(require "bigfloat-struct.rkt")
|
|
|
|
(provide bflog* bflog/ bflog+ bflog- bflog1- bflogb)
|
|
|
|
(: bflog* (Bigfloat Bigfloat -> Bigfloat))
|
|
(define (bflog* log-x log-y) (bf+ log-x log-y))
|
|
|
|
(: bflog/ (Bigfloat Bigfloat -> Bigfloat))
|
|
(define (bflog/ log-x log-y) (bf- log-x log-y))
|
|
|
|
(: bflog+ (Bigfloat Bigfloat -> Bigfloat))
|
|
(define (bflog+ log-x log-y)
|
|
(let-values ([(log-x log-y) (if (log-x . bf> . log-y)
|
|
(values log-x log-y)
|
|
(values log-y log-x))])
|
|
(bf+ log-x (bflog1p (bfexp (bf- log-y log-x))))))
|
|
|
|
(: bflog- (Bigfloat Bigfloat -> Bigfloat))
|
|
(define (bflog- log-x log-y)
|
|
(cond [(log-y . bf> . log-x) +nan.bf]
|
|
[else (bf+ log-x (bflog1p (bf- (bfexp (bf- log-y log-x)))))]))
|
|
|
|
(: bflog1- (Bigfloat -> Bigfloat))
|
|
(define (bflog1- log-x)
|
|
(cond [(log-x . bf> . (bflog (bf 0.5))) (bflog (bf- (bfexpm1 log-x)))]
|
|
[else (bflog1p (bf- (bfexp log-x)))]))
|
|
|
|
(: bflogb (Bigfloat Bigfloat -> Bigfloat))
|
|
(define (bflogb b x)
|
|
(cond [(bf= x 1.bf) 0.bf]
|
|
[(bf= b 1.bf) +nan.bf]
|
|
[(not (and (bf<= 0.bf b) (bf<= b +inf.bf) (bf<= 0.bf x) (bf<= x +inf.bf))) +nan.bf]
|
|
[(bf= b 0.bf)
|
|
(cond [(bf= x 0.bf) +inf.bf]
|
|
[(bf= x +inf.bf) -inf.bf]
|
|
[(bf<= x 1.bf) 0.bf]
|
|
[else -0.bf])]
|
|
[(bf= b +inf.bf)
|
|
(cond [(bf= x 0.bf) -inf.bf]
|
|
[(bf= x +inf.bf) +inf.bf]
|
|
[(bf<= 1.bf x) 0.bf]
|
|
[else -0.bf])]
|
|
[(bf= x 0.bf) (if (bf< b 1.bf) +inf.bf -inf.bf)]
|
|
[(bf= x +inf.bf) (if (bf< b 1.bf) -inf.bf +inf.bf)]
|
|
[else
|
|
(bf/ (bflog x) (bflog b))]))
|