Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ var y = quantile( 0.4, -1.0 );
// returns NaN
```

If provided `lambda` equal to `+Infinity`, the function returns `NaN`.

```javascript
var y = quantile( 0.4, Infinity );
// returns NaN
```

If provided `lambda = 0`, the function evaluates the [quantile function][quantile-function] of a [degenerate distribution][degenerate-distribution] centered at `0.0`.

```javascript
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

If provided a negative value for `λ`, the function returns `NaN`.

If provided `λ` equal to positive infinity, the function returns `NaN`.

Parameters
----------
p: number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function factory( lambda ) {
var sigmaInv;
var sigma;

if ( isnan( lambda ) || lambda < 0.0 ) {
if ( isnan( lambda ) || lambda < 0.0 || lambda === PINF ) {
return constantFunction( NaN );
}
if ( lambda === 0.0 ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ var search = require( './search.js' );
* @example
* var y = quantile( 0.0, NaN );
* // returns NaN
*
* @example
* var y = quantile( 0.5, Infinity );
* // returns NaN
*/
function quantile( p, lambda ) {
var sigmaInv;
Expand All @@ -74,7 +78,7 @@ function quantile( p, lambda ) {
var corr;
var x2;
var x;
if ( isnan( lambda ) || lambda < 0.0 ) {
if ( isnan( lambda ) || lambda < 0.0 || lambda === PINF ) {
return NaN;
}
if ( isnan( p ) || p < 0.0 || p > 1.0 ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ var addon = require( './../src/addon.node' );
* // returns NaN
*
* @example
* var y = quantile( 0.5, Infinity );
* // returns NaN
*
* @example
* var y = quantile( 0.5, -1.0 );
* // returns NaN
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,18 @@ var methods;
* @returns {NonNegativeInteger} `p` quantile of the specified distribution
*/
function searchLeft( x, p, lambda ) {
var xp;
while ( true ) {
if ( x === 0 || cdf( x - 1.0, lambda ) < p ) {
return x;
}
x -= 1;
xp = x - 1.0;

// Guard against non-advancing updates (e.g., when `x` is `NaN` or is so large that decrementing does not change its value) in order to avoid an infinite loop:
if ( !( xp < x ) ) {
return x;
}
x = xp;
}
}

Expand All @@ -58,8 +65,15 @@ function searchLeft( x, p, lambda ) {
* @returns {NonNegativeInteger} `p` quantile of the specified distribution
*/
function searchRight( x, p, lambda ) {
var xn;
while ( true ) {
x += 1;
xn = x + 1.0;

// Guard against non-advancing updates (e.g., when `x` is `NaN` or is so large that incrementing does not change its value) in order to avoid an infinite loop:
if ( !( xn > x ) ) {
return x;
}
x = xn;
if ( cdf( x, lambda ) >= p ) {
return x;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,15 @@
* @return `p` quantile of the specified distribution
*/
static double search_left( double x, const double p, const double lambda ) {
double xp;
while ( x > 0.0 && stdlib_base_dists_poisson_cdf( x - 1.0, lambda ) >= p ) {
x -= 1.0;
xp = x - 1.0;

// Guard against non-advancing updates (e.g., when `x` is `NaN` or is so large that decrementing does not change its value) in order to avoid an infinite loop:
if ( !( xp < x ) ) {
return x;
}
x = xp;
}
return x;
}
Expand All @@ -49,9 +56,16 @@ static double search_left( double x, const double p, const double lambda ) {
* @return `p` quantile of the specified distribution
*/
static double search_right( double x, const double p, const double lambda ) {
x += 1.0;
while ( stdlib_base_dists_poisson_cdf( x, lambda ) < p ) {
x += 1.0;
double xn;

// Guard against non-advancing updates (e.g., when `x` is `NaN` or is so large that incrementing does not change its value) in order to avoid an infinite loop:
xn = x + 1.0;
while ( xn > x ) {
x = xn;
if ( stdlib_base_dists_poisson_cdf( x, lambda ) >= p ) {
return x;
}
xn = x + 1.0;
}
return x;
}
Expand All @@ -75,7 +89,11 @@ double stdlib_base_dists_poisson_quantile( const double p, const double lambda )
double x2;
double x;

if ( stdlib_base_is_nan( lambda ) || lambda < 0.0 ) {
if (
stdlib_base_is_nan( lambda ) ||
lambda < 0.0 ||
lambda == STDLIB_CONSTANT_FLOAT64_PINF
) {
return 0.0 / 0.0; // NaN
}
if ( stdlib_base_is_nan( p ) || p < 0.0 || p > 1.0 ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,36 @@ tape( 'if provided a negative `lambda`, the created function always returns `NaN
t.end();
});

tape( 'if provided `lambda` equal to `+infinity`, the created function always returns `NaN`', function test( t ) {
var quantile;
var y;

quantile = factory( PINF );

y = quantile( 0.5 );
t.strictEqual( isnan( y ), true, 'returns expected value' );

y = quantile( 0.9 );
t.strictEqual( isnan( y ), true, 'returns expected value' );

t.end();
});

tape( 'the created function terminates for very large `lambda` for which unit increments can no longer advance the search', function test( t ) {
var quantile;
var y;

quantile = factory( 1.0e300 );

y = quantile( 0.9 );
t.strictEqual( y, 1.0e300, 'returns expected value' );

y = quantile( 0.1 );
t.strictEqual( y, 1.0e300, 'returns expected value' );

t.end();
});

tape( 'if provided a finite `lambda`, the created function returns `0` for `p = 0`', function test( t ) {
var quantile = factory( 3.0 );
var y = quantile( 0.0 );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,30 @@ tape( 'if provided a negative `lambda`, the function always returns `NaN`', func
t.end();
});

tape( 'if provided `lambda` equal to `+infinity`, the function returns `NaN`', function test( t ) {
var y;

y = quantile( 0.5, PINF );
t.strictEqual( isnan( y ), true, 'returns expected value' );

y = quantile( 0.0, PINF );
t.strictEqual( isnan( y ), true, 'returns expected value' );

t.end();
});

tape( 'the function terminates for very large `lambda` for which unit increments can no longer advance the search', function test( t ) {
var y;

y = quantile( 0.9, 1.0e300 );
t.strictEqual( y, 1.0e300, 'returns expected value' );

y = quantile( 0.1, 1.0e300 );
t.strictEqual( y, 1.0e300, 'returns expected value' );

t.end();
});

tape( 'if provided a `lambda` equal to `0`, the function always returns `0`', function test( t ) {
var y;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,30 @@ tape( 'if provided a negative `lambda`, the function always returns `NaN`', opts
t.end();
});

tape( 'if provided `lambda` equal to `+infinity`, the function returns `NaN`', opts, function test( t ) {
var y;

y = quantile( 0.5, PINF );
t.strictEqual( isnan( y ), true, 'returns expected value' );

y = quantile( 0.0, PINF );
t.strictEqual( isnan( y ), true, 'returns expected value' );

t.end();
});

tape( 'the function terminates for very large `lambda` for which unit increments can no longer advance the search', opts, function test( t ) {
var y;

y = quantile( 0.9, 1.0e300 );
t.strictEqual( y, 1.0e300, 'returns expected value' );

y = quantile( 0.1, 1.0e300 );
t.strictEqual( y, 1.0e300, 'returns expected value' );

t.end();
});

tape( 'if provided a `lambda` equal to `0`, the function always returns `0`', opts, function test( t ) {
var y;

Expand Down