11cb0ef41Sopenharmony_ci/**
21cb0ef41Sopenharmony_ci * hdr_histogram.h
31cb0ef41Sopenharmony_ci * Written by Michael Barker and released to the public domain,
41cb0ef41Sopenharmony_ci * as explained at http://creativecommons.org/publicdomain/zero/1.0/
51cb0ef41Sopenharmony_ci *
61cb0ef41Sopenharmony_ci * The source for the hdr_histogram utilises a few C99 constructs, specifically
71cb0ef41Sopenharmony_ci * the use of stdint/stdbool and inline variable declaration.
81cb0ef41Sopenharmony_ci */
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#ifndef HDR_HISTOGRAM_H
111cb0ef41Sopenharmony_ci#define HDR_HISTOGRAM_H 1
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci#include <stdint.h>
141cb0ef41Sopenharmony_ci#include <stdbool.h>
151cb0ef41Sopenharmony_ci#include <stdio.h>
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_cistruct hdr_histogram
181cb0ef41Sopenharmony_ci{
191cb0ef41Sopenharmony_ci    int64_t lowest_discernible_value;
201cb0ef41Sopenharmony_ci    int64_t highest_trackable_value;
211cb0ef41Sopenharmony_ci    int32_t unit_magnitude;
221cb0ef41Sopenharmony_ci    int32_t significant_figures;
231cb0ef41Sopenharmony_ci    int32_t sub_bucket_half_count_magnitude;
241cb0ef41Sopenharmony_ci    int32_t sub_bucket_half_count;
251cb0ef41Sopenharmony_ci    int64_t sub_bucket_mask;
261cb0ef41Sopenharmony_ci    int32_t sub_bucket_count;
271cb0ef41Sopenharmony_ci    int32_t bucket_count;
281cb0ef41Sopenharmony_ci    int64_t min_value;
291cb0ef41Sopenharmony_ci    int64_t max_value;
301cb0ef41Sopenharmony_ci    int32_t normalizing_index_offset;
311cb0ef41Sopenharmony_ci    double conversion_ratio;
321cb0ef41Sopenharmony_ci    int32_t counts_len;
331cb0ef41Sopenharmony_ci    int64_t total_count;
341cb0ef41Sopenharmony_ci    int64_t* counts;
351cb0ef41Sopenharmony_ci};
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci#ifdef __cplusplus
381cb0ef41Sopenharmony_ciextern "C" {
391cb0ef41Sopenharmony_ci#endif
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci/**
421cb0ef41Sopenharmony_ci * Allocate the memory and initialise the hdr_histogram.
431cb0ef41Sopenharmony_ci *
441cb0ef41Sopenharmony_ci * Due to the size of the histogram being the result of some reasonably
451cb0ef41Sopenharmony_ci * involved math on the input parameters this function it is tricky to stack allocate.
461cb0ef41Sopenharmony_ci * The histogram should be released with hdr_close
471cb0ef41Sopenharmony_ci *
481cb0ef41Sopenharmony_ci * @param lowest_discernible_value The smallest possible value that is distinguishable from 0.
491cb0ef41Sopenharmony_ci * Must be a positive integer that is >= 1. May be internally rounded down to nearest power of 2.
501cb0ef41Sopenharmony_ci * @param highest_trackable_value The largest possible value to be put into the
511cb0ef41Sopenharmony_ci * histogram.
521cb0ef41Sopenharmony_ci * @param significant_figures The level of precision for this histogram, i.e. the number
531cb0ef41Sopenharmony_ci * of figures in a decimal number that will be maintained.  E.g. a value of 3 will mean
541cb0ef41Sopenharmony_ci * the results from the histogram will be accurate up to the first three digits.  Must
551cb0ef41Sopenharmony_ci * be a value between 1 and 5 (inclusive).
561cb0ef41Sopenharmony_ci * @param result Output parameter to capture allocated histogram.
571cb0ef41Sopenharmony_ci * @return 0 on success, EINVAL if lowest_discernible_value is < 1 or the
581cb0ef41Sopenharmony_ci * significant_figure value is outside of the allowed range, ENOMEM if malloc
591cb0ef41Sopenharmony_ci * failed.
601cb0ef41Sopenharmony_ci */
611cb0ef41Sopenharmony_ciint hdr_init(
621cb0ef41Sopenharmony_ci    int64_t lowest_discernible_value,
631cb0ef41Sopenharmony_ci    int64_t highest_trackable_value,
641cb0ef41Sopenharmony_ci    int significant_figures,
651cb0ef41Sopenharmony_ci    struct hdr_histogram** result);
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci/**
681cb0ef41Sopenharmony_ci * Free the memory and close the hdr_histogram.
691cb0ef41Sopenharmony_ci *
701cb0ef41Sopenharmony_ci * @param h The histogram you want to close.
711cb0ef41Sopenharmony_ci */
721cb0ef41Sopenharmony_civoid hdr_close(struct hdr_histogram* h);
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci/**
751cb0ef41Sopenharmony_ci * Allocate the memory and initialise the hdr_histogram.  This is the equivalent of calling
761cb0ef41Sopenharmony_ci * hdr_init(1, highest_trackable_value, significant_figures, result);
771cb0ef41Sopenharmony_ci *
781cb0ef41Sopenharmony_ci * @deprecated use hdr_init.
791cb0ef41Sopenharmony_ci */
801cb0ef41Sopenharmony_ciint hdr_alloc(int64_t highest_trackable_value, int significant_figures, struct hdr_histogram** result);
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci/**
841cb0ef41Sopenharmony_ci * Reset a histogram to zero - empty out a histogram and re-initialise it
851cb0ef41Sopenharmony_ci *
861cb0ef41Sopenharmony_ci * If you want to re-use an existing histogram, but reset everything back to zero, this
871cb0ef41Sopenharmony_ci * is the routine to use.
881cb0ef41Sopenharmony_ci *
891cb0ef41Sopenharmony_ci * @param h The histogram you want to reset to empty.
901cb0ef41Sopenharmony_ci *
911cb0ef41Sopenharmony_ci */
921cb0ef41Sopenharmony_civoid hdr_reset(struct hdr_histogram* h);
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci/**
951cb0ef41Sopenharmony_ci * Get the memory size of the hdr_histogram.
961cb0ef41Sopenharmony_ci *
971cb0ef41Sopenharmony_ci * @param h "This" pointer
981cb0ef41Sopenharmony_ci * @return The amount of memory used by the hdr_histogram in bytes
991cb0ef41Sopenharmony_ci */
1001cb0ef41Sopenharmony_cisize_t hdr_get_memory_size(struct hdr_histogram* h);
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci/**
1031cb0ef41Sopenharmony_ci * Records a value in the histogram, will round this value of to a precision at or better
1041cb0ef41Sopenharmony_ci * than the significant_figure specified at construction time.
1051cb0ef41Sopenharmony_ci *
1061cb0ef41Sopenharmony_ci * @param h "This" pointer
1071cb0ef41Sopenharmony_ci * @param value Value to add to the histogram
1081cb0ef41Sopenharmony_ci * @return false if the value is larger than the highest_trackable_value and can't be recorded,
1091cb0ef41Sopenharmony_ci * true otherwise.
1101cb0ef41Sopenharmony_ci */
1111cb0ef41Sopenharmony_cibool hdr_record_value(struct hdr_histogram* h, int64_t value);
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci/**
1141cb0ef41Sopenharmony_ci * Records a value in the histogram, will round this value of to a precision at or better
1151cb0ef41Sopenharmony_ci * than the significant_figure specified at construction time.
1161cb0ef41Sopenharmony_ci *
1171cb0ef41Sopenharmony_ci * Will record this value atomically, however the whole structure may appear inconsistent
1181cb0ef41Sopenharmony_ci * when read concurrently with this update.  Do NOT mix calls to this method with calls
1191cb0ef41Sopenharmony_ci * to non-atomic updates.
1201cb0ef41Sopenharmony_ci *
1211cb0ef41Sopenharmony_ci * @param h "This" pointer
1221cb0ef41Sopenharmony_ci * @param value Value to add to the histogram
1231cb0ef41Sopenharmony_ci * @return false if the value is larger than the highest_trackable_value and can't be recorded,
1241cb0ef41Sopenharmony_ci * true otherwise.
1251cb0ef41Sopenharmony_ci */
1261cb0ef41Sopenharmony_cibool hdr_record_value_atomic(struct hdr_histogram* h, int64_t value);
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci/**
1291cb0ef41Sopenharmony_ci * Records count values in the histogram, will round this value of to a
1301cb0ef41Sopenharmony_ci * precision at or better than the significant_figure specified at construction
1311cb0ef41Sopenharmony_ci * time.
1321cb0ef41Sopenharmony_ci *
1331cb0ef41Sopenharmony_ci * @param h "This" pointer
1341cb0ef41Sopenharmony_ci * @param value Value to add to the histogram
1351cb0ef41Sopenharmony_ci * @param count Number of 'value's to add to the histogram
1361cb0ef41Sopenharmony_ci * @return false if any value is larger than the highest_trackable_value and can't be recorded,
1371cb0ef41Sopenharmony_ci * true otherwise.
1381cb0ef41Sopenharmony_ci */
1391cb0ef41Sopenharmony_cibool hdr_record_values(struct hdr_histogram* h, int64_t value, int64_t count);
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci/**
1421cb0ef41Sopenharmony_ci * Records count values in the histogram, will round this value of to a
1431cb0ef41Sopenharmony_ci * precision at or better than the significant_figure specified at construction
1441cb0ef41Sopenharmony_ci * time.
1451cb0ef41Sopenharmony_ci *
1461cb0ef41Sopenharmony_ci * Will record this value atomically, however the whole structure may appear inconsistent
1471cb0ef41Sopenharmony_ci * when read concurrently with this update.  Do NOT mix calls to this method with calls
1481cb0ef41Sopenharmony_ci * to non-atomic updates.
1491cb0ef41Sopenharmony_ci *
1501cb0ef41Sopenharmony_ci * @param h "This" pointer
1511cb0ef41Sopenharmony_ci * @param value Value to add to the histogram
1521cb0ef41Sopenharmony_ci * @param count Number of 'value's to add to the histogram
1531cb0ef41Sopenharmony_ci * @return false if any value is larger than the highest_trackable_value and can't be recorded,
1541cb0ef41Sopenharmony_ci * true otherwise.
1551cb0ef41Sopenharmony_ci */
1561cb0ef41Sopenharmony_cibool hdr_record_values_atomic(struct hdr_histogram* h, int64_t value, int64_t count);
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci/**
1591cb0ef41Sopenharmony_ci * Record a value in the histogram and backfill based on an expected interval.
1601cb0ef41Sopenharmony_ci *
1611cb0ef41Sopenharmony_ci * Records a value in the histogram, will round this value of to a precision at or better
1621cb0ef41Sopenharmony_ci * than the significant_figure specified at construction time.  This is specifically used
1631cb0ef41Sopenharmony_ci * for recording latency.  If the value is larger than the expected_interval then the
1641cb0ef41Sopenharmony_ci * latency recording system has experienced co-ordinated omission.  This method fills in the
1651cb0ef41Sopenharmony_ci * values that would have occurred had the client providing the load not been blocked.
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci * @param h "This" pointer
1681cb0ef41Sopenharmony_ci * @param value Value to add to the histogram
1691cb0ef41Sopenharmony_ci * @param expected_interval The delay between recording values.
1701cb0ef41Sopenharmony_ci * @return false if the value is larger than the highest_trackable_value and can't be recorded,
1711cb0ef41Sopenharmony_ci * true otherwise.
1721cb0ef41Sopenharmony_ci */
1731cb0ef41Sopenharmony_cibool hdr_record_corrected_value(struct hdr_histogram* h, int64_t value, int64_t expected_interval);
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci/**
1761cb0ef41Sopenharmony_ci * Record a value in the histogram and backfill based on an expected interval.
1771cb0ef41Sopenharmony_ci *
1781cb0ef41Sopenharmony_ci * Records a value in the histogram, will round this value of to a precision at or better
1791cb0ef41Sopenharmony_ci * than the significant_figure specified at construction time.  This is specifically used
1801cb0ef41Sopenharmony_ci * for recording latency.  If the value is larger than the expected_interval then the
1811cb0ef41Sopenharmony_ci * latency recording system has experienced co-ordinated omission.  This method fills in the
1821cb0ef41Sopenharmony_ci * values that would have occurred had the client providing the load not been blocked.
1831cb0ef41Sopenharmony_ci *
1841cb0ef41Sopenharmony_ci * Will record this value atomically, however the whole structure may appear inconsistent
1851cb0ef41Sopenharmony_ci * when read concurrently with this update.  Do NOT mix calls to this method with calls
1861cb0ef41Sopenharmony_ci * to non-atomic updates.
1871cb0ef41Sopenharmony_ci *
1881cb0ef41Sopenharmony_ci * @param h "This" pointer
1891cb0ef41Sopenharmony_ci * @param value Value to add to the histogram
1901cb0ef41Sopenharmony_ci * @param expected_interval The delay between recording values.
1911cb0ef41Sopenharmony_ci * @return false if the value is larger than the highest_trackable_value and can't be recorded,
1921cb0ef41Sopenharmony_ci * true otherwise.
1931cb0ef41Sopenharmony_ci */
1941cb0ef41Sopenharmony_cibool hdr_record_corrected_value_atomic(struct hdr_histogram* h, int64_t value, int64_t expected_interval);
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci/**
1971cb0ef41Sopenharmony_ci * Record a value in the histogram 'count' times.  Applies the same correcting logic
1981cb0ef41Sopenharmony_ci * as 'hdr_record_corrected_value'.
1991cb0ef41Sopenharmony_ci *
2001cb0ef41Sopenharmony_ci * @param h "This" pointer
2011cb0ef41Sopenharmony_ci * @param value Value to add to the histogram
2021cb0ef41Sopenharmony_ci * @param count Number of 'value's to add to the histogram
2031cb0ef41Sopenharmony_ci * @param expected_interval The delay between recording values.
2041cb0ef41Sopenharmony_ci * @return false if the value is larger than the highest_trackable_value and can't be recorded,
2051cb0ef41Sopenharmony_ci * true otherwise.
2061cb0ef41Sopenharmony_ci */
2071cb0ef41Sopenharmony_cibool hdr_record_corrected_values(struct hdr_histogram* h, int64_t value, int64_t count, int64_t expected_interval);
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_ci/**
2101cb0ef41Sopenharmony_ci * Record a value in the histogram 'count' times.  Applies the same correcting logic
2111cb0ef41Sopenharmony_ci * as 'hdr_record_corrected_value'.
2121cb0ef41Sopenharmony_ci *
2131cb0ef41Sopenharmony_ci * Will record this value atomically, however the whole structure may appear inconsistent
2141cb0ef41Sopenharmony_ci * when read concurrently with this update.  Do NOT mix calls to this method with calls
2151cb0ef41Sopenharmony_ci * to non-atomic updates.
2161cb0ef41Sopenharmony_ci *
2171cb0ef41Sopenharmony_ci * @param h "This" pointer
2181cb0ef41Sopenharmony_ci * @param value Value to add to the histogram
2191cb0ef41Sopenharmony_ci * @param count Number of 'value's to add to the histogram
2201cb0ef41Sopenharmony_ci * @param expected_interval The delay between recording values.
2211cb0ef41Sopenharmony_ci * @return false if the value is larger than the highest_trackable_value and can't be recorded,
2221cb0ef41Sopenharmony_ci * true otherwise.
2231cb0ef41Sopenharmony_ci */
2241cb0ef41Sopenharmony_cibool hdr_record_corrected_values_atomic(struct hdr_histogram* h, int64_t value, int64_t count, int64_t expected_interval);
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci/**
2271cb0ef41Sopenharmony_ci * Adds all of the values from 'from' to 'this' histogram.  Will return the
2281cb0ef41Sopenharmony_ci * number of values that are dropped when copying.  Values will be dropped
2291cb0ef41Sopenharmony_ci * if they around outside of h.lowest_discernible_value and
2301cb0ef41Sopenharmony_ci * h.highest_trackable_value.
2311cb0ef41Sopenharmony_ci *
2321cb0ef41Sopenharmony_ci * @param h "This" pointer
2331cb0ef41Sopenharmony_ci * @param from Histogram to copy values from.
2341cb0ef41Sopenharmony_ci * @return The number of values dropped when copying.
2351cb0ef41Sopenharmony_ci */
2361cb0ef41Sopenharmony_ciint64_t hdr_add(struct hdr_histogram* h, const struct hdr_histogram* from);
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ci/**
2391cb0ef41Sopenharmony_ci * Adds all of the values from 'from' to 'this' histogram.  Will return the
2401cb0ef41Sopenharmony_ci * number of values that are dropped when copying.  Values will be dropped
2411cb0ef41Sopenharmony_ci * if they around outside of h.lowest_discernible_value and
2421cb0ef41Sopenharmony_ci * h.highest_trackable_value.
2431cb0ef41Sopenharmony_ci *
2441cb0ef41Sopenharmony_ci * @param h "This" pointer
2451cb0ef41Sopenharmony_ci * @param from Histogram to copy values from.
2461cb0ef41Sopenharmony_ci * @return The number of values dropped when copying.
2471cb0ef41Sopenharmony_ci */
2481cb0ef41Sopenharmony_ciint64_t hdr_add_while_correcting_for_coordinated_omission(
2491cb0ef41Sopenharmony_ci    struct hdr_histogram* h, struct hdr_histogram* from, int64_t expected_interval);
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_ci/**
2521cb0ef41Sopenharmony_ci * Get minimum value from the histogram.  Will return 2^63-1 if the histogram
2531cb0ef41Sopenharmony_ci * is empty.
2541cb0ef41Sopenharmony_ci *
2551cb0ef41Sopenharmony_ci * @param h "This" pointer
2561cb0ef41Sopenharmony_ci */
2571cb0ef41Sopenharmony_ciint64_t hdr_min(const struct hdr_histogram* h);
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci/**
2601cb0ef41Sopenharmony_ci * Get maximum value from the histogram.  Will return 0 if the histogram
2611cb0ef41Sopenharmony_ci * is empty.
2621cb0ef41Sopenharmony_ci *
2631cb0ef41Sopenharmony_ci * @param h "This" pointer
2641cb0ef41Sopenharmony_ci */
2651cb0ef41Sopenharmony_ciint64_t hdr_max(const struct hdr_histogram* h);
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci/**
2681cb0ef41Sopenharmony_ci * Get the value at a specific percentile.
2691cb0ef41Sopenharmony_ci *
2701cb0ef41Sopenharmony_ci * @param h "This" pointer.
2711cb0ef41Sopenharmony_ci * @param percentile The percentile to get the value for
2721cb0ef41Sopenharmony_ci */
2731cb0ef41Sopenharmony_ciint64_t hdr_value_at_percentile(const struct hdr_histogram* h, double percentile);
2741cb0ef41Sopenharmony_ci
2751cb0ef41Sopenharmony_ci/**
2761cb0ef41Sopenharmony_ci * Get the values at the given percentiles.
2771cb0ef41Sopenharmony_ci *
2781cb0ef41Sopenharmony_ci * @param h "This" pointer.
2791cb0ef41Sopenharmony_ci * @param percentiles The ordered percentiles array to get the values for.
2801cb0ef41Sopenharmony_ci * @param length Number of elements in the arrays.
2811cb0ef41Sopenharmony_ci * @param values Destination array containing the values at the given percentiles.
2821cb0ef41Sopenharmony_ci * The values array should be allocated by the caller.
2831cb0ef41Sopenharmony_ci * @return 0 on success, ENOMEM if the provided destination array is null.
2841cb0ef41Sopenharmony_ci */
2851cb0ef41Sopenharmony_ciint hdr_value_at_percentiles(const struct hdr_histogram *h, const double *percentiles, int64_t *values, size_t length);
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_ci/**
2881cb0ef41Sopenharmony_ci * Gets the standard deviation for the values in the histogram.
2891cb0ef41Sopenharmony_ci *
2901cb0ef41Sopenharmony_ci * @param h "This" pointer
2911cb0ef41Sopenharmony_ci * @return The standard deviation
2921cb0ef41Sopenharmony_ci */
2931cb0ef41Sopenharmony_cidouble hdr_stddev(const struct hdr_histogram* h);
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci/**
2961cb0ef41Sopenharmony_ci * Gets the mean for the values in the histogram.
2971cb0ef41Sopenharmony_ci *
2981cb0ef41Sopenharmony_ci * @param h "This" pointer
2991cb0ef41Sopenharmony_ci * @return The mean
3001cb0ef41Sopenharmony_ci */
3011cb0ef41Sopenharmony_cidouble hdr_mean(const struct hdr_histogram* h);
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_ci/**
3041cb0ef41Sopenharmony_ci * Determine if two values are equivalent with the histogram's resolution.
3051cb0ef41Sopenharmony_ci * Where "equivalent" means that value samples recorded for any two
3061cb0ef41Sopenharmony_ci * equivalent values are counted in a common total count.
3071cb0ef41Sopenharmony_ci *
3081cb0ef41Sopenharmony_ci * @param h "This" pointer
3091cb0ef41Sopenharmony_ci * @param a first value to compare
3101cb0ef41Sopenharmony_ci * @param b second value to compare
3111cb0ef41Sopenharmony_ci * @return 'true' if values are equivalent with the histogram's resolution.
3121cb0ef41Sopenharmony_ci */
3131cb0ef41Sopenharmony_cibool hdr_values_are_equivalent(const struct hdr_histogram* h, int64_t a, int64_t b);
3141cb0ef41Sopenharmony_ci
3151cb0ef41Sopenharmony_ci/**
3161cb0ef41Sopenharmony_ci * Get the lowest value that is equivalent to the given value within the histogram's resolution.
3171cb0ef41Sopenharmony_ci * Where "equivalent" means that value samples recorded for any two
3181cb0ef41Sopenharmony_ci * equivalent values are counted in a common total count.
3191cb0ef41Sopenharmony_ci *
3201cb0ef41Sopenharmony_ci * @param h "This" pointer
3211cb0ef41Sopenharmony_ci * @param value The given value
3221cb0ef41Sopenharmony_ci * @return The lowest value that is equivalent to the given value within the histogram's resolution.
3231cb0ef41Sopenharmony_ci */
3241cb0ef41Sopenharmony_ciint64_t hdr_lowest_equivalent_value(const struct hdr_histogram* h, int64_t value);
3251cb0ef41Sopenharmony_ci
3261cb0ef41Sopenharmony_ci/**
3271cb0ef41Sopenharmony_ci * Get the count of recorded values at a specific value
3281cb0ef41Sopenharmony_ci * (to within the histogram resolution at the value level).
3291cb0ef41Sopenharmony_ci *
3301cb0ef41Sopenharmony_ci * @param h "This" pointer
3311cb0ef41Sopenharmony_ci * @param value The value for which to provide the recorded count
3321cb0ef41Sopenharmony_ci * @return The total count of values recorded in the histogram within the value range that is
3331cb0ef41Sopenharmony_ci * {@literal >=} lowestEquivalentValue(<i>value</i>) and {@literal <=} highestEquivalentValue(<i>value</i>)
3341cb0ef41Sopenharmony_ci */
3351cb0ef41Sopenharmony_ciint64_t hdr_count_at_value(const struct hdr_histogram* h, int64_t value);
3361cb0ef41Sopenharmony_ci
3371cb0ef41Sopenharmony_ciint64_t hdr_count_at_index(const struct hdr_histogram* h, int32_t index);
3381cb0ef41Sopenharmony_ci
3391cb0ef41Sopenharmony_ciint64_t hdr_value_at_index(const struct hdr_histogram* h, int32_t index);
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_cistruct hdr_iter_percentiles
3421cb0ef41Sopenharmony_ci{
3431cb0ef41Sopenharmony_ci    bool seen_last_value;
3441cb0ef41Sopenharmony_ci    int32_t ticks_per_half_distance;
3451cb0ef41Sopenharmony_ci    double percentile_to_iterate_to;
3461cb0ef41Sopenharmony_ci    double percentile;
3471cb0ef41Sopenharmony_ci};
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_cistruct hdr_iter_recorded
3501cb0ef41Sopenharmony_ci{
3511cb0ef41Sopenharmony_ci    int64_t count_added_in_this_iteration_step;
3521cb0ef41Sopenharmony_ci};
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_cistruct hdr_iter_linear
3551cb0ef41Sopenharmony_ci{
3561cb0ef41Sopenharmony_ci    int64_t value_units_per_bucket;
3571cb0ef41Sopenharmony_ci    int64_t count_added_in_this_iteration_step;
3581cb0ef41Sopenharmony_ci    int64_t next_value_reporting_level;
3591cb0ef41Sopenharmony_ci    int64_t next_value_reporting_level_lowest_equivalent;
3601cb0ef41Sopenharmony_ci};
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_cistruct hdr_iter_log
3631cb0ef41Sopenharmony_ci{
3641cb0ef41Sopenharmony_ci    double log_base;
3651cb0ef41Sopenharmony_ci    int64_t count_added_in_this_iteration_step;
3661cb0ef41Sopenharmony_ci    int64_t next_value_reporting_level;
3671cb0ef41Sopenharmony_ci    int64_t next_value_reporting_level_lowest_equivalent;
3681cb0ef41Sopenharmony_ci};
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_ci/**
3711cb0ef41Sopenharmony_ci * The basic iterator.  This is a generic structure
3721cb0ef41Sopenharmony_ci * that supports all of the types of iteration.  Use
3731cb0ef41Sopenharmony_ci * the appropriate initialiser to get the desired
3741cb0ef41Sopenharmony_ci * iteration.
3751cb0ef41Sopenharmony_ci *
3761cb0ef41Sopenharmony_ci * @
3771cb0ef41Sopenharmony_ci */
3781cb0ef41Sopenharmony_cistruct hdr_iter
3791cb0ef41Sopenharmony_ci{
3801cb0ef41Sopenharmony_ci    const struct hdr_histogram* h;
3811cb0ef41Sopenharmony_ci    /** raw index into the counts array */
3821cb0ef41Sopenharmony_ci    int32_t counts_index;
3831cb0ef41Sopenharmony_ci    /** snapshot of the length at the time the iterator is created */
3841cb0ef41Sopenharmony_ci    int64_t total_count;
3851cb0ef41Sopenharmony_ci    /** value directly from array for the current counts_index */
3861cb0ef41Sopenharmony_ci    int64_t count;
3871cb0ef41Sopenharmony_ci    /** sum of all of the counts up to and including the count at this index */
3881cb0ef41Sopenharmony_ci    int64_t cumulative_count;
3891cb0ef41Sopenharmony_ci    /** The current value based on counts_index */
3901cb0ef41Sopenharmony_ci    int64_t value;
3911cb0ef41Sopenharmony_ci    int64_t highest_equivalent_value;
3921cb0ef41Sopenharmony_ci    int64_t lowest_equivalent_value;
3931cb0ef41Sopenharmony_ci    int64_t median_equivalent_value;
3941cb0ef41Sopenharmony_ci    int64_t value_iterated_from;
3951cb0ef41Sopenharmony_ci    int64_t value_iterated_to;
3961cb0ef41Sopenharmony_ci
3971cb0ef41Sopenharmony_ci    union
3981cb0ef41Sopenharmony_ci    {
3991cb0ef41Sopenharmony_ci        struct hdr_iter_percentiles percentiles;
4001cb0ef41Sopenharmony_ci        struct hdr_iter_recorded recorded;
4011cb0ef41Sopenharmony_ci        struct hdr_iter_linear linear;
4021cb0ef41Sopenharmony_ci        struct hdr_iter_log log;
4031cb0ef41Sopenharmony_ci    } specifics;
4041cb0ef41Sopenharmony_ci
4051cb0ef41Sopenharmony_ci    bool (* _next_fp)(struct hdr_iter* iter);
4061cb0ef41Sopenharmony_ci
4071cb0ef41Sopenharmony_ci};
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci/**
4101cb0ef41Sopenharmony_ci * Initalises the basic iterator.
4111cb0ef41Sopenharmony_ci *
4121cb0ef41Sopenharmony_ci * @param itr 'This' pointer
4131cb0ef41Sopenharmony_ci * @param h The histogram to iterate over
4141cb0ef41Sopenharmony_ci */
4151cb0ef41Sopenharmony_civoid hdr_iter_init(struct hdr_iter* iter, const struct hdr_histogram* h);
4161cb0ef41Sopenharmony_ci
4171cb0ef41Sopenharmony_ci/**
4181cb0ef41Sopenharmony_ci * Initialise the iterator for use with percentiles.
4191cb0ef41Sopenharmony_ci */
4201cb0ef41Sopenharmony_civoid hdr_iter_percentile_init(struct hdr_iter* iter, const struct hdr_histogram* h, int32_t ticks_per_half_distance);
4211cb0ef41Sopenharmony_ci
4221cb0ef41Sopenharmony_ci/**
4231cb0ef41Sopenharmony_ci * Initialise the iterator for use with recorded values.
4241cb0ef41Sopenharmony_ci */
4251cb0ef41Sopenharmony_civoid hdr_iter_recorded_init(struct hdr_iter* iter, const struct hdr_histogram* h);
4261cb0ef41Sopenharmony_ci
4271cb0ef41Sopenharmony_ci/**
4281cb0ef41Sopenharmony_ci * Initialise the iterator for use with linear values.
4291cb0ef41Sopenharmony_ci */
4301cb0ef41Sopenharmony_civoid hdr_iter_linear_init(
4311cb0ef41Sopenharmony_ci    struct hdr_iter* iter,
4321cb0ef41Sopenharmony_ci    const struct hdr_histogram* h,
4331cb0ef41Sopenharmony_ci    int64_t value_units_per_bucket);
4341cb0ef41Sopenharmony_ci
4351cb0ef41Sopenharmony_ci/**
4361cb0ef41Sopenharmony_ci * Initialise the iterator for use with logarithmic values
4371cb0ef41Sopenharmony_ci */
4381cb0ef41Sopenharmony_civoid hdr_iter_log_init(
4391cb0ef41Sopenharmony_ci    struct hdr_iter* iter,
4401cb0ef41Sopenharmony_ci    const struct hdr_histogram* h,
4411cb0ef41Sopenharmony_ci    int64_t value_units_first_bucket,
4421cb0ef41Sopenharmony_ci    double log_base);
4431cb0ef41Sopenharmony_ci
4441cb0ef41Sopenharmony_ci/**
4451cb0ef41Sopenharmony_ci * Iterate to the next value for the iterator.  If there are no more values
4461cb0ef41Sopenharmony_ci * available return faluse.
4471cb0ef41Sopenharmony_ci *
4481cb0ef41Sopenharmony_ci * @param itr 'This' pointer
4491cb0ef41Sopenharmony_ci * @return 'false' if there are no values remaining for this iterator.
4501cb0ef41Sopenharmony_ci */
4511cb0ef41Sopenharmony_cibool hdr_iter_next(struct hdr_iter* iter);
4521cb0ef41Sopenharmony_ci
4531cb0ef41Sopenharmony_citypedef enum
4541cb0ef41Sopenharmony_ci{
4551cb0ef41Sopenharmony_ci    CLASSIC,
4561cb0ef41Sopenharmony_ci    CSV
4571cb0ef41Sopenharmony_ci} format_type;
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_ci/**
4601cb0ef41Sopenharmony_ci * Print out a percentile based histogram to the supplied stream.  Note that
4611cb0ef41Sopenharmony_ci * this call will not flush the FILE, this is left up to the user.
4621cb0ef41Sopenharmony_ci *
4631cb0ef41Sopenharmony_ci * @param h 'This' pointer
4641cb0ef41Sopenharmony_ci * @param stream The FILE to write the output to
4651cb0ef41Sopenharmony_ci * @param ticks_per_half_distance The number of iteration steps per half-distance to 100%
4661cb0ef41Sopenharmony_ci * @param value_scale Scale the output values by this amount
4671cb0ef41Sopenharmony_ci * @param format_type Format to use, e.g. CSV.
4681cb0ef41Sopenharmony_ci * @return 0 on success, error code on failure.  EIO if an error occurs writing
4691cb0ef41Sopenharmony_ci * the output.
4701cb0ef41Sopenharmony_ci */
4711cb0ef41Sopenharmony_ciint hdr_percentiles_print(
4721cb0ef41Sopenharmony_ci    struct hdr_histogram* h, FILE* stream, int32_t ticks_per_half_distance,
4731cb0ef41Sopenharmony_ci    double value_scale, format_type format);
4741cb0ef41Sopenharmony_ci
4751cb0ef41Sopenharmony_ci/**
4761cb0ef41Sopenharmony_ci* Internal allocation methods, used by hdr_dbl_histogram.
4771cb0ef41Sopenharmony_ci*/
4781cb0ef41Sopenharmony_cistruct hdr_histogram_bucket_config
4791cb0ef41Sopenharmony_ci{
4801cb0ef41Sopenharmony_ci    int64_t lowest_discernible_value;
4811cb0ef41Sopenharmony_ci    int64_t highest_trackable_value;
4821cb0ef41Sopenharmony_ci    int64_t unit_magnitude;
4831cb0ef41Sopenharmony_ci    int64_t significant_figures;
4841cb0ef41Sopenharmony_ci    int32_t sub_bucket_half_count_magnitude;
4851cb0ef41Sopenharmony_ci    int32_t sub_bucket_half_count;
4861cb0ef41Sopenharmony_ci    int64_t sub_bucket_mask;
4871cb0ef41Sopenharmony_ci    int32_t sub_bucket_count;
4881cb0ef41Sopenharmony_ci    int32_t bucket_count;
4891cb0ef41Sopenharmony_ci    int32_t counts_len;
4901cb0ef41Sopenharmony_ci};
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_ciint hdr_calculate_bucket_config(
4931cb0ef41Sopenharmony_ci    int64_t lowest_discernible_value,
4941cb0ef41Sopenharmony_ci    int64_t highest_trackable_value,
4951cb0ef41Sopenharmony_ci    int significant_figures,
4961cb0ef41Sopenharmony_ci    struct hdr_histogram_bucket_config* cfg);
4971cb0ef41Sopenharmony_ci
4981cb0ef41Sopenharmony_civoid hdr_init_preallocated(struct hdr_histogram* h, struct hdr_histogram_bucket_config* cfg);
4991cb0ef41Sopenharmony_ci
5001cb0ef41Sopenharmony_ciint64_t hdr_size_of_equivalent_value_range(const struct hdr_histogram* h, int64_t value);
5011cb0ef41Sopenharmony_ci
5021cb0ef41Sopenharmony_ciint64_t hdr_next_non_equivalent_value(const struct hdr_histogram* h, int64_t value);
5031cb0ef41Sopenharmony_ci
5041cb0ef41Sopenharmony_ciint64_t hdr_median_equivalent_value(const struct hdr_histogram* h, int64_t value);
5051cb0ef41Sopenharmony_ci
5061cb0ef41Sopenharmony_ci/**
5071cb0ef41Sopenharmony_ci * Used to reset counters after importing data manually into the histogram, used by the logging code
5081cb0ef41Sopenharmony_ci * and other custom serialisation tools.
5091cb0ef41Sopenharmony_ci */
5101cb0ef41Sopenharmony_civoid hdr_reset_internal_counters(struct hdr_histogram* h);
5111cb0ef41Sopenharmony_ci
5121cb0ef41Sopenharmony_ci#ifdef __cplusplus
5131cb0ef41Sopenharmony_ci}
5141cb0ef41Sopenharmony_ci#endif
5151cb0ef41Sopenharmony_ci
5161cb0ef41Sopenharmony_ci#endif
517