|
#include <charconv>
|
|
#include <chrono>
|
|
#include <cstdint>
|
|
#include <cstdlib>
|
|
#include <random>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "fixed.h"
|
|
|
|
// g++ -std=c++17 -O3 parse.cc -o parse
|
|
|
|
void genRandomNumStrings(
|
|
uint32_t number,
|
|
std::vector<std::string>& values,
|
|
uint64_t seed)
|
|
{
|
|
values.clear();
|
|
|
|
std::random_device dev;
|
|
//~ std::mt19937 rng(dev());
|
|
std::mt19937 rng;
|
|
rng.seed(seed);
|
|
std::uniform_int_distribution<std::mt19937::result_type> numDigits(1, 18);
|
|
std::uniform_int_distribution<std::mt19937::result_type> digits(0, 9);
|
|
|
|
for (uint32_t idx = 0; idx < number; ++idx)
|
|
{
|
|
std::ostringstream output;
|
|
// Generate random whole number digits
|
|
for (uint32_t wholeIdx = 0; wholeIdx < numDigits(rng); ++wholeIdx)
|
|
{
|
|
output << digits(rng);
|
|
}
|
|
|
|
output << ".";
|
|
|
|
// Generate random fractional number digits
|
|
for (uint32_t fracIdx = 0; fracIdx < numDigits(rng); ++fracIdx)
|
|
{
|
|
output << digits(rng);
|
|
}
|
|
|
|
values.emplace_back(output.str());
|
|
//~ std::cout << "VAL: " << values.back() << std::endl;
|
|
}
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
std::cout << "Long Double Parse Test Util\n" << std::endl;
|
|
|
|
if (argc < 3)
|
|
{
|
|
std::cerr << "ERROR: not enough arguments" << std::endl;
|
|
return -1;
|
|
}
|
|
|
|
uint32_t parseType = std::strtoul(argv[1], nullptr, 10);
|
|
uint32_t numRandomStrings = std::strtoul(argv[2], nullptr, 10);
|
|
uint64_t seed = 0xDEADBEEF;
|
|
if (argc > 3)
|
|
{
|
|
seed = std::strtoull(argv[3], nullptr, 0);
|
|
}
|
|
|
|
std::vector<std::string> values;
|
|
{
|
|
auto start = std::chrono::system_clock::now();
|
|
genRandomNumStrings(numRandomStrings, values, seed);
|
|
auto end = std::chrono::system_clock::now();
|
|
auto diff = end - start;
|
|
std::cout << "Time to generate " << numRandomStrings << " values: "
|
|
<< std::chrono::duration <double, std::milli>(diff).count()
|
|
<< " ms" << std::endl;
|
|
}
|
|
|
|
long double value = 0.0;
|
|
fixed_64_64 fvalue;
|
|
|
|
// 0) strtold()
|
|
if (parseType == 0)
|
|
{
|
|
std::cout << "Parse type 0: std::strtold()" << std::endl;
|
|
auto start = std::chrono::system_clock::now();
|
|
for (auto& strValue : values)
|
|
{
|
|
value = std::strtold(strValue.c_str(), nullptr);
|
|
//~ std::cout << "In: " << strValue << " -- Out: " << value << std::endl;
|
|
}
|
|
auto end = std::chrono::system_clock::now();
|
|
auto diff = end - start;
|
|
std::cout << "Total parse time: "
|
|
<< std::chrono::duration <double, std::milli>(diff).count()
|
|
<< " ms" << std::endl;
|
|
}
|
|
// 1) stold()
|
|
else if (parseType == 1)
|
|
{
|
|
std::cout << "Parse type 1: std::stold()" << std::endl;
|
|
auto start = std::chrono::system_clock::now();
|
|
for (auto& strValue : values)
|
|
{
|
|
value = std::stold(strValue.c_str(), nullptr);
|
|
//~ std::cout << "In: " << strValue << " -- Out: " << value << std::endl;
|
|
}
|
|
auto end = std::chrono::system_clock::now();
|
|
auto diff = end - start;
|
|
std::cout << "Total parse time: "
|
|
<< std::chrono::duration <double, std::milli>(diff).count()
|
|
<< " ms" << std::endl;
|
|
}
|
|
// 2) istringstream
|
|
else if (parseType == 2)
|
|
{
|
|
std::cout << "Parse type 2: std::istringstream" << std::endl;
|
|
auto start = std::chrono::system_clock::now();
|
|
std::istringstream stream;
|
|
for (auto& strValue : values)
|
|
{
|
|
stream.clear();
|
|
stream.str(strValue);
|
|
stream >> value;
|
|
//~ std::cout << "In: " << strValue << " -- Out: " << value << std::endl;
|
|
}
|
|
auto end = std::chrono::system_clock::now();
|
|
auto diff = end - start;
|
|
std::cout << "Total parse time: "
|
|
<< std::chrono::duration <double, std::milli>(diff).count()
|
|
<< " ms" << std::endl;
|
|
}
|
|
// 3)
|
|
else if (parseType == 3)
|
|
{
|
|
std::cout << "Parse type 3: fixed_64_64" << std::endl;
|
|
auto start = std::chrono::system_clock::now();
|
|
for (auto& strValue : values)
|
|
{
|
|
fvalue.parse(strValue.c_str());
|
|
//~ std::cout << "In: " << strValue << " -- Out: " << fvalue << std::endl;
|
|
}
|
|
auto end = std::chrono::system_clock::now();
|
|
auto diff = end - start;
|
|
std::cout << "Total parse time: "
|
|
<< std::chrono::duration <double, std::milli>(diff).count()
|
|
<< " ms" << std::endl;
|
|
|
|
}
|
|
#if 0 // This needs >= gcc 11
|
|
// 4) from_chars()
|
|
else if (parseType == 4)
|
|
{
|
|
std::cout << "Parse type 4: std::from_chars()" << std::endl;
|
|
auto start = std::chrono::system_clock::now();
|
|
for (auto& strValue : values)
|
|
{
|
|
std::from_chars(strValue.begin(), strValue.end(),
|
|
value, std::chars_format::general);
|
|
//~ std::cout << "In: " << strValue << " -- Out: " << value << std::endl;
|
|
}
|
|
auto end = std::chrono::system_clock::now();
|
|
auto diff = end - start;
|
|
std::cout << "Total parse time: "
|
|
<< std::chrono::duration <double, std::milli>(diff).count()
|
|
<< " ms" << std::endl;
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
std::cerr << "ERROR: invalid parse type: " << parseType << std::endl;
|
|
return -2;
|
|
}
|
|
|
|
return 0;
|
|
}
|