#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
namespace qi = boost::spirit::qi;
#if 1
struct float3
{
float x,y,z;
};
BOOST_FUSION_ADAPT_STRUCT(float3, (float, x)(float, y)(float, z))
typedef std::vector<float3> data_t;
#else
// there is no speed difference when parsing into a straight container
// (only works with the spirit implementation)
typedef std::vector<float> data_t;
#endif
double scan_float(const char* str, size_t& off, size_t len);
int main()
{
#if 0
std::cin.unsetf(std::ios::skipws);
std::istreambuf_iterator<char> f_(std::cin), l_;
const std::vector<char> v(f_, l_);
auto f = v.data(), l = f+v.size();
#elif 1
boost::iostreams::mapped_file mmap(
"input.txt",
boost::iostreams::mapped_file::readonly);
auto f = mmap.const_data();
auto l = f + mmap.size();
#endif
data_t data;
data.reserve(11000000);
#if 0
using namespace qi;
bool ok = phrase_parse(f,l,(double_ > double_ > double_) % eol, blank, data);
if (ok)
std::cout << "parse success\n";
else
std::cerr << "parse failed: '" << std::string(f,l) << "'\n";
if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";
#elif 0
errno = 0;
char* next = nullptr;
float3 tmp;
while (errno == 0 && f && f<(l-12) ) {
tmp.x = strtod(f, &next); f = next;
tmp.y = strtod(f, &next); f = next;
tmp.z = strtod(f, &next); f = next;
data.push_back(tmp);
}
#elif 0
FILE* file = fopen("input.txt", "r");
if (NULL == file) {
printf("Failed to open 'input.txt'");
return 255;
}
float3 tmp;
do {
int nItemsRead = fscanf(file,"%f %f %f\n", &tmp.x, &tmp.y, &tmp.z);
if (3 != nItemsRead)
break;
data.push_back(tmp);
} while (1);
#else
size_t len = std::distance(f,l);
const char* str = f;
float3 tmp;
for (size_t i=0; i<len;)
{
while (i<len && isspace(str[i])) ++i;
tmp.x = scan_float(str, i, len);
while (i<len && isspace(str[i])) ++i;
tmp.y = scan_float(str, i, len);
while (i<len && isspace(str[i])) ++i;
tmp.z = scan_float(str, i, len);
if (i<len) // requires at least trailing newline for now
data.push_back(tmp);
//if (0 == (data.size()%1000)) std::cout << "now at " << data.size() << "/11000000\n";
}
#endif
std::cout << "data.size(): " << data.size() << "\n";
}
double scan_float(const char* str, size_t& off, size_t len)
{
static const double bases[13] = {
0.0, 10.0, 100.0, 1000.0, 10000.0,
100000.0, 1000000.0, 10000000.0, 100000000.0,
1000000000.0, 10000000000.0, 100000000000.0, 1000000000000.0,
};
bool begin = false;
bool fail = false;
bool minus = false;
int pfrac = 0;
double dec = 0.0;
double frac = 0.0;
for (; !fail && off<len; ++off)
{
char c = str[off];
if (c == '+')
{
if (!begin)
begin = true;
else
fail = true;
}
else if (c == '-')
{
if (!begin)
begin = true;
else
fail = true;
minus = true;
}
else if (c == '.')
{
if (!begin)
begin = true;
else if (pfrac)
fail = true;
pfrac = 1;
}
else if (c >= '0' && c <= '9')
{
if (!begin)
begin = true;
if (pfrac == 0)
{
dec *= 10;
dec += c - '0';
}
else if (pfrac < 13)
{
frac += (c - '0') / bases[pfrac];
++pfrac;
}
}
else
{
break;
}
}
if (!fail)
{
double f = dec + frac;
if (minus)
f = -f;
return f;
}
return 0.0;
}
I2luY2x1ZGUgPGJvb3N0L2Z1c2lvbi9hZGFwdGVkLmhwcD4KI2luY2x1ZGUgPGJvb3N0L3NwaXJpdC9pbmNsdWRlL3FpLmhwcD4KI2luY2x1ZGUgPGJvb3N0L2lvc3RyZWFtcy9kZXZpY2UvbWFwcGVkX2ZpbGUuaHBwPgoKbmFtZXNwYWNlIHFpID0gYm9vc3Q6OnNwaXJpdDo6cWk7CgojaWYgMQogICAgc3RydWN0IGZsb2F0MwogICAgewogICAgICAgIGZsb2F0IHgseSx6OwogICAgfTsKCiAgICBCT09TVF9GVVNJT05fQURBUFRfU1RSVUNUKGZsb2F0MywgKGZsb2F0LCB4KShmbG9hdCwgeSkoZmxvYXQsIHopKQoKICAgIHR5cGVkZWYgc3RkOjp2ZWN0b3I8ZmxvYXQzPiBkYXRhX3Q7CiNlbHNlCiAgICAvLyB0aGVyZSBpcyBubyBzcGVlZCBkaWZmZXJlbmNlIHdoZW4gcGFyc2luZyBpbnRvIGEgc3RyYWlnaHQgY29udGFpbmVyCiAgICAvLyAob25seSB3b3JrcyB3aXRoIHRoZSBzcGlyaXQgaW1wbGVtZW50YXRpb24pCiAgICB0eXBlZGVmIHN0ZDo6dmVjdG9yPGZsb2F0PiBkYXRhX3Q7CiNlbmRpZgoKZG91YmxlIHNjYW5fZmxvYXQoY29uc3QgY2hhciogc3RyLCBzaXplX3QmIG9mZiwgc2l6ZV90IGxlbik7CgppbnQgbWFpbigpCnsKI2lmIDAKICAgIHN0ZDo6Y2luLnVuc2V0ZihzdGQ6Omlvczo6c2tpcHdzKTsKICAgIHN0ZDo6aXN0cmVhbWJ1Zl9pdGVyYXRvcjxjaGFyPiBmXyhzdGQ6OmNpbiksIGxfOwoKICAgIGNvbnN0IHN0ZDo6dmVjdG9yPGNoYXI+IHYoZl8sIGxfKTsKICAgIGF1dG8gZiA9IHYuZGF0YSgpLCBsID0gZit2LnNpemUoKTsKI2VsaWYgMQogICAgYm9vc3Q6Omlvc3RyZWFtczo6bWFwcGVkX2ZpbGUgbW1hcCgKICAgICAgICAgICAgImlucHV0LnR4dCIsIAogICAgICAgICAgICBib29zdDo6aW9zdHJlYW1zOjptYXBwZWRfZmlsZTo6cmVhZG9ubHkpOwogICAgYXV0byBmID0gbW1hcC5jb25zdF9kYXRhKCk7CiAgICBhdXRvIGwgPSBmICsgbW1hcC5zaXplKCk7CiNlbmRpZgoKICAgIGRhdGFfdCBkYXRhOwogICAgZGF0YS5yZXNlcnZlKDExMDAwMDAwKTsKCiNpZiAwCiAgICB1c2luZyBuYW1lc3BhY2UgcWk7CiAgICBib29sIG9rID0gcGhyYXNlX3BhcnNlKGYsbCwoZG91YmxlXyA+IGRvdWJsZV8gPiBkb3VibGVfKSAlIGVvbCwgYmxhbmssIGRhdGEpOwogICAgaWYgKG9rKSAgIAogICAgICAgIHN0ZDo6Y291dCA8PCAicGFyc2Ugc3VjY2Vzc1xuIjsKICAgIGVsc2UgCiAgICAgICAgc3RkOjpjZXJyIDw8ICJwYXJzZSBmYWlsZWQ6ICciIDw8IHN0ZDo6c3RyaW5nKGYsbCkgPDwgIidcbiI7CgogICAgaWYgKGYhPWwpIHN0ZDo6Y2VyciA8PCAidHJhaWxpbmcgdW5wYXJzZWQ6ICciIDw8IHN0ZDo6c3RyaW5nKGYsbCkgPDwgIidcbiI7CiNlbGlmIDAKICAgIGVycm5vID0gMDsKICAgIGNoYXIqIG5leHQgPSBudWxscHRyOwogICAgZmxvYXQzIHRtcDsKICAgIHdoaWxlIChlcnJubyA9PSAwICYmIGYgJiYgZjwobC0xMikgKSB7CiAgICAgICAgdG1wLnggPSBzdHJ0b2QoZiwgJm5leHQpOyBmID0gbmV4dDsKICAgICAgICB0bXAueSA9IHN0cnRvZChmLCAmbmV4dCk7IGYgPSBuZXh0OwogICAgICAgIHRtcC56ID0gc3RydG9kKGYsICZuZXh0KTsgZiA9IG5leHQ7CiAgICAgICAgZGF0YS5wdXNoX2JhY2sodG1wKTsKICAgIH0KI2VsaWYgMAogICAgRklMRSogZmlsZSA9IGZvcGVuKCJpbnB1dC50eHQiLCAiciIpOwogICAgaWYgKE5VTEwgPT0gZmlsZSkgewogICAgICAgIHByaW50ZigiRmFpbGVkIHRvIG9wZW4gJ2lucHV0LnR4dCciKTsKICAgICAgICByZXR1cm4gMjU1OwogICAgfQogICAgZmxvYXQzIHRtcDsKICAgIGRvIHsKICAgICAgICBpbnQgbkl0ZW1zUmVhZCA9IGZzY2FuZihmaWxlLCIlZiAlZiAlZlxuIiwgJnRtcC54LCAmdG1wLnksICZ0bXAueik7CiAgICAgICAgaWYgKDMgIT0gbkl0ZW1zUmVhZCkKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgZGF0YS5wdXNoX2JhY2sodG1wKTsKICAgIH0gd2hpbGUgKDEpOwojZWxzZQogICAgc2l6ZV90IGxlbiA9IHN0ZDo6ZGlzdGFuY2UoZixsKTsKICAgIGNvbnN0IGNoYXIqIHN0ciA9IGY7CiAgICBmbG9hdDMgdG1wOwogICAgZm9yIChzaXplX3QgaT0wOyBpPGxlbjspCiAgICB7CiAgICAgICAgd2hpbGUgKGk8bGVuICYmIGlzc3BhY2Uoc3RyW2ldKSkgKytpOwogICAgICAgIHRtcC54ID0gc2Nhbl9mbG9hdChzdHIsIGksIGxlbik7CiAgICAgICAgd2hpbGUgKGk8bGVuICYmIGlzc3BhY2Uoc3RyW2ldKSkgKytpOwogICAgICAgIHRtcC55ID0gc2Nhbl9mbG9hdChzdHIsIGksIGxlbik7CiAgICAgICAgd2hpbGUgKGk8bGVuICYmIGlzc3BhY2Uoc3RyW2ldKSkgKytpOwogICAgICAgIHRtcC56ID0gc2Nhbl9mbG9hdChzdHIsIGksIGxlbik7CgogICAgICAgIGlmIChpPGxlbikgLy8gcmVxdWlyZXMgYXQgbGVhc3QgdHJhaWxpbmcgbmV3bGluZSBmb3Igbm93CiAgICAgICAgICAgIGRhdGEucHVzaF9iYWNrKHRtcCk7CiAgICAgICAgLy9pZiAoMCA9PSAoZGF0YS5zaXplKCklMTAwMCkpIHN0ZDo6Y291dCA8PCAibm93IGF0ICIgPDwgZGF0YS5zaXplKCkgPDwgIi8xMTAwMDAwMFxuIjsKICAgIH0KI2VuZGlmCgogICAgc3RkOjpjb3V0IDw8ICJkYXRhLnNpemUoKTogICAiIDw8IGRhdGEuc2l6ZSgpIDw8ICJcbiI7Cn0KCmRvdWJsZSBzY2FuX2Zsb2F0KGNvbnN0IGNoYXIqIHN0ciwgc2l6ZV90JiBvZmYsIHNpemVfdCBsZW4pCnsKICAgIHN0YXRpYyBjb25zdCBkb3VibGUgYmFzZXNbMTNdID0gewogICAgICAgIDAuMCwgMTAuMCwgMTAwLjAsIDEwMDAuMCwgMTAwMDAuMCwKICAgICAgICAxMDAwMDAuMCwgMTAwMDAwMC4wLCAxMDAwMDAwMC4wLCAxMDAwMDAwMDAuMCwKICAgICAgICAxMDAwMDAwMDAwLjAsIDEwMDAwMDAwMDAwLjAsIDEwMDAwMDAwMDAwMC4wLCAxMDAwMDAwMDAwMDAwLjAsCiAgICB9OwoKICAgIGJvb2wgICBiZWdpbiA9IGZhbHNlOwogICAgYm9vbCAgIGZhaWwgID0gZmFsc2U7CiAgICBib29sICAgbWludXMgPSBmYWxzZTsKICAgIGludCAgICBwZnJhYyA9IDA7CgogICAgZG91YmxlIGRlYyAgID0gMC4wOwogICAgZG91YmxlIGZyYWMgID0gMC4wOwoKICAgIGZvciAoOyAhZmFpbCAmJiBvZmY8bGVuOyArK29mZikKICAgIHsKICAgICAgICBjaGFyIGMgPSBzdHJbb2ZmXTsKICAgICAgICBpZiAoYyA9PSAnKycpCiAgICAgICAgewogICAgICAgICAgICBpZiAoIWJlZ2luKQogICAgICAgICAgICAgICAgYmVnaW4gPSB0cnVlOwogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICBmYWlsID0gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAoYyA9PSAnLScpCiAgICAgICAgewogICAgICAgICAgICBpZiAoIWJlZ2luKQogICAgICAgICAgICAgICAgYmVnaW4gPSB0cnVlOwogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICBmYWlsID0gdHJ1ZTsKICAgICAgICAgICAgbWludXMgPSB0cnVlOwogICAgICAgIH0KICAgICAgICBlbHNlIGlmIChjID09ICcuJykKICAgICAgICB7CiAgICAgICAgICAgIGlmICghYmVnaW4pCiAgICAgICAgICAgICAgICBiZWdpbiA9IHRydWU7CiAgICAgICAgICAgIGVsc2UgaWYgKHBmcmFjKQogICAgICAgICAgICAgICAgZmFpbCA9IHRydWU7CiAgICAgICAgICAgIHBmcmFjID0gMTsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAoYyA+PSAnMCcgJiYgYyA8PSAnOScpCiAgICAgICAgewogICAgICAgICAgICBpZiAoIWJlZ2luKQogICAgICAgICAgICAgICAgYmVnaW4gPSB0cnVlOwogICAgICAgICAgICBpZiAocGZyYWMgPT0gMCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgZGVjICo9IDEwOwogICAgICAgICAgICAgICAgZGVjICs9IGMgLSAnMCc7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAocGZyYWMgPCAxMykKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgZnJhYyArPSAoYyAtICcwJykgLyBiYXNlc1twZnJhY107CiAgICAgICAgICAgICAgICArK3BmcmFjOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgIH0KCiAgICBpZiAoIWZhaWwpCiAgICB7CiAgICAgICAgZG91YmxlIGYgPSBkZWMgKyBmcmFjOwogICAgICAgIGlmIChtaW51cykKICAgICAgICAgICAgZiA9IC1mOwogICAgICAgIHJldHVybiBmOwogICAgfQoKICAgIHJldHVybiAwLjA7Cn0KCg==