Address PR feedback on Random.NextXx#127849
Conversation
|
Tagging subscribers to this area: @dotnet/area-system-numerics |
There was a problem hiding this comment.
Pull request overview
This PR updates System.Random’s new generic integer APIs (NextInteger<T>) to address post-merge feedback, primarily around documenting/enforcing assumptions for supported IBinaryInteger<T> implementations and simplifying the full-range generation path.
Changes:
- Updates
NextInteger<T>type requirements in XML docs (two’s-complement/full-range wording). - Adjusts
NextInteger<T>()to validateT.MaxValuesign and simplifies generation (removes rejection loop). - Refactors range generation logic (ternary simplification) and folds the generic rejection-sampling helper into
NextBinaryIntegerInRange.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.Private.CoreLib/src/System/Random.cs | Tweaks docs/validation and refactors generic integer random generation logic for NextInteger<T> and helpers. |
Copilot's findings
- Files reviewed: 1/1 changed files
- Comments generated: 3
| /// <c>NextInteger<int>()</c> returns an <see cref="int"/> in the inclusive range from zero through | ||
| /// <see cref="int.MaxValue"/> and may return <see cref="int.MaxValue"/>. | ||
| /// <typeparamref name="T"/> must use a two's complement representation for signed values. | ||
| /// <remarks><typeparamref name="T"/> must behave as if it were a two's complement value with all values in range being representable.</remarks> |
| } | ||
|
|
||
| Debug.Assert(T.IsPositive(T.MaxValue)); | ||
| throw new ArgumentOutOfRangeException(nameof(T), SR.Format(SR.ArgumentOutOfRange_Generic_MustBeNonNegative, nameof(T.MaxValue), T.MaxValue)); |
| NextBytes(bytes); | ||
| bytes[^1] &= topMask; | ||
|
|
||
| T value = T.ReadLittleEndian(bytes, isUnsigned: true); | ||
| if (value <= T.MaxValue) | ||
| { | ||
| return value; | ||
| } | ||
| } | ||
| return T.ReadLittleEndian(bytes, isUnsigned: true); |
| if (T.MaxValue == T.Zero) | ||
| { | ||
| return T.Zero; | ||
| } |
There was a problem hiding this comment.
This check should be unnecessary as IsPositive strictly covers Zero. The only thing it'd catch is an edge case where a user has a one's complement integer that can only represent negative values and so MaxValue is -0, but I'm not sure that's worth handling since we say this returns a positive number (and -0 is not positive)
/// <summary>Determines if a value represents zero or a positive real number.</summary>
/// <param name="value">The value to be checked.</param>
/// <returns><c>true</c> if <paramref name="value" /> represents (positive) zero or a positive real number; otherwise, <c>false</c>.</returns>
/// <remarks>
/// <para>If this type has signed zero, then <c>-0</c> is not considered positive, but <c>+0</c> is.</para>
/// <para>This function returning <c>false</c> does not imply that <see cref="IsNegative(TSelf)" /> will return <c>true</c>. A complex number, <c>a + bi</c> for non-zero <c>b</c>, is not positive nor negative</para>
/// </remarks>
static abstract bool IsPositive(TSelf value);
Somehow the extra commit didn't get into the PR before it merged.
cc: @tannergooding