cpc/icon_estimator.go (46 lines of code) (raw):
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cpc
import "math"
func iconEstimate(lgK int, c uint64) float64 {
if c == 0 {
return 0.0
}
if c < 2 {
return 1.0
}
k := 1 << lgK
doubleK := float64(k)
doubleC := float64(c)
// Differing thresholds ensure that the approximated estimator is monotonically increasing.
var thresholdFactor float64
if lgK < 14 {
thresholdFactor = 5.7
} else {
thresholdFactor = 5.6
}
if doubleC > (thresholdFactor * doubleK) {
return iconExponentialApproximation(doubleK, doubleC)
}
factor := evaluatePolynomial(
iconPolynomialCoefficents,
iconPolynomialNumCoefficients*(lgK-minLgK),
iconPolynomialNumCoefficients,
// The constant 2.0 is baked into the table iconPolynomialCoefficients[].
// This factor, although somewhat arbitrary, is based on extensive characterization studies
// and is considered a safe conservative factor.
doubleC/(2.0*doubleK))
ratio := doubleC / doubleK
// The constant 66.774757 is baked into the table iconPolynomialCoefficients[].
// This factor, although somewhat arbitrary, is based on extensive characterization studies
// and is considered a safe conservative factor.
term := 1.0 + ((ratio * ratio * ratio) / 66.774757)
result := doubleC * factor * term
if result >= doubleC {
return result
}
return doubleC
}
func iconExponentialApproximation(k, c float64) float64 {
return 0.7940236163830469 * k * math.Pow(2.0, c/k)
}
func evaluatePolynomial(coefficients []float64, start, num int, x float64) float64 {
end := start + num - 1
total := coefficients[end]
for j := end - 1; j >= start; j-- {
total *= x
total += coefficients[j]
}
return total
}