blazingio is a performant minimal drop-in replacement for C++ standard input and output facilities. It's stupid, doesn't guard against invalid data and can't do much, but it can read/write integers, strings, and other primitives 5x faster than libstdc++ with sync_with_stdio(false);
, and that's what matters in areas like competitive programming.
These results are from 64-bit Linux using gcc with libstdc++. Performance of blazingio is almost the same on other architectures. blazingio is just as fast on 32-bit machines, except for 64-bit I/O, which gets a bit slower. <iostream>
, <cstdio>
, however, experience major degradations in some cases. <iostream>
is slow under libc++, which concidentally means blazingio is going to be faster on Apple, relatively speaking. <iostream>
is also slow-ish under MSVC. On MinGW, <iostream>
is slow on floating-point numbers, and <cstdio>
is slow on integers. See raw data and more plots.
You don't. For the love of god, don't use this library anywhere but for programming competitions. IT CAN TRIGGER ANY SORT OF UB ON INVALID INPUT, INCLUDING SECURITY VULNERABILITIES.
Copy-paste blazingio.min.hpp from this repository into your working program, right after all your includes. You're all set now.
Yes, really. The selling point is you don't have to re-learn I/O. It's just magically optimized.
Certain programming competitions impose a limit on the source code size, often 64 KiB or 256 KiB. Regardless of how minimal the library is by C++ standards, anything larger than a few kilobytes in source code is likely to hinder its use by the competitive programming community.
Additionally, participants may be expected to read each other's code during a hack session, and while it's typically useful to be able to read algorithms themselves, such meager things as optimized I/O are just clutter. Indeed, blazingio can handle anything testlib accepts and is covered with tests, so it can be thought of as "obviously correct" if you're looking for a logic error, just like libstdc++.
So here's a compromise: I compress the library so that it's so small and tidy there are few downsides in copy-pasting it straight to your template. The compressed version also includes a link to this repository so that the code is not considered obfuscated.
blazingio's mocked std::cin
can read most types std::iostream
can via operator>>
:
char
- non-
char
integral types, e.g.int
float
,double
std::complex<T>
std::string
,std::string_view
,const char*
, etc.std::bitset<N>
Other methods are not supported. std::getline
is available, though.
The differences in format are:
- Integral types can't start with positive sign
+
. - Floating-point accuracy is worse than 1 ulp. (You can, however, increase
double
accuracy by reading intolong double
and then casting todouble
, and similarly withfloat
viadouble
.) - Only decimal formats are supported for both ints and floats.
std::bitset<N>
can't handle input strings shorter thanN
(std would zero-pad them).- Parameters of PRNGs (
std::linear_congruential_engine
andstd::uniform_int_distribution
) cannot be loaded. (Did you even know these can be read?) - Pointers (
const void*
) cannot be read. (There's no compelling reason to.)
Failures are not handled in any way, i.e. they may cause UB. The only handled condition is EOF, which you can check via if (std::cin)
, just like with std. You're supposed to stop reading input the moment this happens: if you keep reading, you'll trigger UB.
Similar considerations apply to std::cout
. Most types can be written, although the exact format may differ from the one produced by std:
- Floating-point numbers less than 1e16 are formatted with exactly 12 digits after the decimal separator:
0.100000000000
,0.012300000000
,0.333333333333
,123456789123456.125000000000
. Floating-point numbers greater than 1e16 are formatted in scientific-like notation:0.123456789012e17
. This notably differs from std, which uses scientific notation for numbers less than 1 too, but this use case is rather uncommon. - Parameters of PRNGs (
std::linear_congruential_engine
andstd::uniform_int_distribution
) cannot be formatted. - Pointers (
const void*
andstd::nullptr_t
) cannot be written. (There's no compelling reason to.) precision
andwidth
are not handled.
Output is limited by 0.5 GiB typically and by 24 MiB on old-style ejudge problems. Unfortunately, most ejudge problems are old-style, so whether outputting more will work depends on your luck. Neither sunwalker nor Yandex.Contest have this limitation. Hopefully this particular use case is rare enough.
It also goes without saying that you won't be able to use this library if you can't or aren't allowed to use external code.
With -DONLINE_JUDGE
(enabled on Codeforces, among others), std::cerr
is replaced with a mock that doesn't do anything. This means you don't have to comment out logs for performance.
freopen
works with blazingio's streams, provided that you call freopen
before any other I/O.
Here's a neat bonus: you can make your own slim build of blazingio, stripped of anything you don't need and thus much smaller, by editing the configuration file at config
and running python3 minimize.py
.