1a8c51b3fSopenharmony_ci#undef NDEBUG
2a8c51b3fSopenharmony_ci#include <algorithm>
3a8c51b3fSopenharmony_ci#include <cassert>
4a8c51b3fSopenharmony_ci#include <cmath>
5a8c51b3fSopenharmony_ci#include <cstdlib>
6a8c51b3fSopenharmony_ci#include <vector>
7a8c51b3fSopenharmony_ci
8a8c51b3fSopenharmony_ci#include "benchmark/benchmark.h"
9a8c51b3fSopenharmony_ci#include "output_test.h"
10a8c51b3fSopenharmony_ci
11a8c51b3fSopenharmony_cinamespace {
12a8c51b3fSopenharmony_ci
13a8c51b3fSopenharmony_ci#define ADD_COMPLEXITY_CASES(...) \
14a8c51b3fSopenharmony_ci  int CONCAT(dummy, __LINE__) = AddComplexityTest(__VA_ARGS__)
15a8c51b3fSopenharmony_ci
16a8c51b3fSopenharmony_ciint AddComplexityTest(const std::string &test_name,
17a8c51b3fSopenharmony_ci                      const std::string &big_o_test_name,
18a8c51b3fSopenharmony_ci                      const std::string &rms_test_name,
19a8c51b3fSopenharmony_ci                      const std::string &big_o, int family_index) {
20a8c51b3fSopenharmony_ci  SetSubstitutions({{"%name", test_name},
21a8c51b3fSopenharmony_ci                    {"%bigo_name", big_o_test_name},
22a8c51b3fSopenharmony_ci                    {"%rms_name", rms_test_name},
23a8c51b3fSopenharmony_ci                    {"%bigo_str", "[ ]* %float " + big_o},
24a8c51b3fSopenharmony_ci                    {"%bigo", big_o},
25a8c51b3fSopenharmony_ci                    {"%rms", "[ ]*[0-9]+ %"}});
26a8c51b3fSopenharmony_ci  AddCases(
27a8c51b3fSopenharmony_ci      TC_ConsoleOut,
28a8c51b3fSopenharmony_ci      {{"^%bigo_name %bigo_str %bigo_str[ ]*$"},
29a8c51b3fSopenharmony_ci       {"^%bigo_name", MR_Not},  // Assert we we didn't only matched a name.
30a8c51b3fSopenharmony_ci       {"^%rms_name %rms %rms[ ]*$", MR_Next}});
31a8c51b3fSopenharmony_ci  AddCases(
32a8c51b3fSopenharmony_ci      TC_JSONOut,
33a8c51b3fSopenharmony_ci      {{"\"name\": \"%bigo_name\",$"},
34a8c51b3fSopenharmony_ci       {"\"family_index\": " + std::to_string(family_index) + ",$", MR_Next},
35a8c51b3fSopenharmony_ci       {"\"per_family_instance_index\": 0,$", MR_Next},
36a8c51b3fSopenharmony_ci       {"\"run_name\": \"%name\",$", MR_Next},
37a8c51b3fSopenharmony_ci       {"\"run_type\": \"aggregate\",$", MR_Next},
38a8c51b3fSopenharmony_ci       {"\"repetitions\": %int,$", MR_Next},
39a8c51b3fSopenharmony_ci       {"\"threads\": 1,$", MR_Next},
40a8c51b3fSopenharmony_ci       {"\"aggregate_name\": \"BigO\",$", MR_Next},
41a8c51b3fSopenharmony_ci       {"\"aggregate_unit\": \"time\",$", MR_Next},
42a8c51b3fSopenharmony_ci       {"\"cpu_coefficient\": %float,$", MR_Next},
43a8c51b3fSopenharmony_ci       {"\"real_coefficient\": %float,$", MR_Next},
44a8c51b3fSopenharmony_ci       {"\"big_o\": \"%bigo\",$", MR_Next},
45a8c51b3fSopenharmony_ci       {"\"time_unit\": \"ns\"$", MR_Next},
46a8c51b3fSopenharmony_ci       {"}", MR_Next},
47a8c51b3fSopenharmony_ci       {"\"name\": \"%rms_name\",$"},
48a8c51b3fSopenharmony_ci       {"\"family_index\": " + std::to_string(family_index) + ",$", MR_Next},
49a8c51b3fSopenharmony_ci       {"\"per_family_instance_index\": 0,$", MR_Next},
50a8c51b3fSopenharmony_ci       {"\"run_name\": \"%name\",$", MR_Next},
51a8c51b3fSopenharmony_ci       {"\"run_type\": \"aggregate\",$", MR_Next},
52a8c51b3fSopenharmony_ci       {"\"repetitions\": %int,$", MR_Next},
53a8c51b3fSopenharmony_ci       {"\"threads\": 1,$", MR_Next},
54a8c51b3fSopenharmony_ci       {"\"aggregate_name\": \"RMS\",$", MR_Next},
55a8c51b3fSopenharmony_ci       {"\"aggregate_unit\": \"percentage\",$", MR_Next},
56a8c51b3fSopenharmony_ci       {"\"rms\": %float$", MR_Next},
57a8c51b3fSopenharmony_ci       {"}", MR_Next}});
58a8c51b3fSopenharmony_ci  AddCases(TC_CSVOut, {{"^\"%bigo_name\",,%float,%float,%bigo,,,,,$"},
59a8c51b3fSopenharmony_ci                       {"^\"%bigo_name\"", MR_Not},
60a8c51b3fSopenharmony_ci                       {"^\"%rms_name\",,%float,%float,,,,,,$", MR_Next}});
61a8c51b3fSopenharmony_ci  return 0;
62a8c51b3fSopenharmony_ci}
63a8c51b3fSopenharmony_ci
64a8c51b3fSopenharmony_ci}  // end namespace
65a8c51b3fSopenharmony_ci
66a8c51b3fSopenharmony_ci// ========================================================================= //
67a8c51b3fSopenharmony_ci// --------------------------- Testing BigO O(1) --------------------------- //
68a8c51b3fSopenharmony_ci// ========================================================================= //
69a8c51b3fSopenharmony_ci
70a8c51b3fSopenharmony_civoid BM_Complexity_O1(benchmark::State &state) {
71a8c51b3fSopenharmony_ci  for (auto _ : state) {
72a8c51b3fSopenharmony_ci    for (int i = 0; i < 1024; ++i) {
73a8c51b3fSopenharmony_ci      benchmark::DoNotOptimize(i);
74a8c51b3fSopenharmony_ci    }
75a8c51b3fSopenharmony_ci  }
76a8c51b3fSopenharmony_ci  state.SetComplexityN(state.range(0));
77a8c51b3fSopenharmony_ci}
78a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O1)->Range(1, 1 << 18)->Complexity(benchmark::o1);
79a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O1)->Range(1, 1 << 18)->Complexity();
80a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O1)
81a8c51b3fSopenharmony_ci    ->Range(1, 1 << 18)
82a8c51b3fSopenharmony_ci    ->Complexity([](benchmark::IterationCount) { return 1.0; });
83a8c51b3fSopenharmony_ci
84a8c51b3fSopenharmony_ciconst char *one_test_name = "BM_Complexity_O1";
85a8c51b3fSopenharmony_ciconst char *big_o_1_test_name = "BM_Complexity_O1_BigO";
86a8c51b3fSopenharmony_ciconst char *rms_o_1_test_name = "BM_Complexity_O1_RMS";
87a8c51b3fSopenharmony_ciconst char *enum_big_o_1 = "\\([0-9]+\\)";
88a8c51b3fSopenharmony_ci// FIXME: Tolerate both '(1)' and 'lgN' as output when the complexity is auto
89a8c51b3fSopenharmony_ci// deduced.
90a8c51b3fSopenharmony_ci// See https://github.com/google/benchmark/issues/272
91a8c51b3fSopenharmony_ciconst char *auto_big_o_1 = "(\\([0-9]+\\))|(lgN)";
92a8c51b3fSopenharmony_ciconst char *lambda_big_o_1 = "f\\(N\\)";
93a8c51b3fSopenharmony_ci
94a8c51b3fSopenharmony_ci// Add enum tests
95a8c51b3fSopenharmony_ciADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name,
96a8c51b3fSopenharmony_ci                     enum_big_o_1, /*family_index=*/0);
97a8c51b3fSopenharmony_ci
98a8c51b3fSopenharmony_ci// Add auto enum tests
99a8c51b3fSopenharmony_ciADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name,
100a8c51b3fSopenharmony_ci                     auto_big_o_1, /*family_index=*/1);
101a8c51b3fSopenharmony_ci
102a8c51b3fSopenharmony_ci// Add lambda tests
103a8c51b3fSopenharmony_ciADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name,
104a8c51b3fSopenharmony_ci                     lambda_big_o_1, /*family_index=*/2);
105a8c51b3fSopenharmony_ci
106a8c51b3fSopenharmony_ci// ========================================================================= //
107a8c51b3fSopenharmony_ci// --------------------------- Testing BigO O(N) --------------------------- //
108a8c51b3fSopenharmony_ci// ========================================================================= //
109a8c51b3fSopenharmony_ci
110a8c51b3fSopenharmony_cistd::vector<int> ConstructRandomVector(int64_t size) {
111a8c51b3fSopenharmony_ci  std::vector<int> v;
112a8c51b3fSopenharmony_ci  v.reserve(static_cast<size_t>(size));
113a8c51b3fSopenharmony_ci  for (int i = 0; i < size; ++i) {
114a8c51b3fSopenharmony_ci    v.push_back(static_cast<int>(std::rand() % size));
115a8c51b3fSopenharmony_ci  }
116a8c51b3fSopenharmony_ci  return v;
117a8c51b3fSopenharmony_ci}
118a8c51b3fSopenharmony_ci
119a8c51b3fSopenharmony_civoid BM_Complexity_O_N(benchmark::State &state) {
120a8c51b3fSopenharmony_ci  auto v = ConstructRandomVector(state.range(0));
121a8c51b3fSopenharmony_ci  // Test worst case scenario (item not in vector)
122a8c51b3fSopenharmony_ci  const int64_t item_not_in_vector = state.range(0) * 2;
123a8c51b3fSopenharmony_ci  for (auto _ : state) {
124a8c51b3fSopenharmony_ci    auto it = std::find(v.begin(), v.end(), item_not_in_vector);
125a8c51b3fSopenharmony_ci    benchmark::DoNotOptimize(it);
126a8c51b3fSopenharmony_ci  }
127a8c51b3fSopenharmony_ci  state.SetComplexityN(state.range(0));
128a8c51b3fSopenharmony_ci}
129a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O_N)
130a8c51b3fSopenharmony_ci    ->RangeMultiplier(2)
131a8c51b3fSopenharmony_ci    ->Range(1 << 10, 1 << 16)
132a8c51b3fSopenharmony_ci    ->Complexity(benchmark::oN);
133a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O_N)
134a8c51b3fSopenharmony_ci    ->RangeMultiplier(2)
135a8c51b3fSopenharmony_ci    ->Range(1 << 10, 1 << 16)
136a8c51b3fSopenharmony_ci    ->Complexity([](benchmark::IterationCount n) -> double {
137a8c51b3fSopenharmony_ci      return static_cast<double>(n);
138a8c51b3fSopenharmony_ci    });
139a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O_N)
140a8c51b3fSopenharmony_ci    ->RangeMultiplier(2)
141a8c51b3fSopenharmony_ci    ->Range(1 << 10, 1 << 16)
142a8c51b3fSopenharmony_ci    ->Complexity();
143a8c51b3fSopenharmony_ci
144a8c51b3fSopenharmony_ciconst char *n_test_name = "BM_Complexity_O_N";
145a8c51b3fSopenharmony_ciconst char *big_o_n_test_name = "BM_Complexity_O_N_BigO";
146a8c51b3fSopenharmony_ciconst char *rms_o_n_test_name = "BM_Complexity_O_N_RMS";
147a8c51b3fSopenharmony_ciconst char *enum_auto_big_o_n = "N";
148a8c51b3fSopenharmony_ciconst char *lambda_big_o_n = "f\\(N\\)";
149a8c51b3fSopenharmony_ci
150a8c51b3fSopenharmony_ci// Add enum tests
151a8c51b3fSopenharmony_ciADD_COMPLEXITY_CASES(n_test_name, big_o_n_test_name, rms_o_n_test_name,
152a8c51b3fSopenharmony_ci                     enum_auto_big_o_n, /*family_index=*/3);
153a8c51b3fSopenharmony_ci
154a8c51b3fSopenharmony_ci// Add lambda tests
155a8c51b3fSopenharmony_ciADD_COMPLEXITY_CASES(n_test_name, big_o_n_test_name, rms_o_n_test_name,
156a8c51b3fSopenharmony_ci                     lambda_big_o_n, /*family_index=*/4);
157a8c51b3fSopenharmony_ci
158a8c51b3fSopenharmony_ci// ========================================================================= //
159a8c51b3fSopenharmony_ci// ------------------------- Testing BigO O(N*lgN) ------------------------- //
160a8c51b3fSopenharmony_ci// ========================================================================= //
161a8c51b3fSopenharmony_ci
162a8c51b3fSopenharmony_cistatic void BM_Complexity_O_N_log_N(benchmark::State &state) {
163a8c51b3fSopenharmony_ci  auto v = ConstructRandomVector(state.range(0));
164a8c51b3fSopenharmony_ci  for (auto _ : state) {
165a8c51b3fSopenharmony_ci    std::sort(v.begin(), v.end());
166a8c51b3fSopenharmony_ci  }
167a8c51b3fSopenharmony_ci  state.SetComplexityN(state.range(0));
168a8c51b3fSopenharmony_ci}
169a8c51b3fSopenharmony_cistatic const double kLog2E = 1.44269504088896340736;
170a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O_N_log_N)
171a8c51b3fSopenharmony_ci    ->RangeMultiplier(2)
172a8c51b3fSopenharmony_ci    ->Range(1 << 10, 1 << 16)
173a8c51b3fSopenharmony_ci    ->Complexity(benchmark::oNLogN);
174a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O_N_log_N)
175a8c51b3fSopenharmony_ci    ->RangeMultiplier(2)
176a8c51b3fSopenharmony_ci    ->Range(1 << 10, 1 << 16)
177a8c51b3fSopenharmony_ci    ->Complexity([](benchmark::IterationCount n) {
178a8c51b3fSopenharmony_ci      return kLog2E * static_cast<double>(n) * log(static_cast<double>(n));
179a8c51b3fSopenharmony_ci    });
180a8c51b3fSopenharmony_ciBENCHMARK(BM_Complexity_O_N_log_N)
181a8c51b3fSopenharmony_ci    ->RangeMultiplier(2)
182a8c51b3fSopenharmony_ci    ->Range(1 << 10, 1 << 16)
183a8c51b3fSopenharmony_ci    ->Complexity();
184a8c51b3fSopenharmony_ci
185a8c51b3fSopenharmony_ciconst char *n_lg_n_test_name = "BM_Complexity_O_N_log_N";
186a8c51b3fSopenharmony_ciconst char *big_o_n_lg_n_test_name = "BM_Complexity_O_N_log_N_BigO";
187a8c51b3fSopenharmony_ciconst char *rms_o_n_lg_n_test_name = "BM_Complexity_O_N_log_N_RMS";
188a8c51b3fSopenharmony_ciconst char *enum_auto_big_o_n_lg_n = "NlgN";
189a8c51b3fSopenharmony_ciconst char *lambda_big_o_n_lg_n = "f\\(N\\)";
190a8c51b3fSopenharmony_ci
191a8c51b3fSopenharmony_ci// Add enum tests
192a8c51b3fSopenharmony_ciADD_COMPLEXITY_CASES(n_lg_n_test_name, big_o_n_lg_n_test_name,
193a8c51b3fSopenharmony_ci                     rms_o_n_lg_n_test_name, enum_auto_big_o_n_lg_n,
194a8c51b3fSopenharmony_ci                     /*family_index=*/6);
195a8c51b3fSopenharmony_ci
196a8c51b3fSopenharmony_ci// Add lambda tests
197a8c51b3fSopenharmony_ciADD_COMPLEXITY_CASES(n_lg_n_test_name, big_o_n_lg_n_test_name,
198a8c51b3fSopenharmony_ci                     rms_o_n_lg_n_test_name, lambda_big_o_n_lg_n,
199a8c51b3fSopenharmony_ci                     /*family_index=*/7);
200a8c51b3fSopenharmony_ci
201a8c51b3fSopenharmony_ci// ========================================================================= //
202a8c51b3fSopenharmony_ci// -------- Testing formatting of Complexity with captured args ------------ //
203a8c51b3fSopenharmony_ci// ========================================================================= //
204a8c51b3fSopenharmony_ci
205a8c51b3fSopenharmony_civoid BM_ComplexityCaptureArgs(benchmark::State &state, int n) {
206a8c51b3fSopenharmony_ci  for (auto _ : state) {
207a8c51b3fSopenharmony_ci    // This test requires a non-zero CPU time to avoid divide-by-zero
208a8c51b3fSopenharmony_ci    auto iterations = state.iterations();
209a8c51b3fSopenharmony_ci    benchmark::DoNotOptimize(iterations);
210a8c51b3fSopenharmony_ci  }
211a8c51b3fSopenharmony_ci  state.SetComplexityN(n);
212a8c51b3fSopenharmony_ci}
213a8c51b3fSopenharmony_ci
214a8c51b3fSopenharmony_ciBENCHMARK_CAPTURE(BM_ComplexityCaptureArgs, capture_test, 100)
215a8c51b3fSopenharmony_ci    ->Complexity(benchmark::oN)
216a8c51b3fSopenharmony_ci    ->Ranges({{1, 2}, {3, 4}});
217a8c51b3fSopenharmony_ci
218a8c51b3fSopenharmony_ciconst std::string complexity_capture_name =
219a8c51b3fSopenharmony_ci    "BM_ComplexityCaptureArgs/capture_test";
220a8c51b3fSopenharmony_ci
221a8c51b3fSopenharmony_ciADD_COMPLEXITY_CASES(complexity_capture_name, complexity_capture_name + "_BigO",
222a8c51b3fSopenharmony_ci                     complexity_capture_name + "_RMS", "N", /*family_index=*/9);
223a8c51b3fSopenharmony_ci
224a8c51b3fSopenharmony_ci// ========================================================================= //
225a8c51b3fSopenharmony_ci// --------------------------- TEST CASES END ------------------------------ //
226a8c51b3fSopenharmony_ci// ========================================================================= //
227a8c51b3fSopenharmony_ci
228a8c51b3fSopenharmony_ciint main(int argc, char *argv[]) { RunOutputTests(argc, argv); }
229