Last active
December 18, 2015 12:09
-
-
Save FrankHB/5780662 to your computer and use it in GitHub Desktop.
g++ -std=c++11 -O3 a.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string> | |
#include <algorithm> | |
#include <cstring> | |
#include <utility> | |
#include <cassert> | |
#include <iostream> | |
using namespace std; | |
#if 1 | |
// FrankHB | |
template<class T, class TR, class A> | |
void | |
seq_cat(basic_string<T, TR, A>& s, size_t n) | |
{ | |
assert(n != 0); | |
if(1 < n) | |
{ | |
const auto len(s.length()); | |
seq_cat(s, n / 2); | |
s.append(&(s)[0], s.length()); | |
if(n % 2 != 0) | |
s.append(&(s)[0], len); | |
} | |
} | |
template<class T, class TR, class A> | |
basic_string<T, TR, A>& | |
operator*=(basic_string<T, TR, A>& s, size_t n) | |
{ | |
#if 1 | |
switch(n) | |
{ | |
case 0: | |
s.clear(); | |
case 1: | |
break; | |
default: | |
s.reserve(s.length() * n); | |
seq_cat(s, n); | |
} | |
#elif 0 | |
switch(n) | |
{ | |
case 0: | |
s.clear(); | |
case 1: | |
break; | |
default: | |
{ | |
const auto len(s.length()); | |
s *= n / 2; | |
s.append(&(s)[0], s.length()); | |
if(n % 2 != 0) | |
s.append(&(s)[0], len); | |
} | |
} | |
#elif 0 | |
const auto q = s; | |
if(n > 1) | |
{ | |
s.reserve(s.length() * n); | |
while(--n != 0) | |
s += q; | |
} | |
else if(n == 0) | |
s.clear(); | |
#else | |
const auto q = s; | |
if(n > 1) | |
{ | |
const auto len(s.length()); | |
s.resize(len * n); | |
auto p(&s[0]); | |
while(--n != 0) | |
{ | |
const auto q(p + len); | |
std::copy(p, q, q); | |
p = q; | |
} | |
} | |
else if(n == 0) | |
s.clear(); | |
#endif | |
return s; | |
} | |
#elif 0 | |
// | |
template<class T, class TR, class A> | |
basic_string<T, TR, A>& | |
operator*=(basic_string<T, TR, A>& s, size_t n) | |
{ | |
switch(n) | |
{ | |
case 0: | |
s.clear(); | |
case 1: | |
break; | |
default: | |
{ | |
auto news = s; | |
basic_string<T, TR, A> addone; | |
s.reserve(s.length() * n); | |
while(n) | |
{ | |
if(n % 2) | |
addone += s; | |
news += s; | |
n /= 2; | |
} | |
news += addone; | |
swap(s, news); | |
} | |
} | |
return s; | |
} | |
#elif 0 | |
// | |
string& operator *=(string& lfs, const size_t multiplier) | |
{ | |
size_t existed = 1; | |
const size_t singleLength = lfs.length(); | |
lfs.resize(singleLength * multiplier); | |
while (existed <= multiplier / 2) { | |
memcpy(&lfs[existed * singleLength], &lfs[0], singleLength * existed); | |
existed *= 2; | |
} | |
if (multiplier > existed) { | |
memcpy(&lfs[existed * singleLength], &lfs[0], singleLength * (multiplier - existed)); | |
} | |
return lfs; | |
} | |
#elif 0 | |
// mouse | |
std::string &operator*=(std::string &src, std::size_t rep){ | |
if(!src.empty()){ | |
switch(rep){ | |
case 0: | |
src.clear(); | |
break; | |
case 1: | |
break; | |
default: | |
{ | |
const std::size_t old_size = src.size(); | |
src.reserve(old_size * rep); | |
const std::size_t MASK = 1 << (sizeof(rep) * CHAR_BIT - 1); | |
std::size_t cnt = 0; | |
while((rep & MASK) == 0){ | |
rep <<= 1; | |
++cnt; | |
} | |
do { | |
rep <<= 1; | |
++cnt; | |
const std::size_t cur_size = src.size(); | |
for(std::size_t i = 0; i < cur_size; ++i){ | |
src.push_back(src[i]); | |
} | |
if((rep & MASK) != 0){ | |
for(std::size_t i = 0; i < old_size; ++i){ | |
src.push_back(src[i]); | |
} | |
} | |
} while(cnt < sizeof(rep) * CHAR_BIT - 1); | |
} | |
break; | |
} | |
} | |
return src; | |
} | |
std::string operator*(const std::string &src, std::size_t rep){ | |
std::string tmp(src); | |
tmp *= rep; | |
return std::move(tmp); | |
} | |
std::string operator*(std::string &&src, std::size_t rep){ | |
std::string tmp(std::move(src)); | |
tmp *= rep; | |
return std::move(tmp); | |
} | |
#elif 0 | |
// rox | |
std::string& rox_cat(std::string& str, size_t n) { | |
size_t len = str.length(); | |
char* s; | |
s = (char*)::operator new(n * str.length() + 1); | |
strcpy(s, str.c_str()); | |
for(size_t i = len; i < n * len; i++) { | |
s[i] = s[i - len]; | |
} | |
str.assign(s, s + n * len); | |
::operator delete(s); | |
return str; | |
} | |
template<class T, class TR, class A> | |
basic_string<T, TR, A>& | |
operator*=(basic_string<T, TR, A>& s, size_t n) | |
{ | |
switch(n) | |
{ | |
case 0: | |
s.clear(); | |
case 1: | |
break; | |
default: | |
s.reserve(s.length() * n); | |
rox_cat(s, n); | |
} | |
return s; | |
} | |
#elif 0 | |
// rox2 | |
std::string& operator *=(std::string& str, size_t n) { | |
if(n == 0) { str.clear(); return str; } | |
if(n == 1) { return str; } | |
size_t length = str.length(); | |
size_t i; | |
const size_t split = sqrt(n); | |
const size_t count = (n - 1) / split; | |
const size_t rest = (n - 1) % split; | |
str.reserve(length * n); | |
for(i = 0; i < split; i++) str.append((char*)&str[0], length); | |
for(i = 1; i < count; i++) str.append((char*)&str[0], length * split); | |
str.append((char*)&str[0], length * rest); | |
return str; | |
} | |
#elif 1 | |
// mouse2 | |
std::string &operator*=(std::string &src, std::size_t rep){ | |
if(src.empty()){ | |
return src; | |
} else if(rep == 0){ | |
src.clear(); | |
return src; | |
} else if(rep == 1){ | |
return src; | |
} | |
#ifdef _M_IX86 | |
const std::size_t ALIGN = 4; | |
#else | |
const std::size_t ALIGN = 16; | |
#endif | |
const std::size_t src_size = src.size(); | |
const std::size_t new_size = src_size * rep; | |
if(rep < ALIGN){ | |
src.resize(new_size); | |
for(std::size_t i = src_size; i < new_size; ++i){ | |
src[i] = src[i - src_size]; | |
} | |
return src; | |
} | |
const std::size_t aligned_size = src_size * ALIGN; | |
char *const buff = (char *)::operator new(new_size); | |
char *const buff_end = buff + (std::ptrdiff_t)new_size; | |
char *wp = buff; | |
for(std::size_t i = 0; i < ALIGN; ++i){ | |
std::memcpy(wp, src.data(), src_size); | |
wp += src_size; | |
} | |
char *const align_end = buff_end - (std::ptrdiff_t)ALIGN; | |
while(wp < align_end){ | |
std::memcpy(wp, buff, aligned_size); | |
wp += aligned_size; | |
} | |
while(wp < buff_end){ | |
std::memcpy(wp, src.data(), src_size); | |
wp += src_size; | |
} | |
src.assign(buff, buff_end); | |
::operator delete[](buff); | |
return src; | |
} | |
std::string operator*(const std::string &src, std::size_t rep){ | |
std::string tmp(src); | |
tmp *= rep; | |
return std::move(tmp); | |
} | |
std::string operator*(std::string &&src, std::size_t rep){ | |
std::string tmp(std::move(src)); | |
tmp *= rep; | |
return std::move(tmp); | |
} | |
#else | |
#endif | |
int main() | |
{ | |
std::string s = "abcdef"; | |
#ifdef CHECK | |
for(std::size_t i = 0; i < 20; ++i) | |
{ | |
auto q = s; | |
q *= i; | |
cout << q << endl; | |
#else | |
for(std::size_t i = 0; i < 20000; ++i) | |
{ | |
auto q = s; | |
q *= i; | |
// rox_cat(q, i); | |
volatile auto x(q.length()); | |
#endif | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment