/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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 com.android.internal.util;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.Log;
import java.util.Arrays;
/**
* A histogram for positive integers where each bucket is twice the size of the previous one.
*/
public class ExponentiallyBucketedHistogram {
@NonNull
private final int[] mData;
/**
* Create a new histogram.
*
* @param numBuckets The number of buckets. The highest bucket is for all value >=
* 2numBuckets - 1
*/
public ExponentiallyBucketedHistogram(@IntRange(from = 1, to = 31) int numBuckets) {
numBuckets = Preconditions.checkArgumentInRange(numBuckets, 1, 31, "numBuckets");
mData = new int[numBuckets];
}
/**
* Add a new value to the histogram.
*
* All values <= 0 are in the first bucket. The last bucket contains all values >=
* 2numBuckets - 1
*
* @param value The value to add
*/
public void add(int value) {
if (value <= 0) {
mData[0]++;
} else {
mData[Math.min(mData.length - 1, 32 - Integer.numberOfLeadingZeros(value))]++;
}
}
/**
* Clear all data from the histogram
*/
public void reset() {
Arrays.fill(mData, 0);
}
/**
* Write the histogram to the log.
*
* @param tag The tag to use when logging
* @param prefix A custom prefix that is printed in front of the histogram
*/
public void log(@NonNull String tag, @Nullable CharSequence prefix) {
StringBuilder builder = new StringBuilder(prefix);
builder.append('[');
for (int i = 0; i < mData.length; i++) {
if (i != 0) {
builder.append(", ");
}
if (i < mData.length - 1) {
builder.append("<");
builder.append(1 << i);
} else {
builder.append(">=");
builder.append(1 << (i - 1));
}
builder.append(": ");
builder.append(mData[i]);
}
builder.append("]");
Log.d(tag, builder.toString());
}
}