#include #include #include #include #include #include #include using namespace std; using namespace boost; using namespace boost::chrono; namespace qi = boost::spirit::qi; int parse_int(const string& valueStr) { int result; qi::parse(valueStr.begin(), valueStr.end(), qi::int_, result); return result; } double parse_double(const string& valueStr) { double result; qi::parse(valueStr.begin(), valueStr.end(), qi::double_, result); return result; } template T tabs(T x) {return x < 0 ? -x : x;} bool AlmostEqual2sComplement(double A, double B, int maxUlps) { // Make sure maxUlps is non-negative and small enough that the // default NAN won't compare as equal to anything. assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024); int64_t aInt = *(int64_t*)&A; // Make aInt lexicographically ordered as a twos-complement int if (aInt < 0) aInt = 0x8000000000000000 - aInt; // Make bInt lexicographically ordered as a twos-complement int int64_t bInt = *(int64_t*)&B; if (bInt < 0) bInt = 0x8000000000000000 - bInt; int64_t intDiff = tabs(aInt - bInt); if (intDiff <= maxUlps) return true; return false; } template bool test(T value, const std::string& valueStr) { typedef steady_clock test_clock; test_clock::time_point start, stop; const int iterations = 1000000; cout << endl << iterations << " iterations of \"" << valueStr << "\":" << endl; bool isInteger = (double) atoi(valueStr.c_str()) == (double) value; if (isInteger) { start = test_clock::now(); for (int i=0; i < iterations; ++i) if (atoi(valueStr.c_str()) != value) return false; stop = test_clock::now(); cout << "atoi: " << duration(stop - start) << endl; start = test_clock::now(); for (int i=0; i < iterations; ++i) if (strtol(valueStr.c_str(), NULL, 10) != (long) value) return false; stop = test_clock::now(); cout << "strtol: " << duration(stop - start) << endl; start = test_clock::now(); for (int i=0; i < iterations; ++i) if (parse_int(valueStr) != value) return false; stop = test_clock::now(); cout << "Spirit: " << duration(stop - start) << endl; } else { start = test_clock::now(); for (int i=0; i < iterations; ++i) if (!AlmostEqual2sComplement(atof(valueStr.c_str()), value, 1)) return false; stop = test_clock::now(); cout << "atof: " << duration(stop - start) << endl; start = test_clock::now(); for (int i=0; i < iterations; ++i) if (!AlmostEqual2sComplement(strtod(valueStr.c_str(), NULL), value, 1)) return false; stop = test_clock::now(); cout << "strtod: " << duration(stop - start) << endl; start = test_clock::now(); for (int i=0; i < iterations; ++i) if (!AlmostEqual2sComplement(parse_double(valueStr), value, 1)) return false; stop = test_clock::now(); cout << "Spirit: " << duration(stop - start) << endl; } start = test_clock::now(); for (int i=0; i < iterations; ++i) if (lexical_cast(valueStr) != value) return false; stop = test_clock::now(); cout << "lexical_cast(string): " << duration(stop - start) << endl; iterator_range valueRng = make_iterator_range(valueStr.begin(), valueStr.end()); start = test_clock::now(); for (int i=0; i < iterations; ++i) if (lexical_cast(valueRng) != value) return false; stop = test_clock::now(); cout << "lexical_cast(iterator_range): " << duration(stop - start) << endl; start = test_clock::now(); for (int i=0; i < iterations; ++i) if (lexical_cast(string(valueRng.begin(), valueRng.end())) != value) return false; stop = test_clock::now(); cout << "lexical_cast(iterator_range->string): " << duration(stop - start) << endl; return true; } int main() { test(123, "123"); test(123567890, "123567890"); test(1.23456, "1.23456"); test(1.23456789e42, "1.23456789e42"); return 0; }