diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj index f19b464f..0063697a 100644 --- a/src/Numerics/Numerics.csproj +++ b/src/Numerics/Numerics.csproj @@ -167,6 +167,11 @@ + + True + True + Resources.resx + @@ -428,11 +433,6 @@ - - True - True - Resources.resx - @@ -472,8 +472,8 @@ PublicResXFileCodeGenerator - Resources.Designer.cs Designer + Resources.Designer.cs diff --git a/src/Numerics/Properties/Resources.Designer.cs b/src/Numerics/Properties/Resources.Designer.cs index b4650370..ca56ef13 100644 --- a/src/Numerics/Properties/Resources.Designer.cs +++ b/src/Numerics/Properties/Resources.Designer.cs @@ -314,6 +314,15 @@ namespace MathNet.Numerics.Properties { } } + /// + /// Looks up a localized string similar to In the specified range, the exclusive maximum must be greater than the inclusive minimum.. + /// + public static string ArgumentMaxExclusiveMustBeLargerThanMinInclusive { + get { + return ResourceManager.GetString("ArgumentMaxExclusiveMustBeLargerThanMinInclusive", resourceCulture); + } + } + /// /// Looks up a localized string similar to In the specified range, the minimum is greater than maximum.. /// diff --git a/src/Numerics/Properties/Resources.resx b/src/Numerics/Properties/Resources.resx index e3c53791..13cc7a6e 100644 --- a/src/Numerics/Properties/Resources.resx +++ b/src/Numerics/Properties/Resources.resx @@ -1,17 +1,17 @@  - @@ -282,6 +282,9 @@ In the specified range, the minimum is greater than maximum. + + In the specified range, the exclusive maximum must be greater than the inclusive minimum. + The upper bound must be at least as large as the lower bound. diff --git a/src/Numerics/Random/RandomSource.cs b/src/Numerics/Random/RandomSource.cs index 33f66653..c9089f4c 100644 --- a/src/Numerics/Random/RandomSource.cs +++ b/src/Numerics/Random/RandomSource.cs @@ -3,7 +3,7 @@ // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics // -// Copyright (c) 2009-2015 Math.NET +// Copyright (c) 2009-2016 Math.NET // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -133,28 +133,39 @@ namespace MathNet.Numerics.Random return DoSampleInteger(); } } - - return DoSampleInteger(); + else + { + return DoSampleInteger(); + } } /// /// Returns a random number less then a specified maximum. /// - /// The exclusive upper bound of the random number returned. + /// The exclusive upper bound of the random number returned. Range: maxExclusive ≥ 1. /// A 32-bit signed integer less than . - /// is negative. + /// is zero or negative. public sealed override int Next(int maxExclusive) { + // Invalid case: Zero and less are not valid use cases. if (maxExclusive <= 0) { throw new ArgumentException(Resources.ArgumentMustBePositive); } + // Fast case: Only zero is allowed to be returned. No sampling is needed. + if (maxExclusive == 1) + { + return 0; + } + + // Simple case: standard range if (maxExclusive == int.MaxValue) { return Next(); } + // Sample with 1 < maxExclusive < int.MaxValue if (_threadSafe) { lock (_lock) @@ -162,28 +173,39 @@ namespace MathNet.Numerics.Random return DoSampleInteger(maxExclusive); } } - - return DoSampleInteger(maxExclusive); + else + { + return DoSampleInteger(maxExclusive); + } } /// /// Returns a random number within a specified range. /// /// The inclusive lower bound of the random number returned. - /// The exclusive upper bound of the random number returned. must be greater than or equal to . + /// The exclusive upper bound of the random number returned. Range: maxExclusive > minExclusive. /// /// A 32-bit signed integer greater than or equal to and less than ; that is, the range of return values includes but not . If equals , is returned. /// /// is greater than . public sealed override int Next(int minInclusive, int maxExclusive) { - if (minInclusive > maxExclusive) + // Invalid case: empty range. + if (minInclusive >= maxExclusive) { - throw new ArgumentException(Resources.ArgumentMinValueGreaterThanMaxValue); + throw new ArgumentException(Resources.ArgumentMaxExclusiveMustBeLargerThanMinInclusive); + } + + // Fast case: Only minInclusive is allowed to be returned. No sampling is needed. + if (maxExclusive == minInclusive + 1) + { + return minInclusive; } + // Simple case: simple range if (minInclusive == 0) { + // Simple case: standard range if (maxExclusive == int.MaxValue) { return Next(); @@ -192,6 +214,7 @@ namespace MathNet.Numerics.Random return Next(maxExclusive); } + // Sample with minInclusive + 1 < maxExclusive if (_threadSafe) { lock (_lock) @@ -199,8 +222,10 @@ namespace MathNet.Numerics.Random return DoSampleInteger(minInclusive, maxExclusive); } } - - return DoSampleInteger(minInclusive, maxExclusive); + else + { + return DoSampleInteger(minInclusive, maxExclusive); + } } /// @@ -243,15 +268,30 @@ namespace MathNet.Numerics.Random /// Fills an array with random numbers within a specified range. /// /// The array to fill with random values. - /// The exclusive upper bound of the random number returned. + /// The exclusive upper bound of the random number returned. Range: maxExclusive ≥ 1. public void NextInt32s(int[] values, int maxExclusive) { + // Invalid case: Zero and less are not valid use cases. + if (maxExclusive <= 0) + { + throw new ArgumentException(Resources.ArgumentMustBePositive); + } + + // Fast case: Only zero is allowed to be returned. No sampling is needed. + if (maxExclusive == 1) + { + Array.Clear(values, 0, values.Length); + return; + } + + // Simple case: standard range if (maxExclusive == int.MaxValue) { NextInt32s(values); return; } + // Sample with 1 < maxExclusive < int.MaxValue if (_threadSafe) { lock (_lock) @@ -271,27 +311,46 @@ namespace MathNet.Numerics.Random } } + /// + /// Returns an array with random 32-bit signed integers within the specified range. + /// + /// The size of the array to fill. + /// The exclusive upper bound of the random number returned. Range: maxExclusive ≥ 1. + public int[] NextInt32s(int count, int maxExclusive) + { + var values = new int[count]; + NextInt32s(values, maxExclusive); + return values; + } + /// /// Fills an array with random numbers within a specified range. /// /// The array to fill with random values. /// The inclusive lower bound of the random number returned. - /// The exclusive upper bound of the random number returned. must be greater than or equal to . + /// The exclusive upper bound of the random number returned. Range: maxExclusive > minExclusive. public void NextInt32s(int[] values, int minInclusive, int maxExclusive) { - if (minInclusive > maxExclusive) + // Invalid case: empty range. + if (minInclusive >= maxExclusive) { - throw new ArgumentException(Resources.ArgumentMinValueGreaterThanMaxValue); + throw new ArgumentException(Resources.ArgumentMaxExclusiveMustBeLargerThanMinInclusive); } - if (maxExclusive == int.MaxValue && minInclusive == 0) + // Fast case: Only minInclusive is allowed to be returned. No sampling is needed. + if (maxExclusive == minInclusive + 1) { - NextInt32s(values); + for (var i = 0; i < values.Length; i++) + { + values[i] = minInclusive; + } return; } + // Simple case: simple range if (minInclusive == 0) { + // Simple case: standard range if (maxExclusive == int.MaxValue) { NextInt32s(values); @@ -302,6 +361,7 @@ namespace MathNet.Numerics.Random return; } + // Sample with minInclusive + 1 < maxExclusive if (_threadSafe) { lock (_lock) @@ -326,7 +386,7 @@ namespace MathNet.Numerics.Random /// /// The size of the array to fill. /// The inclusive lower bound of the random number returned. - /// The exclusive upper bound of the random number returned. must be greater than or equal to . + /// The exclusive upper bound of the random number returned. Range: maxExclusive > minExclusive. public int[] NextInt32s(int count, int minInclusive, int maxExclusive) { var values = new int[count]; @@ -359,7 +419,7 @@ namespace MathNet.Numerics.Random /// Returns an infinite sequence of random numbers within a specified range. /// /// The inclusive lower bound of the random number returned. - /// The exclusive upper bound of the random number returned. must be greater than or equal to . + /// The exclusive upper bound of the random number returned. Range: maxExclusive > minExclusive. public IEnumerable NextInt32Sequence(int minInclusive, int maxExclusive) { if (minInclusive > maxExclusive) @@ -461,6 +521,7 @@ namespace MathNet.Numerics.Random { return 0; } + var bytes = new byte[4]; DoSampleBytes(bytes); @@ -484,6 +545,7 @@ namespace MathNet.Numerics.Random { return 0; } + var bytes = new byte[8]; DoSampleBytes(bytes); @@ -498,7 +560,7 @@ namespace MathNet.Numerics.Random /// /// Returns a random 32-bit signed integer within the specified range. /// - /// The exclusive upper bound of the random number returned. + /// The exclusive upper bound of the random number returned. Range: maxExclusive ≥ 1. protected virtual int DoSampleInteger(int maxExclusive) { // Fast case: Only a single number is allowed to be returned @@ -507,7 +569,7 @@ namespace MathNet.Numerics.Random { return 0; } - + // non-biased implementation // (biased: return (int)(DoSample() * maxExclusive);) @@ -535,7 +597,7 @@ namespace MathNet.Numerics.Random /// Returns a random 32-bit signed integer within the specified range. /// /// The inclusive lower bound of the random number returned. - /// The exclusive upper bound of the random number returned. must be greater than or equal to . + /// The exclusive upper bound of the random number returned. Range: maxExclusive > minExclusive. protected virtual int DoSampleInteger(int minInclusive, int maxExclusive) { return DoSampleInteger(maxExclusive - minInclusive) + minInclusive;