xref: /aosp_15_r20/external/google-benchmark/src/benchmark_register.h (revision dbb99499c3810fa1611fa2242a2fc446be01a57c)
1*dbb99499SAndroid Build Coastguard Worker #ifndef BENCHMARK_REGISTER_H
2*dbb99499SAndroid Build Coastguard Worker #define BENCHMARK_REGISTER_H
3*dbb99499SAndroid Build Coastguard Worker 
4*dbb99499SAndroid Build Coastguard Worker #include <algorithm>
5*dbb99499SAndroid Build Coastguard Worker #include <limits>
6*dbb99499SAndroid Build Coastguard Worker #include <vector>
7*dbb99499SAndroid Build Coastguard Worker 
8*dbb99499SAndroid Build Coastguard Worker #include "check.h"
9*dbb99499SAndroid Build Coastguard Worker 
10*dbb99499SAndroid Build Coastguard Worker namespace benchmark {
11*dbb99499SAndroid Build Coastguard Worker namespace internal {
12*dbb99499SAndroid Build Coastguard Worker 
13*dbb99499SAndroid Build Coastguard Worker // Append the powers of 'mult' in the closed interval [lo, hi].
14*dbb99499SAndroid Build Coastguard Worker // Returns iterator to the start of the inserted range.
15*dbb99499SAndroid Build Coastguard Worker template <typename T>
AddPowers(std::vector<T> * dst,T lo,T hi,int mult)16*dbb99499SAndroid Build Coastguard Worker typename std::vector<T>::iterator AddPowers(std::vector<T>* dst, T lo, T hi,
17*dbb99499SAndroid Build Coastguard Worker                                             int mult) {
18*dbb99499SAndroid Build Coastguard Worker   BM_CHECK_GE(lo, 0);
19*dbb99499SAndroid Build Coastguard Worker   BM_CHECK_GE(hi, lo);
20*dbb99499SAndroid Build Coastguard Worker   BM_CHECK_GE(mult, 2);
21*dbb99499SAndroid Build Coastguard Worker 
22*dbb99499SAndroid Build Coastguard Worker   const size_t start_offset = dst->size();
23*dbb99499SAndroid Build Coastguard Worker 
24*dbb99499SAndroid Build Coastguard Worker   static const T kmax = std::numeric_limits<T>::max();
25*dbb99499SAndroid Build Coastguard Worker 
26*dbb99499SAndroid Build Coastguard Worker   // Space out the values in multiples of "mult"
27*dbb99499SAndroid Build Coastguard Worker   for (T i = static_cast<T>(1); i <= hi; i = static_cast<T>(i * mult)) {
28*dbb99499SAndroid Build Coastguard Worker     if (i >= lo) {
29*dbb99499SAndroid Build Coastguard Worker       dst->push_back(i);
30*dbb99499SAndroid Build Coastguard Worker     }
31*dbb99499SAndroid Build Coastguard Worker     // Break the loop here since multiplying by
32*dbb99499SAndroid Build Coastguard Worker     // 'mult' would move outside of the range of T
33*dbb99499SAndroid Build Coastguard Worker     if (i > kmax / mult) break;
34*dbb99499SAndroid Build Coastguard Worker   }
35*dbb99499SAndroid Build Coastguard Worker 
36*dbb99499SAndroid Build Coastguard Worker   return dst->begin() + static_cast<int>(start_offset);
37*dbb99499SAndroid Build Coastguard Worker }
38*dbb99499SAndroid Build Coastguard Worker 
39*dbb99499SAndroid Build Coastguard Worker template <typename T>
AddNegatedPowers(std::vector<T> * dst,T lo,T hi,int mult)40*dbb99499SAndroid Build Coastguard Worker void AddNegatedPowers(std::vector<T>* dst, T lo, T hi, int mult) {
41*dbb99499SAndroid Build Coastguard Worker   // We negate lo and hi so we require that they cannot be equal to 'min'.
42*dbb99499SAndroid Build Coastguard Worker   BM_CHECK_GT(lo, std::numeric_limits<T>::min());
43*dbb99499SAndroid Build Coastguard Worker   BM_CHECK_GT(hi, std::numeric_limits<T>::min());
44*dbb99499SAndroid Build Coastguard Worker   BM_CHECK_GE(hi, lo);
45*dbb99499SAndroid Build Coastguard Worker   BM_CHECK_LE(hi, 0);
46*dbb99499SAndroid Build Coastguard Worker 
47*dbb99499SAndroid Build Coastguard Worker   // Add positive powers, then negate and reverse.
48*dbb99499SAndroid Build Coastguard Worker   // Casts necessary since small integers get promoted
49*dbb99499SAndroid Build Coastguard Worker   // to 'int' when negating.
50*dbb99499SAndroid Build Coastguard Worker   const auto lo_complement = static_cast<T>(-lo);
51*dbb99499SAndroid Build Coastguard Worker   const auto hi_complement = static_cast<T>(-hi);
52*dbb99499SAndroid Build Coastguard Worker 
53*dbb99499SAndroid Build Coastguard Worker   const auto it = AddPowers(dst, hi_complement, lo_complement, mult);
54*dbb99499SAndroid Build Coastguard Worker 
55*dbb99499SAndroid Build Coastguard Worker   std::for_each(it, dst->end(), [](T& t) { t = static_cast<T>(t * -1); });
56*dbb99499SAndroid Build Coastguard Worker   std::reverse(it, dst->end());
57*dbb99499SAndroid Build Coastguard Worker }
58*dbb99499SAndroid Build Coastguard Worker 
59*dbb99499SAndroid Build Coastguard Worker template <typename T>
AddRange(std::vector<T> * dst,T lo,T hi,int mult)60*dbb99499SAndroid Build Coastguard Worker void AddRange(std::vector<T>* dst, T lo, T hi, int mult) {
61*dbb99499SAndroid Build Coastguard Worker   static_assert(std::is_integral<T>::value && std::is_signed<T>::value,
62*dbb99499SAndroid Build Coastguard Worker                 "Args type must be a signed integer");
63*dbb99499SAndroid Build Coastguard Worker 
64*dbb99499SAndroid Build Coastguard Worker   BM_CHECK_GE(hi, lo);
65*dbb99499SAndroid Build Coastguard Worker   BM_CHECK_GE(mult, 2);
66*dbb99499SAndroid Build Coastguard Worker 
67*dbb99499SAndroid Build Coastguard Worker   // Add "lo"
68*dbb99499SAndroid Build Coastguard Worker   dst->push_back(lo);
69*dbb99499SAndroid Build Coastguard Worker 
70*dbb99499SAndroid Build Coastguard Worker   // Handle lo == hi as a special case, so we then know
71*dbb99499SAndroid Build Coastguard Worker   // lo < hi and so it is safe to add 1 to lo and subtract 1
72*dbb99499SAndroid Build Coastguard Worker   // from hi without falling outside of the range of T.
73*dbb99499SAndroid Build Coastguard Worker   if (lo == hi) return;
74*dbb99499SAndroid Build Coastguard Worker 
75*dbb99499SAndroid Build Coastguard Worker   // Ensure that lo_inner <= hi_inner below.
76*dbb99499SAndroid Build Coastguard Worker   if (lo + 1 == hi) {
77*dbb99499SAndroid Build Coastguard Worker     dst->push_back(hi);
78*dbb99499SAndroid Build Coastguard Worker     return;
79*dbb99499SAndroid Build Coastguard Worker   }
80*dbb99499SAndroid Build Coastguard Worker 
81*dbb99499SAndroid Build Coastguard Worker   // Add all powers of 'mult' in the range [lo+1, hi-1] (inclusive).
82*dbb99499SAndroid Build Coastguard Worker   const auto lo_inner = static_cast<T>(lo + 1);
83*dbb99499SAndroid Build Coastguard Worker   const auto hi_inner = static_cast<T>(hi - 1);
84*dbb99499SAndroid Build Coastguard Worker 
85*dbb99499SAndroid Build Coastguard Worker   // Insert negative values
86*dbb99499SAndroid Build Coastguard Worker   if (lo_inner < 0) {
87*dbb99499SAndroid Build Coastguard Worker     AddNegatedPowers(dst, lo_inner, std::min(hi_inner, T{-1}), mult);
88*dbb99499SAndroid Build Coastguard Worker   }
89*dbb99499SAndroid Build Coastguard Worker 
90*dbb99499SAndroid Build Coastguard Worker   // Treat 0 as a special case (see discussion on #762).
91*dbb99499SAndroid Build Coastguard Worker   if (lo < 0 && hi >= 0) {
92*dbb99499SAndroid Build Coastguard Worker     dst->push_back(0);
93*dbb99499SAndroid Build Coastguard Worker   }
94*dbb99499SAndroid Build Coastguard Worker 
95*dbb99499SAndroid Build Coastguard Worker   // Insert positive values
96*dbb99499SAndroid Build Coastguard Worker   if (hi_inner > 0) {
97*dbb99499SAndroid Build Coastguard Worker     AddPowers(dst, std::max(lo_inner, T{1}), hi_inner, mult);
98*dbb99499SAndroid Build Coastguard Worker   }
99*dbb99499SAndroid Build Coastguard Worker 
100*dbb99499SAndroid Build Coastguard Worker   // Add "hi" (if different from last value).
101*dbb99499SAndroid Build Coastguard Worker   if (hi != dst->back()) {
102*dbb99499SAndroid Build Coastguard Worker     dst->push_back(hi);
103*dbb99499SAndroid Build Coastguard Worker   }
104*dbb99499SAndroid Build Coastguard Worker }
105*dbb99499SAndroid Build Coastguard Worker 
106*dbb99499SAndroid Build Coastguard Worker }  // namespace internal
107*dbb99499SAndroid Build Coastguard Worker }  // namespace benchmark
108*dbb99499SAndroid Build Coastguard Worker 
109*dbb99499SAndroid Build Coastguard Worker #endif  // BENCHMARK_REGISTER_H
110