Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix {i,o}stream support for pcg128_t #20

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions include/pcg_extras.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,21 @@ namespace pcg_extras {
*
* This code provides enough functionality to print 128-bit ints in decimal
* and zero-padded in hex. It's not a full-featured implementation.
*
* Note that we cannot simply define operator<< implementations,
* because pcg128_t is (sometimes!) a typedef; Koenig lookup on typedefs
* looks at the resolved type, which is __uint128_t in the global namespace.
*/

template <typename CharT, typename Traits, typename T>
std::basic_ostream<CharT, Traits>&
Output(std::basic_ostream<CharT, Traits>& out, const T &t) {
return out << t;
}

template <typename CharT, typename Traits>
std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& out, pcg128_t value)
Output(std::basic_ostream<CharT,Traits>& out, pcg128_t value)
{
auto desired_base = out.flags() & out.basefield;
bool want_hex = desired_base == out.hex;
Expand Down Expand Up @@ -161,9 +171,15 @@ operator<<(std::basic_ostream<CharT,Traits>& out, pcg128_t value)
return out << pos;
}

template <typename CharT, typename Traits, typename T>
std::basic_istream<CharT, Traits>&
Input(std::basic_istream<CharT, Traits>& in, T &t) {
return in >> t;
}

template <typename CharT, typename Traits>
std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& in, pcg128_t& value)
Input(std::basic_istream<CharT,Traits>& in, pcg128_t& value)
{
typename std::basic_istream<CharT,Traits>::sentry s(in);

Expand Down
15 changes: 9 additions & 6 deletions include/pcg_random.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -561,16 +561,18 @@ operator<<(std::basic_ostream<CharT,Traits>& out,
auto space = out.widen(' ');
auto orig_fill = out.fill();

out << rng.multiplier() << space
<< rng.increment() << space
<< rng.state_;
pcg_extras::Output(out, rng.multiplier());
out << space;
pcg_extras::Output(out, rng.increment());
out << space;
pcg_extras::Output(out, rng.state_);
out << space;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note this change is intentional: the current parsing routine for pcg128_t is actually broken at EOF. (This only showed up with this change, as it's not used anywhere currently.


out.flags(orig_flags);
out.fill(orig_fill);
return out;
}


template <typename CharT, typename Traits,
typename xtype, typename itype,
typename output_mixin, bool output_previous,
Expand All @@ -584,8 +586,9 @@ operator>>(std::basic_istream<CharT,Traits>& in,
auto orig_flags = in.flags(std::ios_base::dec | std::ios_base::skipws);

itype multiplier, increment, state;
in >> multiplier >> increment >> state;

pcg_extras::Input(in, multiplier);
pcg_extras::Input(in, increment);
pcg_extras::Input(in, state);
if (!in.fail()) {
bool good = true;
if (multiplier != rng.multiplier()) {
Expand Down
13 changes: 11 additions & 2 deletions test-high/pcg-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <cassert>
#include <climits>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <numeric>
Expand Down Expand Up @@ -139,8 +140,9 @@ int main(int argc, char** argv)
printf(" Rolls:");
for (int i = 0; i < 33; ++i)
cout << " " << (uint32_t(rng(6)) + 1);
cout << "\n --> rolling dice used "
<< (rng - rng_copy) << " random numbers" << endl;
cout << "\n --> rolling dice used "
<< static_cast<size_t>(rng - rng_copy)
<< " random numbers" << endl;

/* Deal some cards using pcg_extras::shuffle, which follows
* the algorithm for shuffling that most programmers would expect.
Expand All @@ -167,6 +169,13 @@ int main(int argc, char** argv)
cout << "\n" << endl;
}

// Ensure that the input/output functions work.
std::stringstream ss;
ss << rng;
RNG from_string;
ss >> from_string;
assert(from_string == rng);

return 0;
}

Expand Down