Skip to content

Instantly share code, notes, and snippets.

@FrankHB
Last active December 18, 2015 12:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FrankHB/5780662 to your computer and use it in GitHub Desktop.
Save FrankHB/5780662 to your computer and use it in GitHub Desktop.
g++ -std=c++11 -O3 a.cc
#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