C++11のつもり。パブリックドメイン。無保証。
- #include <cmath>
- #include <cstdlib>
- #include <cstdint>
- #include <iostream>
- #include <ratio>
- #include <chrono>
- template<class T>
- constexpr int constlog10(T v){
- return
- v <= 0 ?(
- std::abort(), 0
- ):(
- (v <= 1 && v*10 > 1) || (v >= 1 && v/10 < 1) ?(
- 0
- ):(
- v < 1 ?(
- constlog10(v * 10) - 1
- ):(
- constlog10(v / 10) + 1
- )
- )
- );
- }
- constexpr std::uint64_t constpow10(unsigned v){
- return
- v == 0 ?
- 1
- :
- constpow10(v - 1) * 10;
- ;
- }
- template<class T, class S>
- void dump_duration(S&& target, const T& dur){
- constexpr int punit3
- = constlog10(T::period::num) - constlog10(T::period::den);
- using pr = std::ratio<
- T::period::num * constpow10(punit3<0 ? -punit3 : 0),
- T::period::den * constpow10(punit3>0 ? punit3 : 0)
- >;
- if(dur.count() == 0){
- target << "0s";
- return;
- }
- int unit3 = std::log10(dur.count());
- char prefix_small[] = "munp";
- char prefix_big[] = "kMGT";
- char prefix = 0;
- int uunit3 = unit3 + punit3;
- if(uunit3 < 0){
- int ud = -uunit3 % 3 - 3;
- unit3 += ud;
- uunit3 += ud;
- if(uunit3 < -12){
- unit3 += -uunit3 - 12;
- uunit3 = -12;
- }
- }else{
- int ud = uunit3 % 3;
- unit3 -= ud;
- uunit3 -= ud;
- if(uunit3 > 12){
- unit3 -= uunit3 - 12;
- uunit3 = 12;
- }
- }
- if(uunit3 < 0){
- prefix = prefix_small[-uunit3 / 3 - 1];
- }else if(uunit3 > 0){
- prefix = prefix_big[uunit3 / 3 - 1];
- }
- auto cnt = dur.count();
- if(unit3 < 0){
- cnt *= constpow10(-unit3);
- }else{
- cnt /= constpow10(unit3);
- }
- cnt *= pr::num;
- cnt /= pr::den;
- target << cnt;
- if(prefix){
- target << prefix;
- }
- target << "s";
- }
- template<class O, class T, class S>
- void dump_duration(S&& target, const T& dur){
- dump_duration(
- std::forward<S>(target),
- std::chrono::duration_cast<
- std::chrono::duration<O, typename T::period>
- >(dur)
- );
- }
- int main(){
- auto start = std::chrono::steady_clock::now();
- dump_duration(std::cout,
- std::chrono::duration<int, std::ratio<1, 1000>>(1));
- std::cout << '\n';
- dump_duration(std::cout,
- std::chrono::duration<int, std::ratio<1, 1>>(1));
- std::cout << '\n';
- dump_duration(std::cout,
- std::chrono::duration<int, std::ratio<1000, 1>>(1));
- std::cout << '\n';
- auto end = std::chrono::steady_clock::now();
- std::cout << "proc time: ";
- dump_duration<double>(std::cout, end - start);
- std::cout << '\n';
- return 0;
- }