Exponential Bucket Histogram - part 6 (#3494)
This commit is contained in:
parent
6f2b1a0b34
commit
44ac86cb74
|
|
@ -14,7 +14,6 @@
|
|||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
|
|
@ -136,15 +135,4 @@ internal static class MathHelper
|
|||
return !double.IsInfinity(value) && !double.IsNaN(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static string DoubleToString(double value)
|
||||
{
|
||||
var repr = Convert.ToString(BitConverter.DoubleToInt64Bits(value), 2);
|
||||
return new string('0', 64 - repr.Length) + repr;
|
||||
}
|
||||
|
||||
public static double DoubleFromString(string value)
|
||||
{
|
||||
return BitConverter.Int64BitsToDouble(Convert.ToInt64(value, 2));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,49 @@ internal class ExponentialBucketHistogram
|
|||
|
||||
public ExponentialBucketHistogram(int scale, int maxBuckets = 160)
|
||||
{
|
||||
Guard.ThrowIfOutOfRange(scale, min: -20, max: 20); // TODO: calculate the actual range
|
||||
/*
|
||||
The following table is calculated based on [ MapToIndex(double.Epsilon), MapToIndex(double.MaxValue) ]:
|
||||
|
||||
| Scale | Index Range |
|
||||
| ----- | ------------------------- |
|
||||
| < -11 | [-1, 0] |
|
||||
| -11 | [-1, 0] |
|
||||
| -10 | [-2, 0] |
|
||||
| -9 | [-3, 1] |
|
||||
| -8 | [-5, 3] |
|
||||
| -7 | [-9, 7] |
|
||||
| -6 | [-17, 15] |
|
||||
| -5 | [-34, 31] |
|
||||
| -4 | [-68, 63] |
|
||||
| -3 | [-135, 127] |
|
||||
| -2 | [-269, 255] |
|
||||
| -1 | [-538, 511] |
|
||||
| 0 | [-1075, 1023] |
|
||||
| 1 | [-2149, 2047] |
|
||||
| 2 | [-4297, 4095] |
|
||||
| 3 | [-8593, 8191] |
|
||||
| 4 | [-17185, 16383] |
|
||||
| 5 | [-34369, 32767] |
|
||||
| 6 | [-68737, 65535] |
|
||||
| 7 | [-137473, 131071] |
|
||||
| 8 | [-274945, 262143] |
|
||||
| 9 | [-549889, 524287] |
|
||||
| 10 | [-1099777, 1048575] |
|
||||
| 11 | [-2199553, 2097151] |
|
||||
| 12 | [-4399105, 4194303] |
|
||||
| 13 | [-8798209, 8388607] |
|
||||
| 14 | [-17596417, 16777215] |
|
||||
| 15 | [-35192833, 33554431] |
|
||||
| 16 | [-70385665, 67108863] |
|
||||
| 17 | [-140771329, 134217727] |
|
||||
| 18 | [-281542657, 268435455] |
|
||||
| 19 | [-563085313, 536870911] |
|
||||
| 20 | [-1126170625, 1073741823] |
|
||||
| 21 | [underflow, 2147483647] |
|
||||
| > 21 | [underflow, overflow] |
|
||||
*/
|
||||
Guard.ThrowIfOutOfRange(scale, min: -11, max: 20);
|
||||
|
||||
Guard.ThrowIfOutOfRange(maxBuckets, min: 1);
|
||||
|
||||
this.Scale = scale;
|
||||
|
|
@ -88,17 +130,26 @@ internal class ExponentialBucketHistogram
|
|||
Debug.Assert(value != 0, "IEEE-754 zero values should be handled by ZeroCount.");
|
||||
Debug.Assert(!double.IsNegative(value), "IEEE-754 negative values should be normalized before calling this method.");
|
||||
|
||||
var bits = BitConverter.DoubleToInt64Bits(value);
|
||||
var fraction = bits & 0xFFFFFFFFFFFFFL /* fraction mask */;
|
||||
|
||||
if (this.Scale > 0)
|
||||
{
|
||||
// TODO: do we really need this given the lookup table is needed for scale>0 anyways?
|
||||
if (fraction == 0)
|
||||
{
|
||||
var exp = (int)((bits & 0x7FF0000000000000L /* exponent mask */) >> 52 /* fraction width */);
|
||||
return ((exp - 1023 /* exponent bias */) << this.Scale) - 1;
|
||||
}
|
||||
|
||||
// TODO: due to precision issue, the values that are close to the bucket
|
||||
// boundaries should be closely examined to avoid off-by-one.
|
||||
|
||||
return (int)Math.Ceiling(Math.Log(value) * this.scalingFactor) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
var bits = BitConverter.DoubleToInt64Bits(value);
|
||||
var exp = (int)((bits & 0x7FF0000000000000L /* exponent mask */) >> 52 /* fraction width */);
|
||||
var fraction = bits & 0xFFFFFFFFFFFFFL /* fraction mask */;
|
||||
|
||||
if (exp == 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#if NET6_0_OR_GREATER
|
||||
|
||||
using System;
|
||||
using OpenTelemetry.Tests;
|
||||
using Xunit;
|
||||
|
||||
namespace OpenTelemetry.Metrics.Tests;
|
||||
|
|
@ -40,47 +41,123 @@ public class ExponentialBucketHistogramTest
|
|||
// bucket[3]: (8, 16]
|
||||
// ...
|
||||
|
||||
var histogram_scale0 = new ExponentialBucketHistogram(0);
|
||||
var histogram = new ExponentialBucketHistogram(0);
|
||||
|
||||
Assert.Equal(-1075, histogram_scale0.MapToIndex(double.Epsilon));
|
||||
Assert.Equal(-1075, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000001"))); // ~4.9406564584124654E-324 (minimum subnormal positive, double.Epsilon)
|
||||
Assert.Equal(-1074, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000010"))); // double.Epsilon * 2
|
||||
Assert.Equal(-1073, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000011"))); // double.Epsilon * 3
|
||||
Assert.Equal(-1073, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000100"))); // double.Epsilon * 4
|
||||
Assert.Equal(-1072, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000101"))); // double.Epsilon * 5
|
||||
Assert.Equal(-1072, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000110"))); // double.Epsilon * 6
|
||||
Assert.Equal(-1072, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000111"))); // double.Epsilon * 7
|
||||
Assert.Equal(-1072, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000001000"))); // double.Epsilon * 8
|
||||
Assert.Equal(-1024, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 1000000000000000000000000000000000000000000000000000"))); // ~1.1125369292536007E-308
|
||||
Assert.Equal(-1023, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 1000000000000000000000000000000000000000000000000001"))); // ~1.112536929253601E-308
|
||||
Assert.Equal(-1023, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 1111111111111111111111111111111111111111111111111111"))); // ~2.2250738585072009E-308 (maximum subnormal positive)
|
||||
Assert.Equal(-1023, histogram.MapToIndex(IEEE754Double.FromString("0 00000000001 0000000000000000000000000000000000000000000000000000"))); // ~2.2250738585072014E-308 (minimum normal positive)
|
||||
Assert.Equal(-1022, histogram.MapToIndex(IEEE754Double.FromString("0 00000000001 0000000000000000000000000000000000000000000000000001"))); // ~2.225073858507202E-308
|
||||
Assert.Equal(-3, histogram.MapToIndex(IEEE754Double.FromString("0 01111111101 0000000000000000000000000000000000000000000000000000"))); // 0.25
|
||||
Assert.Equal(-2, histogram.MapToIndex(IEEE754Double.FromString("0 01111111110 0000000000000000000000000000000000000000000000000000"))); // 0.5
|
||||
Assert.Equal(-1, histogram.MapToIndex(IEEE754Double.FromString("0 01111111110 0000000000000000000000000000000000000000000000000001"))); // ~0.5000000000000001
|
||||
Assert.Equal(-1, histogram.MapToIndex(IEEE754Double.FromString("0 01111111111 0000000000000000000000000000000000000000000000000000"))); // 1
|
||||
Assert.Equal(0, histogram.MapToIndex(IEEE754Double.FromString("0 01111111111 0000000000000000000000000000000000000000000000000001"))); // ~1.0000000000000002
|
||||
Assert.Equal(0, histogram.MapToIndex(IEEE754Double.FromString("0 10000000000 0000000000000000000000000000000000000000000000000000"))); // 2
|
||||
Assert.Equal(1, histogram.MapToIndex(IEEE754Double.FromString("0 10000000001 0000000000000000000000000000000000000000000000000000"))); // 4
|
||||
Assert.Equal(2, histogram.MapToIndex(IEEE754Double.FromString("0 10000000010 0000000000000000000000000000000000000000000000000000"))); // 8
|
||||
Assert.Equal(3, histogram.MapToIndex(IEEE754Double.FromString("0 10000000011 0000000000000000000000000000000000000000000000000000"))); // 16
|
||||
Assert.Equal(4, histogram.MapToIndex(IEEE754Double.FromString("0 10000000100 0000000000000000000000000000000000000000000000000000"))); // 32
|
||||
Assert.Equal(1022, histogram.MapToIndex(IEEE754Double.FromString("0 11111111110 0000000000000000000000000000000000000000000000000000"))); // ~8.98846567431158E+307
|
||||
Assert.Equal(1023, histogram.MapToIndex(IEEE754Double.FromString("0 11111111110 0000000000000000000000000000000000000000000000000001"))); // ~8.988465674311582E+307
|
||||
Assert.Equal(1023, histogram.MapToIndex(IEEE754Double.FromString("0 11111111110 1111111111111111111111111111111111111111111111111110"))); // ~1.7976931348623155E+308
|
||||
Assert.Equal(1023, histogram.MapToIndex(IEEE754Double.FromString("0 11111111110 1111111111111111111111111111111111111111111111111111"))); // ~1.7976931348623157E+308 (maximum normal positive, double.MaxValue)
|
||||
|
||||
Assert.Equal(-1074, histogram_scale0.MapToIndex(double.Epsilon * 2));
|
||||
// An exponential bucket histogram with scale = -1.
|
||||
// The base is 2 ^ (2 ^ 1) = 4.
|
||||
// The buckets are:
|
||||
//
|
||||
// ...
|
||||
// bucket[-3]: (1/64, 1/16]
|
||||
// bucket[-2]: (1/16, 1/4]
|
||||
// bucket[-1]: (1/4, 1]
|
||||
// bucket[0]: (1, 4]
|
||||
// bucket[1]: (4, 16]
|
||||
// bucket[2]: (16, 64]
|
||||
// bucket[3]: (64, 256]
|
||||
// ...
|
||||
|
||||
Assert.Equal(-1073, histogram_scale0.MapToIndex(double.Epsilon * 3));
|
||||
Assert.Equal(-1073, histogram_scale0.MapToIndex(double.Epsilon * 4));
|
||||
histogram = new ExponentialBucketHistogram(-1);
|
||||
|
||||
Assert.Equal(-1072, histogram_scale0.MapToIndex(double.Epsilon * 5));
|
||||
Assert.Equal(-1072, histogram_scale0.MapToIndex(double.Epsilon * 6));
|
||||
Assert.Equal(-1072, histogram_scale0.MapToIndex(double.Epsilon * 7));
|
||||
Assert.Equal(-1072, histogram_scale0.MapToIndex(double.Epsilon * 8));
|
||||
Assert.Equal(-538, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000001"))); // ~4.9406564584124654E-324 (minimum subnormal positive, double.Epsilon)
|
||||
Assert.Equal(-537, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000010"))); // double.Epsilon * 2
|
||||
Assert.Equal(-537, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000011"))); // double.Epsilon * 3
|
||||
Assert.Equal(-537, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000100"))); // double.Epsilon * 4
|
||||
Assert.Equal(-536, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000101"))); // double.Epsilon * 5
|
||||
Assert.Equal(-536, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000110"))); // double.Epsilon * 6
|
||||
Assert.Equal(-536, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000111"))); // double.Epsilon * 7
|
||||
Assert.Equal(-536, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000001000"))); // double.Epsilon * 8
|
||||
Assert.Equal(-512, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 1000000000000000000000000000000000000000000000000000"))); // ~1.1125369292536007E-308
|
||||
Assert.Equal(-512, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 1000000000000000000000000000000000000000000000000001"))); // ~1.112536929253601E-308
|
||||
Assert.Equal(-512, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 1111111111111111111111111111111111111111111111111111"))); // ~2.2250738585072009E-308 (maximum subnormal positive)
|
||||
Assert.Equal(-512, histogram.MapToIndex(IEEE754Double.FromString("0 00000000001 0000000000000000000000000000000000000000000000000000"))); // ~2.2250738585072014E-308 (minimum normal positive)
|
||||
Assert.Equal(-511, histogram.MapToIndex(IEEE754Double.FromString("0 00000000001 0000000000000000000000000000000000000000000000000001"))); // ~2.225073858507202E-308
|
||||
Assert.Equal(-2, histogram.MapToIndex(IEEE754Double.FromString("0 01111111101 0000000000000000000000000000000000000000000000000000"))); // 0.25
|
||||
Assert.Equal(-1, histogram.MapToIndex(IEEE754Double.FromString("0 01111111110 0000000000000000000000000000000000000000000000000000"))); // 0.5
|
||||
Assert.Equal(-1, histogram.MapToIndex(IEEE754Double.FromString("0 01111111110 0000000000000000000000000000000000000000000000000001"))); // ~0.5000000000000001
|
||||
Assert.Equal(-1, histogram.MapToIndex(IEEE754Double.FromString("0 01111111111 0000000000000000000000000000000000000000000000000000"))); // 1
|
||||
Assert.Equal(0, histogram.MapToIndex(IEEE754Double.FromString("0 01111111111 0000000000000000000000000000000000000000000000000001"))); // ~1.0000000000000002
|
||||
Assert.Equal(0, histogram.MapToIndex(IEEE754Double.FromString("0 10000000000 0000000000000000000000000000000000000000000000000000"))); // 2
|
||||
Assert.Equal(0, histogram.MapToIndex(IEEE754Double.FromString("0 10000000001 0000000000000000000000000000000000000000000000000000"))); // 4
|
||||
Assert.Equal(1, histogram.MapToIndex(IEEE754Double.FromString("0 10000000010 0000000000000000000000000000000000000000000000000000"))); // 8
|
||||
Assert.Equal(1, histogram.MapToIndex(IEEE754Double.FromString("0 10000000011 0000000000000000000000000000000000000000000000000000"))); // 16
|
||||
Assert.Equal(2, histogram.MapToIndex(IEEE754Double.FromString("0 10000000100 0000000000000000000000000000000000000000000000000000"))); // 32
|
||||
Assert.Equal(511, histogram.MapToIndex(IEEE754Double.FromString("0 11111111110 0000000000000000000000000000000000000000000000000000"))); // ~8.98846567431158E+307
|
||||
Assert.Equal(511, histogram.MapToIndex(IEEE754Double.FromString("0 11111111110 0000000000000000000000000000000000000000000000000001"))); // ~8.988465674311582E+307
|
||||
Assert.Equal(511, histogram.MapToIndex(IEEE754Double.FromString("0 11111111110 1111111111111111111111111111111111111111111111111110"))); // ~1.7976931348623155E+308
|
||||
Assert.Equal(511, histogram.MapToIndex(IEEE754Double.FromString("0 11111111110 1111111111111111111111111111111111111111111111111111"))); // ~1.7976931348623157E+308 (maximum normal positive, double.MaxValue)
|
||||
|
||||
Assert.Equal(-1023, histogram_scale0.MapToIndex(2.2250738585072009E-308));
|
||||
Assert.Equal(-1023, histogram_scale0.MapToIndex(2.2250738585072014E-308));
|
||||
// An exponential bucket histogram with scale = -2.
|
||||
// The base is 2 ^ (2 ^ 2) = 16.
|
||||
// The buckets are:
|
||||
//
|
||||
// ...
|
||||
// bucket[-3]: (1/4096, 1/256]
|
||||
// bucket[-2]: (1/256, 1/16]
|
||||
// bucket[-1]: (1/16, 1]
|
||||
// bucket[0]: (1, 16]
|
||||
// bucket[1]: (16, 256]
|
||||
// bucket[2]: (256, 4096]
|
||||
// bucket[3]: (4096, 65536]
|
||||
// ...
|
||||
|
||||
Assert.Equal(-3, histogram_scale0.MapToIndex(0.25));
|
||||
histogram = new ExponentialBucketHistogram(-2);
|
||||
|
||||
Assert.Equal(-2, histogram_scale0.MapToIndex(0.375));
|
||||
Assert.Equal(-2, histogram_scale0.MapToIndex(0.5));
|
||||
|
||||
Assert.Equal(-1, histogram_scale0.MapToIndex(0.75));
|
||||
Assert.Equal(-1, histogram_scale0.MapToIndex(1));
|
||||
|
||||
Assert.Equal(0, histogram_scale0.MapToIndex(1.5));
|
||||
Assert.Equal(0, histogram_scale0.MapToIndex(2));
|
||||
|
||||
Assert.Equal(1, histogram_scale0.MapToIndex(3));
|
||||
Assert.Equal(1, histogram_scale0.MapToIndex(4));
|
||||
|
||||
Assert.Equal(2, histogram_scale0.MapToIndex(5));
|
||||
Assert.Equal(2, histogram_scale0.MapToIndex(6));
|
||||
Assert.Equal(2, histogram_scale0.MapToIndex(7));
|
||||
Assert.Equal(2, histogram_scale0.MapToIndex(8));
|
||||
|
||||
Assert.Equal(3, histogram_scale0.MapToIndex(9));
|
||||
Assert.Equal(3, histogram_scale0.MapToIndex(16));
|
||||
|
||||
Assert.Equal(4, histogram_scale0.MapToIndex(17));
|
||||
Assert.Equal(4, histogram_scale0.MapToIndex(32));
|
||||
Assert.Equal(-269, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000001"))); // ~4.9406564584124654E-324 (minimum subnormal positive, double.Epsilon)
|
||||
Assert.Equal(-269, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000010"))); // double.Epsilon * 2
|
||||
Assert.Equal(-269, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000011"))); // double.Epsilon * 3
|
||||
Assert.Equal(-269, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000100"))); // double.Epsilon * 4
|
||||
Assert.Equal(-268, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000101"))); // double.Epsilon * 5
|
||||
Assert.Equal(-268, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000110"))); // double.Epsilon * 6
|
||||
Assert.Equal(-268, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000000111"))); // double.Epsilon * 7
|
||||
Assert.Equal(-268, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 0000000000000000000000000000000000000000000000001000"))); // double.Epsilon * 8
|
||||
Assert.Equal(-256, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 1000000000000000000000000000000000000000000000000000"))); // ~1.1125369292536007E-308
|
||||
Assert.Equal(-256, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 1000000000000000000000000000000000000000000000000001"))); // ~1.112536929253601E-308
|
||||
Assert.Equal(-256, histogram.MapToIndex(IEEE754Double.FromString("0 00000000000 1111111111111111111111111111111111111111111111111111"))); // ~2.2250738585072009E-308 (maximum subnormal positive)
|
||||
Assert.Equal(-256, histogram.MapToIndex(IEEE754Double.FromString("0 00000000001 0000000000000000000000000000000000000000000000000000"))); // ~2.2250738585072014E-308 (minimum normal positive)
|
||||
Assert.Equal(-256, histogram.MapToIndex(IEEE754Double.FromString("0 00000000001 0000000000000000000000000000000000000000000000000001"))); // ~2.225073858507202E-308
|
||||
Assert.Equal(-1, histogram.MapToIndex(IEEE754Double.FromString("0 01111111101 0000000000000000000000000000000000000000000000000000"))); // 0.25
|
||||
Assert.Equal(-1, histogram.MapToIndex(IEEE754Double.FromString("0 01111111110 0000000000000000000000000000000000000000000000000000"))); // 0.5
|
||||
Assert.Equal(-1, histogram.MapToIndex(IEEE754Double.FromString("0 01111111110 0000000000000000000000000000000000000000000000000001"))); // ~0.5000000000000001
|
||||
Assert.Equal(-1, histogram.MapToIndex(IEEE754Double.FromString("0 01111111111 0000000000000000000000000000000000000000000000000000"))); // 1
|
||||
Assert.Equal(0, histogram.MapToIndex(IEEE754Double.FromString("0 01111111111 0000000000000000000000000000000000000000000000000001"))); // ~1.0000000000000002
|
||||
Assert.Equal(0, histogram.MapToIndex(IEEE754Double.FromString("0 10000000000 0000000000000000000000000000000000000000000000000000"))); // 2
|
||||
Assert.Equal(0, histogram.MapToIndex(IEEE754Double.FromString("0 10000000001 0000000000000000000000000000000000000000000000000000"))); // 4
|
||||
Assert.Equal(0, histogram.MapToIndex(IEEE754Double.FromString("0 10000000010 0000000000000000000000000000000000000000000000000000"))); // 8
|
||||
Assert.Equal(0, histogram.MapToIndex(IEEE754Double.FromString("0 10000000011 0000000000000000000000000000000000000000000000000000"))); // 16
|
||||
Assert.Equal(1, histogram.MapToIndex(IEEE754Double.FromString("0 10000000100 0000000000000000000000000000000000000000000000000000"))); // 32
|
||||
Assert.Equal(255, histogram.MapToIndex(IEEE754Double.FromString("0 11111111110 0000000000000000000000000000000000000000000000000000"))); // ~8.98846567431158E+307
|
||||
Assert.Equal(255, histogram.MapToIndex(IEEE754Double.FromString("0 11111111110 0000000000000000000000000000000000000000000000000001"))); // ~8.988465674311582E+307
|
||||
Assert.Equal(255, histogram.MapToIndex(IEEE754Double.FromString("0 11111111110 1111111111111111111111111111111111111111111111111110"))); // ~1.7976931348623155E+308
|
||||
Assert.Equal(255, histogram.MapToIndex(IEEE754Double.FromString("0 11111111110 1111111111111111111111111111111111111111111111111111"))); // ~1.7976931348623157E+308 (maximum normal positive, double.MaxValue)
|
||||
|
||||
// An exponential bucket histogram with scale = 1.
|
||||
// The base is 2 ^ (2 ^ -1) = sqrt(2) = 1.41421356237.
|
||||
|
|
@ -96,17 +173,7 @@ public class ExponentialBucketHistogramTest
|
|||
// bucket[3]: (2.82842712474, 4]
|
||||
// ...
|
||||
|
||||
var histogram_scale1 = new ExponentialBucketHistogram(1);
|
||||
|
||||
Assert.Equal(-3, histogram_scale1.MapToIndex(0.5));
|
||||
|
||||
Assert.Equal(-2, histogram_scale1.MapToIndex(0.6));
|
||||
|
||||
Assert.Equal(-1, histogram_scale1.MapToIndex(1));
|
||||
|
||||
Assert.Equal(1, histogram_scale1.MapToIndex(2));
|
||||
|
||||
Assert.Equal(3, histogram_scale1.MapToIndex(4));
|
||||
histogram = new ExponentialBucketHistogram(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,103 @@
|
|||
// <copyright file="IEEE754Double.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry 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.
|
||||
// </copyright>
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace OpenTelemetry.Tests;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct IEEE754Double
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public double DoubleValue = 0;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public long LongValue = 0;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public ulong ULongValue = 0;
|
||||
|
||||
public IEEE754Double(double value)
|
||||
{
|
||||
this.DoubleValue = value;
|
||||
}
|
||||
|
||||
public static implicit operator double(IEEE754Double value)
|
||||
{
|
||||
return value.DoubleValue;
|
||||
}
|
||||
|
||||
public static IEEE754Double operator ++(IEEE754Double value)
|
||||
{
|
||||
value.ULongValue++;
|
||||
return value;
|
||||
}
|
||||
|
||||
public static IEEE754Double operator --(IEEE754Double value)
|
||||
{
|
||||
value.ULongValue--;
|
||||
return value;
|
||||
}
|
||||
|
||||
public static IEEE754Double FromDouble(double value)
|
||||
{
|
||||
return new IEEE754Double(value);
|
||||
}
|
||||
|
||||
public static IEEE754Double FromLong(long value)
|
||||
{
|
||||
return new IEEE754Double { LongValue = value };
|
||||
}
|
||||
|
||||
public static IEEE754Double FromULong(ulong value)
|
||||
{
|
||||
return new IEEE754Double { ULongValue = value };
|
||||
}
|
||||
|
||||
public static IEEE754Double FromString(string value)
|
||||
{
|
||||
return IEEE754Double.FromLong(Convert.ToInt64(value.Replace(" ", string.Empty), 2));
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
Span<char> chars = stackalloc char[66];
|
||||
|
||||
var bits = this.ULongValue;
|
||||
var index = chars.Length - 1;
|
||||
|
||||
for (int i = 0; i < 52; i++)
|
||||
{
|
||||
chars[index--] = (char)(bits & 0x01 | 0x30);
|
||||
bits >>= 1;
|
||||
}
|
||||
|
||||
chars[index--] = ' ';
|
||||
|
||||
for (int i = 0; i < 11; i++)
|
||||
{
|
||||
chars[index--] = (char)(bits & 0x01 | 0x30);
|
||||
bits >>= 1;
|
||||
}
|
||||
|
||||
chars[index--] = ' ';
|
||||
|
||||
chars[index--] = (char)(bits & 0x01 | 0x30);
|
||||
|
||||
return $"{chars.ToString()} ({this.DoubleValue})";
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue