#include <iostream>
#include <cmath>
#include <unordered_set>
#include <chrono>
struct EqualPred
{
constexpr bool operator()(const double& lhs, const double& rhs) const
{
if (std::isnan(lhs) && std::isnan(rhs)) return true;
return lhs == rhs;
}
};
template <typename T>
struct Hash
{
size_t operator()(const T& value) const
{
return std::hash<T>()( std::isnan(value) ? NAN : value);
}
};
std::unordered_set<double, Hash<double>, EqualPred> s;
constexpr int N=5000;
void test_insert(double value)
{
auto begin = std::chrono::high_resolution_clock::now();
for (int i = 0; i < N; i++) {
s.insert(value);
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << "Duration: " << (std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin).count() / 1e9) << "\n";
std::cout << "Number of elements: "<<s.size()<<"\n";
}
int main(){
std::cout << "Not NAN\n";
test_insert(1.0); //takes 0.0001 s
std::cout << "NAN\n";
test_insert(NAN);
test_insert(-NAN);
std::cout << s.size() << std::endl;
//takes 0.2 s
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8Y21hdGg+CiNpbmNsdWRlIDx1bm9yZGVyZWRfc2V0PgojaW5jbHVkZSA8Y2hyb25vPgoKc3RydWN0IEVxdWFsUHJlZAp7CiAgICBjb25zdGV4cHIgYm9vbCBvcGVyYXRvcigpKGNvbnN0IGRvdWJsZSYgbGhzLCBjb25zdCBkb3VibGUmIHJocykgY29uc3QKICAgIHsKICAgICAgICBpZiAoc3RkOjppc25hbihsaHMpICYmIHN0ZDo6aXNuYW4ocmhzKSkgcmV0dXJuIHRydWU7CiAgICAgICAgcmV0dXJuIGxocyA9PSByaHM7CiAgICB9Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IEhhc2gKewoJc2l6ZV90IG9wZXJhdG9yKCkoY29uc3QgVCYgdmFsdWUpIGNvbnN0Cgl7CgkJcmV0dXJuICBzdGQ6Omhhc2g8VD4oKSggc3RkOjppc25hbih2YWx1ZSkgPyBOQU4gOiB2YWx1ZSk7Cgl9CgkKCQp9OwoKc3RkOjp1bm9yZGVyZWRfc2V0PGRvdWJsZSwgSGFzaDxkb3VibGU+LCBFcXVhbFByZWQ+IHM7Cgpjb25zdGV4cHIgaW50IE49NTAwMDsKdm9pZCB0ZXN0X2luc2VydChkb3VibGUgdmFsdWUpCnsKICAgIAogICAgYXV0byBiZWdpbiA9IHN0ZDo6Y2hyb25vOjpoaWdoX3Jlc29sdXRpb25fY2xvY2s6Om5vdygpOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBOOyBpKyspIHsKICAgICAgICBzLmluc2VydCh2YWx1ZSk7CiAgICB9CiAgICBhdXRvIGVuZCA9IHN0ZDo6Y2hyb25vOjpoaWdoX3Jlc29sdXRpb25fY2xvY2s6Om5vdygpOwogICAgc3RkOjpjb3V0IDw8ICJEdXJhdGlvbjogIiA8PCAoc3RkOjpjaHJvbm86OmR1cmF0aW9uX2Nhc3Q8c3RkOjpjaHJvbm86Om5hbm9zZWNvbmRzPihlbmQgLSBiZWdpbikuY291bnQoKSAvIDFlOSkgPDwgIlxuIjsKICAgIHN0ZDo6Y291dCA8PCAiTnVtYmVyIG9mIGVsZW1lbnRzOiAiPDxzLnNpemUoKTw8IlxuIjsKfQoKaW50IG1haW4oKXsKICAgIHN0ZDo6Y291dCA8PCAiTm90IE5BTlxuIjsKICAgIHRlc3RfaW5zZXJ0KDEuMCk7ICAgICAgICAgICAvL3Rha2VzIDAuMDAwMSBzCiAgICBzdGQ6OmNvdXQgPDwgIk5BTlxuIjsKICAgIHRlc3RfaW5zZXJ0KE5BTik7ICAKICAgIHRlc3RfaW5zZXJ0KC1OQU4pOwogICAgCiAgICBzdGQ6OmNvdXQgPDwgcy5zaXplKCkgPDwgc3RkOjplbmRsOwogICAgLy90YWtlcyAwLjIgcwp9