Skip to content

fix: update C implementation for stats/base/dists/kumaraswamy/median #5452

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 1, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ for ( i = 0; i < 10; i++ ) {
Returns the [median][median] of a [Kumaraswamy's double bounded][kumaraswamy-distribution] distribution with first shape parameter `a` and second shape parameter `b`.

```c
double out = stdlib_base_dists_kumaraswamy_median( 2.0, 3.0 );
// returns ~1.817
double out = stdlib_base_dists_kumaraswamy_median( 1.0, 1.0 );
// returns 0.5
```

The function accepts the following arguments:
Expand Down Expand Up @@ -212,7 +212,7 @@ double stdlib_base_dists_kumaraswamy_median( const double a, const double b );

static double random_uniform( const double min, const double max ) {
double v = (double)rand() / ( (double)RAND_MAX + 1.0 );
return min + ( v * (max - min) );
return min + ( v*(max-min) );
}

int main( void ) {
Expand All @@ -225,7 +225,7 @@ int main( void ) {
a = random_uniform( 0.1, 10.0 );
b = random_uniform( 0.1, 10.0 );
y = stdlib_base_dists_kumaraswamy_median( a, b );
printf( "a: %lf, b: %lf, Median(a, b): %lf\n", a, b, y );
printf( "a: %lf, b: %lf, Median(X;a,b): %lf\n", a, b, y );
}

return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

var bench = require( '@stdlib/bench' );
var Float64Array = require( '@stdlib/array/float64' );
var randu = require( '@stdlib/random/base/randu' );
var uniform = require( '@stdlib/random/base/uniform' );
var isnan = require( '@stdlib/math/base/assert/is-nan' );
var EPS = require( '@stdlib/constants/float64/eps' );
var pkg = require( './../package.json' ).name;
Expand All @@ -42,8 +42,8 @@ bench( pkg, function benchmark( b ) {
alpha = new Float64Array( len );
beta = new Float64Array( len );
for ( i = 0; i < len; i++ ) {
alpha[ i ] = ( randu() * 10.0 ) + EPS;
beta[ i ] = ( randu() * 10.0 ) + EPS;
alpha[ i ] = uniform( EPS, 10.0 );
beta[ i ] = uniform( EPS, 10.0 );
}

b.tic();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
var resolve = require( 'path' ).resolve;
var bench = require( '@stdlib/bench' );
var Float64Array = require( '@stdlib/array/float64' );
var randu = require( '@stdlib/random/base/randu' );
var uniform = require( '@stdlib/random/base/uniform' );
var EPS = require( '@stdlib/constants/float64/eps' );
var isnan = require( '@stdlib/math/base/assert/is-nan' );
var tryRequire = require( '@stdlib/utils/try-require' );
Expand Down Expand Up @@ -51,8 +51,8 @@ bench( pkg+'::native', opts, function benchmark( b ) {
alpha = new Float64Array( len );
beta = new Float64Array( len );
for ( i = 0; i < len; i++ ) {
alpha[ i ] = ( randu() * 10.0 ) + EPS;
beta[ i ] = ( randu() * 10.0 ) + EPS;
alpha[ i ] = uniform( EPS, 10.0 );
beta[ i ] = uniform( EPS, 10.0 );
}

b.tic();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ static double random_uniform( const double min, const double max ) {
* @return elapsed time in seconds
*/
static double benchmark( void ) {
double elapsed;
double a[ 100 ];
double b[ 100 ];
double elapsed;
double y;
double t;
int i;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ int main( void ) {
b = random_uniform( 0.1, 10.0 );

y = stdlib_base_dists_kumaraswamy_median( a, b );
printf( "a: %lf, b: %lf, Median(a,b): %lf\n", a, b, y );
printf( "a: %lf, b: %lf, Median(X;a,b): %lf\n", a, b, y );
}

return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ extern "C" {
#endif

/**
* Returns the median of a Kumaraswamy distribution.
* Returns the median of a Kumaraswamy's double bounded distribution.
*/
double stdlib_base_dists_kumaraswamy_median( const double a, const double b );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,39 @@ var addon = require( './../src/addon.node' );
// MAIN //

/**
* Returns the median of a Kumaraswamy distribution.
* Returns the median of a Kumaraswamy's double bounded distribution.
*
* @private
* @param {number} a - shape parameter
* @param {number} b - shape parameter
* @returns {number} median
* @param {PositiveNumber} a - first shape parameter
* @param {PositiveNumber} b - second shape parameter
* @returns {PositiveNumber} median
*
* @example
* var v = median( 2.0, 3.0 );
* // returns ~0.2062994740159002
* var v = median( 0.5, 1.0 );
* // returns 0.25
*
* @example
* var v = median( 1.0, 5.0 );
* // returns ~0.12944943670387588
* var v = median( 4.0, 12.0 );
* // returns ~0.487
*
* @example
* var v = median( 2.0, -0.5 );
* var v = median( 12.0, 2.0 );
* // returns ~0.903
*
* @example
* var v = median( 1.0, -0.1 );
* // returns NaN
*
* @example
* var v = median( -0.1, 1.0 );
* // returns NaN
*
* @example
* var v = median( 2.0, NaN );
* // returns NaN
*
* @example
* var v = median( NaN, 2.0 );
* // returns NaN
*/
function median( a, b ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@
"dependencies": [
"@stdlib/math/base/napi/binary",
"@stdlib/math/base/assert/is-nan",
"@stdlib/math/base/special/pow",
"@stdlib/constants/float64/eps"
"@stdlib/math/base/special/pow"
]
},
{
Expand Down Expand Up @@ -74,8 +73,7 @@
"libpath": [],
"dependencies": [
"@stdlib/math/base/assert/is-nan",
"@stdlib/math/base/special/pow",
"@stdlib/constants/float64/eps"
"@stdlib/math/base/special/pow"
]
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@
#include "stdlib/math/base/special/pow.h"

/**
* Returns the median of a Kumaraswamy distribution.
* Returns the median of a Kumaraswamy's double bounded distribution.
*
* @param a first shape parameter
* @param b second shape parameter
* @return median
*
* @example
* double y = stdlib_base_dists_kumaraswamy_median( 2.0, 3.0 );
* // returns 1.0
* double y = stdlib_base_dists_kumaraswamy_median( 0.5, 1.0 );
* // returns 0.25
*/
double stdlib_base_dists_kumaraswamy_median( const double a, const double b ) {
if (
Expand All @@ -39,5 +39,5 @@ double stdlib_base_dists_kumaraswamy_median( const double a, const double b ) {
) {
return 0.0/0.0; // NaN
}
return 1.0 - stdlib_base_pow( 0.5, 1.0 / b );
return stdlib_base_pow( 1.0 - stdlib_base_pow( 2.0, -1.0/b ), 1.0/a );
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ Generate fixture data and write to file.

# Arguments

* `a`: shape parameter a (must be positive)
* `b`: shape parameter b (must be positive)
* `a`: first shape parameter
* `b`: second shape parameter
* `name::AbstractString`: output filename

# Examples
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ tape( 'main export is a function', function test( t ) {

tape( 'if provided `NaN` for any parameter, the function returns `NaN`', function test( t ) {
var v = median( NaN, 0.5 );
t.equal( isnan( v ), true, 'returns NaN' );
t.equal( isnan( v ), true, 'returns expected value' );

v = median( 10.0, NaN );
t.equal( isnan( v ), true, 'returns NaN' );
t.equal( isnan( v ), true, 'returns expected value' );

t.end();
});
Expand All @@ -56,25 +56,25 @@ tape( 'if provided a nonpositive `a`, the function returns `NaN`', function test
var y;

y = median( 0.0, 2.0 );
t.equal( isnan( y ), true, 'returns NaN' );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( -1.0, 2.0 );
t.equal( isnan( y ), true, 'returns NaN' );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( -1.0, 2.0 );
t.equal( isnan( y ), true, 'returns NaN' );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( NINF, 1.0 );
t.equal( isnan( y ), true, 'returns NaN' );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( NINF, PINF );
t.equal( isnan( y ), true, 'returns NaN' );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( NINF, NINF );
t.equal( isnan( y ), true, 'returns NaN' );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( NINF, NaN );
t.equal( isnan( y ), true, 'returns NaN' );
t.equal( isnan( y ), true, 'returns expected value' );

t.end();
});
Expand All @@ -83,25 +83,25 @@ tape( 'if provided a nonpositive `b`, the function returns `NaN`', function test
var y;

y = median( 2.0, 0.0 );
t.equal( isnan( y ), true, 'returns NaN' );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( 2.0, -1.0 );
t.equal( isnan( y ), true, 'returns NaN' );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( 2.0, -1/0 );
t.equal( isnan( y ), true, 'returns NaN' );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( 1.0, NINF );
t.equal( isnan( y ), true, 'returns NaN' );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( PINF, NINF );
t.equal( isnan( y ), true, 'returns NaN' );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( NINF, NINF );
t.equal( isnan( y ), true, 'returns NaN' );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( NaN, NINF );
t.equal( isnan( y ), true, 'returns NaN' );
t.equal( isnan( y ), true, 'returns expected value' );

t.end();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,31 +53,64 @@ tape( 'main export is a function', opts, function test( t ) {

tape( 'if provided `NaN` for any parameter, the function returns `NaN`', opts, function test( t ) {
var v = median( NaN, 0.5 );
t.equal( isnan( v ), true, 'returns NaN' );
t.equal( isnan( v ), true, 'returns expected value' );

v = median( 10, NaN );
t.equal( isnan( v ), true, 'returns NaN' );
v = median( 10.0, NaN );
t.equal( isnan( v ), true, 'returns expected value' );

v = median( NaN, NaN );
t.equal( isnan( v ), true, 'returns NaN' );
t.end();
});

tape( 'if provided a nonpositive `a`, the function returns `NaN`', opts, function test( t ) {
var y;

y = median( 0.0, 2.0 );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( -1.0, 2.0 );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( -1.0, 2.0 );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( NINF, 1.0 );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( NINF, PINF );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( NINF, NINF );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( NINF, NaN );
t.equal( isnan( y ), true, 'returns expected value' );

t.end();
});

tape( 'if provided a nonpositive `gamma`, the function always returns `NaN`', opts, function test( t ) {
tape( 'if provided a nonpositive `b`, the function returns `NaN`', opts, function test( t ) {
var y;

y = median( 0.0, 0.0 );
t.equal( isnan( y ), true, 'returns NaN' );
y = median( 2.0, 0.0 );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( 0.0, -1.0 );
t.equal( isnan( y ), true, 'returns NaN' );
y = median( 2.0, -1.0 );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( 0.0, NINF );
t.equal( isnan( y ), true, 'returns NaN' );
y = median( 2.0, -1/0 );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( 1.0, NINF );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( PINF, NINF );
t.equal( isnan( y ), true, 'returns NaN' );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( NINF, NINF );
t.equal( isnan( y ), true, 'returns expected value' );

y = median( NaN, NINF );
t.equal( isnan( y ), true, 'returns expected value' );

t.end();
});
Expand Down