-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsunshine.cpp
135 lines (123 loc) · 3.76 KB
/
sunshine.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
* By Paul Dreik 2019
*
* License:
* dual license, pick your choice. Either Boost license 1.0, or GPL(v2 or later,
* at your option).
*/
#include "safe_duration_cast/chronoconv.hpp"
#include <algorithm>
#include <cassert>
#include <cstring>
#include <iostream>
#include <limits>
/**
* finds the largest input that can be converted from FromDuration to ToDuration
* without danger.
*/
template<class FromDuration, class ToDuration>
constexpr FromDuration
findLargestNonproblematicInput()
{
auto worksfine = [](const typename FromDuration::rep value) /*constexpr*/ {
int ec = 0;
const auto from = FromDuration{ value };
/*const auto result =*/safe_duration_cast::safe_duration_cast<ToDuration>(
from, ec);
return ec == 0;
};
typename FromDuration::rep min = 0;
typename FromDuration::rep max =
std::numeric_limits<typename FromDuration::rep>::max();
// assert(worksfine(min));
if (worksfine(max)) {
return FromDuration{ max };
}
while ((max - min) > 1) {
auto candidate = min + (max - min) / 2;
// std::cout<<"min="<<min<<" max="<<max<<" trying "<<candidate<<'\n';
if (worksfine(candidate)) {
min = candidate;
} else {
max = candidate;
}
}
return FromDuration{ min };
}
template<class FromDuration, class ToDuration>
constexpr FromDuration
findLowestNonproblematicInput()
{
auto worksfine = [](const typename FromDuration::rep value) /*constexpr*/ {
int ec = 0;
const auto from = FromDuration{ value };
/*const auto result =*/safe_duration_cast::safe_duration_cast<ToDuration>(
from, ec);
return ec == 0;
};
typename FromDuration::rep min =
std::numeric_limits<typename FromDuration::rep>::lowest();
typename FromDuration::rep max =
0; // std::numeric_limits<typename FromDuration::rep>::max();
// assert(worksfine(max));
if (worksfine(min)) {
return FromDuration{ min };
}
while ((max - min) > 1) {
auto candidate = min + (max - min) / 2;
// std::cout<<"min="<<min<<" max="<<max<<" trying "<<candidate<<'\n';
if (worksfine(candidate)) {
max = candidate;
} else {
min = candidate;
}
}
return FromDuration{ max };
}
template<bool usestdchrono>
int
doit(int /*argc*/, char* argv[])
{
using From = std::chrono::duration<std::uint64_t>;
using To = std::chrono::duration<std::uint64_t, std::ratio<3, 5>>;
constexpr auto minsafe = findLowestNonproblematicInput<From, To>();
constexpr auto maxsafe = findLargestNonproblematicInput<From, To>();
/*
std::cout << "safe input range is " << minsafe.count() << " to "
<< maxsafe.count() << '\n';
*/
const auto t0 = std::chrono::steady_clock::now();
std::uint64_t dummycount = 0;
const std::uint64_t iterations =
std::min(std::uint64_t{ 2000000000ULL }, maxsafe.count());
for (std::uint64_t i = 0; i < iterations; ++i) {
const std::uint64_t input = i;
int ec;
const auto from = From{ input };
if (!usestdchrono) {
const auto result = safe_duration_cast::safe_duration_cast<To>(from, ec);
dummycount += result.count();
} else {
const auto result = std::chrono::duration_cast<To>(from);
dummycount += result.count();
}
}
const auto t1 = std::chrono::steady_clock::now();
const auto elapsed_seconds =
std::chrono::duration_cast<std::chrono::duration<double>>(t1 - t0).count();
std::cout << (usestdchrono ? "std::chrono::duration_cast"
: "safe_duration_cast")
<< " speed:\t" << iterations / elapsed_seconds
<< " operations per second, dummy=" << dummycount << "\n";
return 0;
}
int
main(int argc, char* argv[])
{
doit<false>(argc, argv);
doit<true>(argc, argv);
doit<false>(argc, argv);
doit<true>(argc, argv);
doit<false>(argc, argv);
doit<true>(argc, argv);
}