Skip to content

Errors in Exponential Histogram Mapping #3630

Description

@MadVikingGod

Problem

When describing the exponential histograms and how to do the mapping in the DataModel all of the formulas have the property of monotonicity, e.g. for two points $a \lt b$ then $index_a \le index_b$. This is true for the first MapToIndex, but not for the second MapToIndex with an exact power of two cases added. When you make the correction, if any of the values around the power of two are in error because of floating point rounding, then they will violate the monotonicity property. For example, see the MapToIndex function around 2^8 image1. This happens similarly for values around 2^-8 and is only made worse for larger exponents.

MapToIndex_8

Solutions

Use a different formula

The Main introduction of error in the current formula is that Log() of large numbers is not accurate. We can eliminate this error by bounding the log to a smaller range. If we split the value into exponent and frac, using Frexp, we can then only take the log of the fraction. Because the fraction is bounded between 0.5 and 1, the log will have a bounded error.

The change would look like this:

// MapToIndex for any scale, exact for powers of two.
func MapToIndex(value float64, scale int) int {
    // Special case for power-of-two values.
    frac, exp := math.Frexp(value)
    scaleFactor := math.Ldexp(math.Log2E, scale)
    return exp<<scale + int(math.Log(frac)*scaleFactor) - 1
}

Remove the "exact" optimization

By only recommending the first MapToIndex function, we can remove the error. This is the simplest solution but the least optimized for any scale above 0.

Appendix

Proof of New Formula

$$\begin{gather*} & & base = 2^{2^{-scale}} & & \\\ & & scaleFactor = \frac{2^{scale}}{Log(2)} & & \\\ base^{index} & < & value & \le & base^{index+1} \\\ 2^{index*2^{-scale}} & < & value & \le & 2^{(index+1)*2^{-scale}} \\\ index*2^{-scale} & < & Log_2(value) & \le & (index+1)*2^{-scale} \\\ index & < & Log_2(value)*2^{scale} & \le & index+1 \\\ index & < & Log_2(2^{exp} * frac)*2^{scale} & \le & index+1 \\\ index & < & (exp + Log_2(frac))*2^{scale} & \le & index+1 \\\ index & < & exp*2^{scale} + Log_2(frac)*2^{scale} & \le & index+1 \\\ & & exp*2^{scale} + Log(frac)*scaleFactor & \le & index+1 \\\ index & \ge & exp*2^{scale} + Log(frac)*scaleFactor - 1 \\\ \end{gather*}$$

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Stalespec:metricsRelated to the specification/metrics directorytriage:accepted:ready-with-sponsorReady to be implemented and has a specification sponsor assigned

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions