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

source code of third-party/benchmark/src/benchmark_register.h