#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono>
#include <set>
#include <ctype.h>
template<int ...Is>
struct IntVector{
using Type = IntVector<Is...>;
};
template<typename T_Vector, int I_New>
struct PushFront;
template<int ...Is, int I_New>
struct PushFront<IntVector<Is...>,I_New> : IntVector<I_New,Is...>{};
template<int I_Size, typename T_Vector = IntVector<>>
struct Iota :
Iota< I_Size-1, typename PushFront<T_Vector,I_Size-1>::Type> {};
template<typename T_Vector>
struct Iota<0,T_Vector> : T_Vector{};
template<char C_In>
struct ToUpperTraits {
enum { value = (C_In >= 'a' && C_In <='z') ? C_In - ('a'-'A'):C_In };
};
template<typename T>
struct TableToUpper;
template<int ...Is>
struct TableToUpper<IntVector<Is...>>{
static char at(const char in){
static const char table[] = {ToUpperTraits<Is>::value...};
return table[in];
}
};
int tableToUpper(const char c){
using Table = TableToUpper<typename Iota<256>::Type>;
return Table::at(c);
}
int myToupper ( int c ){
if(c >= 'a' && c <='z'){
return c - ('a'-'A');
}
return c;
}
void __attribute__ ((noinline))test1(const std::string& in,std::string& out){
std::transform(in.begin(),in.end(),out.begin(),toupper);
}
void __attribute__ ((noinline))test2(const std::string& in,std::string& out){
std::transform(in.begin(),in.end(),out.begin(),myToupper);
}
void __attribute__ ((noinline))test3(const std::string& in,std::string& out){
std::transform(in.begin(),in.end(),out.begin(),tableToUpper);
}
int main() {
std::string s(1024,'.');
std::iota(s.begin(),s.end(),0);
//shuffle (s.begin(), s.end(), std::default_random_engine(1)); //shuffel to make input more realistic
std::string out1(1024,'.');
std::string out2(1024,'.');
std::string out3(1024,'.');
std::chrono::nanoseconds time[3]{{},{}};
for(int i=0;i<100;i++){
const auto t1 = std::chrono::high_resolution_clock::now();
test1(s,out1);
const auto t2 = std::chrono::high_resolution_clock::now();
time[0] += t2 - t1;
const auto t3 = std::chrono::high_resolution_clock::now();
test2(s,out2);
const auto t4 = std::chrono::high_resolution_clock::now();
time[1] += t4 - t3;
const auto t5 = std::chrono::high_resolution_clock::now();
test3(s,out3);
const auto t6 = std::chrono::high_resolution_clock::now();
time[2] += t6 - t5;
}
typedef std::chrono::nanoseconds output_time;
const char* const out_unit = " ns";
std::cout << "1: " << std::chrono::duration_cast<output_time>(time[0]).count() << out_unit << "\n";
std::cout << "2: " << std::chrono::duration_cast<output_time>(time[1]).count() << out_unit << "\n";
std::cout << "3: " << std::chrono::duration_cast<output_time>(time[2]).count() << out_unit << "\n";
std::cout << out1[100] << std::endl;
std::cout << out2[100] << std::endl;
std::cout << out3[100] << std::endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8Y2hyb25vPgojaW5jbHVkZSA8c2V0PgojaW5jbHVkZSA8Y3R5cGUuaD4KCnRlbXBsYXRlPGludCAuLi5Jcz4Kc3RydWN0IEludFZlY3RvcnsKICAgIHVzaW5nIFR5cGUgPSBJbnRWZWN0b3I8SXMuLi4+Owp9OyAKCnRlbXBsYXRlPHR5cGVuYW1lIFRfVmVjdG9yLCBpbnQgSV9OZXc+CnN0cnVjdCBQdXNoRnJvbnQ7CnRlbXBsYXRlPGludCAuLi5JcywgaW50IElfTmV3PgpzdHJ1Y3QgUHVzaEZyb250PEludFZlY3RvcjxJcy4uLj4sSV9OZXc+IDogSW50VmVjdG9yPElfTmV3LElzLi4uPnt9OwoKdGVtcGxhdGU8aW50IElfU2l6ZSwgdHlwZW5hbWUgVF9WZWN0b3IgPSBJbnRWZWN0b3I8Pj4Kc3RydWN0IElvdGEgOiAKICAgIElvdGE8IElfU2l6ZS0xLCB0eXBlbmFtZSBQdXNoRnJvbnQ8VF9WZWN0b3IsSV9TaXplLTE+OjpUeXBlPiB7fTsKdGVtcGxhdGU8dHlwZW5hbWUgVF9WZWN0b3I+CnN0cnVjdCBJb3RhPDAsVF9WZWN0b3I+IDogVF9WZWN0b3J7fTsKCnRlbXBsYXRlPGNoYXIgQ19Jbj4Kc3RydWN0IFRvVXBwZXJUcmFpdHMgewoJZW51bSB7IHZhbHVlID0gKENfSW4gPj0gJ2EnICYmIENfSW4gPD0neicpID8gQ19JbiAtICgnYSctJ0EnKTpDX0luIH07Cn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpzdHJ1Y3QgVGFibGVUb1VwcGVyOwp0ZW1wbGF0ZTxpbnQgLi4uSXM+CnN0cnVjdCBUYWJsZVRvVXBwZXI8SW50VmVjdG9yPElzLi4uPj57CglzdGF0aWMgY2hhciBhdChjb25zdCBjaGFyIGluKXsKCQlzdGF0aWMgY29uc3QgY2hhciB0YWJsZVtdID0ge1RvVXBwZXJUcmFpdHM8SXM+Ojp2YWx1ZS4uLn07CgkJcmV0dXJuIHRhYmxlW2luXTsKCX0KfTsKCmludCB0YWJsZVRvVXBwZXIoY29uc3QgY2hhciBjKXsKCXVzaW5nIFRhYmxlID0gVGFibGVUb1VwcGVyPHR5cGVuYW1lIElvdGE8MjU2Pjo6VHlwZT47CglyZXR1cm4gVGFibGU6OmF0KGMpOwp9CgppbnQgbXlUb3VwcGVyICggaW50IGMgKXsKICAgIGlmKGMgPj0gJ2EnICYmIGMgPD0neicpewogICAgICAgIHJldHVybiBjIC0gKCdhJy0nQScpOwogICAgfQogICAgcmV0dXJuIGM7Cn0gCgp2b2lkIF9fYXR0cmlidXRlX18gKChub2lubGluZSkpdGVzdDEoY29uc3Qgc3RkOjpzdHJpbmcmIGluLHN0ZDo6c3RyaW5nJiBvdXQpewoJc3RkOjp0cmFuc2Zvcm0oaW4uYmVnaW4oKSxpbi5lbmQoKSxvdXQuYmVnaW4oKSx0b3VwcGVyKTsKfQp2b2lkIF9fYXR0cmlidXRlX18gKChub2lubGluZSkpdGVzdDIoY29uc3Qgc3RkOjpzdHJpbmcmIGluLHN0ZDo6c3RyaW5nJiBvdXQpewoJc3RkOjp0cmFuc2Zvcm0oaW4uYmVnaW4oKSxpbi5lbmQoKSxvdXQuYmVnaW4oKSxteVRvdXBwZXIpOwp9CnZvaWQgX19hdHRyaWJ1dGVfXyAoKG5vaW5saW5lKSl0ZXN0Myhjb25zdCBzdGQ6OnN0cmluZyYgaW4sc3RkOjpzdHJpbmcmIG91dCl7CglzdGQ6OnRyYW5zZm9ybShpbi5iZWdpbigpLGluLmVuZCgpLG91dC5iZWdpbigpLHRhYmxlVG9VcHBlcik7Cn0KCmludCBtYWluKCkgewoJc3RkOjpzdHJpbmcgcygxMDI0LCcuJyk7CglzdGQ6OmlvdGEocy5iZWdpbigpLHMuZW5kKCksMCk7CgkvL3NodWZmbGUgKHMuYmVnaW4oKSwgcy5lbmQoKSwgc3RkOjpkZWZhdWx0X3JhbmRvbV9lbmdpbmUoMSkpOyAgLy9zaHVmZmVsIHRvIG1ha2UgaW5wdXQgbW9yZSByZWFsaXN0aWMKCXN0ZDo6c3RyaW5nIG91dDEoMTAyNCwnLicpOwoJc3RkOjpzdHJpbmcgb3V0MigxMDI0LCcuJyk7CglzdGQ6OnN0cmluZyBvdXQzKDEwMjQsJy4nKTsKIAoJc3RkOjpjaHJvbm86Om5hbm9zZWNvbmRzIHRpbWVbM117e30se319OwogCglmb3IoaW50IGk9MDtpPDEwMDtpKyspewoJCWNvbnN0IGF1dG8gdDEgPSBzdGQ6OmNocm9ubzo6aGlnaF9yZXNvbHV0aW9uX2Nsb2NrOjpub3coKTsKCQl0ZXN0MShzLG91dDEpOwoJCWNvbnN0IGF1dG8gdDIgPSBzdGQ6OmNocm9ubzo6aGlnaF9yZXNvbHV0aW9uX2Nsb2NrOjpub3coKTsKCQl0aW1lWzBdICs9IHQyIC0gdDE7CgkJY29uc3QgYXV0byB0MyA9IHN0ZDo6Y2hyb25vOjpoaWdoX3Jlc29sdXRpb25fY2xvY2s6Om5vdygpOwoJCXRlc3QyKHMsb3V0Mik7CgkJY29uc3QgYXV0byB0NCA9IHN0ZDo6Y2hyb25vOjpoaWdoX3Jlc29sdXRpb25fY2xvY2s6Om5vdygpOwoJCXRpbWVbMV0gKz0gdDQgLSB0MzsKCQljb25zdCBhdXRvIHQ1ID0gc3RkOjpjaHJvbm86OmhpZ2hfcmVzb2x1dGlvbl9jbG9jazo6bm93KCk7CgkJdGVzdDMocyxvdXQzKTsKCQljb25zdCBhdXRvIHQ2ID0gc3RkOjpjaHJvbm86OmhpZ2hfcmVzb2x1dGlvbl9jbG9jazo6bm93KCk7CgkJdGltZVsyXSArPSB0NiAtIHQ1OwoJfQogCgl0eXBlZGVmIHN0ZDo6Y2hyb25vOjpuYW5vc2Vjb25kcyBvdXRwdXRfdGltZTsKCWNvbnN0IGNoYXIqIGNvbnN0IG91dF91bml0ID0gIiBucyI7CiAKCXN0ZDo6Y291dCA8PCAiMTogIiA8PCBzdGQ6OmNocm9ubzo6ZHVyYXRpb25fY2FzdDxvdXRwdXRfdGltZT4odGltZVswXSkuY291bnQoKSA8PCBvdXRfdW5pdCA8PCAiXG4iOwoJc3RkOjpjb3V0IDw8ICIyOiAiIDw8IHN0ZDo6Y2hyb25vOjpkdXJhdGlvbl9jYXN0PG91dHB1dF90aW1lPih0aW1lWzFdKS5jb3VudCgpIDw8IG91dF91bml0IDw8ICJcbiI7CglzdGQ6OmNvdXQgPDwgIjM6ICIgPDwgc3RkOjpjaHJvbm86OmR1cmF0aW9uX2Nhc3Q8b3V0cHV0X3RpbWU+KHRpbWVbMl0pLmNvdW50KCkgPDwgb3V0X3VuaXQgPDwgIlxuIjsKCXN0ZDo6Y291dCA8PCBvdXQxWzEwMF0gPDwgc3RkOjplbmRsOwoJc3RkOjpjb3V0IDw8IG91dDJbMTAwXSA8PCBzdGQ6OmVuZGw7CglzdGQ6OmNvdXQgPDwgb3V0M1sxMDBdIDw8IHN0ZDo6ZW5kbDsKCXJldHVybiAwOwp9