Skip to content
Open
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 @@ -23,7 +23,7 @@
var constantFunction = require( '@stdlib/utils/constant-function' );
var degenerate = require( '@stdlib/stats/base/dists/degenerate/cdf' ).factory;
var isnan = require( '@stdlib/math/base/assert/is-nan' );
var exp = require( '@stdlib/math/base/special/exp' );
var expm1 = require( '@stdlib/math/base/special/expm1' );
var pow = require( '@stdlib/math/base/special/pow' );


Expand All @@ -44,14 +44,12 @@ var pow = require( '@stdlib/math/base/special/pow' );
* // returns ~0.118
*/
function factory( sigma ) {
var s2;
if ( isnan( sigma ) || sigma < 0.0 ) {
return constantFunction( NaN );
}
if ( sigma === 0.0 ) {
return degenerate( 0.0 );
}
s2 = pow( sigma, 2.0 );
return cdf;

/**
Expand All @@ -72,7 +70,7 @@ function factory( sigma ) {
if ( x < 0.0 ) {
return 0.0;
}
return 1.0 - exp( -pow( x, 2.0 ) / ( 2.0 * s2 ) );
return -expm1( -0.5 * pow( x / sigma, 2.0 ) );
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
// MODULES //

var isnan = require( '@stdlib/math/base/assert/is-nan' );
var exp = require( '@stdlib/math/base/special/exp' );
var expm1 = require( '@stdlib/math/base/special/expm1' );
var pow = require( '@stdlib/math/base/special/pow' );


Expand Down Expand Up @@ -60,7 +60,6 @@ var pow = require( '@stdlib/math/base/special/pow' );
* // returns NaN
*/
function cdf( x, sigma ) {
var s2;
if (
isnan( x ) ||
isnan( sigma ) ||
Expand All @@ -74,8 +73,7 @@ function cdf( x, sigma ) {
if ( x < 0.0 ) {
return 0.0;
}
s2 = pow( sigma, 2.0 );
return 1.0 - exp( -pow( x, 2.0 ) / ( 2.0 * s2 ) );
return -expm1( -0.5 * pow( x / sigma, 2.0 ) );
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"dependencies": [
"@stdlib/math/base/napi/binary",
"@stdlib/math/base/assert/is-nan",
"@stdlib/math/base/special/exp",
"@stdlib/math/base/special/expm1",
"@stdlib/math/base/special/pow"
]
},
Expand All @@ -57,7 +57,7 @@
"libpath": [],
"dependencies": [
"@stdlib/math/base/assert/is-nan",
"@stdlib/math/base/special/exp",
"@stdlib/math/base/special/expm1",
"@stdlib/constants/float64/eps",
"@stdlib/math/base/special/pow"
]
Expand All @@ -75,7 +75,7 @@
"libpath": [],
"dependencies": [
"@stdlib/math/base/assert/is-nan",
"@stdlib/math/base/special/exp",
"@stdlib/math/base/special/expm1",
"@stdlib/math/base/special/pow"
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

#include "stdlib/stats/base/dists/rayleigh/cdf.h"
#include "stdlib/math/base/assert/is_nan.h"
#include "stdlib/math/base/special/exp.h"
#include "stdlib/math/base/special/expm1.h"
#include "stdlib/math/base/special/pow.h"

/**
Expand All @@ -33,7 +33,6 @@
* // returns ~0.199
*/
double stdlib_base_dists_rayleigh_cdf( const double x, const double sigma ) {
double s2;
if (
stdlib_base_is_nan( x ) ||
stdlib_base_is_nan( sigma ) ||
Expand All @@ -47,6 +46,5 @@ double stdlib_base_dists_rayleigh_cdf( const double x, const double sigma ) {
if ( x < 0.0 ) {
return 0.0;
}
s2 = stdlib_base_pow( sigma, 2.0 );
return 1.0 - stdlib_base_exp( -stdlib_base_pow( x, 2.0 ) / ( 2.0 * s2 ) );
return -stdlib_base_expm1( -0.5 * stdlib_base_pow( x / sigma, 2.0 ) );
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
Distributions 0.23.8
julia 1.5
JSON 0.21

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import Distributions: cdf, Rayleigh
import JSON

"""
Expand All @@ -39,9 +38,9 @@ julia> gen( x, sigma, \"data.json\" );
```
"""
function gen( x, sigma, name )
z = Array{Float64}( undef, length(x) );
for i in eachindex(x)
z[ i ] = cdf( Rayleigh( sigma[i] ), x[i] );
# The CDF is evaluated in extended precision using the textbook formula `1 - exp(-x^2 / (2*sigma^2))`, as subtracting the exponential from `1` in double precision cancels for small `x/sigma`...
z = setprecision( BigFloat, 2048 ) do
Float64.( 1 .- exp.( .-( BigFloat.( x ) .^ 2 ) ./ ( 2 .* BigFloat.( sigma ) .^ 2 ) ) );
end
Comment on lines 40 to 44

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
function gen( x, sigma, name )
z = Array{Float64}( undef, length(x) );
for i in eachindex(x)
z[ i ] = cdf( Rayleigh( sigma[i] ), x[i] );
z = setprecision( BigFloat, 2048 ) do
Float64.( 1 .- exp.( .-( BigFloat.( x ) .^ 2 ) ./ ( 2 .* BigFloat.( sigma ) .^ 2 ) ) )
end
function gen( x, sigma, name )
# The CDF is evaluated in extended precision using the textbook formula `1 - exp(-x^2 / (2*sigma^2))`, as subtracting the exponential from `1` in double precision cancels for small `x/sigma`...
z = setprecision( BigFloat, 2048 ) do
Float64.( 1 .- exp.( .-( BigFloat.( x ) .^ 2 ) ./ ( 2 .* BigFloat.( sigma ) .^ 2 ) ) );
end

And drop the docstring paragraph at line 26. Matches kgryte's follow-up commits to runner.jl in #15774.


# Store data to be written to file as a collection:
Expand Down Expand Up @@ -81,3 +80,8 @@ gen( x, sigma, "medium_scale.json" );
x = rand( 1000 ) .* 20.0;
sigma = rand( 1000 ) .* 5.0;
gen( x, sigma, "small_scale.json" );

# Small `x`:
sigma = exp10.( ( rand( 1000 ) .* 400.0 ) .- 200.0 );
x = sigma .* exp10.( range( -150.0, stop = -1.0, length = 1000 ) );
gen( x, sigma, "small_x.json" );
Comment on lines +84 to +87

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Small `x`:
x = exp10.( range( -150.0, stop = -1.0, length = 1000 ) );
sigma = ( rand( 1000 ) .* 10.0 ) .+ 0.1;
gen( x, sigma, "small_x.json" );
# Small `x`:
sigma = exp10.( ( rand( 1000 ) .* 400.0 ) .- 200.0 );
x = sigma .* exp10.( range( -150.0, stop = -1.0, length = 1000 ) );
gen( x, sigma, "small_x.json" );

With sigma in [0.1, 10.1] this fixture can't catch the issue above. With this range the current code fails 415/1000 points at 2 ULP (115 NaN), the ratio version none.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var cdf = require( './../lib' );
var smallScale = require( './fixtures/julia/small_scale.json' );
var mediumScale = require( './fixtures/julia/medium_scale.json' );
var largeScale = require( './fixtures/julia/large_scale.json' );
var smallX = require( './fixtures/julia/small_x.json' );


// TESTS //
Expand Down Expand Up @@ -102,7 +103,7 @@ tape( 'the function evaluates the cdf for `x` given small scale parameter `sigma
sigma = smallScale.sigma;
for ( i = 0; i < x.length; i++ ) {
y = cdf( x[i], sigma[i] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 0 ), true, 'returns expected value' );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});
Expand All @@ -119,7 +120,7 @@ tape( 'the function evaluates the cdf for `x` given medium scale parameter `sigm
sigma = mediumScale.sigma;
for ( i = 0; i < x.length; i++ ) {
y = cdf( x[i], sigma[i] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 0 ), true, 'returns expected value' );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});
Expand All @@ -136,7 +137,24 @@ tape( 'the function evaluates the cdf for `x` given large scale parameter `sigma
sigma = largeScale.sigma;
for ( i = 0; i < x.length; i++ ) {
y = cdf( x[i], sigma[i] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 0 ), true, 'returns expected value' );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});

tape( 'the function evaluates the cdf for small `x`', function test( t ) {
var expected;
var sigma;
var i;
var x;
var y;

expected = smallX.expected;
x = smallX.x;
sigma = smallX.sigma;
for ( i = 0; i < expected.length; i++ ) {
y = cdf( x[i], sigma[i] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var factory = require( './../lib/factory.js' );
var smallScale = require( './fixtures/julia/small_scale.json' );
var mediumScale = require( './fixtures/julia/medium_scale.json' );
var largeScale = require( './fixtures/julia/large_scale.json' );
var smallX = require( './fixtures/julia/small_x.json' );


// TESTS //
Expand Down Expand Up @@ -137,7 +138,7 @@ tape( 'the created function evaluates the cdf for `x` given small scale paramete
for ( i = 0; i < x.length; i++ ) {
cdf = factory( sigma[i] );
y = cdf( x[i] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 0 ), true, 'returns expected value' );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});
Expand All @@ -156,7 +157,7 @@ tape( 'the created function evaluates the cdf for `x` given medium scale paramet
for ( i = 0; i < x.length; i++ ) {
cdf = factory( sigma[i] );
y = cdf( x[i] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 0 ), true, 'returns expected value' );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});
Expand All @@ -175,7 +176,26 @@ tape( 'the created function evaluates the cdf for `x` given large scale paramete
for ( i = 0; i < x.length; i++ ) {
cdf = factory( sigma[i] );
y = cdf( x[i] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 0 ), true, 'returns expected value' );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});

tape( 'the created function evaluates the cdf for small `x`', function test( t ) {
var expected;
var sigma;
var cdf;
var i;
var x;
var y;

expected = smallX.expected;
x = smallX.x;
sigma = smallX.sigma;
for ( i = 0; i < expected.length; i++ ) {
cdf = factory( sigma[i] );
y = cdf( x[i] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ var NINF = require( '@stdlib/constants/float64/ninf' );
var smallScale = require( './fixtures/julia/small_scale.json' );
var mediumScale = require( './fixtures/julia/medium_scale.json' );
var largeScale = require( './fixtures/julia/large_scale.json' );
var smallX = require( './fixtures/julia/small_x.json' );


// VARIABLES //
Expand Down Expand Up @@ -111,7 +112,7 @@ tape( 'the function evaluates the cdf for `x` given small scale parameter `sigma
sigma = smallScale.sigma;
for ( i = 0; i < x.length; i++ ) {
y = cdf( x[i], sigma[i] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 0 ), true, 'returns expected value' );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});
Expand All @@ -128,7 +129,7 @@ tape( 'the function evaluates the cdf for `x` given medium scale parameter `sigm
sigma = mediumScale.sigma;
for ( i = 0; i < x.length; i++ ) {
y = cdf( x[i], sigma[i] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 0 ), true, 'returns expected value' );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});
Expand All @@ -145,7 +146,24 @@ tape( 'the function evaluates the cdf for `x` given large scale parameter `sigma
sigma = largeScale.sigma;
for ( i = 0; i < x.length; i++ ) {
y = cdf( x[i], sigma[i] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 0 ), true, 'returns expected value' );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});

tape( 'the function evaluates the cdf for small `x`', opts, function test( t ) {
var expected;
var sigma;
var i;
var x;
var y;

expected = smallX.expected;
x = smallX.x;
sigma = smallX.sigma;
for ( i = 0; i < expected.length; i++ ) {
y = cdf( x[i], sigma[i] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});
Loading