- #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