Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/**
* @license Apache-2.0
*
* Copyright (c) 2026 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 bench = require( '@stdlib/bench' );
var uniform = require( '@stdlib/random/array/uniform' );
var Float64Array = require( '@stdlib/array/float64' );
var isnan = require( '@stdlib/math/base/assert/is-nan' );
var pow = require( '@stdlib/math/base/special/pow' );
var format = require( '@stdlib/string/format' );
var pkg = require( './../package.json' ).name;
var dkmeansInitPlusPlus = require( './../lib/dkmeans_init_plus_plus.js' );


// VARIABLES //

var LAYOUTS = [
'row-major',
'column-major'
];

var options = {
'dtype': 'float64'
};


// FUNCTIONS //

/**
* Creates a benchmark function.
*
* @private
* @param {string} order - storage layout
* @param {PositiveInteger} k - number of clusters
* @param {PositiveInteger} M - number of data points
* @param {PositiveInteger} N - number of features
* @param {string} metric - distance metric
* @param {PositiveInteger} trials - number of potential centroids per iteration (>= 1)
* @returns {Function} benchmark function
*/
function createBenchmark( order, k, M, N, metric, trials ) {
var out = new Float64Array( k*N );
var x = uniform( M*N, -100.0, 100.0, options );
return benchmark;

/**
* Benchmark function.
*
* @private
* @param {Benchmark} b - benchmark instance
*/
function benchmark( b ) {
var c;
var i;

b.tic();
for ( i = 0; i < b.iterations; i++ ) {
c = dkmeansInitPlusPlus( order, k, M, N, out, N, x, N, metric, trials, 44 ); // eslint-disable-line max-len
if ( isnan( c[ i%(k*N) ] ) ) {
b.fail( 'should not return NaN' );
}
}
b.toc();
if ( isnan( c[ 0 ] ) ) {
b.fail( 'should not return NaN' );
}
b.pass( 'benchmark finished' );
b.end();
}
}


// MAIN //

/**
* Main execution sequence.
*
* @private
*/
function main() {
var metrics;
var trials;
var min;
var max;
var M;
var N;
var k;
var t;
var m;
var i;
var j;
var f;

min = 1; // 10^min
max = 4; // 10^max

// Benchmark: vary order with defaults k=2, M=100, N=2, metric=sqeuclidean, trials=1...
for ( i = 0; i <= LAYOUTS.length; i++ ) {
f = createBenchmark( LAYOUTS[ i ], 2, 100, 2, 'sqeuclidean', 1 );
bench( format( '%s::vary_M:order=%s,k=2,M=100,N=2,metric=sqeuclidean,trials=1', pkg, LAYOUTS[ i ] ), f );
}

// Benchmark: vary number of data points (M) with defaults k=2, N=2, metric=sqeuclidean, trials=1...
for ( i = min; i <= max; i++ ) {
M = pow( 10, i );
f = createBenchmark( 'row-major', 2, M, 2, 'sqeuclidean', 1 );
bench( format( '%s::vary_M:order=row-major,k=2,M=%d,N=2,metric=sqeuclidean,trials=1', pkg, M ), f );
}

// Benchmark: vary number of features (N) with defaults k=2, M=10, metric=sqeuclidean, trials=1...
for ( i = min; i <= max; i++ ) {
N = pow( 10, i );
f = createBenchmark( 'row-major', 2, 10, N, 'sqeuclidean', 1 );
bench( format( '%s::vary_N:order=row-major,k=2,M=1000,N=%d,metric=sqeuclidean,trials=1', pkg, N ), f );
}

// Benchmark: vary number of clusters (k) with defaults M=1000, N=2, metric=sqeuclidean, trials=1...
for ( i = 1; i <= 4; i++ ) {
k = pow( 2, i );
f = createBenchmark( 'row-major', k, 1000, 2, 'sqeuclidean', 1 );
bench( format( '%s::vary_k:order=row-major,k=%d,M=1000,N=2,metric=sqeuclidean,trials=1', pkg, k ), f );
}

// Benchmark: vary number of trials with defaults k=2, M=1000, N=2, metric=sqeuclidean...
trials = [ 1, 10, 100, 1000 ];
for ( j = 0; j < trials.length; j++ ) {
t = trials[ j ];
f = createBenchmark( 'row-major', 2, 1000, 2, 'sqeuclidean', t );
bench( format( '%s::vary_trials:order=row-major,k=2,M=1000,N=2,metric=sqeuclidean,trials=%d', pkg, t ), f );
}

// Benchmark: vary metric with defaults k=2, M=1000, N=2, trials=1...
metrics = [ 'sqeuclidean', 'cosine', 'cityblock', 'correlation' ];
for ( j = 0; j < metrics.length; j++ ) {
m = metrics[ j ];
f = createBenchmark( 'row-major', 2, 1000, 2, m, 1 );
bench( format( '%s::vary_metric:order=row-major,k=2,M=1000,N=2,metric=%s,trials=1', pkg, m ), f );
}
}

main();
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/**
* @license Apache-2.0
*
* Copyright (c) 2026 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 bench = require( '@stdlib/bench' );
var uniform = require( '@stdlib/random/array/uniform' );
var Float64Array = require( '@stdlib/array/float64' );
var isnan = require( '@stdlib/math/base/assert/is-nan' );
var pow = require( '@stdlib/math/base/special/pow' );
var format = require( '@stdlib/string/format' );
var pkg = require( './../package.json' ).name;
var dkmeansInitPlusPlus = require( './../lib/ndarray.js' );


// VARIABLES //

var options = {
'dtype': 'float64'
};


// FUNCTIONS //

/**
* Creates a benchmark function.
*
* @private
* @param {PositiveInteger} k - number of clusters
* @param {PositiveInteger} M - number of data points
* @param {PositiveInteger} N - number of features
* @param {string} metric - distance metric
* @param {PositiveInteger} trials - number of potential centroids per iteration (>= 1)
* @returns {Function} benchmark function
*/
function createBenchmark( k, M, N, metric, trials ) {
var out = new Float64Array( k*N );
var x = uniform( M*N, -100.0, 100.0, options );
return benchmark;

/**
* Benchmark function.
*
* @private
* @param {Benchmark} b - benchmark instance
*/
function benchmark( b ) {
var c;
var i;

b.tic();
for ( i = 0; i < b.iterations; i++ ) {
c = dkmeansInitPlusPlus( k, M, N, out, N, 1, 0, x, N, 1, 0, metric, trials, 44 ); // eslint-disable-line max-len
if ( isnan( c[ i%(k*N) ] ) ) {
b.fail( 'should not return NaN' );
}
}
b.toc();
if ( isnan( c[ 0 ] ) ) {
b.fail( 'should not return NaN' );
}
b.pass( 'benchmark finished' );
b.end();
}
}


// MAIN //

/**
* Main execution sequence.
*
* @private
*/
function main() {
var metrics;
var trials;
var min;
var max;
var M;
var N;
var k;
var t;
var m;
var i;
var j;
var f;

min = 1; // 10^min
max = 4; // 10^max

// Benchmark: vary number of data points (M) with defaults k=2, N=2, metric=sqeuclidean, trials=1...
for ( i = min; i <= max; i++ ) {
M = pow( 10, i );
f = createBenchmark( 2, M, 2, 'sqeuclidean', 1 );
bench( format( '%s::vary_M:k=2,M=%d,N=2,metric=sqeuclidean,trials=1', pkg, M ), f );
}

// Benchmark: vary number of features (N) with defaults k=2, M=10, metric=sqeuclidean, trials=1...
for ( i = min; i <= max; i++ ) {
N = pow( 10, i );
f = createBenchmark( 2, 10, N, 'sqeuclidean', 1 );
bench( format( '%s::vary_N:k=2,M=1000,N=%d,metric=sqeuclidean,trials=1', pkg, N ), f );
}

// Benchmark: vary number of clusters (k) with defaults M=1000, N=2, metric=sqeuclidean, trials=1...
for ( i = 1; i <= 4; i++ ) {
k = pow( 2, i );
f = createBenchmark( k, 1000, 2, 'sqeuclidean', 1 );
bench( format( '%s::vary_k:k=%d,M=1000,N=2,metric=sqeuclidean,trials=1', pkg, k ), f );
}

// Benchmark: vary number of trials with defaults k=2, M=1000, N=2, metric=sqeuclidean...
trials = [ 1, 10, 100 ];
for ( j = 0; j < trials.length; j++ ) {
t = trials[ j ];
f = createBenchmark( 2, 1000, 2, 'sqeuclidean', t );
bench( format( '%s::vary_trials:k=2,M=1000,N=2,metric=sqeuclidean,trials=%d', pkg, t ), f );
}

// Benchmark: vary metric with defaults k=2, M=1000, N=2, trials=1...
metrics = [ 'sqeuclidean', 'cosine', 'cityblock', 'correlation' ];
for ( j = 0; j < metrics.length; j++ ) {
m = metrics[ j ];
f = createBenchmark( 2, 1000, 2, m, 1 );
bench( format( '%s::vary_metric:k=2,M=1000,N=2,metric=%s,trials=1', pkg, m ), f );
}
}

main();
Loading
Loading