#ifndef BENCHMARK_REGISTER_H #define BENCHMARK_REGISTER_H #include #include #include #include "check.h" namespace benchmark { namespace internal { // Append the powers of 'mult' in the closed interval [lo, hi]. // Returns iterator to the start of the inserted range. template typename std::vector::iterator AddPowers(std::vector* dst, T lo, T hi, int mult) { BM_CHECK_GE(lo, 0); BM_CHECK_GE(hi, lo); BM_CHECK_GE(mult, 2); const size_t start_offset = dst->size(); static const T kmax = std::numeric_limits::max(); // Space out the values in multiples of "mult" for (T i = static_cast(1); i <= hi; i *= static_cast(mult)) { if (i >= lo) { dst->push_back(i); } // Break the loop here since multiplying by // 'mult' would move outside of the range of T if (i > kmax / mult) break; } return dst->begin() + static_cast(start_offset); } template void AddNegatedPowers(std::vector* dst, T lo, T hi, int mult) { // We negate lo and hi so we require that they cannot be equal to 'min'. BM_CHECK_GT(lo, std::numeric_limits::min()); BM_CHECK_GT(hi, std::numeric_limits::min()); BM_CHECK_GE(hi, lo); BM_CHECK_LE(hi, 0); // Add positive powers, then negate and reverse. // Casts necessary since small integers get promoted // to 'int' when negating. const auto lo_complement = static_cast(-lo); const auto hi_complement = static_cast(-hi); const auto it = AddPowers(dst, hi_complement, lo_complement, mult); std::for_each(it, dst->end(), [](T& t) { t *= -1; }); std::reverse(it, dst->end()); } template void AddRange(std::vector* dst, T lo, T hi, int mult) { static_assert(std::is_integral::value && std::is_signed::value, "Args type must be a signed integer"); BM_CHECK_GE(hi, lo); BM_CHECK_GE(mult, 2); // Add "lo" dst->push_back(lo); // Handle lo == hi as a special case, so we then know // lo < hi and so it is safe to add 1 to lo and subtract 1 // from hi without falling outside of the range of T. if (lo == hi) return; // Ensure that lo_inner <= hi_inner below. if (lo + 1 == hi) { dst->push_back(hi); return; } // Add all powers of 'mult' in the range [lo+1, hi-1] (inclusive). const auto lo_inner = static_cast(lo + 1); const auto hi_inner = static_cast(hi - 1); // Insert negative values if (lo_inner < 0) { AddNegatedPowers(dst, lo_inner, std::min(hi_inner, T{-1}), mult); } // Treat 0 as a special case (see discussion on #762). if (lo < 0 && hi >= 0) { dst->push_back(0); } // Insert positive values if (hi_inner > 0) { AddPowers(dst, std::max(lo_inner, T{1}), hi_inner, mult); } // Add "hi" (if different from last value). if (hi != dst->back()) { dst->push_back(hi); } } } // namespace internal } // namespace benchmark #endif // BENCHMARK_REGISTER_H