175 lines
3.7 KiB
JavaScript
175 lines
3.7 KiB
JavaScript
/**
|
||
* @license Apache-2.0
|
||
*
|
||
* Copyright (c) 2018 The Stdlib Authors.
|
||
*
|
||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
* you may not use this file except in compliance with the License.
|
||
* You may obtain a copy of the License at
|
||
*
|
||
* http://www.apache.org/licenses/LICENSE-2.0
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software
|
||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
* See the License for the specific language governing permissions and
|
||
* limitations under the License.
|
||
*/
|
||
|
||
'use strict';
|
||
|
||
// MODULES //
|
||
|
||
var floor = require( '@stdlib/math/base/special/floor' );
|
||
var sqrt = require( '@stdlib/math/base/special/sqrt' );
|
||
var pow = require( '@stdlib/math/base/special/pow' );
|
||
var exp = require( '@stdlib/math/base/special/exp' );
|
||
var Float64Array = require( '@stdlib/array/float64' );
|
||
|
||
|
||
// MAIN //
|
||
|
||
/**
|
||
* Evaluates the Kolmogorov distribution. This function is a JavaScript implementation of a procedure developed by Marsaglia & Tsang.
|
||
*
|
||
* ## References
|
||
*
|
||
* - Marsaglia, George, Wai Wan Tsang, and Jingbo Wang. 2003. "Evaluating Kolmogorov's Distribution." _Journal of Statistical Software_ 8 (18): 1–4. doi:[10.18637/jss.v008.i18](https://doi.org/10.18637/jss.v008.i18).
|
||
*
|
||
* @private
|
||
* @param {number} d - the argument of the CDF of D_n
|
||
* @param {number} n - number of variates
|
||
* @returns {number} evaluated CDF, i.e. P( D_n < d )
|
||
*/
|
||
function pKolmogorov( d, n ) {
|
||
var eH;
|
||
var eQ;
|
||
var h;
|
||
var H;
|
||
var Q;
|
||
var g;
|
||
var i;
|
||
var j;
|
||
var k;
|
||
var m;
|
||
var s;
|
||
|
||
s = d * d * n;
|
||
if ( s > 7.24 || ( s > 3.76 && n > 99 ) ) {
|
||
return 1 - (2 * exp( -( 2.000071 + (0.331/sqrt(n)) + (1.409/n) ) * s ));
|
||
}
|
||
k = floor( n * d ) + 1;
|
||
m = (2*k) - 1;
|
||
h = k - (n*d);
|
||
H = new Float64Array( m * m );
|
||
Q = new Float64Array( m * m );
|
||
for ( i = 0; i < m; i++ ) {
|
||
for ( j = 0; j < m; j++ ) {
|
||
if ( i - j + 1 < 0 ) {
|
||
H[ (i*m) + j ] = 0;
|
||
} else {
|
||
H[ (i*m) + j ] = 1;
|
||
}
|
||
}
|
||
}
|
||
for ( i = 0; i < m; i++ ) {
|
||
H[ i * m ] -= pow( h, i+1 );
|
||
H[ ((m-1) * m) + i ] -= pow( h, (m-i) );
|
||
}
|
||
H[ (m-1) * m ] += ( ( (2*h)-1 > 0 ) ? pow( (2*h)-1, m ) : 0 );
|
||
for ( i = 0; i < m; i++ ) {
|
||
for ( j = 0; j < m; j++ ) {
|
||
if ( i - j + 1 > 0 ) {
|
||
for ( g = 1; g <= i - j + 1; g++ ) {
|
||
H[ (i*m) + j ] /= g;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
eH = 0;
|
||
mpow( H, eH, n );
|
||
s = Q[ ((k-1) * m) + k - 1 ];
|
||
for ( i = 1; i <= n; i++ ) {
|
||
s = s * i / n;
|
||
if ( s < 1e-140 ) {
|
||
s *= 1e140;
|
||
eQ -= 140;
|
||
}
|
||
}
|
||
s *= pow( 10, eQ );
|
||
return s;
|
||
|
||
/**
|
||
* Matrix exponentiation. Mutates Q matrix.
|
||
*
|
||
* @private
|
||
* @param {Float64Array} A - input matrix
|
||
* @param {number} eA - matrix power
|
||
* @param {number} n - number of variates
|
||
*/
|
||
function mpow( A, eA, n ) {
|
||
var eB;
|
||
var B;
|
||
var i;
|
||
|
||
if ( n === 1 ) {
|
||
for ( i = 0; i < m*m; i++ ) {
|
||
Q[ i ] = A[ i ];
|
||
eQ = eA;
|
||
}
|
||
return;
|
||
}
|
||
mpow( A, eA, floor( n/2 ) );
|
||
B = mmult( Q, Q );
|
||
eB = 2 * eQ;
|
||
if ( n % 2 === 0 ) {
|
||
for ( i = 0; i < m*m; i++ ) {
|
||
Q[ i ] = B[ i ];
|
||
}
|
||
eQ = eB;
|
||
} else {
|
||
Q = mmult( A, B );
|
||
eQ = eA + eB;
|
||
}
|
||
if ( Q[ (floor(m/2) * m) + floor(m/2) ] > 1e140 ) {
|
||
for ( i = 0; i < m*m; i++ ) {
|
||
Q[ i ] *= 1e-140;
|
||
}
|
||
eQ += 140;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Multiply matrices x and y.
|
||
*
|
||
* @private
|
||
* @param {Float64Array} x - first input matrix
|
||
* @param {Float64Array} y - second input matrix
|
||
* @returns {Float64Array} matrix product
|
||
*/
|
||
function mmult( x, y ) {
|
||
var i;
|
||
var j;
|
||
var k;
|
||
var s;
|
||
var z;
|
||
|
||
z = new Float64Array( m * m );
|
||
for ( i = 0; i < m; i++) {
|
||
for ( j = 0; j < m; j++ ) {
|
||
s = 0;
|
||
for ( k = 0; k < m; k++ ) {
|
||
s += x[ (i*m) + k ] * y[ (k*m) + j ];
|
||
z[ (i*m) + j ] = s;
|
||
}
|
||
}
|
||
}
|
||
return z;
|
||
}
|
||
}
|
||
|
||
|
||
// EXPORTS //
|
||
|
||
module.exports = pKolmogorov;
|