| | #include <iostream>
#include <string>
#include <vector>
#include <chrono>
#include <algorithm>
#include <unordered_map>
#include <string.h>
#include <cassert>
//elements in array literal
#define ITEMS_IN(a) (sizeof(a)/sizeof(a[0]))
//chars in sting literal
#define CHARS_IN(s) (sizeof(s) / sizeof(s[0]) - 1)
namespace aux
{
template <typename T >
struct slice
{
const T* start;
unsigned int length;
slice() : start(0), length(0) {}
slice(const T* start_, size_t length_) { start = start_; length = (unsigned int)length_; }
slice(const slice& src) : start(src.start), length(src.length) {}
slice(const std::basic_string<T>& src) : start(src.c_str()), length((unsigned int)src.length()) {}
slice& operator = (const slice& src) { start = src.start; length = src.length; return *this; }
const T* end() const { return start + length; }
bool operator == (const slice& r) const
{
if (length != r.length)
return false;
for (unsigned int i = 0; i < length; ++i)
if (start[i] != r.start[i])
return false;
return true;
}
bool operator == (volatile const slice& r) const
{
if (length != r.length)
return false;
for (unsigned int i = 0; i < length; ++i)
if (start[i] != r.start[i])
return false;
return true;
}
bool operator != (const slice& r) const { return !operator==(r); }
T operator[] (unsigned int idx) const
{
assert(idx < length);
if (idx < length)
return start[idx];
return 0;
}
T last() const
{
if (length)
return start[length - 1];
return 0;
}
// [idx1..length)
slice operator() (unsigned int idx1) const
{
assert(idx1 < length);
if (idx1 < length)
return slice(start + idx1, length - idx1);
return slice();
}
// [idx1..idx2)
slice operator() (unsigned int idx1, unsigned int idx2) const
{
assert(idx1 < length);
assert(idx2 <= length);
assert(idx1 <= idx2);
if (idx1 < idx2)
return slice(start + idx1, idx2 - idx1);
return slice();
}
int index_of(T e) const
{
for (unsigned int i = 0; i < length; ++i) if (start[i] == e) return i;
return -1;
}
int last_index_of(T e) const
{
for (unsigned int i = length; i > 0;) if (start[--i] == e) return i;
return -1;
}
int index_of(const slice& s) const
{
if (s.length > length) return -1;
if (s.length == 0) return -1;
unsigned int l = length - s.length;
for (unsigned int i = 0; i < l; ++i)
if (start[i] == *s.start)
{
const T* p = s.start;
unsigned int last = i + s.length;
for (unsigned int j = i + 1; j < last; ++j)
if (*(++p) != start[j])
goto next_i;
return i;
next_i: continue;
}
return -1;
}
int last_index_of(const slice& s) const
{
if (s.length > length) return -1;
if (s.length == 0) return -1;
const T* ps = s.end() - 1;
for (unsigned int i = length; i > 0; )
if (start[--i] == *ps)
{
const T* p = ps;
unsigned int j, first = i - s.length + 1;
for (j = i; j > first; )
if (*(--p) != start[--j])
goto next_i;
return j;
next_i: continue;
}
return -1;
}
void prune(unsigned int from_start, unsigned int from_end = 0)
{
unsigned int s = from_start >= length ? length : from_start;
unsigned int e = length - (from_end >= length ? length : from_end);
start += s;
if (s < e) length = e - s;
else length = 0;
}
};
typedef slice<char> chars;
typedef slice<wchar_t> wchars;
typedef slice<unsigned char> bytes;
// Note: CS here is a string literal!
#define CHARS(CS) aux::slice<char>(CS,CHARS_IN(CS))
#define WCHARS(CS) aux::slice<wchar_t>(WSTR(CS),CHARS_IN(_WSTR(CS)))
inline wchars chars_of(const wchar_t *t) { return t ? wchars(t, (unsigned int)wcslen(t)) : wchars(); }
inline chars chars_of(const char *t) { return t ? chars(t, (unsigned int)strlen(t)) : chars(); }
template<typename T>
slice<T> chars_of(const std::basic_string<T> &s) { return slice<T>(s.c_str(), s.length()); }
template<typename T>
slice<T> elements_of(const std::vector<T> &s) { return slice<T>(s.cbegin(), s.size()); }
template<typename T, int size>
slice<T> elements_of(T(&arr)[size]) { return slice<T>(&arr[0], size); }
template<typename T, int size>
slice<T> elements_of(const T(&arr)[size]) { return slice<T>(&arr[0], size); }
template<typename T>
std::basic_string<T> make_string(aux::slice<T> s) { return std::basic_string<T>(s.start, s.length); }
}
enum FormatterType {
simple_formatter,
integer_formatter,
decimal_formatter,
currency_formatter,
date_formatter,
date_local_formatter,
time_formatter,
time_local_formatter,
enum_formatter,
duration_formatter
};
enum { TOTAL_RUNS = 10000 };
std::string input_tokens[] = { "", "text", "integer", "decimal", "currency", "date", "date-local", "time", "time-local", "enum" };
std::vector<std::string> input;
void generate_input() {
for (int n = 0; n < TOTAL_RUNS; ++n)
input.push_back(std::string(input_tokens[std::rand() % ITEMS_IN(input_tokens)]));
}
FormatterType if_t2e(const std::string& name)
{
aux::chars name_chars = aux::chars_of(name);
auto result =
name_chars == CHARS("text") ? simple_formatter
: name_chars == CHARS("integer") ? integer_formatter
: name_chars == CHARS("decimal") ? decimal_formatter
: name_chars == CHARS("currency") ? currency_formatter
: name_chars == CHARS("date") ? date_formatter
: name_chars == CHARS("date-local") ? date_local_formatter
: name_chars == CHARS("time") ? time_formatter
: name_chars == CHARS("time-local") ? time_local_formatter
: name_chars == CHARS("enum") ? enum_formatter
: name_chars == CHARS("duration") ? duration_formatter
: simple_formatter;
return result;
}
volatile aux::chars aux_text = CHARS("text");
volatile aux::chars aux_integer = CHARS("integer");
volatile aux::chars aux_decimal = CHARS("decimal");
volatile aux::chars aux_currency = CHARS("currency");
volatile aux::chars aux_date = CHARS("date");
volatile aux::chars aux_datelocal = CHARS("date-local");
volatile aux::chars aux_time = CHARS("time");
volatile aux::chars aux_timelocal = CHARS("time-local");
volatile aux::chars aux_enum = CHARS("enum");
volatile aux::chars aux_duration = CHARS("duration");
FormatterType if_t2e_disable_opt(const std::string& name)
{
aux::chars name_chars = aux::chars_of(name);
return name_chars == aux_text ? simple_formatter
: name_chars == aux_integer ? integer_formatter
: name_chars == aux_decimal ? decimal_formatter
: name_chars == aux_currency ? currency_formatter
: name_chars == aux_date ? date_formatter
: name_chars == aux_datelocal ? date_local_formatter
: name_chars == aux_time ? time_formatter
: name_chars == aux_timelocal ? time_local_formatter
: name_chars == aux_enum ? enum_formatter
: name_chars == aux_duration ? duration_formatter
: simple_formatter;
}
std::vector<std::pair<std::string, FormatterType>> vector_string_no_order = {
std::pair<std::string,FormatterType> { "text", simple_formatter },
std::pair<std::string,FormatterType> { "integer", integer_formatter },
std::pair<std::string,FormatterType> { "decimal", decimal_formatter },
std::pair<std::string,FormatterType> { "currency", currency_formatter },
std::pair<std::string,FormatterType> { "date", date_formatter },
std::pair<std::string,FormatterType> { "date-local", date_local_formatter },
std::pair<std::string,FormatterType> { "time", time_formatter },
std::pair<std::string,FormatterType> { "time-local", time_local_formatter },
std::pair<std::string,FormatterType> { "enum", enum_formatter },
std::pair<std::string,FormatterType> { "duration", duration_formatter }
};
std::vector<std::pair<std::string, FormatterType>> vector_string_order = {
std::pair<std::string,FormatterType> { "text", simple_formatter },
std::pair<std::string,FormatterType> { "date", date_formatter },
std::pair<std::string,FormatterType> { "time", time_formatter },
std::pair<std::string,FormatterType> { "enum", enum_formatter },
std::pair<std::string,FormatterType> { "integer", integer_formatter },
std::pair<std::string,FormatterType> { "decimal", decimal_formatter },
std::pair<std::string,FormatterType> { "currency", currency_formatter },
std::pair<std::string,FormatterType> { "duration", duration_formatter },
std::pair<std::string,FormatterType> { "date-local", date_local_formatter },
std::pair<std::string,FormatterType> { "time-local", time_local_formatter },
};
std::vector<std::pair<aux::chars, FormatterType>> vector_slice_no_order = {
std::pair<aux::chars,FormatterType> { CHARS("text"), simple_formatter },
std::pair<aux::chars,FormatterType> { CHARS("integer"), integer_formatter },
std::pair<aux::chars,FormatterType> { CHARS("decimal"), decimal_formatter },
std::pair<aux::chars,FormatterType> { CHARS("currency"), currency_formatter },
std::pair<aux::chars,FormatterType> { CHARS("date"), date_formatter },
std::pair<aux::chars,FormatterType> { CHARS("date-local"), date_local_formatter },
std::pair<aux::chars,FormatterType> { CHARS("time"), time_formatter },
std::pair<aux::chars,FormatterType> { CHARS("time-local"), time_local_formatter },
std::pair<aux::chars,FormatterType> { CHARS("enum"), enum_formatter },
std::pair<aux::chars,FormatterType> { CHARS("duration"), duration_formatter }
};
std::vector<std::pair<aux::chars, FormatterType>> vector_slice_order = {
std::pair<aux::chars,FormatterType> { CHARS("text"), simple_formatter },
std::pair<aux::chars,FormatterType> { CHARS("date"), date_formatter },
std::pair<aux::chars,FormatterType> { CHARS("time"), time_formatter },
std::pair<aux::chars,FormatterType> { CHARS("enum"), enum_formatter },
std::pair<aux::chars,FormatterType> { CHARS("integer"), integer_formatter },
std::pair<aux::chars,FormatterType> { CHARS("decimal"), decimal_formatter },
std::pair<aux::chars,FormatterType> { CHARS("currency"), currency_formatter },
std::pair<aux::chars,FormatterType> { CHARS("duration"), duration_formatter },
std::pair<aux::chars,FormatterType> { CHARS("date-local"), date_local_formatter },
std::pair<aux::chars,FormatterType> { CHARS("time-local"), time_local_formatter },
};
FormatterType search_vector_string_no_order(const std::string& name)
{
auto it = std::find_if(vector_string_no_order.begin(), vector_string_no_order.end(),
[&name](const std::pair<std::string, FormatterType>& p) { return name == p.first; });
return (it != vector_string_no_order.end()) ? it->second : simple_formatter;
}
FormatterType search_vector_string_order(const std::string& name)
{
for (auto& value : vector_string_order)
{
if (value.first == name) return value.second;
}
return simple_formatter;
}
FormatterType search_vector_slice_no_order(const std::string& name)
{
aux::chars name_chars = aux::chars_of(name);
for (auto& value : vector_slice_no_order)
{
if (value.first == name_chars) return value.second;
}
return simple_formatter;
}
FormatterType search_vector_slice_order(const std::string& name)
{
aux::chars name_chars = aux::chars_of(name);
for (auto& value : vector_slice_order)
{
if (value.first == name_chars) return value.second;
}
return simple_formatter;
}
int main(int argc, char *argv[])
{
generate_input();
auto start = std::chrono::steady_clock::now();
unsigned tn = 0;
for (int n = 0; n < TOTAL_RUNS; ++n)
for (int i = 0; i < TOTAL_RUNS; ++i)
tn += (unsigned)if_t2e(input[i]);
auto finish = std::chrono::steady_clock::now();
double elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double> >(finish - start).count();
std::cout << "if_t2e" << " " << elapsed_seconds << " " << tn << std::endl;
start = std::chrono::steady_clock::now();
tn = 0;
for (int n = 0; n < TOTAL_RUNS; ++n)
for (int i = 0; i < TOTAL_RUNS; ++i)
tn += (unsigned)if_t2e_disable_opt(input[i]);
finish = std::chrono::steady_clock::now();
elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double> >(finish - start).count();
std::cout << "if_t2e_disable_opt " << elapsed_seconds << " " << tn << std::endl;
start = std::chrono::steady_clock::now();
tn = 0;
for (int n = 0; n < TOTAL_RUNS; ++n)
for (int i = 0; i < TOTAL_RUNS; ++i)
tn += (unsigned)search_vector_string_no_order(input[i]);
finish = std::chrono::steady_clock::now();
elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double> >(finish - start).count();
std::cout << "search_vector_string_no_order " << elapsed_seconds << " " << tn << std::endl;
start = std::chrono::steady_clock::now();
tn = 0;
for (int n = 0; n < TOTAL_RUNS; ++n)
for (int i = 0; i < TOTAL_RUNS; ++i)
tn += (unsigned)search_vector_string_order(input[i]);
finish = std::chrono::steady_clock::now();
elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double> >(finish - start).count();
std::cout << "search_vector_string_order " << elapsed_seconds << " " << tn << std::endl;
start = std::chrono::steady_clock::now();
tn = 0;
for (int n = 0; n < TOTAL_RUNS; ++n)
for (int i = 0; i < TOTAL_RUNS; ++i)
tn += (unsigned)search_vector_slice_no_order(input[i]);
finish = std::chrono::steady_clock::now();
elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double> >(finish - start).count();
std::cout << "search_vector_slice_no_order " << elapsed_seconds << " " << tn << std::endl;
start = std::chrono::steady_clock::now();
tn = 0;
for (int n = 0; n < TOTAL_RUNS; ++n)
for (int i = 0; i < TOTAL_RUNS; ++i)
tn += (unsigned)search_vector_slice_order(input[i]);
finish = std::chrono::steady_clock::now();
elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double> >(finish - start).count();
std::cout << "search_vector_slice_order " << elapsed_seconds << " " << tn << std::endl;
return 0;
}
|