public interface IndexMapping
double positive values and int values that imposes relative
guarantees on the composition of value(int) and index(double). Specifically, for any value
v between minIndexableValue() and maxIndexableValue(), implementations
of IndexMapping must be such that value(index(v)) is close to v with a
relative error that is less than relativeAccuracy().
In addition, index(double) is required to be increasing, and mappings provide additional
methods lowerBound(int) and upperBound(int) that are such that for any valid index,
lowerBound(index) <= value(index) <= upperBound(index),
lowerBound(index + 1) == upperBound(index) if index + 1 is a valid index,
value is such that lowerBound(index) < value < upperBound(index), then
index(value) == index.
IndexMapping defines indexed contiguous buckets whose bounds are
provided by lowerBound(int) and upperBound(int).
In implementations of IndexMapping, there generally is a trade-off between the cost of
computing the index and the number of indices that are required to cover a given range of values
(memory optimality). The most memory-optimal mapping is the LogarithmicMapping, but it
requires the costly evaluation of the logarithm when computing the index. Other mappings can
approximate the logarithmic mapping, while being less computationally costly. The following table
shows the characteristics of a few implementations of IndexMapping, highlighting the
above-mentioned trade-off.
| Mapping | Index usage overhead given actual guarantee | Max index usage overhead given requested guarantee | Computational cost (rough estimate) |
LogarithmicMapping |
\(0\%\) (optimal) | \(0\%\) (optimal) | \(100\%\) (reference) |
QuarticallyInterpolatedMapping |
\(\frac{25}{36\log2}-1 \approx 0.19\%\) | \(\frac{25}{36\log2}-1 \approx 0.19\%\) | \(\sim 19\%\) |
CubicallyInterpolatedMapping |
\(\frac{7}{10\log2}-1 \approx 1.0\%\) | \(\frac{7}{10\log2}-1 \approx 1.0\%\) | \(\sim 16\%\) |
QuadraticallyInterpolatedMapping |
\(\frac{3}{4\log2}-1 \approx 8.2\%\) | \(\frac{3}{4\log2}-1 \approx 8.2\%\) | \(\sim 14\%\) |
LinearlyInterpolatedMapping |
\(\frac{1}{\log2}-1 \approx 44\%\) | \(\frac{1}{\log2}-1 \approx 44\%\) | \(\sim 12\%\) |
BitwiseLinearlyInterpolatedMapping |
\(\frac{1}{\log2}-1 \approx 44\%\) | \(\frac{2}{\log2}-1 \approx 189\%\) | \(\sim 7\%\) |
CubicallyInterpolatedMapping, which uses a polynomial of degree 3 to approximate the
logarithm, usually is a good compromise as its memory overhead compared to the optimal
logarithmic mapping is only 1%, and it is about 6 times faster than the logarithmic mapping.
Using a polynomial of higher degree (e.g., QuarticallyInterpolatedMapping) does not yield
a significant gain in memory space efficiency (less than 1%), while it degrades its insertion
speed to some extent.
| Modifier and Type | Method and Description |
|---|---|
static IndexMapping |
decode(Input input,
IndexMappingLayout layout) |
void |
encode(Output output) |
int |
index(double value) |
double |
lowerBound(int index) |
double |
maxIndexableValue() |
double |
minIndexableValue() |
double |
relativeAccuracy() |
void |
serialize(Serializer serializer) |
int |
serializedSize() |
double |
upperBound(int index) |
double |
value(int index) |
int index(double value)
double value(int index)
double lowerBound(int index)
double upperBound(int index)
double relativeAccuracy()
double minIndexableValue()
double maxIndexableValue()
void encode(Output output) throws java.io.IOException
java.io.IOExceptionstatic IndexMapping decode(Input input, IndexMappingLayout layout) throws java.io.IOException
java.io.IOExceptionint serializedSize()
void serialize(Serializer serializer)