Skip to content

Conversation

@khlebnikov
Copy link
Collaborator

No description provided.

Copy link
Collaborator Author

@khlebnikov khlebnikov left a comment

Choose a reason for hiding this comment

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

Added some comments to the GuidUtil integration. Will make another review round when you apply all the changes we discussed.

Harold Bott added 3 commits October 7, 2020 20:03
Comment on lines +149 to +152
if (0 != RandomDevice::getRandomBytes((unsigned char *)&state,
sizeof(state))) {
state = time(NULL) ^ (intptr_t)&bsl::printf; // fallback state
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

(for the future) This might be a candidate for factoring into local function - this is repeated twice here.

Copy link
Owner

Choose a reason for hiding this comment

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

Yes, I considered that. Also in the GuidUtil implementation, the following code is duplicated (by my new function). Perhaps a candidate for factoring as well:
while (bytes != end) {
typedef unsigned char uc;
bytes[6] = uc(0x40 | (bytes[6] & 0x0F));
bytes[8] = uc(0x80 | (bytes[8] & 0x3F));
bytes += Guid::k_GUID_NUM_BYTES;
}
My reasoning there was that I ought not touch working code.

///Example 1: Generating random 32-bit numbers
///- - - - - - - - - - - - - - - - - - - - - -
// The PCGRandomGenerator constructor takes two 64-bit constants (the initial
// state, and the rng sequence selector. Instances of PCGRandomGenerator with
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
// state, and the rng sequence selector. Instances of PCGRandomGenerator with
// state, and the rng sequence selector. Instances of 'PCGRandomGenerator' with

Copy link

@mversche mversche left a comment

Choose a reason for hiding this comment

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

I would lean towards having:

bsl::uint32_t bdlb::Random::generatePcg(PcgRandomGenerator *);

Which I realize is window dressing, but is where users will likely first look for a function providing random numbers.

// The behavior is undefined unless 'result' refers to a contiguous
// sequence of at least 'numGuids' Guid objects. Note that this
// function uses the PCG random engine to generate high quality, albeit
// not cryptographically secure, random numbers for Guids.
Copy link

Choose a reason for hiding this comment

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

We should explain why someone might chose t use this method:

...random numbers for Guids, which is typically faster than generating cryptographically secure guids.

// specified, 0 is used as the initial state. If 'streamSelector' is
// not specified, 1 is used as the stream selector.

//! PCGRandomGenerator(const PCGRandomGenerator& original) = default;
Copy link

Choose a reason for hiding this comment

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

Why is this a value semantic type?


public:
// CREATORS
PCGRandomGenerator(bsl::uint64_t initState = 0,
Copy link

Choose a reason for hiding this comment

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

What are 'initState' and 'streamSelector'? they are not explained what they do or control.

Further, there needs to be some discussion in this component (probably in whatever usage example we choose to show first) how these values should typically be chosen. This should probably show both how one might want to deterministically select them, and how one might want to generate them randomly from bdlb_RandomDevice (or whatever).

In summary: explain what initState and streamSelector do in the function doc here, then have the function doc refer to a usage example showing how someone might use these values

// 'variant' bits set to '10' and four 'version' bits set to '0100'.

static void generateNonSecure(Guid *result, bsl::size_t numGuids = 1);
// Generate a sequence of GUIDs meeting the RFC 4122 version 4
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

bde-format

// is typically faster than generating cryptographically secure Guids.

static Guid generateNonSecure();
// Generate and return a single GUID meeting the RFC 4122 version 4
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
// Generate and return a single GUID meeting the RFC 4122 version 4
// Generate and return a single GUID meeting the RFC 4122 version 4


cout << "TEST " << __FILE__ << " CASE " << test << endl;;
switch (test) { case 0:
case 8: {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Make this case 7, Usage - case 8.

// int Die::roll()
// {
// int result;

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

//


// int d1 = a.roll();
// int d2 = b.roll();
// ASSERT(d2 == d1);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
// ASSERT(d2 == d1);
// assert(d2 == d1);


static bsl::uint32_t generatePcg(PcgRandomGenerator *generator);
// Return the next unsigned 32-bit random number generated from the
// specified PcgRandomGenerator.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
// specified PcgRandomGenerator.
// specified 'PcgRandomGenerator'.

"==============" "\n";

enum { NUM_ITERATIONS = 2000 };
{
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Add generatePcg to the test plan.

Copy link
Collaborator Author

@khlebnikov khlebnikov left a comment

Choose a reason for hiding this comment

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

Couple small comments.


void GuidUtil::generate(unsigned char *result, bsl::size_t numGuids)
namespace {
inline
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
inline

void GuidUtil::generate(unsigned char *result, bsl::size_t numGuids)
namespace {
inline
void makeRfc4122Compliant(unsigned char *bytes, unsigned char *end)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Move this function into the anonymous namespace at the beginning of the file: we always put such implementation helper functions before implementation of any functions from the header.

// algorithm. PCG stands for "permuted congruential generator." The state
// is 64 bits. It uses a so-called stream selector, also 64 bits. For
// details, please refer below to the constructor. For details of the
// algorithm,see http://www.pcg-random.org.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
// algorithm,see http://www.pcg-random.org.
// algorithm, see http://www.pcg-random.org.

Harold Bott added 3 commits October 13, 2020 17:04
…; added documentation to GuidUtil component; changed to the way streamSelector is generated in GuidUtil::generateNonSecure
… beginning of the file; cleaned up some formatting
Comment on lines 40 to 47
///RANDOMNESS:
///-----------
// There are two different ways provided for generating GUIDs:
// 1. 'generate': comparatively more secure but slower
// 2. 'generateNonSecure': comparatively less secure but faster
// 'generateNonSecure' employs the PCG random engine toproduce
// high-quality, but not cryptographically secure, GUIDs.
//
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

  1. I think the proper name for this section is Cryptographic Security rather than RANDOMNESS
  2. EXAMPLES below refers to the GUID String Format section, so the security section should go after those examples.
  3. We need to provide the people who read our doc with a coherent narrative, otherwise it's difficult to understand without prior knowledge. Maybe something like this:

'GuidUtil' provides two families of functions for generating GUIDs: 'generate' and 'generateNonSecure'. The primary difference between them is cryptographic security of the resulting GUIDs and performance. The slower 'generate' methods aim to produce cryptographically secure GUIDs by accessing the underlying system resources to obtain truly random numbers, whereas faster 'generateNonSecure' methods use a fast high-quality (but not strictly cryptographically secure) in-process random-number generator.

Comment on lines 219 to 222
// sequence of at least 'numGuids' Guid objects. Note that this
// function uses the PCG random engine to generate high quality, albeit
// not cryptographically secure, random numbers for Guids. This method
// is typically faster than generating cryptographically secure Guids.
// not cryptographically secure, random numbers for GUIDs. This method
// is typically faster than generating cryptographically secure GUIDs.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think we should remove mention of our implementation details from out public documentation. Maybe we decide to switch to something else than PCG - it shouldn't matter to our clients. Given our changes to the component documentation, I think we should only leave Note that this function generates high-quality, albeit not cryptographically secure GUIDs. Kind of "for safety" and to explain the function name.

Comment on lines 19 to 20
// linear congruential generator. In the PCG algorithm, rather than a single
// seed parameter, there are two parameters, 'initState' and 'streamSelector'.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
// linear congruential generator. In the PCG algorithm, rather than a single
// seed parameter, there are two parameters, 'initState' and 'streamSelector'.
// linear congruential generator. The PCG algorithm is seeded with two
// values: its initial state and a "stream selector".

// linear congruential generator.
// linear congruential generator. In the PCG algorithm, rather than a single
// seed parameter, there are two parameters, 'initState' and 'streamSelector'.
// The use of a second parameter ('streamSelector') is to address a potential
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
// The use of a second parameter ('streamSelector') is to address a potential
// Stream selector is intended to address a potential

// linear congruential generator. In the PCG algorithm, rather than a single
// seed parameter, there are two parameters, 'initState' and 'streamSelector'.
// The use of a second parameter ('streamSelector') is to address a potential
// hazard when multiple instances of a random number generator are used: an
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
// hazard when multiple instances of a random number generator are used: an
// hazard of multiple instances of a random number generators having unintended correlation between their outputs.

Comment on lines 166 to 170
// This class implements a random number generator (RNG) based on the PCG
// algorithm. PCG stands for "permuted congruential generator." The state
// is 64 bits. It uses a so-called stream selector, also 64 bits. For
// details, please refer below to the constructor. For details of the
// algorithm, see http://www.pcg-random.org.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Incorporate this sentence PCG stands for "permuted congruential generator." and the link in component doc. Leave only the first sentence here.

PcgRandomGenerator(bsl::uint64_t initState = 0,
bsl::uint64_t streamSelector = 1);
// Create a 'PcgRandomGenerator' object and seed it with the optionally
// specified 'initState' and 'streamSelector.' If 'initState' is not
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
// specified 'initState' and 'streamSelector.' If 'initState' is not
// specified 'initState' and 'streamSelector'. If 'initState' is not

The ticks are for code font, they don't abide by the rules of English text, so the period goes outside the quote.

Comment on lines 189 to 194
// not specified, 1 is used as the stream selector. 'initState' is the
// starting state for the RNG. Any 64-bit value may be passed.
// 'streamSelector' selects the output sequence for the RNG. Any
// 64-bit value may be passed, although only the low 63 bits are
// significant. There are 2^63 different RNGs available, and
// 'streamSelector' selects from among them. Invoking different
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Too much information here, which is at the same time unclear. Most of it covered in component doc, so let's keep this simple.

Suggested change
// not specified, 1 is used as the stream selector. 'initState' is the
// starting state for the RNG. Any 64-bit value may be passed.
// 'streamSelector' selects the output sequence for the RNG. Any
// 64-bit value may be passed, although only the low 63 bits are
// significant. There are 2^63 different RNGs available, and
// 'streamSelector' selects from among them. Invoking different
// not specified, 1 is used as the stream selector. Only the
// low 63 bits of 'streamSelector' are
// significant. Note that invoking different

Comment on lines 223 to 224
// Extracted from component header file. For 'generatePcg' (PCG)
// usage example please refer bdlb_pcgrandomgenerator.t.cpp.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
// Extracted from component header file. For 'generatePcg' (PCG)
// usage example please refer bdlb_pcgrandomgenerator.t.cpp.
// Extracted from component header file.

This is not really relevant for the test driver. The PCG stuff should be just be linked in component documentation in @SEE_ALSO section - search the code for where it goes and how it's formatted.


static bsl::uint32_t generatePcg(PcgRandomGenerator *generator);
// Return the next unsigned 32-bit random number generated from the
// specified 'PcgRandomGenerator'.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
// specified 'PcgRandomGenerator'.
// specified 'generator'.

Comment on lines 224 to 225
// secure, random numbers for GUIDs. This method is typically faster
// than generating cryptographically secure GUIDs.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Remove the last sentence - it doesn't refer to this function only, thus this information is in the component doc. Also please update the rest of generateNonSecure function doc to match.

// a backup mechanism for obtaining random bytes.
///Example 2: Generating unique random sequences of 32-bit numbers
///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// This example shows how one might construct two sequences of random numbers
Copy link
Collaborator Author

@khlebnikov khlebnikov Oct 16, 2020

Choose a reason for hiding this comment

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

I took a stab at this example - please see the differences in the delivery style (also note that code is indented with 2 spaces after //):

///Example 2: Using stream selector to guarantee uncorrelated sequences
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// This example illustrates how the stream selector can be used to guarantee
// that two distinct instances of 'PCGRandomGenerator' produce uncorrelated
// sequences.
//
// First, we use the 'RandomDevice' to choose the initial states for the
// generators using a source of true randomness:
//..
//  uint64_t state1;
//  int rc = bdlb::RandomDevice::getRandomBytes(
//      reinterpret_cast<unsigned char *>(&state1), sizeof(state1));
//  (void)rc;  // error handling omitted
//
//  uint64_t state2;
//  int rc = bdlb::RandomDevice::getRandomBytes(
//      reinterpret_cast<unsigned char *>(&state2), sizeof(state2));
//  (void)rc;  // error handling omitted
//..
// Then we select two distinct stream selectors for the generators, which, due
// to the PCG algorithmic properties will guarantee that the sequences will be
// uncorrelated even if the initial state is exactly the same:
//..
//  const uint64_t streamSelector1 = 1;
//  const uint64_t streamSelector2 = 2;
//..
// Finally, we initialize the generators with their respective initial states
// and stream selectors and check that they produce distinct sequences of
// random numbers.  The check is guaranteed to pass even in the rare, but
// possible case of 'state1 == state2'.
//..
//  bdlb::PcgRandomGenerator rng1(state1, streamSelector1);
//  bdlb::PcgRandomGenerator rng2(state2, streamSelector2);
//
//  const int NUM_VALUES = 1000;
//  bsl::vector<bsl::uint32_t> sequence1(NUM_VALUES);
//  bsl::vector<bsl::uint32_t> sequence2(NUM_VALUES);
//
//  for (int i = 0; i < NUM_VALUES; ++i) {
//      sequence1[i] = rng1.generate();
//      sequence2[i] = rng2.generate();
//  }
//
//  assert(sequence1 != sequence2);
//..

Comment on lines 18 to 19
// stands for "permuted congruential generator." For details of the algorithm,
// see http://www.pcg-random.org. The PCG technique employs the concepts of
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
// stands for "permuted congruential generator." For details of the algorithm,
// see http://www.pcg-random.org. The PCG technique employs the concepts of
// stands for "permuted congruential generator" (see http://www.pcg-random.org
// for details). The PCG technique employs the concepts of

bottha123 pushed a commit that referenced this pull request Mar 14, 2021
* add references to 'bdlb_stringviewutil' in the doc

* add 'std::string' overloads; test 'toLower', 'toUpper'

* 'std::string' overloads: test 'pad'

* 'std::string' overloads: test 'ltrim', 'rtrim', 'trim'

* add 'std::pmr::string' overloads; test 'toLower', 'toUpper'

* clear compiler warnings and bde_verify diagnostics

* 'std::pmr::string' overloads: test 'pad'

* 'std::pmr::string' overloads: test 'ltrim', 'rtrim', 'trim'

* fix build for use of 'std::pmr::string'

* adjust 'bdlb_string.h' doc

* clear bde_verify warning

* doc improvements prompted by Attila's review comments

* implementation changes suggested by Attila

* test driver changes per Attila's review comments

* final test driver changes per Attila's review comments

* address Attila's review comments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants