#include #include #include #include template class log_sum { static_assert(N > 0, "N must be positive"); Float regs_[N] = {0}; void rebalance() { for (int i = 0; i < N-1; i++) { if (regs_[i] > regs_[i + 1]) { regs_[i + 1] += regs_[i]; regs_[i] = 0; } } } public: log_sum(Float initial) { regs_[N-1] = initial; } log_sum &operator +=(Float value) { regs_[0] += value; rebalance(); return *this; } Float get() const { Float sum = 0; for (int i = N - 1; i >= 0; i--) { sum += regs_[i]; } return sum; } explicit operator int64_t() const { return get(); } }; template void test_sum(uint64_t count) { Precise precise_sum = 0; Approx approx_sum = 0; std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution sample(77, 8888); std::cout << "Calculating..." << std::flush; for (uint64_t i = 0; i < count; i++) { auto value = sample(gen); precise_sum += value; approx_sum += value; } std::cout << " OK" << std::endl; auto actual_approx_sum = static_cast(approx_sum); auto delta = precise_sum - actual_approx_sum; std::cout << "precise sum = " << precise_sum << std::endl; std::cout << " approx sum = " << actual_approx_sum << std::endl; std::cout << " delta = " << delta << std::endl; std::cout << " eps = " << (double(delta) * 100 / precise_sum) << "%" << std::endl; } int main(int argc, char *argv[]) { if (argc != 2) { return 1; } auto count = std::stoull(argv[1]); test_sum(count); test_sum, int64_t>(count); return 0; }