chickadee » math » fplogb

fplogb b xprocedure
b
flonum
x
flonum

Computes the base-b log of x more accurately than (/ (fplog x) (fplog b)), and handles limit values correctly.

Maximum observed error is 2.1 ulps (see fpulp), but is usually less than 0.7 (i.e. near rounding error).

Except possibly at limit values (such as 0.0 and +inf.0, and b = 1.0) and except when the inner expression underflows or overflows, fplogb approximately meets these identities for b > 0.0:

  • Left inverse: (fplogb b (fpexpt b y)) = y
  • Right inverse: (fpexpt b (fplogb b x)) = x when x > 0.0

Unlike with fpexpt, there is no standard for fplogb’s behavior at limit values. Fortunately, deriving the following rules (applied in order) is not prohibitively difficult.

Case Condition Value
(fplogb b 1.0) 0.0
(fplogb 1.0 x) +nan.0
(fplogb b x) b < 0.0 or x < 0.0 +nan.0
Double limits
(fplogb 0.0 0.0) +inf.0
(fplogb 0.0 +inf.0) -inf.0
(fplogb +inf 0.0) -inf.0
(fplogb +inf +inf.0) +inf.0
Limits with respect to b
(fplogb 0.0 x) x < 1.0 0.0
(fplogb 0.0 x) x > 1.0 -0.0
(fplogb +inf.0 x) x > 1.0 0.0
(fplogb +inf.0 x) x < 1.0 -0.0
Limits with respect to x
(fplogb b 0.0) x < 1.0 +inf.0
(fplogb b 0.0) x > 1.0 -inf.0
(fplogb b +inf.0) x > 1.0 +inf.0
(fplogb b +inf.0) x < 1.0 -inf.0

Most of these rules are derived by taking limits of the mathematical base-b log function. Except for (fplogb 1.0 x), when doing so gives rise to ambiguities, they are resolved using fpexpt’s behavior, which follows the IEEE 754 and C99 standards for {{pow}.

For example, consider (fplogb 0.0 0.0). Taking an interated limit, we get ∞ if the outer limit is with respect to x, or 0 if the outer limit is with respect to b. This would normally mean (fplogb 0.0 0.0) = +nan.0.

However, choosing +inf.0 ensures that these additional left-inverse and right-inverse identities hold:

(fplogb 0.0 (fpexpt 0.0 +inf.0)) = +inf.0
(fpexpt 0.0 (fplogb 0.0 0.0)) = 0.0

Further, choosing 0.0 does not ensure that any additional identities hold.