FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/tests/checkasm/ext/src/stats.h
Date: 2026-07-16 17:05:34
Exec Total Coverage
Lines: 0 42 0.0%
Functions: 0 12 0.0%
Branches: 0 10 0.0%

Line Branch Exec Source
1 /*
2 * Copyright © 2025, Niklas Haas
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #ifndef CHECKASM_STATS_H
28 #define CHECKASM_STATS_H
29
30 #include <assert.h>
31 #include <math.h>
32 #include <stdint.h>
33 #include <string.h>
34
35 typedef struct CheckasmVar {
36 double lmean, lvar; /* log mean and variance */
37 } CheckasmVar;
38
39 /* Sample the PDF of a random variable at the given quantile */
40 static inline double checkasm_sample(const CheckasmVar x, const double q)
41 {
42 return exp(x.lmean + q * sqrt(x.lvar));
43 }
44
45 static inline double checkasm_median(const CheckasmVar x)
46 {
47 return exp(x.lmean);
48 }
49
50 static inline double checkasm_mode(const CheckasmVar x)
51 {
52 return exp(x.lmean - x.lvar);
53 }
54
55 static inline double checkasm_mean(const CheckasmVar x)
56 {
57 return exp(x.lmean + 0.5 * x.lvar);
58 }
59
60 static inline double checkasm_stddev(const CheckasmVar x)
61 {
62 return exp(x.lmean + 0.5 * x.lvar) * sqrt(exp(x.lvar) - 1.0);
63 }
64
65 static inline CheckasmVar checkasm_var_const(double x)
66 {
67 return (CheckasmVar) { log(x), 0.0 };
68 }
69
70 /* Assumes independent random variables */
71 CheckasmVar checkasm_var_scale(CheckasmVar a, double s);
72 CheckasmVar checkasm_var_pow(CheckasmVar a, double exp);
73 CheckasmVar checkasm_var_add(CheckasmVar a, CheckasmVar b); /* approximation */
74 CheckasmVar checkasm_var_sub(CheckasmVar a, CheckasmVar b); /* approximation */
75 CheckasmVar checkasm_var_mul(CheckasmVar a, CheckasmVar b);
76 CheckasmVar checkasm_var_div(CheckasmVar a, CheckasmVar b);
77 CheckasmVar checkasm_var_inv(CheckasmVar a);
78
79 /* Statistical analysis helpers */
80 typedef struct CheckasmSample {
81 uint64_t sum; /* batched sum of data points */
82 int count; /* number of data points in batch */
83 } CheckasmSample;
84
85 typedef struct CheckasmStats {
86 /* With a ~12% exponential growth on the number of data points per sample,
87 * 256 samples can effectively represent many billions of data points */
88 #define CHECKASM_STATS_SAMPLES 256
89 CheckasmSample samples[CHECKASM_STATS_SAMPLES];
90 int nb_samples;
91 int next_count;
92 } CheckasmStats;
93
94 static inline void checkasm_stats_reset(CheckasmStats *const stats)
95 {
96 stats->nb_samples = 0;
97 stats->next_count = 1;
98 }
99
100 static inline void checkasm_stats_add(CheckasmStats *const stats, const CheckasmSample s)
101 {
102 if (s.sum > 0 && s.count > 0) {
103 assert(stats->nb_samples < CHECKASM_STATS_SAMPLES);
104 stats->samples[stats->nb_samples++] = s;
105 }
106 }
107
108 static inline void checkasm_stats_count_grow(CheckasmStats *const stats, uint64_t cycles,
109 uint64_t target_cycles)
110 {
111 if (cycles < target_cycles >> 10) { /* sum[(1+1/64)^n | n < 200] */
112 /* Function is very fast, increase iteration count dramatically */
113 stats->next_count <<= 1;
114 } else if (stats->next_count < 1 << 25) {
115 /* Grow more slowly at 1/64 = ~1.5% growth */
116 stats->next_count = ((stats->next_count << 6) + stats->next_count + 63) >> 6;
117 }
118 }
119
120 CheckasmVar checkasm_stats_estimate(const CheckasmStats *stats);
121
122 typedef struct CheckasmMeasurement {
123 CheckasmVar product;
124 int nb_measurements;
125 CheckasmStats stats; /* last measurement run */
126 } CheckasmMeasurement;
127
128 static inline void checkasm_measurement_init(CheckasmMeasurement *measurement)
129 {
130 measurement->product = checkasm_var_const(1.0);
131 measurement->nb_measurements = 0;
132 measurement->stats.nb_samples = 0;
133 }
134
135 static inline void checkasm_measurement_update(CheckasmMeasurement *measurement,
136 const CheckasmStats stats)
137 {
138 const CheckasmVar est = checkasm_stats_estimate(&stats);
139 measurement->product = checkasm_var_mul(measurement->product, est);
140 measurement->nb_measurements++;
141 measurement->stats.nb_samples = stats.nb_samples;
142 memcpy(measurement->stats.samples, stats.samples,
143 sizeof(stats.samples[0]) * stats.nb_samples);
144 }
145
146 static inline CheckasmVar
147 checkasm_measurement_result(const CheckasmMeasurement measurement)
148 {
149 return checkasm_var_pow(measurement.product, 1.0 / measurement.nb_measurements);
150 }
151
152 #endif /* CHECKASM_STATS_H */
153