You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: histogram.go
    path of file: ./repos/hubble-ui/backend/vendor/github.com/prometheus/client_golang/prometheus
    
    the code of the file until where you have to start completion: // Copyright 2015 The Prometheus Authors
// Licensed 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 prometheus

import (
	"fmt"
	"math"
	"runtime"
	"sort"
	"sync"
	"sync/atomic"
	"time"

	dto "github.com/prometheus/client_model/go"

	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/types/known/timestamppb"
)

// nativeHistogramBounds for the frac of observed values. Only relevant for
// schema > 0. The position in the slice is the schema. (0 is never used, just
// here for convenience of using the schema directly as the index.)
//
// TODO(beorn7): Currently, we do a binary search into these slices. There are
// ways to turn it into a small number of simple array lookups. It probably only
// matters for schema 5 and beyond, but should be investigated. See this comment
// as a starting point:
// https://github.com/open-telemetry/opentelemetry-specification/issues/1776#issuecomment-870164310
var nativeHistogramBounds = [][]float64{
	// Schema "0":
	{0.5},
	// Schema 1:
	{0.5, 0.7071067811865475},
	// Schema 2:
	{0.5, 0.5946035575013605, 0.7071067811865475, 0.8408964152537144},
	// Schema 3:
	{
		0.5, 0.5452538663326288, 0.5946035575013605, 0.6484197773255048,
		0.7071067811865475, 0.7711054127039704, 0.8408964152537144, 0.9170040432046711,
	},
	// Schema 4:
	{
		0.5, 0.5221368912137069, 0.5452538663326288, 0.5693943173783458,
		0.5946035575013605, 0.620928906036742, 0.6484197773255048, 0.6771277734684463,
		0.7071067811865475, 0.7384130729697496, 0.7711054127039704, 0.805245165
    
func getLe(key int, schema int32) float64 {
	// Here a bit of context about the behavior for the last bucket counting
	// regular numbers (called simply "last bucket" below) and the bucket
	// counting observations of ±Inf (called "inf bucket" below, with a key
	// one higher than that of the "last bucket"):
	//
	// If we apply the usual formula to the last bucket, its upper bound
	// would be calculated as +Inf. The reason is that the max possible
	// regular float64 number (math.MaxFloat64) doesn't coincide with one of
	// the calculated bucket boundaries. So the calculated boundary has to
	// be larger than math.MaxFloat64, and the only float64 larger than
	// math.MaxFloat64 is +Inf. However, we want to count actual
	// observations of ±Inf in the inf bucket. Therefore, we have to treat
	// the upper bound of the last bucket specially and set it to
	// math.MaxFloat64. (The upper bound of the inf bucket, with its key
	// being one higher than that of the last bucket, naturally comes out as
	// +Inf by the usual formula. So that's fine.)
	//
	// math.MaxFloat64 has a frac of 0.9999999999999999 and an exp of
	// 1024. If there were a float64 number following math.MaxFloat64, it
	// would have a frac of 1.0 and an exp of 1024, or equivalently a frac
	// of 0.5 and an exp of 1025. However, since frac must be smaller than
	// 1, and exp must be smaller than 1025, either representation overflows
	// a float64. (Which, in turn, is the reason that math.MaxFloat64 is the
	// largest possible float64. Q.E.D.) However, the formula for
	// calculating the upper bound from the idx and schema of the last
	// bucket results in precisely that. It is either frac=1.0 & exp=1024
	// (for schema < 0) or frac=0.5 & exp=1025 (for schema >=0). (This is,
	// by the way, a power of two where the exponent itself is a power of
	// two, 2¹⁰ in fact, which coinicides with a bucket boundary in all
	// schemas.) So these are the special cases we have to catch below.
	if schema < 0 {
		exp := key << -schema
		if exp == 1024 {
			// This is the last bucket before the overflow bucket
			// (for ±Inf observations). Return math.MaxFloat64 as
			// explained above.
			return math.MaxFloat64
		}
		return math.Ldexp(1, exp)
	}

	fracIdx := key & ((1 << schema) - 1)
	frac := nativeHistogramBounds[schema][fracIdx]
	exp := (key >> schema) + 1
	if frac == 0.5 && exp == 1025 {
		// This is the last bucket before the overflow bucket (for ±Inf
		// observations). Return math.MaxFloat64 as explained above.
		return math.MaxFloat64
	}
	return math.Ldexp(frac, exp)
}