diff --git a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/README.md b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/README.md index 5ffc4a05b885..b44e9604b7a8 100644 --- a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/README.md +++ b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/README.md @@ -26,20 +26,20 @@ limitations under the License. The [quantile function][quantile-function] for a [discrete uniform][discrete-uniform-distribution] random variable is - + ```math -Q(p) = a + \lfloor p \cdot ( b - a + 1 ) \rfloor +Q(p) = a - 1 + \lceil p \cdot ( b - a + 1 ) \rceil ``` - -for `0 <= p <= 1`, where `a` is the minimum support and `b` is the maximum support. The parameters must satisfy `a <= b`. +for `0 < p <= 1`, where `a` is the minimum support and `b` is the maximum support, and `Q(0) = a`. This is the smallest `x` in the support for which the cumulative distribution function is at least `p`. The parameters must satisfy `a <= b`. @@ -109,7 +109,7 @@ Returns a function for evaluating the quantile function of a [discrete uniform][ ```javascript var myquantile = quantile.factory( 0, 4 ); var y = myquantile( 0.8 ); -// returns 4 +// returns 3 y = myquantile( 0.3 ); // returns 1 diff --git a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/docs/repl.txt b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/docs/repl.txt index 910dad38d9ed..fc539fc64c97 100644 --- a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/docs/repl.txt +++ b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/docs/repl.txt @@ -69,7 +69,7 @@ -------- > var myQuantile = {{alias}}.factory( 0, 4 ); > var y = myQuantile( 0.8 ) - 4 + 3 See Also -------- diff --git a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/docs/types/index.d.ts b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/docs/types/index.d.ts index 5e82b90be7d1..c1c9646a895a 100644 --- a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/docs/types/index.d.ts @@ -121,7 +121,7 @@ interface Quantile { * * var myQuantile = quantile.factory( 0, 4 ); * y = myQuantile( 0.8 ); -* // returns 4 +* // returns 3 */ declare var quantile: Quantile; diff --git a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/lib/factory.js b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/lib/factory.js index aa7d41ec13ae..661cdd7462e5 100644 --- a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/lib/factory.js +++ b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/lib/factory.js @@ -23,7 +23,7 @@ var constantFunction = require( '@stdlib/utils/constant-function' ); var isInteger = require( '@stdlib/math/base/assert/is-integer' ); var isnan = require( '@stdlib/math/base/assert/is-nan' ); -var floor = require( '@stdlib/math/base/special/floor' ); +var ceil = require( '@stdlib/math/base/special/ceil' ); // MAIN // @@ -69,10 +69,18 @@ function factory( a, b ) { * // returns */ function quantile( p ) { + var k; if ( isnan( p ) || p < 0.0 || p > 1.0 ) { return NaN; } - return a + floor( p * n ); + if ( p === 0.0 ) { + return a; + } + k = ceil( p * n ); + if ( ( k-1 ) / n >= p ) { + k -= 1; + } + return a + k - 1; } } diff --git a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/lib/index.js b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/lib/index.js index 12a34fccfd57..ec6bf125929b 100644 --- a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/lib/index.js +++ b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/lib/index.js @@ -34,7 +34,7 @@ * * var myQuantile = quantile.factory( 0, 4 ); * y = myQuantile( 0.8 ); -* // returns 4 +* // returns 3 */ // MODULES // diff --git a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/lib/main.js b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/lib/main.js index 352a77960abe..e00de768d620 100644 --- a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/lib/main.js +++ b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/lib/main.js @@ -22,7 +22,7 @@ var isInteger = require( '@stdlib/math/base/assert/is-integer' ); var isnan = require( '@stdlib/math/base/assert/is-nan' ); -var floor = require( '@stdlib/math/base/special/floor' ); +var ceil = require( '@stdlib/math/base/special/ceil' ); // MAIN // @@ -30,6 +30,16 @@ var floor = require( '@stdlib/math/base/special/floor' ); /** * Evaluates the quantile function for a discrete uniform distribution with minimum support `a` and maximum support `b` at a probability `p`. * +* ## Method +* +* The quantile is the smallest \\(x\\) in the support with \\(F(x) \geq p\\). As \\(F(x) = (x-a+1)/n\\), where \\(n = b-a+1\\), this is +* +* ```tex +* Q(p) = a - 1 + \lceil p n \rceil +* ``` +* +* for \\(p > 0\\), and \\(Q(0) = a\\). Because \\(pn\\) can round up past an integer (e.g., \\(0.3 \cdot 10 = 3.0000000000000004\\)), the function steps \\(k = \lceil pn \rceil\\) back by one when \\((k-1)/n \geq p\\), which is the same comparison the CDF makes. +* * @param {Probability} p - input value * @param {integer} a - minimum support * @param {integer} b - maximum support @@ -73,6 +83,7 @@ var floor = require( '@stdlib/math/base/special/floor' ); */ function quantile( p, a, b ) { var n; + var k; if ( isnan( p ) || isnan( a ) || @@ -85,8 +96,15 @@ function quantile( p, a, b ) { ) { return NaN; } + if ( p === 0.0 ) { + return a; + } n = b - a + 1; - return a + floor( p * n ); + k = ceil( p * n ); + if ( ( k-1 ) / n >= p ) { + k -= 1; + } + return a + k - 1; } diff --git a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/manifest.json b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/manifest.json index f60b8c621079..af938de05469 100644 --- a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/manifest.json +++ b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/manifest.json @@ -40,7 +40,7 @@ "dependencies": [ "@stdlib/math/base/napi/ternary", "@stdlib/math/base/assert/is-nan", - "@stdlib/math/base/special/floor" + "@stdlib/math/base/special/ceil" ] }, { @@ -57,7 +57,7 @@ "dependencies": [ "@stdlib/math/base/special/round", "@stdlib/math/base/assert/is-nan", - "@stdlib/math/base/special/floor" + "@stdlib/math/base/special/ceil" ] }, { @@ -74,7 +74,7 @@ "dependencies": [ "@stdlib/math/base/special/round", "@stdlib/math/base/assert/is-nan", - "@stdlib/math/base/special/floor" + "@stdlib/math/base/special/ceil" ] } ] diff --git a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/src/main.c b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/src/main.c index ee7411bb0343..95d23b2bde10 100644 --- a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/src/main.c +++ b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/src/main.c @@ -18,12 +18,22 @@ #include "stdlib/stats/base/dists/discrete-uniform/quantile.h" #include "stdlib/math/base/assert/is_nan.h" -#include "stdlib/math/base/special/floor.h" +#include "stdlib/math/base/special/ceil.h" #include /** * Evaluates the quantile function for a discrete uniform distribution with minimum support `a` and maximum support `b` at a probability `p`. * +* ## Method +* +* The quantile is the smallest `x` in the support with `F(x) \geq p`. As `F(x) = (x-a+1)/n`, where `n = b-a+1`, this is +* +* ```tex +* Q(p) = a - 1 + \lceil p n \rceil +* ``` +* +* for `p > 0`, and `Q(0) = a`. Because `pn` can round up past an integer (e.g., `0.3 \cdot 10 = 3.0000000000000004`), the function steps `k = \lceil pn \rceil` back by one when `(k-1)/n \geq p`, which is the same comparison the CDF makes. +* * @param p input probability * @param a minimum support * @param b maximum support @@ -34,6 +44,8 @@ * // returns 1.0 */ double stdlib_base_dists_discrete_uniform_quantile( const double p, const int32_t a, const int32_t b ) { + double n; + double k; if ( stdlib_base_is_nan( p ) || a > b || @@ -42,5 +54,13 @@ double stdlib_base_dists_discrete_uniform_quantile( const double p, const int32_ ) { return 0.0/0.0; // NaN } - return a + stdlib_base_floor( p * ( b - a + 1.0 ) ); + if ( p == 0.0 ) { + return a; + } + n = b - a + 1.0; + k = stdlib_base_ceil( p * n ); + if ( ( k-1.0 ) / n >= p ) { + k -= 1.0; + } + return a + k - 1.0; } diff --git a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/test/test.factory.js b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/test/test.factory.js index 2c429a67806e..b074ed587203 100644 --- a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/test/test.factory.js +++ b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/test/test.factory.js @@ -129,6 +129,39 @@ tape( 'if provided `a > b`, the created function always returns `NaN`', function t.end(); }); +tape( 'if provided `p = 0`, the created function returns `a`, and if provided `p = 1`, the created function returns `b`', function test( t ) { + var quantile; + + quantile = factory( 2, 5 ); + t.strictEqual( quantile( 0.0 ), 2, 'returns expected value' ); + t.strictEqual( quantile( 1.0 ), 5, 'returns expected value' ); + + quantile = factory( -3, -3 ); + t.strictEqual( quantile( 0.0 ), -3, 'returns expected value' ); + t.strictEqual( quantile( 1.0 ), -3, 'returns expected value' ); + + t.end(); +}); + +tape( 'the created function returns the smallest `x` such that `F(x) >= p` when `p*(b-a+1)` is an integer', function test( t ) { + var quantile; + var a; + var n; + var k; + var y; + + for ( a = -3; a <= 3; a += 3 ) { + for ( n = 1; n <= 10; n++ ) { + quantile = factory( a, a+n-1 ); + for ( k = 1; k <= n; k++ ) { + y = quantile( k/n ); + t.strictEqual( y, a+k-1, 'a: '+a+', b: '+(a+n-1)+', p: '+(k/n)+', y: '+y+', expected: '+(a+k-1) ); + } + } + } + t.end(); +}); + tape( 'the created function evaluates the quantile for `p` given a small range `b - a`', function test( t ) { var expected; var quantile; diff --git a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/test/test.native.js b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/test/test.native.js index 0c06f6cb3ff1..072e6a60938d 100644 --- a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/test/test.native.js +++ b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/test/test.native.js @@ -77,6 +77,31 @@ tape( 'if provided `a > b`, the function returns `NaN`', opts, function test( t t.end(); }); +tape( 'if provided `p = 0`, the function returns `a`, and if provided `p = 1`, the function returns `b`', opts, function test( t ) { + t.strictEqual( quantile( 0.0, 2, 5 ), 2, 'returns expected value' ); + t.strictEqual( quantile( 1.0, 2, 5 ), 5, 'returns expected value' ); + t.strictEqual( quantile( 0.0, -3, -3 ), -3, 'returns expected value' ); + t.strictEqual( quantile( 1.0, -3, -3 ), -3, 'returns expected value' ); + t.end(); +}); + +tape( 'the function returns the smallest `x` such that `F(x) >= p` when `p*(b-a+1)` is an integer', opts, function test( t ) { + var a; + var n; + var k; + var y; + + for ( a = -3; a <= 3; a += 3 ) { + for ( n = 1; n <= 10; n++ ) { + for ( k = 1; k <= n; k++ ) { + y = quantile( k/n, a, a+n-1 ); + t.strictEqual( y, a+k-1, 'a: '+a+', b: '+(a+n-1)+', p: '+(k/n)+', y: '+y+', expected: '+(a+k-1) ); + } + } + } + t.end(); +}); + tape( 'the function evaluates the quantile for `p` given a small range `b - a`', opts, function test( t ) { var expected; var delta; diff --git a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/test/test.quantile.js b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/test/test.quantile.js index 67ffc297b1e4..75d278cd0449 100644 --- a/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/test/test.quantile.js +++ b/lib/node_modules/@stdlib/stats/base/dists/discrete-uniform/quantile/test/test.quantile.js @@ -89,6 +89,31 @@ tape( 'if provided a non-integer value for `a` or `b`, the function returns `NaN t.end(); }); +tape( 'if provided `p = 0`, the function returns `a`, and if provided `p = 1`, the function returns `b`', function test( t ) { + t.strictEqual( quantile( 0.0, 2, 5 ), 2, 'returns expected value' ); + t.strictEqual( quantile( 1.0, 2, 5 ), 5, 'returns expected value' ); + t.strictEqual( quantile( 0.0, -3, -3 ), -3, 'returns expected value' ); + t.strictEqual( quantile( 1.0, -3, -3 ), -3, 'returns expected value' ); + t.end(); +}); + +tape( 'the function returns the smallest `x` such that `F(x) >= p` when `p*(b-a+1)` is an integer', function test( t ) { + var a; + var n; + var k; + var y; + + for ( a = -3; a <= 3; a += 3 ) { + for ( n = 1; n <= 10; n++ ) { + for ( k = 1; k <= n; k++ ) { + y = quantile( k/n, a, a+n-1 ); + t.strictEqual( y, a+k-1, 'a: '+a+', b: '+(a+n-1)+', p: '+(k/n)+', y: '+y+', expected: '+(a+k-1) ); + } + } + } + t.end(); +}); + tape( 'the function evaluates the quantile for `p` given a small range `b - a`', function test( t ) { var expected; var delta;