diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/README.md b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/README.md
new file mode 100644
index 000000000000..d9e17ff1c823
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/README.md
@@ -0,0 +1,519 @@
+
+
+# dsgdTrainer
+
+> Train a linear model via [stochastic gradient descent][stochastic-gradient-descent].
+
+
+
+## Usage
+
+```javascript
+var dsgdTrainer = require( '@stdlib/ml/strided/dsgd-trainer' );
+```
+
+#### dsgdTrainer( order, M, N, X, LDX, y, sy, w, sw, ws, sws, params )
+
+Trains a linear model via stochastic gradient descent, where `X` is an `M` by `N` input matrix, `y` is a target vector, and `w` is a weight vector.
+
+```javascript
+var Float64Array = require( '@stdlib/array/float64' );
+var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+
+var params = new Params({
+ 'penaltyParams': new Float64Array( [ 1.0e-4, 0.0 ] ),
+ 'learningRateParams': new Float64Array( [ 0.01, 0.0 ] ),
+ 'lossFunctionParams': new Float64Array( [ 0.1 ] ),
+ 'intercept': 0.0,
+ 'maxIter': 5,
+ 'penalty': 'l2',
+ 'learningRate': 'constant',
+ 'lossFunction': 'hinge',
+ 'fitIntercept': true
+});
+
+var X = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
+var y = new Float64Array( [ 1.0, -1.0, 1.0 ] );
+var w = new Float64Array( 3 );
+var ws = new Float64Array( 2 );
+
+var out = dsgdTrainer( 'row-major', 3, 2, X, 2, y, 1, w, 1, ws, 1, params );
+// returns
+
+var bool = ( out === w );
+// returns true
+```
+
+The function has the following parameters:
+
+- **order**: storage layout.
+- **M**: number of samples (i.e., number of rows in the matrix `X`).
+- **N**: number of features (i.e., number of columns in the matrix `X`).
+- **X**: input matrix stored in linear memory as a [`Float64Array`][@stdlib/array/float64].
+- **LDX**: stride of the first dimension of `X` (a.k.a., leading dimension of the matrix `X`).
+- **y**: target [`Float64Array`][@stdlib/array/float64].
+- **sy**: stride length for `y`.
+- **w**: weight [`Float64Array`][@stdlib/array/float64]. Upon return, `w` contains the fitted model coefficients.
+- **sw**: stride length for `w`.
+- **ws**: workspace [`Float64Array`][@stdlib/array/float64].
+- **sws**: stride length for `ws`.
+- **params**: [SGD trainer parameters object][@stdlib/ml/base/sgd/params/float64].
+
+The stride parameters determine how elements are accessed. For example, to iterate over every other element of `y`,
+
+```javascript
+var Float64Array = require( '@stdlib/array/float64' );
+var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+
+var params = new Params({
+ 'penaltyParams': new Float64Array( [ 1.0e-4, 0.0 ] ),
+ 'learningRateParams': new Float64Array( [ 0.01, 0.0 ] ),
+ 'lossFunctionParams': new Float64Array( [ 0.1 ] ),
+ 'intercept': 0.0,
+ 'maxIter': 5,
+ 'penalty': 'l2',
+ 'learningRate': 'constant',
+ 'lossFunction': 'hinge',
+ 'fitIntercept': true
+});
+
+var X = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
+var y = new Float64Array( [ 1.0, 0.0, -1.0, 0.0, 1.0, 0.0 ] );
+var w = new Float64Array( 3 );
+var ws = new Float64Array( 2 );
+
+var out = dsgdTrainer( 'row-major', 3, 2, X, 2, y, 2, w, 1, ws, 1, params );
+// returns
+```
+
+Note that indexing is relative to the first index. To introduce an offset, use [`typed array`][mdn-typed-array] views.
+
+
+
+```javascript
+var Float64Array = require( '@stdlib/array/float64' );
+var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+
+var params = new Params({
+ 'penaltyParams': new Float64Array( [ 1.0e-4, 0.0 ] ),
+ 'learningRateParams': new Float64Array( [ 0.01, 0.0 ] ),
+ 'lossFunctionParams': new Float64Array( [ 0.1 ] ),
+ 'intercept': 0.0,
+ 'maxIter': 5,
+ 'penalty': 'l2',
+ 'learningRate': 'constant',
+ 'lossFunction': 'hinge',
+ 'fitIntercept': true
+});
+
+var X = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
+
+// Initial arrays...
+var y0 = new Float64Array( [ 0.0, 1.0, -1.0, 1.0 ] );
+var w0 = new Float64Array( 4 );
+
+// Create offset views...
+var y1 = new Float64Array( y0.buffer, y0.BYTES_PER_ELEMENT*1 ); // start at 2nd element
+var w1 = new Float64Array( w0.buffer, w0.BYTES_PER_ELEMENT*1 ); // start at 2nd element
+
+var ws = new Float64Array( 2 );
+
+dsgdTrainer( 'row-major', 3, 2, X, 2, y1, 1, w1, 1, ws, 1, params );
+// w0 =>
+```
+
+
+
+#### dsgdTrainer.ndarray( M, N, X, sx1, sx2, ox, y, sy, oy, w, sw, ow, ws, sws, ows, params )
+
+Trains a linear model via stochastic gradient descent using alternative indexing semantics.
+
+```javascript
+var Float64Array = require( '@stdlib/array/float64' );
+var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+
+var params = new Params({
+ 'penaltyParams': new Float64Array( [ 1.0e-4, 0.0 ] ),
+ 'learningRateParams': new Float64Array( [ 0.01, 0.0 ] ),
+ 'lossFunctionParams': new Float64Array( [ 0.1 ] ),
+ 'intercept': 0.0,
+ 'maxIter': 5,
+ 'penalty': 'l2',
+ 'learningRate': 'constant',
+ 'lossFunction': 'hinge',
+ 'fitIntercept': true
+});
+
+var X = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
+var y = new Float64Array( [ 1.0, -1.0, 1.0 ] );
+var w = new Float64Array( 3 );
+var ws = new Float64Array( 2 );
+
+var out = dsgdTrainer.ndarray( 3, 2, X, 2, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, params );
+// returns
+```
+
+The function has the following additional parameters:
+
+- **sx1**: stride of the first dimension of `X`.
+- **sx2**: stride of the second dimension of `X`.
+- **ox**: starting index for `X`.
+- **oy**: starting index for `y`.
+- **ow**: starting index for `w`.
+- **ows**: starting index for `ws`.
+
+While [`typed array`][mdn-typed-array] views mandate a view offset based on the underlying buffer, the offset parameters support indexing semantics based on starting indices. For example,
+
+```javascript
+var Float64Array = require( '@stdlib/array/float64' );
+var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+
+var params = new Params({
+ 'penaltyParams': new Float64Array( [ 1.0e-4, 0.0 ] ),
+ 'learningRateParams': new Float64Array( [ 0.01, 0.0 ] ),
+ 'lossFunctionParams': new Float64Array( [ 0.1 ] ),
+ 'intercept': 0.0,
+ 'maxIter': 5,
+ 'penalty': 'l2',
+ 'learningRate': 'constant',
+ 'lossFunction': 'hinge',
+ 'fitIntercept': true
+});
+
+var X = new Float64Array( [ 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
+var y = new Float64Array( [ 0.0, 1.0, -1.0, 1.0 ] );
+var w = new Float64Array( 4 );
+var ws = new Float64Array( 2 );
+
+var out = dsgdTrainer.ndarray( 3, 2, X, 2, 1, 1, y, 1, 1, w, 1, 1, ws, 1, 0, params );
+// returns
+```
+
+
+
+
+
+
+
+## Notes
+
+- Both functions perform in-place training, mutating and returning `w`.
+
+- When `params.fitIntercept` is `true`, `w` must have `N+1` indexed elements, as the fitted intercept is stored in the element following the `N` feature weights (i.e., at index `ow + (sw*N)`).
+
+- `ws` must have `N` indexed elements. The workspace tracks the cumulative L1 shrinkage applied to each feature and should be zero-filled prior to training.
+
+- Upon return, `w` contains effective (i.e., fully rescaled) weights.
+
+- If `M` or `N` is equal to `0`, both functions return `w` unchanged.
+
+- `params` is an [SGD trainer parameters object][@stdlib/ml/base/sgd/params/float64] specifying the [penalty][@stdlib/ml/base/sgd/penalties], the [learning rate scheduler][@stdlib/ml/base/sgd/learning-rates], the [loss function][@stdlib/ml/base/sgd/loss-functions], and their respective parameter lists, along with the initial intercept, the maximum number of epochs, and whether to fit an intercept.
+
+
+
+
+
+
+
+## Examples
+
+
+
+```javascript
+var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+var uniform = require( '@stdlib/random/array/uniform' );
+var Float64Array = require( '@stdlib/array/float64' );
+var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+var dsgdTrainer = require( '@stdlib/ml/strided/dsgd-trainer' );
+
+var opts = {
+ 'dtype': 'float64'
+};
+
+var M = 50;
+var N = 5;
+
+var X = uniform( M*N, -5.0, 5.0, opts );
+var y = discreteUniform( M, -1, 1, opts );
+
+// Allocate `N+1` elements in order to accommodate the fitted intercept:
+var w = new Float64Array( N+1 );
+var workspace = new Float64Array( N );
+
+var params = new Params({
+ 'penaltyParams': new Float64Array( [ 1.0e-4, 0.15 ] ),
+ 'learningRateParams': new Float64Array( [ 0.01, 0.25 ] ),
+ 'lossFunctionParams': new Float64Array( [ 0.1 ] ),
+ 'intercept': 0.0,
+ 'maxIter': 500,
+ 'penalty': 'l2',
+ 'learningRate': 'constant',
+ 'lossFunction': 'hinge',
+ 'fitIntercept': true
+});
+
+dsgdTrainer( 'row-major', M, N, X, N, y, 1, w, 1, workspace, 1, params );
+console.log( w );
+```
+
+
+
+
+
+
+
+* * *
+
+
+
+## C APIs
+
+
+
+
+
+
+
+
+
+
+
+### Usage
+
+```c
+#include "stdlib/ml/strided/dsgd_trainer.h"
+```
+
+#### stdlib_strided_dsgd_trainer( layout, M, N, \*X, LDX, \*y, strideY, \*w, strideW, \*ws, strideWS, \*params )
+
+Trains a linear model via stochastic gradient descent, where `X` is an `M` by `N` input matrix, `y` is a target vector, and `w` is a weight vector.
+
+```c
+#include "stdlib/ml/base/sgd/learning_rates.h"
+#include "stdlib/ml/base/sgd/loss_functions.h"
+#include "stdlib/ml/base/sgd/penalties.h"
+#include "stdlib/blas/base/shared.h"
+#include
+
+const double X[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
+const double y[] = { 1.0, -1.0, 1.0 };
+double w[] = { 0.0, 0.0, 0.0 };
+double ws[] = { 0.0, 0.0 };
+
+struct stdlib_ml_sgd_float64_params params = {
+ .penaltyParams = { 1.0e-4, 0.0 },
+ .learningRateParams = { 0.01, 0.0 },
+ .lossFunctionParams = { 0.1 },
+ .intercept = 0.0,
+ .maxIter = 500,
+ .penalty = STDLIB_ML_SGD_L2,
+ .learningRate = STDLIB_ML_SGD_CONSTANT,
+ .lossFunction = STDLIB_ML_SGD_HINGE,
+ .fitIntercept = true
+};
+
+stdlib_strided_dsgd_trainer( CblasRowMajor, 3, 2, X, 2, y, 1, w, 1, ws, 1, ¶ms );
+```
+
+The function accepts the following arguments:
+
+- **layout**: `[in] CBLAS_LAYOUT` storage layout of `X`.
+- **M**: `[in] CBLAS_INT` number of samples.
+- **N**: `[in] CBLAS_INT` number of features.
+- **X**: `[in] double*` input matrix.
+- **LDX**: `[in] CBLAS_INT` stride of the major dimension of `X` (a.k.a., leading dimension of the matrix `X`).
+- **y**: `[in] double*` target array.
+- **strideY**: `[in] CBLAS_INT` stride length for `y`.
+- **w**: `[inout] double*` weight array.
+- **strideW**: `[in] CBLAS_INT` stride length for `w`.
+- **ws**: `[inout] double*` workspace array.
+- **strideWS**: `[in] CBLAS_INT` stride length for `ws`.
+- **params**: `[in] struct stdlib_ml_sgd_float64_params*` parameters.
+
+```c
+double* stdlib_strided_dsgd_trainer( const CBLAS_LAYOUT layout, const CBLAS_INT M, const CBLAS_INT N, const double *X, const CBLAS_INT LDX, const double *y, const CBLAS_INT strideY, double *w, const CBLAS_INT strideW, double *ws, const CBLAS_INT strideWS, const struct stdlib_ml_sgd_float64_params *params )
+```
+
+#### stdlib_strided_dsgd_trainer_ndarray( M, N, \*X, sx1, sx2, ox, \*y, sy, oy, \*w, sw, ow, \*ws, sws, ows, \*params )
+
+Trains a linear model via stochastic gradient descent using alternative indexing semantics.
+
+```c
+#include "stdlib/ml/base/sgd/learning_rates.h"
+#include "stdlib/ml/base/sgd/loss_functions.h"
+#include "stdlib/ml/base/sgd/penalties.h"
+#include "stdlib/blas/base/shared.h"
+#include
+
+const double X[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
+const double y[] = { 1.0, -1.0, 1.0 };
+double w[] = { 0.0, 0.0, 0.0 };
+double ws[] = { 0.0, 0.0 };
+
+struct stdlib_ml_sgd_float64_params params = {
+ .penaltyParams = { 1.0e-4, 0.0 },
+ .learningRateParams = { 0.01, 0.0 },
+ .lossFunctionParams = { 0.1 },
+ .intercept = 0.0,
+ .maxIter = 500,
+ .penalty = STDLIB_ML_SGD_L2,
+ .learningRate = STDLIB_ML_SGD_CONSTANT,
+ .lossFunction = STDLIB_ML_SGD_HINGE,
+ .fitIntercept = true
+};
+
+stdlib_strided_dsgd_trainer_ndarray( 3, 2, X, 2, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, ¶ms );
+```
+
+The function accepts the following arguments:
+
+- **M**: `[in] CBLAS_INT` number of samples.
+- **N**: `[in] CBLAS_INT` number of features.
+- **X**: `[in] double*` input matrix.
+- **strideX1**: `[in] CBLAS_INT` stride of the first dimension of `X`.
+- **strideX2**: `[in] CBLAS_INT` stride of the second dimension of `X`.
+- **offsetX**: `[in] CBLAS_INT` starting index for `X`.
+- **y**: `[in] double*` target array.
+- **strideY**: `[in] CBLAS_INT` stride length for `y`.
+- **offsetY**: `[in] CBLAS_INT` starting index for `y`.
+- **w**: `[inout] double*` weight array.
+- **strideW**: `[in] CBLAS_INT` stride length for `w`.
+- **offsetW**: `[in] CBLAS_INT` starting index for `w`.
+- **ws**: `[inout] double*` workspace array.
+- **strideWS**: `[in] CBLAS_INT` stride length for `ws`.
+- **offsetWS**: `[in] CBLAS_INT` starting index for `ws`.
+- **params**: `[in] struct stdlib_ml_sgd_float64_params*` parameters.
+
+```c
+double* stdlib_strided_dsgd_trainer_ndarray( const CBLAS_INT M, const CBLAS_INT N, const double *X, const CBLAS_INT strideX1, const CBLAS_INT strideX2, const CBLAS_INT offsetX, const double *y, const CBLAS_INT strideY, const CBLAS_INT offsetY, double *w, const CBLAS_INT strideW, const CBLAS_INT offsetW, double *ws, const CBLAS_INT strideWS, const CBLAS_INT offsetWS, const struct stdlib_ml_sgd_float64_params *params )
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+### Examples
+
+```c
+#include "stdlib/ml/strided/dsgd_trainer.h"
+#include "stdlib/ml/base/sgd/learning_rates.h"
+#include "stdlib/ml/base/sgd/loss_functions.h"
+#include "stdlib/ml/base/sgd/penalties.h"
+#include "stdlib/blas/base/shared.h"
+#include
+#include
+
+int main( void ) {
+ // Define a 3x2 input matrix stored in row-major order:
+ const double X[ 3*2 ] = {
+ 1.0, 2.0,
+ 3.0, 4.0,
+ 5.0, 6.0
+ };
+
+ // Define a target vector:
+ const double y[ 3 ] = { 1.0, -1.0, 1.0 };
+
+ // Specify the number of samples and features:
+ const CBLAS_INT M = 3;
+ const CBLAS_INT N = 2;
+
+ // Allocate `N+1` elements in order to accommodate the fitted intercept:
+ double w[ 2+1 ] = { 0.0, 0.0, 0.0 };
+
+ // Allocate a zero-filled workspace:
+ double ws[ 2 ] = { 0.0, 0.0 };
+
+ // Define the training parameters:
+ struct stdlib_ml_sgd_float64_params params = {
+ .penaltyParams = { 1.0e-4, 0.0 },
+ .learningRateParams = { 0.01, 0.0 },
+ .lossFunctionParams = { 0.1 },
+ .intercept = 0.0,
+ .maxIter = 500,
+ .penalty = STDLIB_ML_SGD_L2,
+ .learningRate = STDLIB_ML_SGD_CONSTANT,
+ .lossFunction = STDLIB_ML_SGD_HINGE,
+ .fitIntercept = true
+ };
+
+ // Train a linear model:
+ stdlib_strided_dsgd_trainer( CblasRowMajor, M, N, X, N, y, 1, w, 1, ws, 1, ¶ms );
+
+ // Print the result:
+ for ( int i = 0; i < N; i++ ) {
+ printf( "w[ %i ] = %lf\n", i, w[ i ] );
+ }
+ printf( "intercept = %lf\n", w[ N ] );
+}
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[stochastic-gradient-descent]: https://en.wikipedia.org/wiki/Stochastic_gradient_descent
+
+[@stdlib/array/float64]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/float64
+
+[@stdlib/ml/base/sgd/params/float64]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ml/base/sgd/params/float64
+
+[@stdlib/ml/base/sgd/penalties]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ml/base/sgd/penalties
+
+[@stdlib/ml/base/sgd/learning-rates]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ml/base/sgd/learning-rates
+
+[@stdlib/ml/base/sgd/loss-functions]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ml/base/sgd/loss-functions
+
+[mdn-typed-array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray
+
+
+
+
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/benchmark.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/benchmark.js
new file mode 100644
index 000000000000..ff9a4e3eee43
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/benchmark.js
@@ -0,0 +1,122 @@
+/**
+* @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 bench = require( '@stdlib/bench' );
+var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+var format = require( '@stdlib/string/format' );
+var isnan = require( '@stdlib/math/base/assert/is-nan' );
+var pow = require( '@stdlib/math/base/special/pow' );
+var floor = require( '@stdlib/math/base/special/floor' );
+var Float64Array = require( '@stdlib/array/float64' );
+var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+var pkg = require( './../package.json' ).name;
+var dsgdTrainer = require( './../lib/dsgd_trainer.js' );
+
+
+// VARIABLES //
+
+var options = {
+ 'dtype': 'float64'
+};
+
+
+// FUNCTIONS //
+
+/**
+* Creates a benchmark function.
+*
+* @private
+* @param {PositiveInteger} N - array length
+* @returns {Function} benchmark function
+*/
+function createBenchmark( N ) {
+ var ws = new Float64Array( N );
+ var x = discreteUniform( N*N, -10.0, 10.0, options );
+ var y = discreteUniform( N, -10.0, 10.0, options );
+ var w = discreteUniform( N, -0.05, 0.05, options );
+ return benchmark;
+
+ /**
+ * Benchmark function.
+ *
+ * @private
+ * @param {Benchmark} b - benchmark instance
+ */
+ function benchmark( b ) {
+ var params;
+ var z;
+ var i;
+
+ params = new Params();
+
+ params.penalty = 'l2';
+ params.learningRate = 'constant';
+ params.lossFunction = 'hinge';
+ params.intercept = 0.0;
+ params.maxIter = 500;
+ params.penaltyParams = new Float64Array( [ 2.5, 0.0 ] );
+ params.learningRateParams = new Float64Array( [ 0.01, 0.0 ] );
+ params.lossFunctionParams = new Float64Array( [ 0.0 ] );
+ params.fitIntercept = true;
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ z = dsgdTrainer( 'row-major', N, N, x, N, y, 1, w, 1, ws, 1, params );
+ if ( isnan( z[ i%z.length ] ) ) {
+ b.fail( 'should not return NaN' );
+ }
+ }
+ b.toc();
+ if ( isnan( z[ i%z.length ] ) ) {
+ b.fail( 'should not return NaN' );
+ }
+ b.pass( 'benchmark finished' );
+ b.end();
+ }
+}
+
+
+// MAIN //
+
+/**
+* Main execution sequence.
+*
+* @private
+*/
+function main() {
+ var min;
+ var max;
+ var N;
+ var f;
+ var i;
+
+ min = 1; // 10^min
+ max = 6; // 10^max
+
+ for ( i = min; i <= max; i++ ) {
+ N = floor( pow( pow( 10, i ), 1.0/2.0 ) );
+ f = createBenchmark( N );
+ bench( format( '%s:size=%d', pkg, N*N ), f );
+ }
+}
+
+main();
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/benchmark.native.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/benchmark.native.js
new file mode 100644
index 000000000000..d6dcc9d1d96c
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/benchmark.native.js
@@ -0,0 +1,127 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2025 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 resolve = require( 'path' ).resolve;
+var bench = require( '@stdlib/bench' );
+var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+var format = require( '@stdlib/string/format' );
+var isnan = require( '@stdlib/math/base/assert/is-nan' );
+var pow = require( '@stdlib/math/base/special/pow' );
+var floor = require( '@stdlib/math/base/special/floor' );
+var Float64Array = require( '@stdlib/array/float64' );
+var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+var tryRequire = require( '@stdlib/utils/try-require' );
+var pkg = require( './../package.json' ).name;
+
+
+// VARIABLES //
+
+var dsgdTrainer = tryRequire( resolve( __dirname, './../lib/dsgd_trainer.native.js' ) );
+var opts = {
+ 'skip': ( dsgdTrainer instanceof Error )
+};
+var options = {
+ 'dtype': 'float64'
+};
+
+
+// FUNCTIONS //
+
+/**
+* Creates a benchmark function.
+*
+* @private
+* @param {PositiveInteger} N - array length
+* @returns {Function} benchmark function
+*/
+function createBenchmark( N ) {
+ var ws = new Float64Array( N );
+ var x = discreteUniform( N*N, -10.0, 10.0, options );
+ var y = discreteUniform( N, -10.0, 10.0, options );
+ var w = discreteUniform( N, -0.05, 0.05, options );
+ return benchmark;
+
+ /**
+ * Benchmark function.
+ *
+ * @private
+ * @param {Benchmark} b - benchmark instance
+ */
+ function benchmark( b ) {
+ var params;
+ var z;
+ var i;
+
+ params = new Params();
+
+ params.penalty = 'l2';
+ params.learningRate = 'constant';
+ params.lossFunction = 'hinge';
+ params.intercept = 0.0;
+ params.maxIter = 500;
+ params.penaltyParams = new Float64Array( [ 2.5, 0.0 ] );
+ params.learningRateParams = new Float64Array( [ 0.01, 0.0 ] );
+ params.lossFunctionParams = new Float64Array( [ 0.0 ] );
+ params.fitIntercept = true;
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ z = dsgdTrainer( 'row-major', N, N, x, N, y, 1, w, 1, ws, 1, params );
+ if ( isnan( z[ i%z.length ] ) ) {
+ b.fail( 'should not return NaN' );
+ }
+ }
+ b.toc();
+ if ( isnan( z[ i%z.length ] ) ) {
+ b.fail( 'should not return NaN' );
+ }
+ b.pass( 'benchmark finished' );
+ b.end();
+ }
+}
+
+
+// MAIN //
+
+/**
+* Main execution sequence.
+*
+* @private
+*/
+function main() {
+ var min;
+ var max;
+ var N;
+ var f;
+ var i;
+
+ min = 1; // 10^min
+ max = 6; // 10^max
+
+ for ( i = min; i <= max; i++ ) {
+ N = floor( pow( pow( 10, i ), 1.0/2.0 ) );
+ f = createBenchmark( N );
+ bench( format( '%s::native:size=%d', pkg, N*N ), opts, f );
+ }
+}
+
+main();
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/benchmark.ndarray.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/benchmark.ndarray.js
new file mode 100644
index 000000000000..99f2db595df3
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/benchmark.ndarray.js
@@ -0,0 +1,122 @@
+/**
+* @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 bench = require( '@stdlib/bench' );
+var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+var format = require( '@stdlib/string/format' );
+var isnan = require( '@stdlib/math/base/assert/is-nan' );
+var pow = require( '@stdlib/math/base/special/pow' );
+var floor = require( '@stdlib/math/base/special/floor' );
+var Float64Array = require( '@stdlib/array/float64' );
+var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+var pkg = require( './../package.json' ).name;
+var dsgdTrainer = require( './../lib/ndarray.js' );
+
+
+// VARIABLES //
+
+var options = {
+ 'dtype': 'float64'
+};
+
+
+// FUNCTIONS //
+
+/**
+* Creates a benchmark function.
+*
+* @private
+* @param {PositiveInteger} N - array length
+* @returns {Function} benchmark function
+*/
+function createBenchmark( N ) {
+ var ws = new Float64Array( N );
+ var x = discreteUniform( N*N, -10.0, 10.0, options );
+ var y = discreteUniform( N, -10.0, 10.0, options );
+ var w = discreteUniform( N, -0.05, 0.05, options );
+ return benchmark;
+
+ /**
+ * Benchmark function.
+ *
+ * @private
+ * @param {Benchmark} b - benchmark instance
+ */
+ function benchmark( b ) {
+ var params;
+ var z;
+ var i;
+
+ params = new Params();
+
+ params.penalty = 'l2';
+ params.learningRate = 'constant';
+ params.lossFunction = 'hinge';
+ params.intercept = 0.0;
+ params.maxIter = 500;
+ params.penaltyParams = new Float64Array( [ 2.5, 0.0 ] );
+ params.learningRateParams = new Float64Array( [ 0.01, 0.0 ] );
+ params.lossFunctionParams = new Float64Array( [ 0.0 ] );
+ params.fitIntercept = true;
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ z = dsgdTrainer( N, N, x, N, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, params ); // eslint-disable-line max-len
+ if ( isnan( z[ i%z.length ] ) ) {
+ b.fail( 'should not return NaN' );
+ }
+ }
+ b.toc();
+ if ( isnan( z[ i%z.length ] ) ) {
+ b.fail( 'should not return NaN' );
+ }
+ b.pass( 'benchmark finished' );
+ b.end();
+ }
+}
+
+
+// MAIN //
+
+/**
+* Main execution sequence.
+*
+* @private
+*/
+function main() {
+ var min;
+ var max;
+ var N;
+ var f;
+ var i;
+
+ min = 1; // 10^min
+ max = 6; // 10^max
+
+ for ( i = min; i <= max; i++ ) {
+ N = floor( pow( pow( 10, i ), 1.0/2.0 ) );
+ f = createBenchmark( N );
+ bench( format( '%s:ndarray:size=%d', pkg, N*N ), f );
+ }
+}
+
+main();
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/benchmark.ndarray.native.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/benchmark.ndarray.native.js
new file mode 100644
index 000000000000..14856b87d1ba
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/benchmark.ndarray.native.js
@@ -0,0 +1,127 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2025 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 resolve = require( 'path' ).resolve;
+var bench = require( '@stdlib/bench' );
+var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+var format = require( '@stdlib/string/format' );
+var isnan = require( '@stdlib/math/base/assert/is-nan' );
+var pow = require( '@stdlib/math/base/special/pow' );
+var floor = require( '@stdlib/math/base/special/floor' );
+var Float64Array = require( '@stdlib/array/float64' );
+var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+var tryRequire = require( '@stdlib/utils/try-require' );
+var pkg = require( './../package.json' ).name;
+
+
+// VARIABLES //
+
+var dsgdTrainer = tryRequire( resolve( __dirname, './../lib/ndarray.native.js' ) );
+var opts = {
+ 'skip': ( dsgdTrainer instanceof Error )
+};
+var options = {
+ 'dtype': 'float64'
+};
+
+
+// FUNCTIONS //
+
+/**
+* Creates a benchmark function.
+*
+* @private
+* @param {PositiveInteger} N - array length
+* @returns {Function} benchmark function
+*/
+function createBenchmark( N ) {
+ var ws = new Float64Array( N );
+ var x = discreteUniform( N*N, -10.0, 10.0, options );
+ var y = discreteUniform( N, -10.0, 10.0, options );
+ var w = discreteUniform( N, -0.05, 0.05, options );
+ return benchmark;
+
+ /**
+ * Benchmark function.
+ *
+ * @private
+ * @param {Benchmark} b - benchmark instance
+ */
+ function benchmark( b ) {
+ var params;
+ var z;
+ var i;
+
+ params = new Params();
+
+ params.penalty = 'l2';
+ params.learningRate = 'constant';
+ params.lossFunction = 'hinge';
+ params.intercept = 0.0;
+ params.maxIter = 500;
+ params.penaltyParams = new Float64Array( [ 2.5, 0.0 ] );
+ params.learningRateParams = new Float64Array( [ 0.01, 0.0 ] );
+ params.lossFunctionParams = new Float64Array( [ 0.0 ] );
+ params.fitIntercept = true;
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ z = dsgdTrainer( N, N, x, N, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, params ); // eslint-disable-line max-len
+ if ( isnan( z[ i%z.length ] ) ) {
+ b.fail( 'should not return NaN' );
+ }
+ }
+ b.toc();
+ if ( isnan( z[ i%z.length ] ) ) {
+ b.fail( 'should not return NaN' );
+ }
+ b.pass( 'benchmark finished' );
+ b.end();
+ }
+}
+
+
+// MAIN //
+
+/**
+* Main execution sequence.
+*
+* @private
+*/
+function main() {
+ var min;
+ var max;
+ var N;
+ var f;
+ var i;
+
+ min = 1; // 10^min
+ max = 6; // 10^max
+
+ for ( i = min; i <= max; i++ ) {
+ N = floor( pow( pow( 10, i ), 1.0/2.0 ) );
+ f = createBenchmark( N );
+ bench( format( '%s::native:ndarray:size=%d', pkg, N*N ), opts, f );
+ }
+}
+
+main();
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/c/Makefile b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/c/Makefile
new file mode 100644
index 000000000000..cce2c865d7ad
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/c/Makefile
@@ -0,0 +1,146 @@
+#/
+# @license Apache-2.0
+#
+# Copyright (c) 2025 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.
+#/
+
+# VARIABLES #
+
+ifndef VERBOSE
+ QUIET := @
+else
+ QUIET :=
+endif
+
+# Determine the OS ([1][1], [2][2]).
+#
+# [1]: https://en.wikipedia.org/wiki/Uname#Examples
+# [2]: http://stackoverflow.com/a/27776822/2225624
+OS ?= $(shell uname)
+ifneq (, $(findstring MINGW,$(OS)))
+ OS := WINNT
+else
+ifneq (, $(findstring MSYS,$(OS)))
+ OS := WINNT
+else
+ifneq (, $(findstring CYGWIN,$(OS)))
+ OS := WINNT
+else
+ifneq (, $(findstring Windows_NT,$(OS)))
+ OS := WINNT
+endif
+endif
+endif
+endif
+
+# Define the program used for compiling C source files:
+ifdef C_COMPILER
+ CC := $(C_COMPILER)
+else
+ CC := gcc
+endif
+
+# Define the command-line options when compiling C files:
+CFLAGS ?= \
+ -std=c99 \
+ -O3 \
+ -Wall \
+ -pedantic
+
+# Determine whether to generate position independent code ([1][1], [2][2]).
+#
+# [1]: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options
+# [2]: http://stackoverflow.com/questions/5311515/gcc-fpic-option
+ifeq ($(OS), WINNT)
+ fPIC ?=
+else
+ fPIC ?= -fPIC
+endif
+
+# List of includes (e.g., `-I /foo/bar -I /beep/boop/include`):
+INCLUDE ?=
+
+# List of source files:
+SOURCE_FILES ?=
+
+# List of libraries (e.g., `-lopenblas -lpthread`):
+LIBRARIES ?=
+
+# List of library paths (e.g., `-L /foo/bar -L /beep/boop`):
+LIBPATH ?=
+
+# List of C targets:
+c_targets := benchmark.length.out
+
+
+# RULES #
+
+#/
+# Compiles source files.
+#
+# @param {string} [C_COMPILER] - C compiler (e.g., `gcc`)
+# @param {string} [CFLAGS] - C compiler options
+# @param {(string|void)} [fPIC] - compiler flag determining whether to generate position independent code (e.g., `-fPIC`)
+# @param {string} [INCLUDE] - list of includes (e.g., `-I /foo/bar -I /beep/boop/include`)
+# @param {string} [SOURCE_FILES] - list of source files
+# @param {string} [LIBPATH] - list of library paths (e.g., `-L /foo/bar -L /beep/boop`)
+# @param {string} [LIBRARIES] - list of libraries (e.g., `-lopenblas -lpthread`)
+#
+# @example
+# make
+#
+# @example
+# make all
+#/
+all: $(c_targets)
+
+.PHONY: all
+
+#/
+# Compiles C source files.
+#
+# @private
+# @param {string} CC - C compiler (e.g., `gcc`)
+# @param {string} CFLAGS - C compiler options
+# @param {(string|void)} fPIC - compiler flag determining whether to generate position independent code (e.g., `-fPIC`)
+# @param {string} INCLUDE - list of includes (e.g., `-I /foo/bar`)
+# @param {string} SOURCE_FILES - list of source files
+# @param {string} LIBPATH - list of library paths (e.g., `-L /foo/bar`)
+# @param {string} LIBRARIES - list of libraries (e.g., `-lopenblas`)
+#/
+$(c_targets): %.out: %.c
+ $(QUIET) $(CC) $(CFLAGS) $(fPIC) $(INCLUDE) -o $@ $(SOURCE_FILES) $< $(LIBPATH) -lm $(LIBRARIES)
+
+#/
+# Runs compiled benchmarks.
+#
+# @example
+# make run
+#/
+run: $(c_targets)
+ $(QUIET) ./$<
+
+.PHONY: run
+
+#/
+# Removes generated files.
+#
+# @example
+# make clean
+#/
+clean:
+ $(QUIET) -rm -f *.o *.out
+
+.PHONY: clean
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/c/benchmark.length.c b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/c/benchmark.length.c
new file mode 100644
index 000000000000..647045598fda
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/benchmark/c/benchmark.length.c
@@ -0,0 +1,256 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2025 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.
+*/
+
+#include "stdlib/ml/strided/dsgd_trainer.h"
+#include "stdlib/ml/base/sgd/penalties.h"
+#include "stdlib/ml/base/sgd/learning_rates.h"
+#include "stdlib/ml/base/sgd/loss_functions.h"
+#include
+#include
+#include
+#include
+#include
+
+#define NAME "dsgd_trainer"
+#define ITERATIONS 10000000
+#define REPEATS 3
+#define MIN 1
+#define MAX 6
+
+/**
+* Prints the TAP version.
+*/
+static void print_version( void ) {
+ printf( "TAP version 13\n" );
+}
+
+/**
+* Prints the TAP summary.
+*
+* @param total total number of tests
+* @param passing total number of passing tests
+*/
+static void print_summary( int total, int passing ) {
+ printf( "#\n" );
+ printf( "1..%d\n", total ); // TAP plan
+ printf( "# total %d\n", total );
+ printf( "# pass %d\n", passing );
+ printf( "#\n" );
+ printf( "# ok\n" );
+}
+
+/**
+* Prints benchmarks results.
+*
+* @param iterations number of iterations
+* @param elapsed elapsed time in seconds
+*/
+static void print_results( int iterations, double elapsed ) {
+ double rate = (double)iterations / elapsed;
+ printf( " ---\n" );
+ printf( " iterations: %d\n", iterations );
+ printf( " elapsed: %0.9f\n", elapsed );
+ printf( " rate: %0.9f\n", rate );
+ printf( " ...\n" );
+}
+
+/**
+* Returns a clock time.
+*
+* @return clock time
+*/
+static double tic( void ) {
+ struct timeval now;
+ gettimeofday( &now, NULL );
+ return (double)now.tv_sec + (double)now.tv_usec/1.0e6;
+}
+
+/**
+* Generates a random number on the interval [min,max).
+*
+* @param min minimum value (inclusive)
+* @param max maximum value (exclusive)
+* @return random number
+*/
+static double random_uniform( const double min, const double max ) {
+ double v = (double)rand() / ( (double)RAND_MAX + 1.0 );
+ return min + ( v*(max-min) );
+}
+
+/**
+* Runs a benchmark.
+*
+* @param iterations number of iterations
+* @param N number of features
+* @return elapsed time in seconds
+*/
+static double benchmark1( int iterations, int N ) {
+ double elapsed;
+ double *ws;
+ double *x;
+ double *y;
+ double *w;
+ double t;
+ int i;
+ int j;
+
+ x = (double *) malloc( N * N * sizeof( double ) );
+ y = (double *) malloc( N * sizeof( double ) );
+ w = (double *) malloc( N * sizeof( double ) );
+ ws = (double *) malloc( N * sizeof( double ) );
+ for ( i = 0; i < N; i++ ) {
+ y[ i ] = random_uniform( -10.0, 10.0 ); // sgd regression
+ for ( j = 0; j < N; j++ ) {
+ w[ ( i*N ) + j ] = random_uniform( -0.05, 0.05 );
+ }
+ x[ i ] = random_uniform( -10.0, 10.0 );
+ }
+ struct stdlib_ml_sgd_float64_params params = {
+ .penaltyParams = { 2.5, 0.0 },
+ .learningRateParams = { 0.01, 0.0 },
+ .lossFunctionParams = { 0.0 },
+ .intercept = 0.0,
+ .maxIter = 500,
+ .penalty = STDLIB_ML_SGD_L2,
+ .learningRate = STDLIB_ML_SGD_CONSTANT,
+ .lossFunction = STDLIB_ML_SGD_HINGE,
+ .fitIntercept = true
+ };
+
+
+ t = tic();
+ for ( i = 0; i < iterations; i++ ) {
+ for ( j = 0; j < N; j++ ) {
+ ws[ j ] = 0.0;
+ }
+ stdlib_strided_dsgd_trainer( CblasRowMajor, N, N, x, N, y, 1, w, 1, ws, 1, ¶ms );
+ if ( y[ i%N ] != y[ i%N ] ) {
+ printf( "should not return NaN\n" );
+ break;
+ }
+ }
+ elapsed = tic() - t;
+ if ( y[ i%N ] != y[ i%N ] ) {
+ printf( "should not return NaN\n" );
+ }
+ free( x );
+ free( y );
+ free( w );
+ free( ws );
+ return elapsed;
+}
+
+/**
+* Runs a benchmark.
+*
+* @param iterations number of iterations
+* @param N number of features
+* @return elapsed time in seconds
+*/
+static double benchmark2( int iterations, int N ) {
+ double elapsed;
+ double *ws;
+ double *x;
+ double *y;
+ double *w;
+ double t;
+ int i;
+ int j;
+
+ x = (double *) malloc( N * N * sizeof( double ) );
+ y = (double *) malloc( N * sizeof( double ) );
+ w = (double *) malloc( N * sizeof( double ) );
+ ws = (double *) malloc( N * sizeof( double ) );
+ for ( i = 0; i < N; i++ ) {
+ y[ i ] = random_uniform( -10.0, 10.0 ); // sgd regression
+ for ( j = 0; j < N; j++ ) {
+ w[ ( i*N ) + j ] = random_uniform( -0.05, 0.05 );
+ }
+ x[ i ] = random_uniform( -10.0, 10.0 );
+ }
+ struct stdlib_ml_sgd_float64_params params = {
+ .penaltyParams = { 2.5, 0.0 },
+ .learningRateParams = { 0.01, 0.0 },
+ .lossFunctionParams = { 0.0 },
+ .intercept = 0.0,
+ .maxIter = 500,
+ .penalty = 2, // l2
+ .learningRate = 0, // constant
+ .lossFunction = 0, // hinge
+ .fitIntercept = true
+ };
+
+
+ t = tic();
+ for ( i = 0; i < iterations; i++ ) {
+ for ( j = 0; j < N; j++ ) {
+ ws[ j ] = 0.0;
+ }
+ stdlib_strided_dsgd_trainer_ndarray( N, N, x, N, N, 0, y, 1, 0, w, 1, 0, ws, 1, 0, ¶ms );
+ if ( y[ i%N ] != y[ i%N ] ) {
+ printf( "should not return NaN\n" );
+ break;
+ }
+ }
+ elapsed = tic() - t;
+ if ( y[ i%N ] != y[ i%N ] ) {
+ printf( "should not return NaN\n" );
+ }
+ free( x );
+ free( y );
+ free( w );
+ free( ws );
+ return elapsed;
+}
+
+/**
+* Main execution sequence.
+*/
+int main( void ) {
+ double elapsed;
+ int count;
+ int iter;
+ int N;
+ int i;
+ int j;
+
+ // Use the current time to seed the random number generator:
+ srand( time( NULL ) );
+
+ print_version();
+ count = 0;
+ for ( i = MIN; i <= MAX; i++ ) {
+ N = floor( pow( pow( 10, i ), 1.0/2.0 ) );
+ iter = ITERATIONS / pow( 10, i-1 );
+ for ( j = 0; j < REPEATS; j++ ) {
+ count += 1;
+ printf( "# c::%s:size=%d\n", NAME, N*N );
+ elapsed = benchmark1( iter, N );
+ print_results( iter, elapsed );
+ printf( "ok %d benchmark finished\n", count );
+ }
+ for ( j = 0; j < REPEATS; j++ ) {
+ count += 1;
+ printf( "# c::%s:ndarray:size=%d\n", NAME, N*N );
+ elapsed = benchmark2( iter, N );
+ print_results( iter, elapsed );
+ printf( "ok %d benchmark finished\n", count );
+ }
+ }
+ print_summary( count, count );
+}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/docs/repl.txt b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/docs/repl.txt
new file mode 100644
index 000000000000..5f39e8690d66
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/docs/repl.txt
@@ -0,0 +1,224 @@
+
+{{alias}}( order, M, N, X, LDX, y, sy, w, sw, ws, sws, params )
+ Trains a linear model via stochastic gradient descent.
+
+ Indexing is relative to the first index. To introduce an offset, use typed
+ array views.
+
+ If `M` or `N` is equal to `0`, the function returns `w` unchanged.
+
+ Parameters
+ ----------
+ order: string
+ Row-major (C-style) or column-major (Fortran-style) order.
+
+ M: integer
+ Number of samples.
+
+ N: integer
+ Number of features.
+
+ X: Float64Array
+ Input matrix.
+
+ LDX: integer
+ Stride of the first dimension of `X` (a.k.a., leading dimension of the
+ matrix `X`).
+
+ y: Float64Array
+ Target array.
+
+ sy: integer
+ Stride length for `y`.
+
+ w: Float64Array
+ Weight array.
+
+ sw: integer
+ Stride length for `w`.
+
+ ws: Float64Array
+ Workspace array.
+
+ sws: integer
+ Stride length for `ws`.
+
+ params: Object
+ Params object.
+
+ Returns
+ -------
+ w: Float64Array
+ Weight array.
+
+ Examples
+ --------
+ // Standard usage:
+ > var ord = 'row-major';
+ > var M = 50;
+ > var N = 5;
+ > var lambda = 2.5;
+ > var eta0 = 0.01;
+ >
+ > var y = {{alias:@stdlib/random/array/discrete-uniform}}( M, 0.0, 30.0 );
+ > var X = {{alias:@stdlib/random/array/discrete-uniform}}( M*N, -5.0, 5.0 );
+ > var w = {{alias:@stdlib/random/array/discrete-uniform}}( N, -0.05, 0.05 );
+ > var workspace = new {{alias:@stdlib/array/float64}}( N );
+ >
+ > var params = {{alias:@stdlib/ml/base/sgd/params/float64}}({
+ ... 'penaltyParams': new Float64Array( [ lambda, 0.0 ] ),
+ ... 'learningRateParams': new Float64Array( [ eta0, 0.0 ] ),
+ ... 'intercept': 0.0,
+ ... 'maxIter': 500,
+ ... 'penalty': 'l2',
+ ... 'learningRate': 'constant',
+ ... 'lossFunction': 'hinge',
+ ... 'fitIntercept': true
+ > });
+ > {{alias}}( ord, M, N, X, N, y, 1, w, 1, workspace, 1, params );
+ [ ... ]
+
+ // Advanced indexing:
+ > var ord = 'row-major';
+ > var M = 50;
+ > var N = 5;
+ > var lambda = 2.5;
+ > var eta0 = 0.01;
+ >
+ > var y = {{alias:@stdlib/random/array/discrete-uniform}}( M, 0.0, 30.0 );
+ > var X = {{alias:@stdlib/random/array/discrete-uniform}}( M*N, -5.0, 5.0 );
+ > var w = {{alias:@stdlib/random/array/discrete-uniform}}( N, -0.05, 0.05 );
+ > var workspace = new {{alias:@stdlib/array/float64}}( N );
+ >
+ > var params = {{alias:@stdlib/ml/base/sgd/params/float64}}({
+ ... 'penaltyParams': new Float64Array( [ lambda, 0.0 ] ),
+ ... 'learningRateParams': new Float64Array( [ eta0, 0.0 ] ),
+ ... 'intercept': 0.0,
+ ... 'maxIter': 500,
+ ... 'penalty': 'l2',
+ ... 'learningRate': 'constant',
+ ... 'lossFunction': 'hinge',
+ ... 'fitIntercept': true
+ });
+ > {{alias}}( M, N, X, N, y, -1, w, -1, workspace, -1, params );
+ [ ... ]
+
+ // Using typed array views:
+ > var ord = 'row-major';
+ > var M = 50;
+ > var N = 5;
+ > var lambda = 2.5;
+ > var eta0 = 0.01;
+ >
+ > var y0 = {{alias:@stdlib/random/array/discrete-uniform}}( M, 0.0, 30.0 );
+ > var X0 = {{alias:@stdlib/random/array/discrete-uniform}}( M*N, -5.0, 5.0 );
+ > var w0 = {{alias:@stdlib/random/array/discrete-uniform}}( N, -0.05, 0.05 );
+ > var workspace = new {{alias:@stdlib/array/float64}}( N );
+ >
+ > var y1 = new {{alias:@stdlib/array/float64}}( y0.buffer, y0.BYTES_PER_ELEMENT*1 );
+ > var w1 = new {{alias:@stdlib/array/float64}}( w0.buffer, w0.BYTES_PER_ELEMENT*1 );
+ > var params = {{alias:@stdlib/ml/base/sgd/params/float64}}({
+ ... 'penaltyParams': new Float64Array( [ lambda, 0.0 ] ),
+ ... 'learningRateParams': new Float64Array( [ eta0, 0.0 ] ),
+ ... 'intercept': 0.0,
+ ... 'maxIter': 500,
+ ... 'penalty': 'l2',
+ ... 'learningRate': 'constant',
+ ... 'lossFunction': 'hinge',
+ ... 'fitIntercept': true
+ });
+ > {{alias}}( M, N, X, N, y1, -1, w1, -1, workspace, -1, params );
+ [ ... ]
+
+
+{{alias}}.ndarray( M,N, X, sx1,sx2,ox, y, sy,oy, w, sw,ow, ws, sws,ows, params )
+ Trains a linear model via stochastic gradient descent using alternative
+ indexing semantics.
+
+ While typed array views mandate a view offset based on the underlying
+ buffer, the offset parameters support indexing semantics based on starting
+ indices.
+
+ Parameters
+ ----------
+ M: integer
+ Number of samples.
+
+ N: integer
+ Number of features.
+
+ X: Float64Array
+ Input matrix.
+
+ sx1: integer
+ First stride length for `X`.
+
+ sx2: integer
+ Second stride length for `X`.
+
+ ox: integer
+ Starting index for `X`.
+
+ y: Float64Array
+ Target array.
+
+ sy: integer
+ Stride length for `y`.
+
+ oy: integer
+ Starting index for `y`.
+
+ w: Float64Array
+ Weight array.
+
+ sw: integer
+ Stride length for `w`.
+
+ ow: integer
+ Starting index for `w`.
+
+ ws: Float64Array
+ Workspace array.
+
+ sws: integer
+ Stride length for `ws`.
+
+ ows: integer
+ Starting index for `ws`.
+
+ params: Object
+ Params object.
+
+ Returns
+ -------
+ w: Float64Array
+ Weight array.
+
+ Examples
+ --------
+ > var ord = 'row-major';
+ > var M = 50;
+ > var N = 5;
+ > var lambda = 2.5;
+ > var eta0 = 0.01;
+ >
+ > var y = {{alias:@stdlib/random/array/discrete-uniform}}( M, 0.0, 30.0 );
+ > var X = {{alias:@stdlib/random/array/discrete-uniform}}( M*N, -5.0, 5.0 );
+ > var w = {{alias:@stdlib/random/array/discrete-uniform}}( N, -0.05, 0.05 );
+ > var workspace = new {{alias:@stdlib/array/float64}}( N );
+ >
+ > var params = {{alias:@stdlib/ml/base/sgd/params/float64}}({
+ ... 'penaltyParams': new Float64Array( [ lambda, 0.0 ] ),
+ ... 'learningRateParams': new Float64Array( [ eta0, 0.0 ] ),
+ ... 'intercept': 0.0,
+ ... 'maxIter': 500,
+ ... 'penalty': 'l2',
+ ... 'learningRate': 'constant',
+ ... 'lossFunction': 'hinge',
+ ... 'fitIntercept': true
+ > });
+ > {{alias}}( M, N, X, N, 1, 0, y, 1, 0, w, 1, 0, workspace, 1, 0, params );
+ [ ... ]
+
+ See Also
+ --------
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/docs/types/index.d.ts b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/docs/types/index.d.ts
new file mode 100644
index 000000000000..129d2edd4a0d
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/docs/types/index.d.ts
@@ -0,0 +1,311 @@
+/*
+* @license Apache-2.0
+*
+* Copyright (c) 2024 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.
+*/
+
+// TypeScript Version: 4.1
+
+///
+
+import { Layout } from '@stdlib/types/blas';
+
+/**
+* Interface describing SGD trainer parameters.
+*/
+interface Params {
+ /**
+ * Parameters specific to the regularization function being used.
+ *
+ * ## Notes
+ *
+ * - Must be an array having length `2`, with any unused elements set to zero. The expected array contents depend on the penalty:
+ *
+ * - **l1**: `[ lambda, 0.0 ]`
+ * - **l2**: `[ lambda, 0.0 ]`
+ * - **elasticnet**: `[ lambda, l1Ratio ]`
+ * - **none**: `[ 0.0, 0.0 ]` (unused)
+ *
+ * where:
+ *
+ * - **lambda**: regularization parameter which determines the amount of shrinkage inflicted on the model coefficients.
+ * - **l1Ratio**: mixing parameter on the interval `[0,1]` which determines the relative contribution of the L1 and L2 penalties.
+ */
+ penaltyParams?: Float64Array;
+
+ /**
+ * Parameters specific to the learning rate scheduler being used.
+ *
+ * ## Notes
+ *
+ * - Must be an array having length `2`, with any unused elements set to zero. The expected array contents depend on the learning rate scheduler:
+ *
+ * - **basic**: `[ 0.0, 0.0 ]` (unused)
+ * - **constant**: `[ eta0, 0.0 ]`
+ * - **invscaling**: `[ eta0, powerT ]`
+ * - **pegasos**: `[ lambda, 0.0 ]`
+ *
+ * where:
+ *
+ * - **eta0**: initial learning rate.
+ * - **powerT**: exponent controlling how quickly the learning rate decreases.
+ * - **lambda**: regularization parameter.
+ */
+ learningRateParams?: Float64Array;
+
+ /**
+ * Parameters specific to the loss function being used.
+ *
+ * ## Notes
+ *
+ * - Must be an array having length `1`. The expected array contents depend on the loss function:
+ *
+ * - **epsilon-insensitive**: `[ epsilon ]`
+ * - **squared-epsilon-insensitive**: `[ epsilon ]`
+ * - **huber**: `[ threshold ]`
+ * - all other loss functions: `[ 0.0 ]` (unused)
+ *
+ * where:
+ *
+ * - **epsilon**: insensitivity parameter (i.e., errors whose absolute value is less than `epsilon` incur no penalty).
+ * - **threshold**: error magnitude at which the loss transitions from squared-error loss to linear loss.
+ */
+ lossFunctionParams?: Float64Array;
+
+ /**
+ * Initial intercept value.
+ *
+ * ## Notes
+ *
+ * - Only applicable when `fitIntercept` is `true`.
+ */
+ intercept?: number;
+
+ /**
+ * Maximum number of iterations to run.
+ */
+ maxIter?: number;
+
+ /**
+ * Regularization function.
+ */
+ penalty?: number;
+
+ /**
+ * Learning rate scheduler.
+ */
+ learningRate?: number;
+
+ /**
+ * Loss function.
+ */
+ lossFunction?: number;
+
+ /**
+ * Boolean indicating whether to include intercept.
+ *
+ * ## Notes
+ *
+ * - If `true`, an element equal to one is implicitly added to each provided feature vector. If `false`, the model assumes that feature vectors are already centered.
+ */
+ fitIntercept?: boolean;
+}
+
+/**
+* Interface describing `dsgdTrainer`.
+*/
+interface Routine {
+ /**
+ * Trains a linear model via stochastic gradient descent.
+ *
+ * @param order - storage layout
+ * @param M - number of samples
+ * @param N - number of features
+ * @param X - input matrix
+ * @param LDX - stride of the first dimension of `X` (a.k.a., leading dimension of the matrix `X`)
+ * @param y - target array
+ * @param strideY - stride length for `y`
+ * @param w - weight array
+ * @param strideW - stride length for `w`
+ * @param workspace - workspace array of size `N` for tracking total L1 shrinkage applied to each feature
+ * @param strideWS - stride length for `workspace`
+ * @param params - parameters object
+ * @returns `w`
+ *
+ * @example
+ * var Float64Array = require( '@stdlib/array/float64' );
+ * var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+ * var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+ *
+ * var M = 50;
+ * var N = 5;
+ * var lambda = 2.5;
+ * var eta0 = 0.01;
+ *
+ * var params = new Params({
+ * 'penaltyParams': new Float64Array( [ lambda, 0.0 ] ),
+ * 'learningRateParams': new Float64Array( [ eta0, 0.0 ] ),
+ * 'intercept': 0.0,
+ * 'maxIter': 500,
+ * 'penalty': 'l2',
+ * 'learningRate': 'constant',
+ * 'lossFunction': 'hinge',
+ * 'fitIntercept': true
+ * });
+ *
+ * var y = discreteUniform( M, 0.0, 30.0 );
+ * var x = discreteUniform( M*N, -5.0, 5.0 );
+ * var w = discreteUniform( N, -0.05, 0.05 );
+ * var workspace = new Float64Array( N );
+ *
+ * var out = dsgdTrainer( 'row-major', M, N, x, N, y, 1, w, 1, workspace, 1, params );
+ * returns
+ */
+ ( order: Layout, M: number, N: number, X: Float64Array, LDX: number, y: Float64Array, strideY: number, w: Float64Array, strideW: number, ws: Float64Array, strideWS: number, params: Params ): Float64Array;
+
+ /**
+ * Trains a linear model via stochastic gradient descent using alternative indexing semantics.
+ *
+ * @param M - number of samples
+ * @param N - number of features
+ * @param X - input matrix
+ * @param strideX1 - stride of the first dimension of `X`
+ * @param strideX2 - stride of the second dimension of `X`
+ * @param offsetX - starting index for `X`
+ * @param y - target array
+ * @param strideY - stride length for `y`
+ * @param offsetY - starting index for `y`
+ * @param w - weight array
+ * @param strideW - stride length for `w`
+ * @param offsetW - starting index for `w`
+ * @param workspace - workspace array
+ * @param strideWS - stride length for `workspace`
+ * @param offsetWS - starting index for `workspace`
+ * @param {Params} params - parameters object
+ * @returns `y`
+ *
+ * @example
+ * var Float64Array = require( '@stdlib/array/float64' );
+ * var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+ * var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+ *
+ * var M = 50;
+ * var N = 5;
+ * var lambda = 2.5;
+ * var eta0 = 0.01;
+ *
+ * var params = new Params({
+ * 'penaltyParams': new Float64Array( [ lambda, 0.0 ] ),
+ * 'learningRateParams': new Float64Array( [ eta0, 0.0 ] ),
+ * 'intercept': 0.0,
+ * 'maxIter': 500,
+ * 'penalty': 'l2',
+ * 'learningRate': 'constant',
+ * 'lossFunction': 'hinge',
+ * 'fitIntercept': true
+ * });
+ *
+ * var y = discreteUniform( M, 0.0, 30.0 );
+ * var X = discreteUniform( M*N, -5.0, 5.0 );
+ * var w = discreteUniform( N, -0.05, 0.05 );
+ * var workspace = new Float64Array( N );
+ *
+ * var out = dsgdTrainer.ndarray( M, N, X, N, 1, 0, y, 1, 0, w, 1, 0, workspace, 1, 0, params );
+ * returns
+ */
+ ndarray( M: number, N: number, X: Float64Array, strideX1: number, strideX2: number, offsetX: number, y: Float64Array, strideY: number, offset: number, w: Float64Array, strideW: number, offsetW: number, ws: Float64Array, strideWS: number, offsetWS: number, params: Params ): Float64Array;
+}
+
+/**
+* Trains a linear model via stochastic gradient descent.
+*
+* @param order - storage layout
+* @param M - number of samples
+* @param N - number of features
+* @param X - input matrix
+* @param LDX - stride of the first dimension of `X` (a.k.a., leading dimension of the matrix `X`)
+* @param y - target array
+* @param strideY - stride length for `y`
+* @param w - weight array
+* @param strideW - stride length for `w`
+* @param workspace - workspace array of size `N` for tracking total L1 shrinkage applied to each feature
+* @param strideWS - stride length for `workspace`
+* @param params - parameters object
+* @returns `w`
+*
+* @example
+* var Float64Array = require( '@stdlib/array/float64' );
+* var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+* var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+*
+* var M = 50;
+* var N = 5;
+* var lambda = 2.5;
+* var eta0 = 0.01;
+*
+* var params = new Params({
+* 'penaltyParams': new Float64Array( [ lambda, 0.0 ] ),
+* 'learningRateParams': new Float64Array( [ eta0, 0.0 ] ),
+* 'intercept': 0.0,
+* 'maxIter': 500,
+* 'penalty': 'l2',
+* 'learningRate': 'constant',
+* 'lossFunction': 'hinge',
+* 'fitIntercept': true
+* });
+*
+* var y = discreteUniform( M, 0.0, 30.0 );
+* var x = discreteUniform( M*N, -5.0, 5.0 );
+* var w = discreteUniform( N, -0.05, 0.05 );
+* var workspace = new Float64Array( N );
+*
+* var out = dsgdTrainer( 'row-major', M, N, x, N, y, 1, w, 1, workspace, 1, params );
+* returns
+*
+* @example
+* var Float64Array = require( '@stdlib/array/float64' );
+* var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+* var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+*
+* var M = 50;
+* var N = 5;
+* var lambda = 2.5;
+* var eta0 = 0.01;
+*
+* var params = new Params({
+* 'penaltyParams': new Float64Array( [ lambda, 0.0 ] ),
+* 'learningRateParams': new Float64Array( [ eta0, 0.0 ] ),
+* 'intercept': 0.0,
+* 'maxIter': 500,
+* 'penalty': 'l2',
+* 'learningRate': 'constant',
+* 'lossFunction': 'hinge',
+* 'fitIntercept': true
+* });
+*
+* var y = discreteUniform( M, 0.0, 30.0 );
+* var X = discreteUniform( M*N, -5.0, 5.0 );
+* var w = discreteUniform( N, -0.05, 0.05 );
+* var workspace = new Float64Array( N );
+*
+* var out = dsgdTrainer.ndarray( M, N, X, N, 1, 0, y, 1, 0, w, 1, 0, workspace, 1, 0, params );
+* returns
+*/
+declare var dsgdTrainer: Routine;
+
+
+// EXPORTS //
+
+export = dsgdTrainer;
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/docs/types/test.ts b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/docs/types/test.ts
new file mode 100644
index 000000000000..81d6bc70eec3
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/docs/types/test.ts
@@ -0,0 +1,564 @@
+/*
+* @license Apache-2.0
+*
+* Copyright (c) 2024 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.
+*/
+
+import Float64Params = require( '@stdlib/ml/base/sgd/params/float64' );
+import dsgdTrainer = require( './index' );
+
+
+// TESTS //
+
+
+// The function returns a Float64Array...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectType Float64Array
+}
+
+// The compiler throws an error if the function is provided a first argument which is not a string...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer( 10, 10, 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( true, 10, 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( false, 10, 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( null, 10, 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( undefined, 10, 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( [], 10, 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( {}, 10, 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( ( x: number ): number => x, 10, 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a second argument which is not a number...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer( 'row-major', '10', 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', true, 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', false, 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', null, 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', undefined, 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', [ '1' ], 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', {}, 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', ( x: number ): number => x, 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a third argument which is not a number...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer( 'row-major', 10, '10', x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, true, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, false, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, null, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, undefined, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, [], x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, {}, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, ( x: number ): number => x, x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a fourth argument which is not a Float64Array...
+{
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer( 'row-major', 10, 10, '10', 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, true, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, false, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, null, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, undefined, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, [], 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, {}, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, ( x: number ): number => x, 10, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a fifth argument which is not a number...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer( 'row-major', 10, 10, x, '10', y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, true, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, false, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, null, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, undefined, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, [], y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, {}, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, ( x: number ): number => x, y, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a sixth argument which is not a Float64Array...
+{
+ const x = new Float64Array( 10*10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer( 'row-major', 10, 10, x, 10, 10, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, '10', 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, true, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, false, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, null, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, undefined, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, [ '1' ], 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, {}, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, ( x: number ): number => x, 1, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a seventh argument which is not a number...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, '10', w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, true, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, false, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, null, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, undefined, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, [], w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, {}, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, ( x: number ): number => x, w, 1, ws, 1, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided an eighth argument which is not a Float64Array...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, 10, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, '10', 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, true, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, false, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, null, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, undefined, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, [ '1' ], 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, {}, 1, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, ( x: number ): number => x, 1, ws, 1, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a ninth argument which is not a number...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, '10', ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, true, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, false, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, null, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, undefined, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, [], ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, {}, ws, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, ( x: number ): number => x, ws, 1, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a tenth argument which is not a Float64Array...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, '10', 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, true, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, false, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, null, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, undefined, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, [], 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, {}, 1, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ( x: number ): number => x, 1, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided an eleventh argument which is not a number...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, 10, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, '10', new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, true, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, false, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, null, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, undefined, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, [ '1' ], new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, {}, new Float64Params() ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, ( x: number ): number => x, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a twelfth argument which is not a params object...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, 1, 10 ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, 1, '10' ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, 1, true ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, 1, false ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, 1, null ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, 1, undefined ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, 1, [ '1' ] ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, 1, {} ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, 1, ( x: number ): number => x ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided an unsupported number of arguments...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer(); // $ExpectError
+ dsgdTrainer( 'row-major' ); // $ExpectError
+ dsgdTrainer( 'row-major', 10 ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10 ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10 ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1 ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1 ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, 1 ); // $ExpectError
+ dsgdTrainer( 'row-major', 10, 10, x, 10, y, 1, w, 1, ws, 1, new Float64Params(), 10 ); // $ExpectError
+}
+
+// Attached to main export is an `ndarray` method which returns a Float64Array...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectType Float64Array
+}
+
+// The compiler throws an error if the function is provided a first argument which is not a number...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray( '10', 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( true, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( false, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( null, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( undefined, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( [ '1' ], 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( {}, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( ( x: number ): number => x, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a second argument which is not a number...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray( 10, '10', x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, true, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, false, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, null, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, undefined, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, [], x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, {}, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, ( x: number ): number => x, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a third argument which is not a Float64Array...
+{
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray( 10, 10, '10', 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, true, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, false, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, null, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, undefined, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, [], 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, {}, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, ( x: number ): number => x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a fourth argument which is not a number...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray( 10, 10, x, '10', 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, true, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, false, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, null, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, undefined, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, [], 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, {}, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, ( x: number ): number => x, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a fifth argument which is not a number...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray( 10, 10, x, 10, '10', 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, true, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, false, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, null, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, undefined, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, [], 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, {}, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, ( x: number ): number => x, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a sixth argument which is not a number...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, '10', y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, true, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, false, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, null, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, undefined, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, [], y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, {}, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, ( x: number ): number => x, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a seventh argument which is not a Float64Array...
+{
+ const x = new Float64Array( 10*10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, '10', 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, true, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, false, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, null, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, undefined, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, [], 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, {}, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, ( x: number ): number => x, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided an eighth argument which is not a number...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Params( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, '10', 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, true, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, false, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, null, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, undefined, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, [], 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, {}, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, ( x: number ): number => x, 0, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a ninth argument which is not a number...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Params( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, '10', w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, true, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, false, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, null, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, undefined, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, [], w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, {}, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, ( x: number ): number => x, w, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a tenth argument which is not a Float64Array...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Params( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, '10', 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, true, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, false, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, null, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, undefined, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, [], 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, {}, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, ( x: number ): number => x, 1, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided an eleventh argument which is not a number...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Params( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, '10', 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, true, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, false, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, null, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, undefined, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, [], 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, {}, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, ( x: number ): number => x, 0, ws, 1, 0, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a twelfth argument which is not a number...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Params( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, '10', ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, true, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, false, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, null, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, undefined, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, [], ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, {}, ws, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, ( x: number ): number => x, ws, 1, 0, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a thirteenth argument which is not a Float64Array...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Params( 10 );
+ const w = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, '10', 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, true, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, false, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, null, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, undefined, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, [], 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, {}, 1, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ( x: number ): number => x, 1, 0, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a fourteenth argument which is not a number...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Params( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, '10', 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, true, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, false, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, null, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, undefined, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, [], 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, {}, 0, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, ( x: number ): number => x, 0, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a fifteenth argument which is not a number...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Params( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, '10', new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, true, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, false, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, null, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, undefined, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, [], new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, {}, new Float64Params() ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, ( x: number ): number => x, new Float64Params() ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a sixteenth argument which is not a params object...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Params( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, '10' ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, true ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, false ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, null ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, undefined ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, [] ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, {} ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, ( x: number ): number => x ); // $ExpectError
+}
+
+// The compiler throws an error if the `ndarray` method is provided an unsupported number of arguments...
+{
+ const x = new Float64Array( 10*10 );
+ const y = new Float64Array( 10 );
+ const w = new Float64Array( 10 );
+ const ws = new Float64Array( 10 );
+
+ dsgdTrainer.ndarray(); // $ExpectError
+ dsgdTrainer.ndarray( 10 ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10 ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10 ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1 ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0 ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1 ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0 ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1 ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0 ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1 ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0 ); // $ExpectError
+ dsgdTrainer.ndarray( 10, 10, x, 10, 1, 0, y, 1, 0, w, 1, 0, ws, 1, 0, new Float64Params(), 10 ); // $ExpectError
+}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/include/stdlib/ml/strided/dsgd_trainer.h b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/include/stdlib/ml/strided/dsgd_trainer.h
new file mode 100644
index 000000000000..2e4d26cec812
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/include/stdlib/ml/strided/dsgd_trainer.h
@@ -0,0 +1,85 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2025 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.
+*/
+
+/**
+* Header file containing function declarations for training a linear model via stochastic gradient descent.
+*/
+#ifndef STDLIB_ML_STRIDED_DSGD_TRAINER_H
+#define STDLIB_ML_STRIDED_DSGD_TRAINER_H
+
+#include "stdlib/ml/base/sgd/learning_rates.h"
+#include "stdlib/ml/base/sgd/loss_functions.h"
+#include "stdlib/ml/base/sgd/penalties.h"
+#include "stdlib/blas/base/shared.h"
+#include
+#include
+
+/*
+* If C++, prevent name mangling so that the compiler emits a binary file having undecorated names, thus mirroring the behavior of a C compiler.
+*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* Struct for storing SGD parameters.
+*/
+struct stdlib_ml_sgd_float64_params {
+ // Parameters specific to the regularization function being used:
+ double penaltyParams[ 2 ];
+
+ // Parameters specific to the learning rate scheduler being used:
+ double learningRateParams[ 2 ];
+
+ // Parameters specific to the loss function being used:
+ double lossFunctionParams[ 1 ];
+
+ // Initial intercept value:
+ double intercept;
+
+ // Maximum number of iterations to run:
+ int32_t maxIter;
+
+ // Regularization function to be used:
+ int8_t penalty;
+
+ // Learning rate scheduler to be used:
+ int8_t learningRate;
+
+ // Loss function to be used:
+ int8_t lossFunction;
+
+ // Boolean indicating whether to include intercept:
+ bool fitIntercept;
+};
+
+/**
+* Trains a linear model via stochastic gradient descent.
+*/
+double* API_SUFFIX(stdlib_strided_dsgd_trainer)( const CBLAS_LAYOUT layout, const CBLAS_INT M, const CBLAS_INT N, const double *X, const CBLAS_INT LDX, const double *y, const CBLAS_INT strideY, double *w, const CBLAS_INT strideW, double *ws, const CBLAS_INT strideWS, const struct stdlib_ml_sgd_float64_params *params );
+
+/**
+* Trains a linear model via stochastic gradient descent using alternative indexing semantics.
+*/
+double* API_SUFFIX(stdlib_strided_dsgd_trainer_ndarray)( const CBLAS_INT M, const CBLAS_INT N, const double *x, const CBLAS_INT strideX1, const CBLAS_INT strideX2, const CBLAS_INT offsetX, const double *y, const CBLAS_INT strideY, const CBLAS_INT offsetY, double *w, const CBLAS_INT strideW, const CBLAS_INT offsetW, double *ws, const CBLAS_INT strideWS, const CBLAS_INT offsetWS, const struct stdlib_ml_sgd_float64_params *params );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !STDLIB_ML_STRIDED_DSGD_TRAINER_H
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/base.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/base.js
new file mode 100644
index 000000000000..d147653ed083
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/base.js
@@ -0,0 +1,226 @@
+/**
+* @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 params2json = require( '@stdlib/ml/base/sgd/params/to-json' );
+
+var logger = require( 'debug' );
+var ddot = require( '@stdlib/blas/base/ddot' ).ndarray;
+var daxpy = require( '@stdlib/blas/base/daxpy' ).ndarray;
+var dscal = require( '@stdlib/blas/base/dscal' ).ndarray;
+var LEARNING_RATE_METHODS = require( './learning_rate.js' );
+var LOSS_FUNCTIONS = require( './loss.js' );
+var DECAYS = require( './decay.js' );
+var TRUNCATIONS = require( './truncation.js' );
+
+
+// VARIABLES //
+
+var debug = logger( 'ml:dsgd-trainer-squared-epsilon-insensitive' );
+
+var MIN_SCALE = 1.0e-9;
+var MAX_DLOSS = 1e12;
+
+
+// MAIN //
+
+/**
+* Trains a linear model via stochastic gradient descent.
+*
+* @private
+* @param {NonNegativeInteger} M - number of samples
+* @param {NonNegativeInteger} N - number of features
+* @param {Float64Array} X - input matrix
+* @param {integer} strideX1 - stride of the first dimension of `X`
+* @param {integer} strideX2 - stride of the second dimension of `X`
+* @param {NonNegativeInteger} offsetX - starting index for `X`
+* @param {Float64Array} y - target array
+* @param {integer} strideY - stride length for `y`
+* @param {NonNegativeInteger} offsetY - starting index for `y`
+* @param {Float64Array} w - weight array
+* @param {integer} strideW - stride length for `w`
+* @param {NonNegativeInteger} offsetW - starting index for `w`
+* @param {Float64Array} workspace - workspace array
+* @param {integer} strideWS - stride length for `workspace`
+* @param {NonNegativeInteger} offsetWS - starting index for `workspace`
+* @param {Params} params - parameters object
+* @returns {Float64Array} `w`
+*
+* @example
+* var Float64Array = require( '@stdlib/array/float64' );
+* var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+* var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+*
+* var M = 50;
+* var N = 5;
+* var lambda = 2.5;
+* var eta0 = 0.01;
+*
+* var params = new Params({
+* 'penaltyParams': new Float64Array( [ lambda, 0.0 ] ),
+* 'learningRateParams': new Float64Array( [ eta0, 0.0 ] ),
+* 'intercept': 0.0,
+* 'maxIter': 500,
+* 'penalty': 'l2',
+* 'learningRate': 'constant',
+* 'lossFunction': 'hinge',
+* 'fitIntercept': true
+* });
+*
+* var y = discreteUniform( M, 0.0, 30.0 );
+* var X = discreteUniform( M*N, -5.0, 5.0 );
+* var w = discreteUniform( N, -0.05, 0.05 );
+* var workspace = new Float64Array( N );
+*
+* var out = dsgdTrainer( M, N, X, N, 1, 0, y, 1, 0, w, 1, 0, workspace, 1, 0, params );
+* returns
+*/
+function dsgdTrainer( M, N, X, strideX1, strideX2, offsetX, y, strideY, offsetY, w, strideW, offsetW, workspace, strideWS, offsetWS, params ) { // eslint-disable-line max-params, max-len
+ var lossFunctionParams;
+ var learningRateParams;
+ var penaltyParams;
+ var lossFunction;
+ var learningRate;
+ var fitIntercept;
+ var scaleFactor;
+ var intercept;
+ var penalty;
+ var decayFn;
+ var truncFn;
+ var maxIter;
+ var lossFn;
+ var update;
+ var epoch;
+ var dloss;
+ var lrFn;
+ var eta;
+ var ox;
+ var oy;
+ var t;
+ var p;
+ var i;
+ var u;
+
+ penalty = params.penalty;
+ lossFunction = params.lossFunction;
+ learningRate = params.learningRate;
+ lrFn = LEARNING_RATE_METHODS[ learningRate ];
+ lossFn = LOSS_FUNCTIONS[ lossFunction ];
+ decayFn = DECAYS[ penalty ];
+ truncFn = TRUNCATIONS[ penalty ];
+ lossFunctionParams = params.lossFunctionParams;
+ learningRateParams = params.learningRateParams;
+ penaltyParams = params.penaltyParams;
+ fitIntercept = params.fitIntercept;
+ intercept = params.intercept;
+ maxIter = params.maxIter;
+
+ debug( 'Starting SGD trainer with %i samples and %i features', M, N );
+ // debug( params2json( params ) );
+
+ /*
+ * w - N (feature vector)
+ * X - M*N (input vector)
+ * y - M (output vector)
+ */
+
+ /**
+ * y -> [ ... ] (vector of size M, as there are M samples)
+ * w -> [ ... ] (vector of size N, as there are N weights, one per input feature)
+ * X -> [ ... ] (vector of size MxN, as there are N features per sample, M samples)
+ */
+
+ if ( penalty === 2 ) { // l2
+ penaltyParams[ 1 ] = 0.0;
+ } else if ( penalty === 1 ) { // l1
+ penaltyParams[ 1 ] = 1.0;
+ }
+
+ t = 1;
+ u = 0.0;
+ scaleFactor = 1.0;
+ for ( epoch = 1; epoch <= maxIter; epoch++ ) {
+ ox = offsetX;
+ oy = offsetY;
+ for ( i = 0; i < M; i++ ) {
+ p = ( scaleFactor*ddot( N, w, strideW, offsetW, X, strideX2, ox ) ) + intercept; // eslint-disable-line max-len
+
+ eta = lrFn( t, learningRateParams ); // eslint-disable-line max-len
+
+ dloss = lossFn( y[ oy ], p, lossFunctionParams ); // eslint-disable-line max-len
+ if ( dloss < -MAX_DLOSS ) {
+ dloss = -MAX_DLOSS;
+ } else if ( dloss > MAX_DLOSS ) {
+ dloss = MAX_DLOSS;
+ }
+ update = -eta * dloss;
+
+ scaleFactor = decayFn( scaleFactor, eta, penaltyParams ); // eslint-disable-line max-len
+ // if ( penalty === 'l2' || penalty === 'elasticnet' ) {
+ // factor = 1.0 - ( ( 1.0 - l1Ratio ) * eta * lambda );
+ // scaleFactor *= max( 0.0, factor );
+ // }
+
+ if ( scaleFactor < MIN_SCALE ) {
+ dscal( N, scaleFactor, w, strideW, offsetW );
+ scaleFactor = 1.0;
+ }
+
+ // Gradient step: as `w_eff = w_stored*scaleFactor`, adding `update*X` to the effective weights amounts to adding `(update/scaleFactor)*X` to the stored weights...
+ daxpy( N, update/scaleFactor, X, strideX2, ox, w, strideW, offsetW ); // eslint-disable-line max-len
+
+ if ( fitIntercept ) {
+ intercept += update;
+ }
+
+ u = truncFn( N, u, eta, scaleFactor, w, strideW, offsetW, workspace, strideWS, offsetWS, penaltyParams ); // eslint-disable-line max-len
+ // if ( penalty === 'l1' || penalty === 'elasticnet' ) {
+ // u += ( l1Ratio * eta * lambda );
+ // l1Penalty( N, u, scaleFactor, w, strideW, offsetW, workspace, strideWS, offsetWS ); // eslint-disable-line max-len
+ // }
+
+ t += 1;
+ ox += strideX1;
+ oy += strideY;
+ }
+ debug( 'Epoch %d done...', epoch );
+ }
+
+ // Fold any residual scale back into the weights so `w` holds effective values:
+ if ( scaleFactor !== 1 ) {
+ dscal( N, scaleFactor, w, strideW, offsetW );
+ scaleFactor = 1.0;
+ }
+
+ debug( 'Finished SGD trainer.' );
+
+ if ( fitIntercept ) {
+ w[ offsetW + ( strideW * N ) ] = intercept; // We expect consumer to pass an array of size N+1 if they set `fitIntercept = true`
+ // TODO: Do a size check in sgd_trainer.js
+ // if `fitIntercept = true`, check if its size is N+1
+ }
+ return w;
+}
+
+
+// EXPORTS //
+
+module.exports = dsgdTrainer;
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/decay.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/decay.js
new file mode 100644
index 000000000000..6a6f74cf8327
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/decay.js
@@ -0,0 +1,87 @@
+/**
+* @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 max = require( '@stdlib/math/base/special/max' );
+
+
+// VARIABLES //
+
+/**
+* Weight decay functions.
+*
+* @private
+* @name DECAYS
+* @constant
+* @type {Object}
+*
+* @example
+* var f = DECAYS[ 'l1' ];
+* // returns
+*/
+var DECAYS = {
+ 'elasticnet': l2Decay,
+ 'l1': identityDecay,
+ 'l2': l2Decay,
+ 'none': identityDecay
+};
+
+
+// FUNCTIONS //
+
+/**
+* Computes scale factor by applying the identity decay.
+*
+* Note:
+*
+* - Here **params**: `[ ]` (empty)
+*
+* @private
+* @param {NonNegativeInteger} scaleFactor - current iteration.
+* @param {NonNegativeInteger} eta - learning rate.
+* @param {Float64Array} params - strided array containing regularizer specific parameters.
+* @returns {number} scale factor
+*/
+function identityDecay( scaleFactor, eta, params ) { // eslint-disable-line no-unused-vars
+ return scaleFactor;
+}
+
+/**
+* Computes scale factor by applying the L2 decay.
+*
+* Note:
+*
+* - Here **params**: `[ lambda, l1Ratio ]`
+*
+* @private
+* @param {NonNegativeInteger} scaleFactor - current iteration.
+* @param {NonNegativeInteger} eta - learning rate.
+* @param {Float64Array} params - strided array containing regularizer specific parameters.
+* @returns {number} scale factor
+*/
+function l2Decay( scaleFactor, eta, params ) {
+ return scaleFactor * max( 0.0, 1.0 - ( ( 1.0 - params[ 1 ] ) * eta * params[ 0 ] ) ); // eslint-disable-line max-len
+}
+
+
+// EXPORTS //
+
+module.exports = DECAYS;
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/dsgd_trainer.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/dsgd_trainer.js
new file mode 100644
index 000000000000..2a35f6acbb07
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/dsgd_trainer.js
@@ -0,0 +1,164 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 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 isLayout = require( '@stdlib/blas/base/assert/is-layout' );
+var resolvePenaltyStr = require( '@stdlib/ml/base/sgd/penalty-resolve-str' );
+var resolveLRStr = require( '@stdlib/ml/base/sgd/learning-rate-resolve-str' );
+var resolveLossFnStr = require( '@stdlib/ml/base/sgd/loss-function-resolve-str' );
+var isColumnMajor = require( '@stdlib/ndarray/base/assert/is-column-major-string' );
+var stride2offset = require( '@stdlib/strided/base/stride2offset' );
+var max = require( '@stdlib/math/base/special/fast/max' );
+var format = require( '@stdlib/string/format' );
+var base = require( './base.js' );
+
+
+// MAIN //
+
+/**
+* Trains a linear model via stochastic gradient descent.
+*
+* @private
+* @param {string} order - storage layout
+* @param {NonNegativeInteger} M - number of samples
+* @param {NonNegativeInteger} N - number of features
+* @param {Float64Array} X - input matrix
+* @param {NonNegativeInteger} LDX - stride of the first dimension of `X` (a.k.a., leading dimension of the matrix `X`)
+* @param {Float64Array} y - target array
+* @param {integer} strideY - stride length for `y`
+* @param {Float64Array} w - weight array
+* @param {integer} strideW - stride length for `w`
+* @param {Float64Array} workspace - workspace array
+* @param {integer} strideWS - stride length for `workspace`
+* @param {Params} params - parameters object
+* @throws {TypeError} first argument must be a valid order
+* @throws {TypeError} thirteenth argument's `penalty` member must be a valid penalty
+* @throws {TypeError} thirteenth argument's `learningRate` member must be a valid learning rate
+* @throws {TypeError} thirteenth argument's `lossFunction` member must be a valid loss function
+* @throws {RangeError} second argument must be a nonnegative integer
+* @throws {RangeError} third argument must be a nonnegative integer
+* @throws {RangeError} fifth argument must be non-zero
+* @throws {RangeError} seventh argument must be a valid stride
+* @throws {RangeError} ninth argument must be a valid stride
+* @throws {RangeError} eleventh argument must be a valid stride
+* @returns {Float64Array} `w`
+*
+* @example
+* var Float64Array = require( '@stdlib/array/float64' );
+* var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+* var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+*
+* var M = 50;
+* var N = 5;
+* var lambda = 2.5;
+* var eta0 = 0.01;
+*
+* var params = new Params({
+* 'penaltyParams': new Float64Array( [ lambda, 0.0 ] ),
+* 'learningRateParams': new Float64Array( [ eta0, 0.0 ] ),
+* 'intercept': 0.0,
+* 'maxIter': 500,
+* 'penalty': 'l2',
+* 'learningRate': 'constant',
+* 'lossFunction': 'hinge',
+* 'fitIntercept': true
+* });
+*
+* var y = discreteUniform( M, 0.0, 30.0 );
+* var X = discreteUniform( M*N, -5.0, 5.0 );
+* var w = discreteUniform( N, -0.05, 0.05 );
+* var workspace = new Float64Array( N );
+*
+* var out = dsgdTrainer( 'row-major', M, N, X, N, y, 1, w, 1, workspace, 1, params );
+* returns
+*/
+function dsgdTrainer( order, M, N, X, LDX, y, strideY, w, strideW, workspace, strideWS, params ) { // eslint-disable-line max-params, max-len
+ var iscm;
+ var lsfn;
+ var vala;
+ var sx1;
+ var sx2;
+ var ows;
+ var oy;
+ var ow;
+ var lr;
+ var p;
+
+ if ( !isLayout( order ) ) {
+ throw new TypeError( format( 'invalid argument. First argument must be a valid order. Value: `%s`.', order ) );
+ }
+ p = resolvePenaltyStr( params.penalty );
+ lr = resolveLRStr( params.learningRate );
+ lsfn = resolveLossFnStr( params.lossFunction );
+ if ( p === null ) {
+ throw new TypeError( format( 'invalid argument. Thirteenth argument\'s `penalty` member must be a valid penalty. Value: `%s`.', params.penalty ) );
+ }
+ if ( lr === null ) {
+ throw new TypeError( format( 'invalid argument. Thirteenth argument\'s `learningRate` member must be a valid learning rate. Value: `%s`.', params.learningRate ) );
+ }
+ if ( lsfn === null ) {
+ throw new TypeError( format( 'invalid argument. Thirteenth argument\'s `lossFunction` member must be a valid loss function. Value: `%s`.', params.lossFunction ) );
+ }
+ if ( M < 0 ) {
+ throw new RangeError( format( 'invalid argument. Second argument must be a nonnegative integer. Value: `%d`.', M ) );
+ }
+ if ( N < 0 ) {
+ throw new RangeError( format( 'invalid argument. Third argument must be a nonnegative integer. Value: `%d`.', N ) );
+ }
+ iscm = isColumnMajor( order );
+ if ( iscm ) {
+ vala = M;
+ } else {
+ vala = N;
+ }
+ if ( LDX < max( 1, vala ) ) {
+ throw new RangeError( format( 'invalid argument. Fifth argument must be greater than or equal to max(1,%d). Value: `%d`.', vala, LDX ) );
+ }
+ if ( strideY === 0 ) {
+ throw new RangeError( format( 'invalid argument. Seventh argument must be non-zero. Value: `%d`.', strideY ) );
+ }
+ if ( strideW === 0 ) {
+ throw new RangeError( format( 'invalid argument. Ninth argument must be non-zero. Value: `%d`.', strideW ) );
+ }
+ if ( strideWS === 0 ) {
+ throw new RangeError( format( 'invalid argument. Eleventh argument must be non-zero. Value: `%d`.', strideY ) );
+ }
+ // Check if we can early return...
+ if ( M === 0 || N === 0 ) {
+ return w;
+ }
+ oy = stride2offset( M, strideY );
+ ow = stride2offset( N, strideW );
+ ows = stride2offset( N, strideWS );
+ if ( iscm ) {
+ sx1 = 1;
+ sx2 = LDX;
+ } else { // order === 'row-major'
+ sx1 = LDX;
+ sx2 = 1;
+ }
+ return base( M, N, X, sx1, sx2, 0, y, strideY, oy, w, strideW, ow, workspace, strideWS, ows, params ); // eslint-disable-line max-len
+}
+
+
+// EXPORTS //
+
+module.exports = dsgdTrainer;
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/dsgd_trainer.native.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/dsgd_trainer.native.js
new file mode 100644
index 000000000000..6a22c83d8f64
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/dsgd_trainer.native.js
@@ -0,0 +1,150 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2025 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 isLayout = require( '@stdlib/blas/base/assert/is-layout' );
+var isColumnMajor = require( '@stdlib/ndarray/base/assert/is-column-major-string' );
+var max = require( '@stdlib/math/base/special/fast/max' );
+var resolveOrder = require( '@stdlib/blas/base/layout-resolve-enum' );
+var resolvePenaltyStr = require( '@stdlib/ml/base/sgd/penalty-resolve-str' );
+var resolveLRStr = require( '@stdlib/ml/base/sgd/learning-rate-resolve-str' );
+var resolveLossFnStr = require( '@stdlib/ml/base/sgd/loss-function-resolve-str' );
+var format = require( '@stdlib/string/format' );
+var addon = require( './../src/addon.node' );
+
+
+// MAIN //
+
+/**
+* Trains a linear model via stochastic gradient descent.
+*
+* @private
+* @param {string} order - storage layout
+* @param {NonNegativeInteger} M - number of samples
+* @param {NonNegativeInteger} N - number of features
+* @param {Float64Array} X - input matrix
+* @param {NonNegativeInteger} LDX - stride of the first dimension of `X` (a.k.a., leading dimension of the matrix `X`)
+* @param {Float64Array} y - target array
+* @param {integer} strideY - stride length for `y`
+* @param {Float64Array} w - weight array
+* @param {integer} strideW - stride length for `w`
+* @param {Float64Array} workspace - workspace array
+* @param {integer} strideWS - stride length for `workspace`
+* @param {Params} params - parameters object
+* @throws {TypeError} first argument must be a valid order
+* @throws {TypeError} thirteenth argument's `penalty` member must be a valid penalty
+* @throws {TypeError} thirteenth argument's `learningRate` member must be a valid learning rate
+* @throws {TypeError} thirteenth argument's `lossFunction` member must be a valid loss function
+* @throws {RangeError} second argument must be a nonnegative integer
+* @throws {RangeError} third argument must be a nonnegative integer
+* @throws {RangeError} sixth argument must be non-zero
+* @throws {RangeError} fifth argument must be a valid stride
+* @throws {RangeError} eighth argument must be a valid stride
+* @throws {RangeError} tenth argument must be a valid stride
+* @throws {RangeError} twelfth argument must be a valid stride
+* @returns {Float64Array} `w`
+*
+* @example
+* var Float64Array = require( '@stdlib/array/float64' );
+* var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+* var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+*
+* var M = 50;
+* var N = 5;
+* var lambda = 2.5;
+* var eta0 = 0.01;
+*
+* var params = new Params({
+* 'penaltyParams': new Float64Array( [ lambda, 0.0 ] ),
+* 'learningRateParams': new Float64Array( [ eta0, 0.0 ] ),
+* 'intercept': 0.0,
+* 'maxIter': 500,
+* 'penalty': 'l2',
+* 'learningRate': 'constant',
+* 'lossFunction': 'hinge',
+* 'fitIntercept': true
+* });
+*
+* var y = discreteUniform( M, 0.0, 30.0 );
+* var X = discreteUniform( M*N, -5.0, 5.0 );
+* var w = discreteUniform( N, -0.05, 0.05 );
+* var workspace = new Float64Array( N );
+*
+* var out = dsgdTrainer( 'row-major', M, N, X, N, y, 1, w, 1, workspace, 1, params );
+* returns
+*/
+function dsgdTrainer( order, M, N, X, LDX, y, strideY, w, strideW, workspace, strideWS, params ) { // eslint-disable-line max-params, max-len
+ var iscm;
+ var lsfn;
+ var vala;
+ var lr;
+ var p;
+
+ if ( !isLayout( order ) ) {
+ throw new TypeError( format( 'invalid argument. First argument must be a valid order. Value: `%s`.', order ) );
+ }
+ p = resolvePenaltyStr( params.penalty );
+ lr = resolveLRStr( params.learningRate );
+ lsfn = resolveLossFnStr( params.lossFunction );
+ if ( p === null ) {
+ throw new TypeError( format( 'invalid argument. Thirteenth argument\'s `penalty` member must be a valid penalty. Value: `%s`.', params.penalty ) );
+ }
+ if ( lr === null ) {
+ throw new TypeError( format( 'invalid argument. Thirteenth argument\'s `learningRate` member must be a valid learning rate. Value: `%s`.', params.learningRate ) );
+ }
+ if ( lsfn === null ) {
+ throw new TypeError( format( 'invalid argument. Thirteenth argument\'s `lossFunction` member must be a valid loss function. Value: `%s`.', params.lossFunction ) );
+ }
+ if ( M < 0 ) {
+ throw new RangeError( format( 'invalid argument. Second argument must be a nonnegative integer. Value: `%d`.', M ) );
+ }
+ if ( N < 0 ) {
+ throw new RangeError( format( 'invalid argument. Third argument must be a nonnegative integer. Value: `%d`.', N ) );
+ }
+ iscm = isColumnMajor( order );
+ if ( iscm ) {
+ vala = M;
+ } else {
+ vala = N;
+ }
+ if ( LDX < max( 1, vala ) ) {
+ throw new RangeError( format( 'invalid argument. Sixth argument must be greater than or equal to max(1,%d). Value: `%d`.', vala, LDX ) );
+ }
+ if ( strideY === 0 ) {
+ throw new RangeError( format( 'invalid argument. Eighth argument must be non-zero. Value: `%d`.', strideY ) );
+ }
+ if ( strideW === 0 ) {
+ throw new RangeError( format( 'invalid argument. Tenth argument must be non-zero. Value: `%d`.', strideW ) );
+ }
+ if ( strideWS === 0 ) {
+ throw new RangeError( format( 'invalid argument. Twelfth argument must be non-zero. Value: `%d`.', strideY ) );
+ }
+ // Check if we can early return...
+ if ( M === 0 || N === 0 ) {
+ return w;
+ }
+ return addon( resolveOrder( order ), M, N, X, LDX, y, strideY, w, strideW, workspace, strideWS, params ); // eslint-disable-line max-len
+}
+
+
+// EXPORTS //
+
+module.exports = dsgdTrainer;
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/index.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/index.js
new file mode 100644
index 000000000000..6cec28670458
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/index.js
@@ -0,0 +1,110 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 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';
+
+/**
+* Trains a linear model via stochastic gradient descent.
+*
+* @module @stdlib/ml/strided/dsgd-trainer
+*
+* @example
+* var Float64Array = require( '@stdlib/array/float64' );
+* var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+* var dsgdTrainer = require( '@stdlib/ml/strided/dsgd-trainer' );
+* var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+*
+* var M = 50;
+* var N = 5;
+* var lambda = 2.5;
+* var eta0 = 0.01;
+*
+* var params = new Params({
+* 'penaltyParams': new Float64Array( [ lambda, 0.0 ] ),
+* 'learningRateParams': new Float64Array( [ eta0, 0.0 ] ),
+* 'intercept': 0.0,
+* 'maxIter': 500,
+* 'penalty': 'l2',
+* 'learningRate': 'constant',
+* 'lossFunction': 'hinge',
+* 'fitIntercept': true
+* });
+*
+* var y = discreteUniform( M, 0.0, 30.0 );
+* var X = discreteUniform( M*N, -5.0, 5.0 );
+* var w = discreteUniform( N, -0.05, 0.05 );
+* var workspace = new Float64Array( N );
+*
+* var out = dsgdTrainer( 'row-major', M, N, X, N, y, 1, w, 1, workspace, 1, params );
+* returns
+*
+* @example
+* var Float64Array = require( '@stdlib/array/float64' );
+* var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+* var dsgdTrainer = require( '@stdlib/ml/strided/dsgd-trainer' );
+* var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+*
+* var M = 50;
+* var N = 5;
+* var lambda = 2.5;
+* var eta0 = 0.01;
+*
+* var params = new Params({
+* 'penaltyParams': new Float64Array( [ lambda, 0.0 ] ),
+* 'learningRateParams': new Float64Array( [ eta0, 0.0 ] ),
+* 'intercept': 0.0,
+* 'maxIter': 500,
+* 'penalty': 'l2',
+* 'learningRate': 'constant',
+* 'lossFunction': 'hinge',
+* 'fitIntercept': true
+* });
+*
+* var y = discreteUniform( M, 0.0, 30.0 );
+* var X = discreteUniform( M*N, -5.0, 5.0 );
+* var w = discreteUniform( N, -0.05, 0.05 );
+* var workspace = new Float64Array( N );
+*
+* var out = dsgdTrainer.ndarray( M, N, X, N, 1, 0, y, 1, 0, w, 1, 0, workspace, 1, 0, params );
+* returns
+*/
+
+// MODULES //
+
+var join = require( 'path' ).join;
+var tryRequire = require( '@stdlib/utils/try-require' );
+var isError = require( '@stdlib/assert/is-error' );
+var main = require( './main.js' );
+
+
+// MAIN //
+
+var dsgdTrainer;
+var tmp = tryRequire( join( __dirname, './native.js' ) );
+if ( isError( tmp ) ) {
+ dsgdTrainer = main;
+} else {
+ dsgdTrainer = tmp;
+}
+
+
+// EXPORTS //
+
+module.exports = dsgdTrainer;
+
+// exports: { "ndarray": "dsgdTrainer.ndarray" }
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/learning_rate.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/learning_rate.js
new file mode 100644
index 000000000000..90fc91f7f8d7
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/learning_rate.js
@@ -0,0 +1,117 @@
+/**
+* @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 pow = require( '@stdlib/math/base/special/pow' );
+
+
+// VARIABLES //
+
+/**
+* Learning rate schedulers.
+*
+* @private
+* @name LEARNING_RATE_METHODS
+* @constant
+* @type {Object}
+*
+* @example
+* var f = LEARNING_RATE_METHODS[ 'invscaling' ];
+* // returns
+*/
+var LEARNING_RATE_METHODS = {
+ 'basic': basic,
+ 'constant': constant,
+ 'invscaling': invscaling,
+ 'pegasos': pegasos
+};
+
+
+// FUNCTIONS //
+
+/**
+* Computes learning rate by applying the `constant` learning rate scheduler.
+*
+* Note:
+*
+* - Here **params**: `[ eta0 ]`
+*
+* @private
+* @param {NonNegativeInteger} t - current iteration.
+* @param {Float64Array} params - strided array containing scheduler specific parameters.
+* @returns {number} learning rate
+*/
+function constant( t, params ) { // eslint-disable-line no-unused-vars
+ return params[ 0 ]; // return eta0
+}
+
+/**
+* Computes learning rate by applying the `basic` learning rate scheduler.
+*
+* Note:
+*
+* - Here **params**: `[ ]` (empty)
+*
+* @private
+* @param {NonNegativeInteger} t - current iteration.
+* @param {Float64Array} params - strided array containing scheduler specific parameters.
+* @returns {number} learning rate
+*/
+function basic( t, params ) { // eslint-disable-line no-unused-vars
+ return 10.0 / ( 10.0*t );
+}
+
+/**
+* Computes learning rate by applying the `invscaling` learning rate scheduler.
+*
+* Note:
+*
+* - Here **params**: `[ eta0, powerT ]`
+*
+* @private
+* @param {NonNegativeInteger} t - current iteration.
+* @param {Float64Array} params - strided array containing scheduler specific parameters.
+* @returns {number} learning rate
+*/
+function invscaling( t, params ) {
+ return params[ 0 ] / pow( t, params[ 1 ] );
+}
+
+/**
+* Computes learning rate by applying the `Pegasos` learning rate scheduler.
+*
+* Note:
+*
+* - Here **params**: `[ lambda ]`
+*
+* @private
+* @param {NonNegativeInteger} t - current iteration.
+* @param {Float64Array} params - strided array containing scheduler specific parameters.
+* @returns {number} learning rate
+*/
+function pegasos( t, params ) {
+ return 1.0 / ( params[ 0 ]*t );
+}
+
+
+// EXPORTS //
+
+module.exports = LEARNING_RATE_METHODS;
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/loss.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/loss.js
new file mode 100644
index 000000000000..aeeb7edc6a3f
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/loss.js
@@ -0,0 +1,218 @@
+/**
+* @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 logGradient = require( '@stdlib/ml/base/loss/float64/log-gradient' );
+var huberGradient = require( '@stdlib/ml/base/loss/float64/huber-gradient' );
+var hingeGradient = require( '@stdlib/ml/base/loss/float64/hinge-gradient' );
+var squaredHingeGradient = require( '@stdlib/ml/base/loss/float64/squared-hinge-gradient' );
+var squaredErrorGradient = require( '@stdlib/ml/base/loss/float64/squared-error-gradient' );
+var modifiedHuberGradient = require( '@stdlib/ml/base/loss/float64/modified-huber-gradient' );
+var epsilonInsensitiveGradient = require( '@stdlib/ml/base/loss/float64/epsilon-insensitive-gradient' );
+var squaredEpsilonInsensitiveGradient = require( '@stdlib/ml/base/loss/float64/squared-epsilon-insensitive-gradient' );
+
+
+// VARIABLES //
+
+/**
+* Loss function gradients.
+*
+* @private
+* @name LOSS_FUNCTIONS
+* @constant
+* @type {Object}
+*
+* @example
+* var f = LOSS_FUNCTIONS[ 'hinge' ];
+* // returns
+*/
+var LOSS_FUNCTIONS = {
+ 'epsilon-insensitive': epsilonInsensitive,
+ 'hinge': hinge,
+ 'huber': huber,
+ 'log': log,
+ 'modified-huber': modifiedHuber,
+ 'perceptron': perceptron,
+ 'squared-epsilon-insensitive': squaredEpsilonInsensitive,
+ 'squared-error': squaredError,
+ 'squared-hinge': squaredHinge
+};
+
+
+// FUNCTIONS //
+
+/**
+* Computes the gradient of the epsilon-insensitive loss.
+*
+* Note:
+*
+* - Here **params**: `[ epsilon ]`
+*
+* @private
+* @param {number} y - target value
+* @param {number} p - predicted value
+* @param {Float64Array} params - strided array containing loss function specific parameters.
+* @returns {number} loss gradient
+*/
+function epsilonInsensitive( y, p, params ) {
+ return epsilonInsensitiveGradient( 1.0, params[ 0 ], y, p ); // Magic number `1.0` as we need per-sample loss.
+}
+
+/**
+* Computes the gradient of the hinge loss.
+*
+* Note:
+*
+* - Here **params**: `[ ]` (empty)
+*
+* @private
+* @param {number} y - target value
+* @param {number} p - predicted value
+* @param {Float64Array} params - strided array containing loss function specific parameters.
+* @returns {number} loss gradient
+*/
+function hinge( y, p, params ) { // eslint-disable-line no-unused-vars
+ return hingeGradient( 1.0, 1.0, y, p ); // Magic numbers `1.0` and `1.0` as we need per-sample loss used by SVM.
+}
+
+/**
+* Computes the gradient of the Huber loss.
+*
+* Note:
+*
+* - Here **params**: `[ threshold ]` (empty)
+*
+* @private
+* @param {number} y - target value
+* @param {number} p - predicted value
+* @param {Float64Array} params - strided array containing loss function specific parameters.
+* @returns {number} loss gradient
+*/
+function huber( y, p, params ) { // eslint-disable-line no-unused-vars
+ return huberGradient( 1.0, params[ 0 ], y, p ); // Magic number `1.0` as we need per-sample loss.
+}
+
+/**
+* Computes the gradient of the log loss.
+*
+* Note:
+*
+* - Here **params**: `[ ]` (empty)
+*
+* @private
+* @param {number} y - target value
+* @param {number} p - predicted value
+* @param {Float64Array} params - strided array containing loss function specific parameters.
+* @returns {number} loss gradient
+*/
+function log( y, p, params ) { // eslint-disable-line no-unused-vars
+ return logGradient( 1.0, y, p ); // Magic number `1.0` as we need per-sample loss.
+}
+
+/**
+* Computes the gradient of the modified Huber loss.
+*
+* Note:
+*
+* - Here **params**: `[ ]` (empty)
+*
+* @private
+* @param {number} y - target value
+* @param {number} p - predicted value
+* @param {Float64Array} params - strided array containing loss function specific parameters.
+* @returns {number} loss gradient
+*/
+function modifiedHuber( y, p, params ) { // eslint-disable-line no-unused-vars
+ return modifiedHuberGradient( 1.0, y, p ); // Magic number `1.0` as we need per-sample loss.
+}
+
+/**
+* Computes the gradient of the perceptron loss.
+*
+* Note:
+*
+* - Here **params**: `[ ]` (empty)
+*
+* @private
+* @param {number} y - target value
+* @param {number} p - predicted value
+* @param {Float64Array} params - strided array containing loss function specific parameters.
+* @returns {number} loss gradient
+*/
+function perceptron( y, p, params ) { // eslint-disable-line no-unused-vars
+ return hingeGradient( 1.0, 0.0, y, p ); // Magic numbers `1.0` and `0.0` as we need per-sample loss used by Perceptron.
+}
+
+/**
+* Computes the gradient of the squared epsilon-insensitive loss.
+*
+* Note:
+*
+* - Here **params**: `[ epsilon ]`
+*
+* @private
+* @param {number} y - target value
+* @param {number} p - predicted value
+* @param {Float64Array} params - strided array containing loss function specific parameters.
+* @returns {number} loss gradient
+*/
+function squaredEpsilonInsensitive( y, p, params ) {
+ return squaredEpsilonInsensitiveGradient( 1.0, params[ 0 ], y, p ); // Magic number `1.0` as we need per-sample loss.
+}
+
+/**
+* Computes the gradient of the squared error loss.
+*
+* Note:
+*
+* - Here **params**: `[ ]` (empty)
+*
+* @private
+* @param {number} y - target value
+* @param {number} p - predicted value
+* @param {Float64Array} params - strided array containing loss function specific parameters.
+* @returns {number} loss gradient
+*/
+function squaredError( y, p, params ) { // eslint-disable-line no-unused-vars
+ return squaredErrorGradient( 1.0, y, p ); // Magic number `1.0` as we need per-sample loss.
+}
+
+/**
+* Computes the gradient of the squared hinge loss.
+*
+* Note:
+*
+* - Here **params**: `[ ]` (empty)
+*
+* @private
+* @param {number} y - target value
+* @param {number} p - predicted value
+* @param {Float64Array} params - strided array containing loss function specific parameters.
+* @returns {number} loss gradient
+*/
+function squaredHinge( y, p, params ) { // eslint-disable-line no-unused-vars
+ return squaredHingeGradient( 1.0, 1.0, y, p ); // Magic numbers `1.0` and `1.0` as we need per-sample loss used by SVM.
+}
+
+
+// EXPORTS //
+
+module.exports = LOSS_FUNCTIONS;
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/main.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/main.js
new file mode 100644
index 000000000000..bff16b5d4900
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/main.js
@@ -0,0 +1,35 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 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 setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' );
+var dsgdTrainer = require( './dsgd_trainer.js' );
+var ndarray = require( './ndarray.js' );
+
+
+// MAIN //
+
+setReadOnly( dsgdTrainer, 'ndarray', ndarray );
+
+
+// EXPORTS //
+
+module.exports = dsgdTrainer;
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/native.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/native.js
new file mode 100644
index 000000000000..faa45719b594
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/native.js
@@ -0,0 +1,35 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2025 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 setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' );
+var dsgdTrainer = require( './dsgd_trainer.native.js' );
+var ndarray = require( './ndarray.native.js' );
+
+
+// MAIN //
+
+setReadOnly( dsgdTrainer, 'ndarray', ndarray );
+
+
+// EXPORTS //
+
+module.exports = dsgdTrainer;
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/ndarray.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/ndarray.js
new file mode 100644
index 000000000000..41c6f6c49a34
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/ndarray.js
@@ -0,0 +1,129 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 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 resolvePenaltyStr = require( '@stdlib/ml/base/sgd/penalty-resolve-str' );
+var resolveLRStr = require( '@stdlib/ml/base/sgd/learning-rate-resolve-str' );
+var resolveLossFnStr = require( '@stdlib/ml/base/sgd/loss-function-resolve-str' );
+var format = require( '@stdlib/string/format' );
+var base = require( './base.js' );
+
+
+// MAIN //
+
+/**
+* Trains a linear model via stochastic gradient descent using alternative indexing semantics.
+*
+* @param {NonNegativeInteger} M - number of samples
+* @param {NonNegativeInteger} N - number of features
+* @param {Float64Array} X - input matrix
+* @param {integer} strideX1 - stride of the first dimension of `X`
+* @param {integer} strideX2 - stride of the second dimension of `X`
+* @param {NonNegativeInteger} offsetX - starting index for `X`
+* @param {Float64Array} y - target array
+* @param {integer} strideY - stride length for `y`
+* @param {NonNegativeInteger} offsetY - starting index for `y`
+* @param {Float64Array} w - weight array
+* @param {integer} strideW - stride length for `w`
+* @param {NonNegativeInteger} offsetW - starting index for `w`
+* @param {Float64Array} workspace - workspace array
+* @param {integer} strideWS - stride length for `workspace`
+* @param {NonNegativeInteger} offsetWS - starting index for `workspace`
+* @param {Params} params - parameters object
+* @throws {TypeError} first argument must be a valid transpose operation
+* @throws {RangeError} second argument must be a nonnegative integer
+* @throws {RangeError} third argument must be a nonnegative integer
+* @throws {RangeError} tenth argument must be non-zero
+* @throws {RangeError} fourteenth argument must be non-zero
+* @returns {Float64Array} `w`
+*
+* @example
+* var Float64Array = require( '@stdlib/array/float64' );
+* var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+* var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+*
+* var M = 50;
+* var N = 5;
+* var lambda = 2.5;
+* var eta0 = 0.01;
+*
+* var params = new Params({
+* 'penaltyParams': new Float64Array( [ lambda, 0.0 ] ),
+* 'learningRateParams': new Float64Array( [ eta0, 0.0 ] ),
+* 'intercept': 0.0,
+* 'maxIter': 500,
+* 'penalty': 'l2',
+* 'learningRate': 'constant',
+* 'lossFunction': 'hinge',
+* 'fitIntercept': true
+* });
+*
+* var y = discreteUniform( M, 0.0, 30.0 );
+* var X = discreteUniform( M*N, -5.0, 5.0 );
+* var w = discreteUniform( N, -0.05, 0.05 );
+* var workspace = new Float64Array( N );
+*
+* var out = dsgdTrainer( M, N, X, N, 1, 0, y, 1, 0, w, 1, 0, workspace, 1, 0, params );
+* returns
+*/
+function dsgdTrainer( M, N, X, strideX1, strideX2, offsetX, y, strideY, offsetY, w, strideW, offsetW, workspace, strideWS, offsetWS, params ) { // eslint-disable-line max-params, max-len
+ var lsfn;
+ var lr;
+ var p;
+
+ p = resolvePenaltyStr( params.penalty );
+ lr = resolveLRStr( params.learningRate );
+ lsfn = resolveLossFnStr( params.lossFunction );
+ if ( p === null ) {
+ throw new TypeError( format( 'invalid argument. Thirteenth argument\'s `penalty` member must be a valid penalty. Value: `%s`.', params.penalty ) );
+ }
+ if ( lr === null ) {
+ throw new TypeError( format( 'invalid argument. Thirteenth argument\'s `learningRate` member must be a valid learning rate. Value: `%s`.', params.learningRate ) );
+ }
+ if ( lsfn === null ) {
+ throw new TypeError( format( 'invalid argument. Thirteenth argument\'s `lossFunction` member must be a valid loss function. Value: `%s`.', params.lossFunction ) );
+ }
+ if ( M < 0 ) {
+ throw new RangeError( format( 'invalid argument. Second argument must be a nonnegative integer. Value: `%d`.', M ) );
+ }
+ if ( N < 0 ) {
+ throw new RangeError( format( 'invalid argument. Third argument must be a nonnegative integer. Value: `%d`.', N ) );
+ }
+ if ( strideY === 0 ) {
+ throw new RangeError( format( 'invalid argument. Eighth argument must be non-zero. Value: `%d`.', strideY ) );
+ }
+ if ( strideW === 0 ) {
+ throw new RangeError( format( 'invalid argument. Tenth argument must be non-zero. Value: `%d`.', strideW ) );
+ }
+ if ( strideWS === 0 ) {
+ throw new RangeError( format( 'invalid argument. Twelfth argument must be non-zero. Value: `%d`.', strideY ) );
+ }
+ // Check if we can early return...
+ if ( M === 0 || N === 0 ) {
+ return w;
+ }
+ return base( M, N, X, strideX1, strideX2, offsetX, y, strideY, offsetY, w, strideW, offsetW, workspace, strideWS, offsetWS, params ); // eslint-disable-line max-len
+}
+
+
+// EXPORTS //
+
+module.exports = dsgdTrainer;
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/ndarray.native.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/ndarray.native.js
new file mode 100644
index 000000000000..eed0506567f4
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/ndarray.native.js
@@ -0,0 +1,130 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2025 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 resolvePenaltyStr = require( '@stdlib/ml/base/sgd/penalty-resolve-str' );
+var resolveLRStr = require( '@stdlib/ml/base/sgd/learning-rate-resolve-str' );
+var resolveLossFnStr = require( '@stdlib/ml/base/sgd/loss-function-resolve-str' );
+var format = require( '@stdlib/string/format' );
+var addon = require( './../src/addon.node' );
+
+
+// MAIN //
+
+/**
+* Trains a linear model via stochastic gradient descent using alternative indexing semantics.
+*
+* @param {NonNegativeInteger} M - number of samples
+* @param {NonNegativeInteger} N - number of features
+* @param {Float64Array} X - input matrix
+* @param {integer} strideX1 - stride of the first dimension of `X`
+* @param {integer} strideX2 - stride of the second dimension of `X`
+* @param {NonNegativeInteger} offsetX - starting index for `X`
+* @param {Float64Array} y - target array
+* @param {integer} strideY - stride length for `y`
+* @param {NonNegativeInteger} offsetY - starting index for `y`
+* @param {Float64Array} w - weight array
+* @param {integer} strideW - stride length for `w`
+* @param {NonNegativeInteger} offsetW - starting index for `w`
+* @param {Float64Array} workspace - workspace array
+* @param {integer} strideWS - stride length for `workspace`
+* @param {NonNegativeInteger} offsetWS - starting index for `workspace`
+* @param {Params} params - parameters object
+* @throws {TypeError} first argument must be a valid transpose operation
+* @throws {RangeError} second argument must be a nonnegative integer
+* @throws {RangeError} third argument must be a nonnegative integer
+* @throws {RangeError} tenth argument must be non-zero
+* @throws {RangeError} fourteenth argument must be non-zero
+* @returns {Float64Array} `w`
+*
+* @example
+* var Float64Array = require( '@stdlib/array/float64' );
+* var Params = require( '@stdlib/ml/base/sgd/params/float64' );
+* var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+*
+* var M = 50;
+* var N = 5;
+* var lambda = 2.5;
+* var eta0 = 0.01;
+*
+* var params = new Params({
+* 'penaltyParams': new Float64Array( [ lambda, 0.0 ] ),
+* 'learningRateParams': new Float64Array( [ eta0, 0.0 ] ),
+* 'intercept': 0.0,
+* 'maxIter': 500,
+* 'penalty': 'l2',
+* 'learningRate': 'constant',
+* 'lossFunction': 'hinge',
+* 'fitIntercept': true
+* });
+*
+* var y = discreteUniform( M, 0.0, 30.0 );
+* var X = discreteUniform( M*N, -5.0, 5.0 );
+* var w = discreteUniform( N, -0.05, 0.05 );
+* var workspace = new Float64Array( N );
+*
+* var out = dsgdTrainer( M, N, X, N, 1, 0, y, 1, 0, w, 1, 0, workspace, 1, 0, params );
+* returns
+*/
+function dsgdTrainer( M, N, X, strideX1, strideX2, offsetX, y, strideY, offsetY, w, strideW, offsetW, workspace, strideWS, offsetWS, params ) { // eslint-disable-line max-params, max-len
+ var lsfn;
+ var lr;
+ var p;
+
+ p = resolvePenaltyStr( params.penalty );
+ lr = resolveLRStr( params.learningRate );
+ lsfn = resolveLossFnStr( params.lossFunction );
+ if ( p === null ) {
+ throw new TypeError( format( 'invalid argument. Thirteenth argument\'s `penalty` member must be a valid penalty. Value: `%s`.', params.penalty ) );
+ }
+ if ( lr === null ) {
+ throw new TypeError( format( 'invalid argument. Thirteenth argument\'s `learningRate` member must be a valid learning rate. Value: `%s`.', params.learningRate ) );
+ }
+ if ( lsfn === null ) {
+ throw new TypeError( format( 'invalid argument. Thirteenth argument\'s `lossFunction` member must be a valid loss function. Value: `%s`.', params.lossFunction ) );
+ }
+ if ( M < 0 ) {
+ throw new RangeError( format( 'invalid argument. Second argument must be a nonnegative integer. Value: `%d`.', M ) );
+ }
+ if ( N < 0 ) {
+ throw new RangeError( format( 'invalid argument. Third argument must be a nonnegative integer. Value: `%d`.', N ) );
+ }
+ if ( strideY === 0 ) {
+ throw new RangeError( format( 'invalid argument. Eighth argument must be non-zero. Value: `%d`.', strideY ) );
+ }
+ if ( strideW === 0 ) {
+ throw new RangeError( format( 'invalid argument. Tenth argument must be non-zero. Value: `%d`.', strideW ) );
+ }
+ if ( strideWS === 0 ) {
+ throw new RangeError( format( 'invalid argument. Twelfth argument must be non-zero. Value: `%d`.', strideY ) );
+ }
+ // Check if we can early return...
+ if ( M === 0 || N === 0 ) {
+ return y;
+ }
+ addon.ndarray( M, N, X, strideX1, strideX2, offsetX, y, strideY, offsetY, w, strideW, offsetW, workspace, strideWS, offsetWS, params ); // eslint-disable-line max-len
+ return y;
+}
+
+
+// EXPORTS //
+
+module.exports = dsgdTrainer;
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/truncation.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/truncation.js
new file mode 100644
index 000000000000..2a15a033d79d
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/lib/truncation.js
@@ -0,0 +1,121 @@
+/**
+* @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 max = require( '@stdlib/math/base/special/max' );
+var min = require( '@stdlib/math/base/special/min' );
+
+
+// VARIABLES //
+
+/**
+* Truncation functions.
+*
+* @private
+* @name TRUNCATIONS
+* @constant
+* @type {Object}
+*
+* @example
+* var f = TRUNCATIONS[ 'l2' ];
+* // returns
+*/
+var TRUNCATIONS = {
+ 'elasticnet': l1Truncation,
+ 'l1': l1Truncation,
+ 'l2': noTruncation,
+ 'none': noTruncation
+};
+
+
+// FUNCTIONS //
+
+/**
+* Applies no truncation.
+*
+* Note:
+*
+* - Here **params**: `[ ]` (empty)
+*
+* @private
+* @param {NonNegativeInteger} N - number of features (length of `w`)
+* @param {number} u - cumulative L1 penalty accumulated so far
+* @param {NonNegativeInteger} eta - learning rate.
+* @param {number} scaleFactor - current scaling factor applied to the stored weights
+* @param {Float64Array} w - weight array
+* @param {integer} strideW - stride length for `w`
+* @param {NonNegativeInteger} offsetW - starting index for `w`
+* @param {Float64Array} workspace - workspace array tracking the total L1 shrinkage applied to each feature
+* @param {integer} strideWS - stride length for `workspace`
+* @param {NonNegativeInteger} offsetWS - starting index for `workspace`
+* @param {Float64Array} params - strided array containing regularizer specific parameters.
+* @returns {number} u
+*/
+function noTruncation( N, u, eta, scaleFactor, w, strideW, offsetW, workspace, strideWS, offsetWS, params ) { // eslint-disable-line no-unused-vars, max-len, max-params
+ return u;
+}
+
+/**
+* Applies the cumulative L1 penalty to the weight vector.
+*
+* Note:
+*
+* - Here **params**: `[ lambda, l1Ratio ]`
+*
+* @private
+* @param {NonNegativeInteger} N - number of features
+* @param {number} u - cumulative L1 penalty accumulated so far
+* @param {NonNegativeInteger} eta - learning rate.
+* @param {number} scaleFactor - current scaling factor applied to the stored weights
+* @param {Float64Array} w - weight array
+* @param {integer} strideW - stride length for `w`
+* @param {NonNegativeInteger} offsetW - starting index for `w`
+* @param {Float64Array} workspace - workspace array tracking the total L1 shrinkage applied to each feature
+* @param {integer} strideWS - stride length for `workspace`
+* @param {NonNegativeInteger} offsetWS - starting index for `workspace`
+* @param {Float64Array} params - strided array containing regularizer specific parameters.
+* @returns {number} u
+*/
+function l1Truncation( N, u, eta, scaleFactor, w, strideW, offsetW, workspace, strideWS, offsetWS, params ) { // eslint-disable-line max-len, max-params
+ var wsIdx;
+ var idx;
+ var z;
+ var j;
+
+ u += ( eta * params[ 0 ] * params[ 1 ] );
+ for ( j = 0; j < N; j++ ) {
+ idx = offsetW + ( j * strideW );
+ wsIdx = offsetWS + ( j * strideWS );
+ z = w[ idx ];
+ if ( scaleFactor * z > 0.0 ) {
+ w[ idx ] = max( 0.0, z - ( ( u + workspace[ wsIdx ] ) / scaleFactor ) ); // eslint-disable-line max-len
+ } else if ( scaleFactor * z < 0.0 ) {
+ w[ idx ] = min( 0.0, z + ( ( u - workspace[ wsIdx ] ) / scaleFactor ) ); // eslint-disable-line max-len
+ }
+ workspace[ wsIdx ] += scaleFactor * ( w[ idx ] - z );
+ }
+ return u;
+}
+
+
+// EXPORTS //
+
+module.exports = TRUNCATIONS;
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/manifest.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/manifest.json
new file mode 100644
index 000000000000..ea2d92986968
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/manifest.json
@@ -0,0 +1,168 @@
+{
+ "options": {
+ "task": "build",
+ "wasm": false
+ },
+ "fields": [
+ {
+ "field": "src",
+ "resolve": true,
+ "relative": true
+ },
+ {
+ "field": "include",
+ "resolve": true,
+ "relative": true
+ },
+ {
+ "field": "libraries",
+ "resolve": false,
+ "relative": false
+ },
+ {
+ "field": "libpath",
+ "resolve": true,
+ "relative": false
+ }
+ ],
+ "confs": [
+ {
+ "task": "build",
+ "wasm": false,
+ "src": [
+ "./src/main.c"
+ ],
+ "include": [
+ "./include"
+ ],
+ "libraries": [],
+ "libpath": [],
+ "dependencies": [
+ "@stdlib/blas/base/shared",
+ "@stdlib/strided/base/stride2offset",
+ "@stdlib/blas/base/ddot",
+ "@stdlib/blas/base/daxpy",
+ "@stdlib/blas/base/dscal",
+ "@stdlib/ml/base/sgd/learning-rates",
+ "@stdlib/ml/base/sgd/loss-functions",
+ "@stdlib/ml/base/sgd/penalties",
+ "@stdlib/ml/base/loss/float64/epsilon-insensitive-gradient",
+ "@stdlib/ml/base/loss/float64/hinge-gradient",
+ "@stdlib/ml/base/loss/float64/huber-gradient",
+ "@stdlib/ml/base/loss/float64/log-gradient",
+ "@stdlib/ml/base/loss/float64/modified-huber-gradient",
+ "@stdlib/ml/base/loss/float64/squared-epsilon-insensitive-gradient",
+ "@stdlib/ml/base/loss/float64/squared-error-gradient",
+ "@stdlib/ml/base/loss/float64/squared-hinge-gradient",
+ "@stdlib/math/base/special/max",
+ "@stdlib/math/base/special/min",
+ "@stdlib/math/base/special/pow",
+ "@stdlib/napi/export",
+ "@stdlib/napi/argv",
+ "@stdlib/napi/argv-int64",
+ "@stdlib/napi/argv-int32",
+ "@stdlib/napi/argv-strided-float64array",
+ "@stdlib/napi/create-double"
+ ]
+ },
+ {
+ "task": "benchmark",
+ "wasm": false,
+ "src": [
+ "./src/main.c"
+ ],
+ "include": [
+ "./include"
+ ],
+ "libraries": [],
+ "libpath": [],
+ "dependencies": [
+ "@stdlib/blas/base/shared",
+ "@stdlib/strided/base/stride2offset",
+ "@stdlib/blas/base/ddot",
+ "@stdlib/blas/base/daxpy",
+ "@stdlib/blas/base/dscal",
+ "@stdlib/ml/base/sgd/learning-rates",
+ "@stdlib/ml/base/sgd/loss-functions",
+ "@stdlib/ml/base/sgd/penalties",
+ "@stdlib/ml/base/loss/float64/epsilon-insensitive-gradient",
+ "@stdlib/ml/base/loss/float64/hinge-gradient",
+ "@stdlib/ml/base/loss/float64/huber-gradient",
+ "@stdlib/ml/base/loss/float64/log-gradient",
+ "@stdlib/ml/base/loss/float64/modified-huber-gradient",
+ "@stdlib/ml/base/loss/float64/squared-epsilon-insensitive-gradient",
+ "@stdlib/ml/base/loss/float64/squared-error-gradient",
+ "@stdlib/ml/base/loss/float64/squared-hinge-gradient",
+ "@stdlib/math/base/special/max",
+ "@stdlib/math/base/special/min",
+ "@stdlib/math/base/special/pow"
+ ]
+ },
+ {
+ "task": "examples",
+ "wasm": false,
+ "src": [
+ "./src/main.c"
+ ],
+ "include": [
+ "./include"
+ ],
+ "libraries": [],
+ "libpath": [],
+ "dependencies": [
+ "@stdlib/blas/base/shared",
+ "@stdlib/strided/base/stride2offset",
+ "@stdlib/blas/base/ddot",
+ "@stdlib/blas/base/daxpy",
+ "@stdlib/blas/base/dscal",
+ "@stdlib/ml/base/sgd/learning-rates",
+ "@stdlib/ml/base/sgd/loss-functions",
+ "@stdlib/ml/base/sgd/penalties",
+ "@stdlib/ml/base/loss/float64/epsilon-insensitive-gradient",
+ "@stdlib/ml/base/loss/float64/hinge-gradient",
+ "@stdlib/ml/base/loss/float64/huber-gradient",
+ "@stdlib/ml/base/loss/float64/log-gradient",
+ "@stdlib/ml/base/loss/float64/modified-huber-gradient",
+ "@stdlib/ml/base/loss/float64/squared-epsilon-insensitive-gradient",
+ "@stdlib/ml/base/loss/float64/squared-error-gradient",
+ "@stdlib/ml/base/loss/float64/squared-hinge-gradient",
+ "@stdlib/math/base/special/max",
+ "@stdlib/math/base/special/min",
+ "@stdlib/math/base/special/pow"
+ ]
+ },
+ {
+ "task": "",
+ "wasm": true,
+ "src": [
+ "./src/main.c"
+ ],
+ "include": [
+ "./include"
+ ],
+ "libraries": [],
+ "libpath": [],
+ "dependencies": [
+ "@stdlib/blas/base/shared",
+ "@stdlib/strided/base/stride2offset",
+ "@stdlib/blas/base/ddot",
+ "@stdlib/blas/base/daxpy",
+ "@stdlib/blas/base/dscal",
+ "@stdlib/ml/base/sgd/learning-rates",
+ "@stdlib/ml/base/sgd/loss-functions",
+ "@stdlib/ml/base/sgd/penalties",
+ "@stdlib/ml/base/loss/float64/epsilon-insensitive-gradient",
+ "@stdlib/ml/base/loss/float64/hinge-gradient",
+ "@stdlib/ml/base/loss/float64/huber-gradient",
+ "@stdlib/ml/base/loss/float64/log-gradient",
+ "@stdlib/ml/base/loss/float64/modified-huber-gradient",
+ "@stdlib/ml/base/loss/float64/squared-epsilon-insensitive-gradient",
+ "@stdlib/ml/base/loss/float64/squared-error-gradient",
+ "@stdlib/ml/base/loss/float64/squared-hinge-gradient",
+ "@stdlib/math/base/special/max",
+ "@stdlib/math/base/special/min",
+ "@stdlib/math/base/special/pow"
+ ]
+ }
+ ]
+}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/package.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/package.json
new file mode 100644
index 000000000000..456c7aae6d17
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/package.json
@@ -0,0 +1,61 @@
+{
+ "name": "@stdlib/ml",
+ "version": "0.0.0",
+ "description": "Machine learning algorithms.",
+ "license": "Apache-2.0",
+ "author": {
+ "name": "The Stdlib Authors",
+ "url": "https://github.com/stdlib-js/stdlib/graphs/contributors"
+ },
+ "contributors": [
+ {
+ "name": "The Stdlib Authors",
+ "url": "https://github.com/stdlib-js/stdlib/graphs/contributors"
+ }
+ ],
+ "main": "./lib",
+ "directories": {
+ "doc": "./docs",
+ "example": "./examples",
+ "lib": "./lib",
+ "test": "./test"
+ },
+ "types": "./docs/types",
+ "scripts": {},
+ "homepage": "https://github.com/stdlib-js/stdlib",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/stdlib-js/stdlib.git"
+ },
+ "bugs": {
+ "url": "https://github.com/stdlib-js/stdlib/issues"
+ },
+ "dependencies": {},
+ "devDependencies": {},
+ "engines": {
+ "node": ">=0.10.0",
+ "npm": ">2.7.0"
+ },
+ "os": [
+ "aix",
+ "darwin",
+ "freebsd",
+ "linux",
+ "macos",
+ "openbsd",
+ "sunos",
+ "win32",
+ "windows"
+ ],
+ "keywords": [
+ "stdlib",
+ "stdml",
+ "sgd",
+ "strided",
+ "schocastic gradient descent",
+ "sgd trainer",
+ "machine",
+ "learning",
+ "ml"
+ ]
+}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/src/Makefile b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/src/Makefile
new file mode 100644
index 000000000000..7733b6180cb4
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/src/Makefile
@@ -0,0 +1,70 @@
+#/
+# @license Apache-2.0
+#
+# Copyright (c) 2025 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.
+#/
+
+# VARIABLES #
+
+ifndef VERBOSE
+ QUIET := @
+else
+ QUIET :=
+endif
+
+# Determine the OS ([1][1], [2][2]).
+#
+# [1]: https://en.wikipedia.org/wiki/Uname#Examples
+# [2]: http://stackoverflow.com/a/27776822/2225624
+OS ?= $(shell uname)
+ifneq (, $(findstring MINGW,$(OS)))
+ OS := WINNT
+else
+ifneq (, $(findstring MSYS,$(OS)))
+ OS := WINNT
+else
+ifneq (, $(findstring CYGWIN,$(OS)))
+ OS := WINNT
+else
+ifneq (, $(findstring Windows_NT,$(OS)))
+ OS := WINNT
+endif
+endif
+endif
+endif
+
+
+# RULES #
+
+#/
+# Removes generated files for building an add-on.
+#
+# @example
+# make clean-addon
+#/
+clean-addon:
+ $(QUIET) -rm -f *.o *.node
+
+.PHONY: clean-addon
+
+#/
+# Removes generated files.
+#
+# @example
+# make clean
+#/
+clean: clean-addon
+
+.PHONY: clean
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/src/addon.c b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/src/addon.c
new file mode 100644
index 000000000000..f8d62df125ee
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/src/addon.c
@@ -0,0 +1,100 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2025 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.
+*/
+
+#include "stdlib/ml/strided/dsgd_trainer.h"
+#include "stdlib/ml/base/sgd/params/float64.h"
+#include "stdlib/blas/base/shared.h"
+#include "stdlib/napi/export.h"
+#include "stdlib/napi/argv.h"
+#include "stdlib/napi/argv_int64.h"
+#include "stdlib/napi/argv_int32.h"
+#include "stdlib/napi/argv_strided_float64array.h"
+#include "stdlib/napi/argv_strided_float64array2d.h"
+#include "stdlib/napi/argv_dataview_cast.h"
+#include
+
+/**
+* Receives JavaScript callback invocation data.
+*
+* @param env environment under which the function is invoked
+* @param info callback data
+* @return Node-API value
+*/
+static napi_value addon( napi_env env, napi_callback_info info ) {
+ CBLAS_INT sx1;
+ CBLAS_INT sx2;
+
+ STDLIB_NAPI_ARGV( env, info, argv, argc, 12 );
+
+ STDLIB_NAPI_ARGV_INT32( env, layout, argv, 0 );
+
+ STDLIB_NAPI_ARGV_INT64( env, M, argv, 1 );
+ STDLIB_NAPI_ARGV_INT64( env, N, argv, 2 );
+ STDLIB_NAPI_ARGV_INT64( env, strideY, argv, 6 );
+ STDLIB_NAPI_ARGV_INT64( env, strideW, argv, 8 );
+ STDLIB_NAPI_ARGV_INT64( env, strideWS, argv, 10 );
+ STDLIB_NAPI_ARGV_INT64( env, LDX, argv, 4 );
+
+ if ( layout == CblasColMajor ) {
+ sx1 = 1;
+ sx2 = LDX;
+ } else { // layout == CblasRowMajor
+ sx1 = LDA;
+ sx2 = 1;
+ }
+ STDLIB_NAPI_ARGV_STRIDED_FLOAT64ARRAY( env, y, M, strideY, argv, 5 );
+ STDLIB_NAPI_ARGV_STRIDED_FLOAT64ARRAY( env, w, N, strideY, argv, 7 );
+ STDLIB_NAPI_ARGV_STRIDED_FLOAT64ARRAY( env, ws, N, strideY, argv, 9 );
+ STDLIB_NAPI_ARGV_STRIDED_FLOAT64ARRAY2D( env, X, M, N, sx1, sx2, argv, 3 );
+ STDLIB_NAPI_ARGV_DATAVIEW_CAST( env, params, struct stdlib_ml_sgd_float64_params, argv, 7 );
+ API_SUFFIX(stdlib_strided_dsgd_trainer)( order, M, N, X, LDX, y, strideY, w, strideW, workspace, strideWS, params );
+ return NULL;
+}
+
+/**
+* Receives JavaScript callback invocation data.
+*
+* @param env environment under which the function is invoked
+* @param info callback data
+* @return Node-API value
+*/
+static napi_value addon_method( napi_env env, napi_callback_info info ) {
+ STDLIB_NAPI_ARGV( env, info, argv, argc, 12 );
+
+ STDLIB_NAPI_ARGV_INT64( env, M, argv, 0 );
+ STDLIB_NAPI_ARGV_INT64( env, N, argv, 1 );
+ STDLIB_NAPI_ARGV_INT64( env, strideY, argv, 7 );
+ STDLIB_NAPI_ARGV_INT64( env, offsetY, argv, 8 );
+ STDLIB_NAPI_ARGV_INT64( env, strideW, argv, 10 );
+ STDLIB_NAPI_ARGV_INT64( env, offsetW, argv, 11 );
+ STDLIB_NAPI_ARGV_INT64( env, strideWS, argv, 12 );
+ STDLIB_NAPI_ARGV_INT64( env, offsetWS, argv, 13 );
+ STDLIB_NAPI_ARGV_INT64( env, strideX1, argv, 3 );
+ STDLIB_NAPI_ARGV_INT64( env, strideX2, argv, 4 );
+ STDLIB_NAPI_ARGV_INT64( env, offsetX, argv, 5 );
+
+ STDLIB_NAPI_ARGV_STRIDED_FLOAT64ARRAY( env, y, M, strideY, argv, 6 );
+ STDLIB_NAPI_ARGV_STRIDED_FLOAT64ARRAY( env, w, N, strideY, argv, 9 );
+ STDLIB_NAPI_ARGV_STRIDED_FLOAT64ARRAY( env, ws, N, strideY, argv, 12 );
+ STDLIB_NAPI_ARGV_STRIDED_FLOAT64ARRAY2D( env, X, M, N, sx1, sx2, argv, 2 );
+ STDLIB_NAPI_ARGV_DATAVIEW_CAST( env, params, struct stdlib_ml_sgd_float64_params, argv, 14 );
+ API_SUFFIX(stdlib_strided_dsgd_trainer_ndarray)( M, N, X, strideX1, strideX2, offsetX, y, strideY, offsetY, w, strideW, offsetW, workspace, strideWS, offsetWS, params );
+ return NULL;
+}
+
+STDLIB_NAPI_MODULE_EXPORT_FCN_WITH_METHOD( addon, "ndarray", addon_method )
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/src/main.c b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/src/main.c
new file mode 100644
index 000000000000..88a4000f00d2
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/src/main.c
@@ -0,0 +1,549 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2025 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.
+*/
+
+#include "stdlib/ml/strided/dsgd_trainer.h"
+#include "stdlib/ml/base/sgd/learning_rates.h"
+#include "stdlib/ml/base/sgd/loss_functions.h"
+#include "stdlib/ml/base/sgd/penalties.h"
+#include "stdlib/ml/base/loss/float64/epsilon_insensitive_gradient.h"
+#include "stdlib/ml/base/loss/float64/hinge_gradient.h"
+#include "stdlib/ml/base/loss/float64/huber_gradient.h"
+#include "stdlib/ml/base/loss/float64/log_gradient.h"
+#include "stdlib/ml/base/loss/float64/modified_huber_gradient.h"
+#include "stdlib/ml/base/loss/float64/squared_epsilon_insensitive_gradient.h"
+#include "stdlib/ml/base/loss/float64/squared_error_gradient.h"
+#include "stdlib/ml/base/loss/float64/squared_hinge_gradient.h"
+#include "stdlib/math/base/special/max.h"
+#include "stdlib/math/base/special/min.h"
+#include "stdlib/math/base/special/pow.h"
+#include "stdlib/blas/base/shared.h"
+#include "stdlib/blas/base/ddot.h"
+#include "stdlib/blas/base/daxpy.h"
+#include "stdlib/blas/base/dscal.h"
+#include "stdlib/strided/base/stride2offset.h"
+#include
+#include
+
+static const double MIN_SCALE = 1.0e-9;
+static const double MAX_DLOSS = 1.0e12;
+
+/**
+* Computes a learning rate according to the `basic` learning rate scheduler.
+*
+* @param t current iteration
+* @return learning rate
+*/
+static double basic( const CBLAS_INT t ) {
+ return 10.0 / ( 10.0*(double)t );
+}
+
+/**
+* Computes a learning rate according to the `constant` learning rate scheduler.
+*
+* ## Notes
+*
+* - The parameter list is `[ eta0 ]`.
+*
+* @param params scheduler parameters
+* @return learning rate
+*/
+static double constant( const double *params ) {
+ return params[ 0 ]; // eta0
+}
+
+/**
+* Computes a learning rate according to the `invscaling` learning rate scheduler.
+*
+* ## Notes
+*
+* - The parameter list is `[ eta0, powerT ]`.
+*
+* @param t current iteration
+* @param params scheduler parameters
+* @return learning rate
+*/
+static double invscaling( const CBLAS_INT t, const double *params ) {
+ return params[ 0 ] / stdlib_base_pow( (double)t, params[ 1 ] );
+}
+
+/**
+* Computes a learning rate according to the `pegasos` learning rate scheduler.
+*
+* ## Notes
+*
+* - The parameter list is `[ lambda ]`.
+*
+* @param t current iteration
+* @param params scheduler parameters
+* @return learning rate
+*/
+static double pegasos( const CBLAS_INT t, const double *params ) {
+ return 1.0 / ( params[ 0 ]*(double)t );
+}
+
+/**
+* Computes the gradient of the epsilon-insensitive loss.
+*
+* ## Notes
+*
+* - The parameter list is `[ epsilon ]`.
+*
+* @param y target value
+* @param p predicted value
+* @param params loss function parameters
+* @return loss gradient
+*/
+static double epsilon_insensitive( const double y, const double p, const double *params ) {
+ return stdlib_base_float64_epsilon_insensitive_gradient( 1.0, params[ 0 ], y, p );
+}
+
+/**
+* Computes the gradient of the hinge loss.
+*
+* @param y target value
+* @param p predicted value
+* @return loss gradient
+*/
+static double hinge( const double y, const double p ) {
+ return stdlib_base_float64_hinge_gradient( 1.0, 1.0, y, p );
+}
+
+/**
+* Computes the gradient of the Huber loss.
+*
+* ## Notes
+*
+* - The parameter list is `[ threshold ]`.
+*
+* @param y target value
+* @param p predicted value
+* @param params loss function parameters
+* @return loss gradient
+*/
+static double huber( const double y, const double p, const double *params ) {
+ return stdlib_base_float64_huber_gradient( 1.0, params[ 0 ], y, p );
+}
+
+/**
+* Computes the gradient of the log loss.
+*
+* @param y target value
+* @param p predicted value
+* @return loss gradient
+*/
+static double log_loss( const double y, const double p ) {
+ return stdlib_base_float64_log_gradient( 1.0, y, p );
+}
+
+/**
+* Computes the gradient of the modified Huber loss.
+*
+* @param y target value
+* @param p predicted value
+* @return loss gradient
+*/
+static double modified_huber( const double y, const double p ) {
+ return stdlib_base_float64_modified_huber_gradient( 1.0, y, p );
+}
+
+/**
+* Computes the gradient of the perceptron loss.
+*
+* ## Notes
+*
+* - The perceptron loss is the hinge loss without a margin, and thus we resolve the gradient using the hinge loss gradient with a zero margin threshold.
+*
+* @param y target value
+* @param p predicted value
+* @return loss gradient
+*/
+static double perceptron( const double y, const double p ) {
+ return stdlib_base_float64_hinge_gradient( 1.0, 0.0, y, p );
+}
+
+/**
+* Computes the gradient of the squared epsilon-insensitive loss.
+*
+* ## Notes
+*
+* - The parameter list is `[ epsilon ]`.
+*
+* @param y target value
+* @param p predicted value
+* @param params loss function parameters
+* @return loss gradient
+*/
+static double squared_epsilon_insensitive( const double y, const double p, const double *params ) {
+ return stdlib_base_float64_squared_epsilon_insensitive_gradient( 1.0, params[ 0 ], y, p );
+}
+
+/**
+* Computes the gradient of the squared error loss.
+*
+* @param y target value
+* @param p predicted value
+* @return loss gradient
+*/
+static double squared_error( const double y, const double p ) {
+ return stdlib_base_float64_squared_error_gradient( 1.0, y, p );
+}
+
+/**
+* Computes the gradient of the squared hinge loss.
+*
+* @param y target value
+* @param p predicted value
+* @return loss gradient
+*/
+static double squared_hinge( const double y, const double p ) {
+ return stdlib_base_float64_squared_hinge_gradient( 1.0, 1.0, y, p );
+}
+
+/**
+* Computes a scale factor by applying the identity decay.
+*
+* @param scaleFactor current scale factor
+* @return scale factor
+*/
+static double identity_decay( const double scaleFactor ) {
+ return scaleFactor;
+}
+
+/**
+* Computes a scale factor by applying the L2 decay.
+*
+* ## Notes
+*
+* - The parameter list is `[ lambda, l1Ratio ]`.
+*
+* @param scaleFactor current scale factor
+* @param eta learning rate
+* @param params penalty parameters
+* @return scale factor
+*/
+static double l2_decay( const double scaleFactor, const double eta, const double *params ) {
+ return scaleFactor * stdlib_base_max( 0.0, 1.0-( ( 1.0-params[ 1 ] )*eta*params[ 0 ] ) );
+}
+
+/**
+* Applies the cumulative L1 penalty to a weight vector.
+*
+* ## Notes
+*
+* - The parameter list is `[ lambda, l1Ratio ]`.
+*
+* @param N number of features
+* @param u cumulative L1 penalty accumulated thus far
+* @param eta learning rate
+* @param scaleFactor current scale factor applied to the stored weights
+* @param w weight array
+* @param strideW stride length for `w`
+* @param offsetW starting index for `w`
+* @param ws workspace array tracking the total L1 shrinkage applied to each feature
+* @param strideWS stride length for `ws`
+* @param offsetWS starting index for `ws`
+* @param params penalty parameters
+* @return cumulative L1 penalty
+*/
+static double l1_truncation( const CBLAS_INT N, double u, const double eta, const double scaleFactor, double *w, const CBLAS_INT strideW, const CBLAS_INT offsetW, double *ws, const CBLAS_INT strideWS, const CBLAS_INT offsetWS, const double *params ) {
+ CBLAS_INT wsIdx;
+ CBLAS_INT idx;
+ CBLAS_INT j;
+ double z;
+
+ u += ( eta*params[ 0 ]*params[ 1 ] );
+ for ( j = 0; j < N; j++ ) {
+ idx = offsetW + ( j*strideW );
+ wsIdx = offsetWS + ( j*strideWS );
+ z = w[ idx ];
+ if ( scaleFactor*z > 0.0 ) {
+ w[ idx ] = stdlib_base_max( 0.0, z-( ( u+ws[ wsIdx ] )/scaleFactor ) );
+ } else if ( scaleFactor*z < 0.0 ) {
+ w[ idx ] = stdlib_base_min( 0.0, z+( ( u-ws[ wsIdx ] )/scaleFactor ) );
+ }
+ ws[ wsIdx ] += scaleFactor*( w[ idx ]-z );
+ }
+ return u;
+}
+
+/**
+* Computes a learning rate according to a specified learning rate scheduler.
+*
+* @param learningRate learning rate scheduler
+* @param t current iteration
+* @param params scheduler parameters
+* @return learning rate
+*/
+static double stdlib_ml_sgd_learning_rate( const enum STDLIB_ML_SGD_LEARNING_RATE learningRate, const CBLAS_INT t, const double *params ) {
+ switch ( learningRate ) {
+ case STDLIB_ML_SGD_CONSTANT:
+ return constant( params );
+ case STDLIB_ML_SGD_INVSCALING:
+ return invscaling( t, params );
+ case STDLIB_ML_SGD_PEGASOS:
+ return pegasos( t, params );
+ case STDLIB_ML_SGD_BASIC:
+ default:
+ return basic( t );
+ }
+}
+
+/**
+* Computes the gradient of a specified loss function.
+*
+* @param lossFunction loss function
+* @param y target value
+* @param p predicted value
+* @param params loss function parameters
+* @return loss gradient
+*/
+static double stdlib_ml_sgd_loss_gradient( const enum STDLIB_ML_SGD_LOSS_FUNCTION lossFunction, const double y, const double p, const double *params ) {
+ switch ( lossFunction ) {
+ case STDLIB_ML_SGD_EPSILON_INSENSITIVE:
+ return epsilon_insensitive( y, p, params );
+ case STDLIB_ML_SGD_HUBER:
+ return huber( y, p, params );
+ case STDLIB_ML_SGD_LOG:
+ return log_loss( y, p );
+ case STDLIB_ML_SGD_MODIFIED_HUBER:
+ return modified_huber( y, p );
+ case STDLIB_ML_SGD_PERCEPTRON:
+ return perceptron( y, p );
+ case STDLIB_ML_SGD_SQUARED_EPSILON_INSENSITIVE:
+ return squared_epsilon_insensitive( y, p, params );
+ case STDLIB_ML_SGD_SQUARED_ERROR:
+ return squared_error( y, p );
+ case STDLIB_ML_SGD_SQUARED_HINGE:
+ return squared_hinge( y, p );
+ case STDLIB_ML_SGD_HINGE:
+ default:
+ return hinge( y, p );
+ }
+}
+
+/**
+* Computes a scale factor according to the weight decay associated with a specified penalty.
+*
+* @param penalty regularization function
+* @param scaleFactor current scale factor
+* @param eta learning rate
+* @param params penalty parameters
+* @return scale factor
+*/
+static double stdlib_ml_sgd_decay( const enum STDLIB_ML_SGD_PENALTY penalty, const double scaleFactor, const double eta, const double *params ) {
+ switch ( penalty ) {
+ case STDLIB_ML_SGD_ELASTICNET:
+ case STDLIB_ML_SGD_L2:
+ return l2_decay( scaleFactor, eta, params );
+ case STDLIB_ML_SGD_L1:
+ case STDLIB_ML_SGD_NONE:
+ default:
+ return identity_decay( scaleFactor );
+ }
+}
+
+/**
+* Applies the truncation associated with a specified penalty to a weight vector.
+*
+* @param penalty regularization function
+* @param N number of features
+* @param u cumulative L1 penalty accumulated thus far
+* @param eta learning rate
+* @param scaleFactor current scale factor applied to the stored weights
+* @param w weight array
+* @param strideW stride length for `w`
+* @param offsetW starting index for `w`
+* @param ws workspace array tracking the total L1 shrinkage applied to each feature
+* @param strideWS stride length for `ws`
+* @param offsetWS starting index for `ws`
+* @param params penalty parameters
+* @return cumulative L1 penalty
+*/
+static double stdlib_ml_sgd_truncation( const enum STDLIB_ML_SGD_PENALTY penalty, const CBLAS_INT N, const double u, const double eta, const double scaleFactor, double *w, const CBLAS_INT strideW, const CBLAS_INT offsetW, double *ws, const CBLAS_INT strideWS, const CBLAS_INT offsetWS, const double *params ) {
+ switch ( penalty ) {
+ case STDLIB_ML_SGD_ELASTICNET:
+ case STDLIB_ML_SGD_L1:
+ return l1_truncation( N, u, eta, scaleFactor, w, strideW, offsetW, ws, strideWS, offsetWS, params );
+ case STDLIB_ML_SGD_L2:
+ case STDLIB_ML_SGD_NONE:
+ default:
+ return u;
+ }
+}
+
+/**
+* Trains a linear model via stochastic gradient descent.
+*
+* ## Notes
+*
+* - When `params->fitIntercept` is `true`, `w` must have `N+1` indexed elements, as the fitted intercept is written to the element following the `N` feature weights.
+* - Upon return, `w` contains effective (i.e., fully rescaled) weights.
+*
+* @param layout storage layout of `X`
+* @param M number of samples
+* @param N number of features
+* @param X input matrix
+* @param LDX stride of the major dimension of `X`
+* @param y target array
+* @param strideY stride length for `y`
+* @param w weight array
+* @param strideW stride length for `w`
+* @param ws workspace array
+* @param strideWS stride length for `ws`
+* @param params parameters
+* @return `w`
+*/
+double* API_SUFFIX(stdlib_strided_dsgd_trainer)( const CBLAS_LAYOUT layout, const CBLAS_INT M, const CBLAS_INT N, const double *X, const CBLAS_INT LDX, const double *y, const CBLAS_INT strideY, double *w, const CBLAS_INT strideW, double *ws, const CBLAS_INT strideWS, const struct stdlib_ml_sgd_float64_params *params ) {
+ CBLAS_INT sx1;
+ CBLAS_INT sx2;
+ CBLAS_INT ows;
+ CBLAS_INT oy;
+ CBLAS_INT ow;
+
+ // Check if we can early return...
+ if ( M <= 0 || N <= 0 ) {
+ return w;
+ }
+ if ( layout == CblasColMajor ) {
+ sx1 = 1;
+ sx2 = LDX;
+ } else { // layout == CblasRowMajor
+ sx1 = LDX;
+ sx2 = 1;
+ }
+ oy = (CBLAS_INT)stdlib_strided_stride2offset( (int64_t)M, (int64_t)strideY );
+ ow = (CBLAS_INT)stdlib_strided_stride2offset( (int64_t)N, (int64_t)strideW );
+ ows = (CBLAS_INT)stdlib_strided_stride2offset( (int64_t)N, (int64_t)strideWS );
+ return API_SUFFIX(stdlib_strided_dsgd_trainer_ndarray)( M, N, X, sx1, sx2, 0, y, strideY, oy, w, strideW, ow, ws, strideWS, ows, params );
+}
+
+/**
+* Trains a linear model via stochastic gradient descent using alternative indexing semantics.
+*
+* ## Notes
+*
+* - When `params->fitIntercept` is `true`, `w` must have `N+1` indexed elements, as the fitted intercept is written to the element following the `N` feature weights.
+* - Upon return, `w` contains effective (i.e., fully rescaled) weights.
+*
+* @param M number of samples
+* @param N number of features
+* @param X input matrix
+* @param strideX1 stride of the first dimension of `X`
+* @param strideX2 stride of the second dimension of `X`
+* @param offsetX starting index for `X`
+* @param y target array
+* @param strideY stride length for `y`
+* @param offsetY starting index for `y`
+* @param w weight array
+* @param strideW stride length for `w`
+* @param offsetW starting index for `w`
+* @param ws workspace array
+* @param strideWS stride length for `ws`
+* @param offsetWS starting index for `ws`
+* @param params parameters
+* @return `w`
+*/
+double* API_SUFFIX(stdlib_strided_dsgd_trainer_ndarray)( const CBLAS_INT M, const CBLAS_INT N, const double *X, const CBLAS_INT strideX1, const CBLAS_INT strideX2, const CBLAS_INT offsetX, const double *y, const CBLAS_INT strideY, const CBLAS_INT offsetY, double *w, const CBLAS_INT strideW, const CBLAS_INT offsetW, double *ws, const CBLAS_INT strideWS, const CBLAS_INT offsetWS, const struct stdlib_ml_sgd_float64_params *params ) {
+ enum STDLIB_ML_SGD_LOSS_FUNCTION lossFunction;
+ enum STDLIB_ML_SGD_LEARNING_RATE learningRate;
+ enum STDLIB_ML_SGD_PENALTY penalty;
+ double penaltyParams[ 2 ];
+ double scaleFactor;
+ double intercept;
+ bool fitIntercept;
+ int32_t maxIter;
+ int32_t epoch;
+ double update;
+ double dloss;
+ double eta;
+ double p;
+ double u;
+ CBLAS_INT ox;
+ CBLAS_INT oy;
+ CBLAS_INT i;
+ CBLAS_INT t;
+
+ // Check if we can early return...
+ if ( M <= 0 || N <= 0 ) {
+ return w;
+ }
+ penalty = (enum STDLIB_ML_SGD_PENALTY)params->penalty;
+ learningRate = (enum STDLIB_ML_SGD_LEARNING_RATE)params->learningRate;
+ lossFunction = (enum STDLIB_ML_SGD_LOSS_FUNCTION)params->lossFunction;
+ fitIntercept = params->fitIntercept;
+ intercept = params->intercept;
+ maxIter = params->maxIter;
+
+ // Resolve the effective L1 ratio, as `l1` and `l2` are the limiting cases of `elasticnet`...
+ penaltyParams[ 0 ] = params->penaltyParams[ 0 ];
+ if ( penalty == STDLIB_ML_SGD_L2 ) {
+ penaltyParams[ 1 ] = 0.0;
+ } else if ( penalty == STDLIB_ML_SGD_L1 ) {
+ penaltyParams[ 1 ] = 1.0;
+ } else {
+ penaltyParams[ 1 ] = params->penaltyParams[ 1 ];
+ }
+
+ t = 1;
+ u = 0.0;
+ scaleFactor = 1.0;
+ for ( epoch = 1; epoch <= maxIter; epoch++ ) {
+ ox = offsetX;
+ oy = offsetY;
+ for ( i = 0; i < M; i++ ) {
+ p = ( scaleFactor*API_SUFFIX(c_ddot_ndarray)( N, w, strideW, offsetW, X, strideX2, ox ) ) + intercept;
+
+ eta = stdlib_ml_sgd_learning_rate( learningRate, t, params->learningRateParams );
+
+ dloss = stdlib_ml_sgd_loss_gradient( lossFunction, y[ oy ], p, params->lossFunctionParams );
+ if ( dloss < -MAX_DLOSS ) {
+ dloss = -MAX_DLOSS;
+ } else if ( dloss > MAX_DLOSS ) {
+ dloss = MAX_DLOSS;
+ }
+ update = -eta * dloss;
+
+ scaleFactor = stdlib_ml_sgd_decay( penalty, scaleFactor, eta, penaltyParams );
+ if ( scaleFactor < MIN_SCALE ) {
+ API_SUFFIX(c_dscal_ndarray)( N, scaleFactor, w, strideW, offsetW );
+ scaleFactor = 1.0;
+ }
+
+ // Gradient step: as `w_eff = w_stored*scaleFactor`, adding `update*X` to the effective weights amounts to adding `(update/scaleFactor)*X` to the stored weights...
+ API_SUFFIX(c_daxpy_ndarray)( N, update/scaleFactor, X, strideX2, ox, w, strideW, offsetW );
+
+ if ( fitIntercept ) {
+ intercept += update;
+ }
+ u = stdlib_ml_sgd_truncation( penalty, N, u, eta, scaleFactor, w, strideW, offsetW, ws, strideWS, offsetWS, penaltyParams );
+
+ t += 1;
+ ox += strideX1;
+ oy += strideY;
+ }
+ }
+ // Fold any residual scaling back into the weights so that `w` holds effective values...
+ if ( scaleFactor != 1.0 ) {
+ API_SUFFIX(c_dscal_ndarray)( N, scaleFactor, w, strideW, offsetW );
+ scaleFactor = 1.0;
+ }
+ if ( fitIntercept ) {
+ w[ offsetW+( strideW*N ) ] = intercept;
+ }
+ return w;
+}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/large_epsilon.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/large_epsilon.json
new file mode 100644
index 000000000000..030fd4e7d036
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/large_epsilon.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [0.22274577223842806, -1.7083359837461911, -0.48593264543917547, -0.15564389511208487, 1.1141617836213031, 0.8817708703819678, -1.0751820757976778, -1.9018224309183172, -0.9705402363426794, -0.3595358804727704, -1.9664040174266906, -0.11380421328565449, 1.4096884434229118, 1.692718793395077, -1.074255464344596, 1.963819657909315, -1.9760084142172412, -0.6589979105217347, 1.1570324517718937, -1.6059539391777093, -0.23067100288255116, -0.47732270207524996, 1.3303938764231757, 0.8478487413814544, -0.5799966971260195, -1.9014546620136668, 0.7740500757099307, -0.3151522344890023, 1.4333977727941112, 0.3002942151591923, 1.7602494486433122, 1.5210220777363088, -0.1674198777895275, -1.9307597298715238, -1.7253814344758114, -0.7175679354479967, 0.36920754750184814, 0.4402097532709326, 0.049710013450857016, -1.420974166639183, 1.507234772811977, 0.9529407166922663, -0.5067184644285883, 1.314745532503959, -1.6390418500336121, -1.7439871251107384, 0.02358779386919485, 1.7337068457391682, -1.4041523281733261, 0.2779151728262823, -1.7610053800982062, -1.322888292544099, -1.7238865596835367, 1.624089804355524, -0.21035975899734938, -1.5744591977166338, 0.6610391141070506, 0.009093508577587617, -0.3631744717872851, 0.9119738813524925], "y": [0.38306968005788355, -0.620994106789678, 1.8263412664555343, 0.7123611387680657, -0.7181045811759956, -0.6272033559573793, -0.3587832253693836, -0.5709853881985854, 0.3770180369958464, -0.21520863563092085, -1.2251363899114658, 1.9043270163760648, -0.3880543279394097, 0.2020596199466619, 0.8406010485785755, 0.4403855623726914, 1.7761122422000957, 0.598255825196784, 0.19698300613574402, -0.3542045970507915], "w": [0.03347067705588824, 0.043413585502444216, -0.0029206644103943052, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "l2", "loss_function": "squared-epsilon-insensitive", "learning_rate": "constant", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 2.0, "max_iter": 5, "fit_intercept": true, "intercept": 0.0, "expected_w": [0.02765563296514642, 0.0382157475828472, -0.005080292874998354], "expected_intercept": 0.003010223004876238}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/large_nfeatures.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/large_nfeatures.json
new file mode 100644
index 000000000000..26acb1ef1120
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/large_nfeatures.json
@@ -0,0 +1 @@
+{"M": 30, "N": 8, "X": [0.24406608575136213, -0.21529754011451363, 1.4211961042580485, 1.6447224913912182, 1.5062591721455232, 1.8617169026554499, -1.1907547762138444, 0.9055034356246567, 0.2852720648873577, 0.33570931844287566, -0.17311241073736605, 0.32844337406901714, -1.7290068633063957, -1.9761979095091267, -0.12795300229978723, 1.160910970386296, 1.6917954318649921, 0.8809656102276806, -1.496275864599847, 0.8763698658885728, 0.4619770776691654, -0.4531263900606386, 1.140856158180573, -1.5946237573897495, -0.3882485148806487, 0.9695867073331166, -1.9502647547520078, 1.7127306800490083, -0.1591060560912143, -1.7214999261614716, 1.639723484584045, -1.5067820003174996, 1.5791266523221297, -1.179759909246731, 1.7279551435546812, -0.008283444613439439, -0.5599837735715942, -1.3565152284267339, 0.9055038844851993, 1.3410994124192426, -0.7244844169012525, 1.9122614588090574, -0.10915525637133516, 0.2645775847486429, -1.4132623630958068, -1.6010223273189461, -1.6539314942656325, 1.012055308806242, 0.9691572003745508, -0.7379745652112271, 1.3812577088027989, 0.13818663028407396, 1.330281417925553, -1.255864060709623, -0.8961878968130037, 0.3322303790036387, 1.7198058487629528, -1.7708184101128936, 1.2731893908106016, -1.3415081022098154, -0.24117557726353267, -0.5339169573863884, -1.7368848491798525, 1.151235517791974, 0.04955223884629545, -1.2926459833764357, 0.0833248701609306, 0.3640362570761879, -0.22184554198509643, -1.4279679795347633, 1.8450564396854516, -0.3289208945959716, -1.479899451144708, 0.6039723036107008, 0.3516216049745906, -0.9810499778518729, -0.850268678833523, 1.2211154388653886, -1.7751694918602339, -0.8872332473934885, 1.7468455701656112, 1.3536262799059595, 1.6326954173592054, 0.3784683498825774, 1.0940052779091949, -0.6236000226751939, -0.464530912125384, -0.4882350677353071, -0.2961433877982409, 0.8275913887469071, -1.0233174829072604, -1.288874549481812, -1.1341381442180412, 0.8975615932442276, 0.5259480771625031, 1.178139615022297, 1.1428740553232348, -1.4200907047539815, -1.6500473826288466, -0.972972302414425, 0.5604696494530224, 0.27883156042496626, 1.5573727815097147, 1.672567463152547, -1.3904602432392985, -1.5240599794547416, -1.9597854210606145, -0.8806420462158604, -1.5083115557885938, -0.1694557012696154, -1.246394058523419, -1.9695541020803402, 1.5853519075513391, 1.9902117953223968, 1.2240162147882647, -1.8793282667131406, 0.14129393779619992, 0.44000200404302836, 1.4056945604678268, -0.3601679845686365, -0.954411898628146, 1.0191639279519582, 1.1643039302757066, 1.149158811795059, 1.7911274743006813, -0.39916705635423044, 0.632865529253098, 0.1025448309565955, -0.3274283776413882, -0.36985873720757967, -0.5149243745409353, 1.3755774971558457, -0.11669568909863148, 0.3395983716545259, -1.3371279134948146, 0.18863297422354064, 0.15527408601039694, 0.030519816092046348, 0.5723235331990484, 0.17873494711133686, -0.7269822167820785, 1.152765358473276, 0.2577013425915573, -0.33768455901425165, -0.688277350887585, 1.6825925546885387, 1.7218770592016175, -1.9572329931260577, -1.6276708837002318, -1.4636422255835022, 0.5093480973462148, -0.9532330984460269, 0.3301718297638234, 0.21960795160166757, -1.1986373428402497, 0.6283204800673983, 1.7728275481211115, -0.5729292637365933, -1.8727949356744116, -0.10589184343790103, -1.7301696308699226, -0.002984552135096852, 0.7685749240111588, -1.6955295357762799, -1.080679881604011, -0.010528531182274925, 0.17116290693535374, -0.02026042182480392, 1.2051318683212102, -0.7681629484841594, -1.543920884992136, 0.24112415512267749, 1.076435400887481, -0.25925229768534086, -1.6658644560151439, 0.3943754747457504, 1.3842565496753068, -1.2669773145341812, 1.6518767655452633, -1.5853909423966077, -1.4927047534677924, -1.983702332562233, 1.138356116290356, 0.24191379767133814, 0.6420805467039874, 0.0872890383804541, 1.1829845893028037, -0.993423393494183, 0.12192601976122841, -1.7747829968363762, -1.450669978352841, -1.4320477493831785, 0.6550718310518415, -1.5686419131829887, 1.0281382568127064, -0.18298026448742366, 0.7765106299217273, -0.5730905019255661, 1.072070869494694, 1.2693109634320097, 1.7069747706981535, -1.171849742990417, 0.4038260920604313, -1.8620887801661237, -0.8280409253527203, -1.830796051704672, -1.6109290088900714, -0.7963339740967319, -1.758933515478339, 0.33271167991059825, 0.897666281747084, 1.0030732022603628, 0.7923976057376598, -1.546564906061482, -0.8521623240892628, -0.9514215862422861, -1.7350877422644877, -1.9912922002916824, -0.9226224013458637, -1.8647568246715989, -0.12855010100772946, 0.16330621420984448, -1.1808980921524945, -1.084806403591437, 0.6133243491281353, -1.9215123600125263, -0.8023356042755481, -0.0783376868449066, 0.08509485307968845, 1.835992203881502, 1.0427188603165107, 1.2137056322879394, -0.681757498211685, -0.49288357133344984, 0.7482264148143973, 0.8290114720901394, -1.5566140346193902, -0.9289890156310094, -1.8778689057312667, -0.39602412251224806], "y": [-2.502127256606556, 1.7537411596711132, -1.7930695858009567, 1.2637896127321737, 1.0933480032453258, 1.9992147413021908, -0.5114017715814466, -1.6281183204216754, 1.8243463750772828, 0.5227249731158873, -0.35632893722236203, 0.2773133179148996, -2.233257676621232, -0.3365155191131898, 0.8895364387022068, 1.7097391994952302, -1.5452770481677645, -0.14981738941872053, 5.239403630903784, -2.832433263918785, 3.2443215404886003, -3.8885431673771294, 2.775101177626189, 1.0412324208482602, 0.2981329913450337, -0.5502558560717105, 2.8751156938322877, 0.05680479483507081, -2.5737729985321924, 1.219111547830647], "w": [-0.018579911916050018, -0.005414648940187491, -0.01989101886640754, -0.006271615693174956, -0.04492253692737036, 0.04535113879074375, -0.03211065826801199, -0.042324728177420334, 0.0], "workspace": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], "order": "row-major", "LDX": 8, "penalty": "elasticnet", "loss_function": "squared-epsilon-insensitive", "learning_rate": "constant", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 5, "fit_intercept": true, "intercept": 0.0, "expected_w": [-0.8614567540526539, 0.3851158853786177, 0.7281998866671436, -0.19026098822582405, -0.5220922878531832, -0.6787293371669859, 0.5479545198714791, -0.12632121990953651], "expected_intercept": 0.049427768231497436}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/learning-rates/lr_constant.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/learning-rates/lr_constant.json
new file mode 100644
index 000000000000..804266349efb
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/learning-rates/lr_constant.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [0.49184863344576346, -0.34814932094747153, -0.5477551911780645, -1.8535882346206338, 1.4725948382875114, 0.6913128505125967, -1.6501135437531054, 1.5478637569455782, 1.1298582030615867, -0.7307823549481589, 1.2732551495480275, 0.03022027296939278, -1.9152267929277276, -0.2659129670848732, -0.21474777618482355, -1.0447200423710807, 1.3209829273643017, 0.9790567064522131, 0.34591600384066234, -0.02852858973807182, -0.050576480635228016, -0.9330372163083185, 0.4200444057588677, 1.014174883961148, -0.9176630881870653, 0.08921313252990393, -1.6066858791457554, 0.8545466998779148, 1.5361623760639285, 0.26821768491201325, 1.977926315588928, -1.2850409189497674, -1.9511996548222879, -0.17200607777167676, 1.7270077674198032, 1.3840987528714987, -0.10668049571895954, 1.6102201041909407, -1.096017894650541, -0.7833850453736546, 0.8599755260540927, 0.896365933751508, -1.9252942423052741, -0.856747586564476, 0.32194534098155536, 1.723146528360679, -0.6440123932849473, -1.5196675077213357, 0.06509083410300853, 0.7968282532453359, -0.8054372916941004, 1.4464384611167111, 1.6232287815714956, 1.0743330073911381, -0.9550734370499776, 1.7538223847865955, 1.7545698220533867, 0.9801781884315104, 1.6429401713892413, -1.051101164821859], "y": [-0.6469006684260985, 1.583828050630603, 1.9861639666704718, 0.8310566289128972, -0.3827396059433048, 1.8269791598268526, -0.06999305823322631, 1.2651470592501224, -1.4047265180421287, 1.1783565828730356, -2.485433620743457, 2.4083030996503925, -0.10546375041122602, 1.3333946999632889, -0.15024329223572774, -1.8716730434183178, -0.24057029797606505, 1.9002328519757954, 2.737890375764529, -0.059906457215955576], "w": [0.005124203335664046, 0.006708121448377999, 0.031834497533628284, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "l2", "loss_function": "squared-epsilon-insensitive", "learning_rate": "constant", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 5, "fit_intercept": true, "intercept": 0.0, "expected_w": [-0.13067946689918927, 0.5935643883857246, 0.7574510089030908], "expected_intercept": 0.054914894415283196}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/learning-rates/lr_invscaling.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/learning-rates/lr_invscaling.json
new file mode 100644
index 000000000000..03673f682b3f
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/learning-rates/lr_invscaling.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [1.7559492152259675, -1.2283943405426072, 0.8513760971698203, 0.7917592169622498, -0.9668140051849408, 1.6632312782692131, 0.1294327463086602, 0.2318576776333856, -0.7089109273394034, -0.6454768696057704, -0.6707937838335223, 1.915272822370985, -1.187139217832068, 0.6681042402589932, 0.299137067767584, -1.7920988537218014, 0.1713524103606554, -1.168203540245476, -1.6356392811404619, 1.479422848035726, -1.8905208820125439, 1.874498088784982, -0.6900004417008394, -0.35888816852966476, -1.457823139815551, -1.491734757020184, -0.344064080943451, 0.46977494415677423, -1.470932388530589, 1.8979248714331152, -1.2774595902218833, 1.041399644785264, -0.0713527391823292, 1.0723154725770456, -0.7884062286809317, -1.9392996368981859, -0.14652525413218287, 0.8133483156760675, -1.7358364283613796, 0.676045670627218, -0.6180837766313587, 0.36688589041237885, -1.08378616877157, -0.9297265500889882, 1.731307942558797, 1.3045802351354268, -1.4182272286659376, 0.5880144395733393, 1.5358046613326701, 0.9654421366229844, 0.06284319737806987, -1.458992625740691, -1.8404653895786032, 1.3372873283558744, -1.5317685228209004, 0.09240925444021597, 1.4922338730262021, -1.8451686521346904, 0.7695631471748134, -0.09492608746937448], "y": [-0.9296034784994464, -1.264883906569768, 0.3244200436650097, -0.7893327336884475, -0.12901061013234016, 2.17915029486798, 1.6436479943506277, -0.2828325139708316, 2.7051784317623735, -0.908484642155605, 0.13598085671561017, 1.9355793676600648, 1.064028085967183, -0.16755055976969824, -0.18857226421413747, -0.2225346690018546, -1.9852899904518522, 1.4482374356704992, -0.4400502699718625, 0.5947804445814224], "w": [0.038104992838066884, -0.04587361188094161, -0.032513223853402065, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "l2", "loss_function": "squared-epsilon-insensitive", "learning_rate": "invscaling", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 5, "fit_intercept": true, "intercept": 0.0, "expected_w": [-0.3851190531127391, -0.1889321969722861, -0.44084917286955105], "expected_intercept": 0.11604942770144361}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_epsilon_insensitive.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_epsilon_insensitive.json
new file mode 100644
index 000000000000..2cce7d396269
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_epsilon_insensitive.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [1.199909651827984, -1.37894397292626, -0.5560321670962898, 1.820301026598949, -1.4793665285813047, -0.9086136593918828, 1.236471472296433, 1.8626282266948766, -1.6303113438782004, 0.3336970808345061, -0.3782947746783134, 1.5972967513969478, -1.6608662177221927, -1.2754548935757462, -1.7973381052573099, -0.7948850474797209, -1.2392645827818267, -1.965578451148518, -1.4899083973821718, -1.5485411047316169, 0.9216578058769334, -1.0424998686530396, 1.606280484150901, -0.685944280986412, 1.496170891144882, -1.0538819400500206, -0.4861815773232916, 0.16916223196505564, 0.06317592910230418, -0.3447915272825641, -0.4445335483876569, -0.638676728304683, -0.39106147917359113, -0.1715604131375006, -0.46803576920007606, 0.6323589094170394, 1.5248568248273653, 0.29069033732332317, -0.2878381718541849, -0.9664882671760537, 1.4610777326900428, -1.3068867970508427, 0.31981129929701657, 0.9095099935114406, 0.9216093414030437, -0.38401673597577624, -1.5282901160587254, 1.0543785236740266, 0.1346443689265837, 0.8881394350392484, 0.390529340078833, -0.308536120048176, 1.7339443506405878, 1.975883972040969, 0.19135535576813867, 0.9209382873709981, -1.8880628597409617, 1.454365106571017, 1.9945230374404606, -0.6987607042286847], "y": [0.749610938002661, 1.0669806352092963, 1.449041914787048, -0.2027322136145916, -1.1907523090788612, -0.5130441498423087, -1.5934292222010968, -0.32632468610617604, 0.9387997549010489, 0.15777404719222937, -0.4906827914004536, -0.12125129754383662, 1.1123844943639383, -0.1891612383971119, 0.4250675111968416, -0.7882957359061169, 0.2830589883577977, 0.02018392020843425, 0.6522398987859501, 1.5662783745917837], "w": [-0.005141598124558555, -0.025561642062394443, 0.031417296433045125, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "l2", "loss_function": "epsilon-insensitive", "learning_rate": "constant", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 5, "fit_intercept": true, "intercept": 0.0, "expected_w": [0.6791123374993187, 0.23541521043475572, -0.11354917748875704], "expected_intercept": 0.03}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_hinge.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_hinge.json
new file mode 100644
index 000000000000..e9131c8a90aa
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_hinge.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [0.7251850780964713, -0.4348667349991602, -1.895182104448605, 0.002398785384576385, 0.11250843628454676, -1.106927833044534, -1.9932412721725878, -0.21374607166859638, 0.021303253327713545, -1.6759246144269841, 1.2909596238500813, -1.0392202778771287, -1.9612388933381713, -1.0998330617252243, -1.6632394519138733, 1.3038583957043048, 0.8590688744396169, -1.0217754488187571, -1.7446526427804505, -0.29298321923164705, 0.8241660788828442, 0.8726143140303257, -1.2262626600145023, 0.9601924041297143, 1.8269194952820405, 0.06357590853621886, -0.2798190845214794, -1.907852979706964, 0.029303859915172925, 0.7462489109559316, -1.447298952162853, 0.6896914489890218, -1.842754154896078, -0.2728939149110836, 1.4171033864036957, -0.3106860657102244, -1.6462035573322895, -1.7732199694559712, -1.5869086177674427, -0.05873721045373825, 0.698628687555658, -1.636420625263392, 1.3288492257950342, 1.1058541236603894, -1.7553465666793362, -0.7103285530906707, -0.49144120618837306, 0.009060023641976223, -0.2001385792629069, -0.13055197818459385, -1.5811423592043021, -0.5049967592801399, -1.9129109521669587, -0.20664892739540974, 1.5724592327526437, 1.1035248954238317, -1.0033547384148207, 0.926178045586854, -0.7394480989901071, -0.015478157111626256], "y": [1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0], "w": [-0.021385740696746414, 0.015864623261680866, -0.040969959085125254, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "l2", "loss_function": "hinge", "learning_rate": "constant", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 5, "fit_intercept": true, "intercept": 0.0, "expected_w": [-0.7488988843283844, -0.0947550639466107, -0.27256202958380776], "expected_intercept": 0.21000000000000005}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_huber.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_huber.json
new file mode 100644
index 000000000000..6a1c07b58976
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_huber.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [0.0734202218991471, -0.09101849860015321, -0.39557436535790025, 1.7224576066603379, 0.06134458779906771, 1.23832807438819, 1.5270889111004813, 1.0506711282824686, -0.14231719127253983, -1.704321581358256, -0.11800256850404356, -1.1977120901693028, -1.165731105617183, -1.2898415992035326, -0.5830342055148456, 1.6470125048668818, -0.2659163238268789, -1.286816454721456, 1.0086489963024912, -1.7981177371888992, -1.6693259304581405, -1.8456662338204755, -0.13888557406837032, 0.4153146539831454, -1.272842627178175, 0.07611880248459935, 0.8406131034542623, 1.6999215137633952, 0.11652657955290557, 1.884742929298596, 0.18901104406482938, -1.9742480859324458, -0.10889300588421014, 0.08835231888271755, -1.3911643676466707, 0.6169363364555531, -1.4782254793323797, -0.18340450516112483, 1.9294458036999829, -1.469943623389541, -1.758884315013728, -1.7285108868714456, -1.6154158118282202, 1.277369499650077, 0.5184260168906558, 1.134524020564299, -1.6914583889513564, 1.8879932430627262, 1.5313342519665665, 0.5217325165983322, 1.716292354177872, -0.4074935773989483, -0.044295613462754346, 0.743212937162042, -0.8736136805761103, 0.7067998169792609, -0.01707314843453034, 1.164567926691066, -1.1246658761953383, 0.9847833462853184], "y": [-0.2456169866406885, 0.6557488459762985, -0.4688200088457306, -0.7951290132629524, -0.1283061153288265, -1.2987719247749145, -1.366740936664777, 0.5237426800942675, 0.8408477963061164, 1.465629026815471, 0.13945727964900279, 0.9306862590635027, 1.5947694168212077, -1.0116978600591013, 0.26938706171898136, 1.742408766115053, 1.2830204432128367, 0.5988547776643325, -0.06369541747909852, 1.000236126591862], "w": [0.016208359650160292, -0.015259577556246996, -0.037143000425776285, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "l2", "loss_function": "huber", "learning_rate": "constant", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 5, "fit_intercept": true, "intercept": 0.0, "expected_w": [0.023310624892916108, -0.01801363663622113, 0.061255512132994794], "expected_intercept": 0.022499551983441297}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_log.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_log.json
new file mode 100644
index 000000000000..0a8ab74fe086
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_log.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [-0.400007232993302, 1.3083908985621004, -0.17843452001748794, 0.7743328238868705, 0.5519213824976434, 0.6235321089670851, 1.0772759788879154, -1.9990910003433129, -0.7972182206399427, 0.7818859536092106, -1.6364503129076313, 0.09459009607780056, 1.5783801145226444, 1.8548234690021017, 0.8227527498689517, 1.0561155480006605, -0.6215685660926722, -0.9925986870784791, 0.668836461511471, -1.4027799396608347, -0.11633323088909098, -1.910832249696596, 1.038844223719198, -1.1773716803736303, 1.3623618965039435, 1.0994173294229173, -1.2953438193329623, 1.538235162376512, -1.62774418388077, -1.1912462182799723, -0.5103780685701529, -1.3053771569074661, -0.6190650291008013, 0.2709539246558572, -1.372192024289176, 1.1029617227006017, -1.865353689072597, -1.95616594389071, -0.7195065779869312, 0.10690841860846145, 0.5189062606613981, 1.526055332471107, 0.5645566914852158, -1.9092483379402063, 0.7807611913926054, 1.538607192275101, 1.0055764198203478, -0.9476881155643966, 0.030297960785700795, -1.5032359448584196, 0.43490277027863833, 0.7732512148821278, -1.688855073010691, -0.38367401024863046, 0.05394755763525261, 1.22826516163967, -1.604134757912683, -0.10987308742979485, 0.26936739220369343, 0.14393477340970495], "y": [1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0], "w": [-0.014970438241412413, -0.029761000195529266, -0.03400558876544127, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "l2", "loss_function": "log", "learning_rate": "constant", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 5, "fit_intercept": true, "intercept": 0.0, "expected_w": [-0.33842846802522253, 0.12477761204380569, 0.10113162761249513], "expected_intercept": -0.1553302347328218}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_modified_huber.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_modified_huber.json
new file mode 100644
index 000000000000..7bb196167d08
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_modified_huber.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [0.20930924077637947, -1.257079594390068, 1.9239054834027463, -1.6162534614599773, 0.9930515227605645, 0.0984736408745297, -0.8369611003066266, -1.0872369898312617, 0.01495664365612015, 1.7278286475329412, 0.29651911099460415, 1.958978463316039, -0.2809078999199688, -0.3345770071510765, 0.5115092130991759, 1.6294733148232408, -1.7223090447214808, 0.2016125720855153, -1.3815766594614751, 0.8742432013513493, -1.4583723920931626, -1.981814134395067, 0.15006470423607565, -1.9336287924628874, 0.14205814201157496, -1.8172317268992395, -1.384082536769911, 1.37204178889714, 1.1917176561924983, -0.7856227444671515, -0.40602645100897394, -0.20282358282124813, -1.9178592922749411, 0.47021646024926644, 1.218219485579037, -1.0633119542160094, -0.399486440456708, -0.026743355999237384, 0.007524475633007732, -0.6660471632735132, -1.5783188834831399, 0.5632313505422779, -1.3941235044004632, -1.2192933643882031, -1.770434181045085, 1.6589781890819872, 1.3226803648555299, -1.3639828888422172, 1.4708267019604437, 0.029192816571451452, -1.4867945171606545, -1.5475289984016771, -1.1088088779729253, 1.5593479001085129, -0.19631165400359363, 0.7888386844478363, -0.4388393853537722, 0.4904950415155427, 0.8657924447231933, 0.003436956893867915], "y": [-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0], "w": [0.006564677152321861, -0.04714419644559209, -0.03596693813754142, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "l2", "loss_function": "modified-huber", "learning_rate": "constant", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 5, "fit_intercept": true, "intercept": 0.0, "expected_w": [0.5341745141973712, 0.5289308896759088, -0.031437735174862244], "expected_intercept": -0.2076235275562692}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_perceptron.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_perceptron.json
new file mode 100644
index 000000000000..dda88b592cf0
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_perceptron.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [-1.784791096896201, 1.4511846722306188, 0.5198815330359134, 1.4786126068731789, -1.6492365005665053, 1.4636152974938628, -1.8350097582036944, 1.8326963629380892, -1.0905276911912605, 1.0074484076643166, -0.39700532191235993, -0.387698302333086, -0.98685212504695, 0.027353798831553977, -1.2617593669900171, -1.7716638948450192, -0.5322938483788713, 0.879349146603877, -0.10330185743288745, 1.6904811103857962, -1.3195107952735943, 0.8735271184967148, 1.4791905561759098, -1.4827609768911016, 1.8962232443372167, 1.0168624855657478, 1.6667098230500477, -1.8491886354076508, -0.8566046118000132, 1.2916315118613868, -0.9010654803355109, -1.7931042078105528, -1.408226874971675, -1.9340293231952503, 1.1296664913335857, -0.6035135700480567, 0.9987113824062832, -1.7801864311312388, -1.6872071053594553, 1.157362099722167, -0.5182477887163492, -1.5561502306701667, -0.3791359049765495, 0.6051951239567321, -0.25484717116859423, -1.1900993964161102, -0.2244416780889149, 0.9685923893992938, -1.6159396310056056, 0.04688505550936739, 1.3744657788806487, 1.9741746082820901, 0.523024709711871, -0.8581066808354083, -1.49591296870725, -1.94657718741546, -0.6473775157892385, -0.06271930725701225, 0.18476418683828877, -1.8558425036712785], "y": [1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0], "w": [0.011054014681613177, 0.015169836591697461, 0.015446516189045967, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "l2", "loss_function": "perceptron", "learning_rate": "constant", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 5, "fit_intercept": true, "intercept": 0.0, "expected_w": [-0.021390167869277752, -0.026227768616922737, 0.01787985269715197], "expected_intercept": 0.01}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_squared_epsilon_insensitive.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_squared_epsilon_insensitive.json
new file mode 100644
index 000000000000..d925f12929d7
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_squared_epsilon_insensitive.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [0.7885975943362533, -0.3615818358251217, -1.9771396629393712, 1.8160574562373295, 0.42101039848294075, -1.9738148936047835, -0.0060260518041546085, 0.3945413840750982, -0.7994101994938219, -0.15297001532503884, -0.01760087537506516, 0.34263656371901163, 1.4785519538274818, 1.3289078367201133, 1.1142521920184327, 0.19373243074836655, 0.4538078260237386, 0.937078908525252, 0.2654763656160064, 1.1008405388652047, 1.9461824230541218, 1.156822758782904, 0.4573439266653798, -1.3668618429874955, -0.09445474314594016, -0.8654033062157427, -1.384750938991433, 1.1088816781166857, -1.7641474664238799, -1.6835099939397296, 0.6569538507576698, 0.09337992420402585, -0.21437244168100866, -0.7726782118590951, -1.9308595144678509, -0.8258926343987372, -0.9288241375511399, -1.8530975933291365, 1.2161583117000623, -0.6648017708216187, 1.5675467382701198, 1.2414129340843973, 1.856404830172147, 1.8308562553420074, 0.364662019712072, -0.7539867225196994, 1.673682921120243, -1.797398175074595, -1.0970292744265278, -0.5491756053038204, -0.35097719375805214, 1.778485182753363, 0.317530180105178, -1.2529593954944747, 0.38593866117567943, 1.735025188745014, -1.4634474385606921, 1.9291341211467254, -1.3844973871078725, 1.2829125498336316], "y": [1.522269486599184, 1.7233769639898104, 0.12944281855697026, -0.16426826424544821, -0.394629820347218, -0.4165319997403697, -1.3445012638485825, 0.9950858460498876, 1.0125504584165494, 1.6969627976008863, 0.2710842922062427, 0.7334737527592142, -0.7003701789362734, -1.186033047467742, 0.05944648338752013, 0.4332262262706267, -0.23715621680951188, 1.1475772865521685, 0.5070616439204056, 0.08936350490635409], "w": [0.049583823804866894, 0.04442045718534875, -0.036885588816160365, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "l2", "loss_function": "squared-epsilon-insensitive", "learning_rate": "constant", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 5, "fit_intercept": true, "intercept": 0.0, "expected_w": [0.2684456154143304, -0.15937811137646452, -0.53171747782223], "expected_intercept": 0.052400477801831546}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_squared_error.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_squared_error.json
new file mode 100644
index 000000000000..9fe3cc426b67
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_squared_error.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [0.04943806854490873, -0.9480780929029344, -1.6044131634325711, 1.1953854271372943, -1.4287888945368952, 1.22266314233821, 1.5181044037318134, -0.0003193432162835741, 1.6570077634717233, -0.3503496341715211, -1.1985056508583987, 0.5742844343053419, -0.40053942757859007, 0.4569259917573443, -0.25075441319587277, 0.3724149866232609, 1.8057600430421696, 0.21248173566721773, 1.6149414288965946, -1.44598098051274, -1.9938249497152953, 0.4513373820941484, 0.16681172093328156, 1.1225226341046848, 1.2859758148085443, 1.8136390245531593, 0.43982436662883817, -0.8396727124941301, 1.3072319756711805, -0.49593242509683844, 0.4367081037151781, 0.4800862268836714, -0.23400012035842632, -1.2049124187491267, -0.2241855163458264, 1.6990693772877248, 0.6857374388257544, -1.6739076134844826, 0.2906369958356443, -1.517351208975994, 1.9998548951145576, 1.9895213890012435, 0.7788485709476332, -0.5044806236072912, -0.3939568441333825, 1.7003976520193884, -1.0205646329090605, 0.6560507215752711, -0.07511699571343478, -1.860225764331251, -1.556418152258496, 1.5814775198684674, 1.568404552068999, 1.6606439512364863, -0.77039331617451, -0.8063214806518224, 0.6370074357056192, 0.38055089043176116, 1.937476046607788, 0.4624890276933491], "y": [-1.8073164017936103, -0.8831961745108083, -0.15891176301131443, -0.16288414114277416, 0.40524208501269776, 1.0924306337468972, -3.200611561493632, 0.44182884926954635, 0.683601519256572, 0.9804389842315738, -0.08895573211328513, 1.7245112749098028, -1.4391218594014126, 3.8454849261944704, -1.0587447863101933, -1.486179319730095, -2.171177263442877, 0.9864679694605235, 0.4515652289689359, 1.171685156995844], "w": [0.012846754097598667, 0.048265104161919356, -0.03236833342087293, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "l2", "loss_function": "squared-error", "learning_rate": "constant", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 5, "fit_intercept": true, "intercept": 0.0, "expected_w": [-0.4664114330704009, 0.6501098229392946, 0.5112476080067482], "expected_intercept": -0.0314852075691766}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_squared_hinge.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_squared_hinge.json
new file mode 100644
index 000000000000..ec09eb65b22a
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/loss-functions/loss_squared_hinge.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [1.2890612359005744, 1.2296571530798683, -1.2335333031297497, 0.5532120811967887, 1.3298584626721843, -0.12069163101502589, 0.32141213306276617, -1.5643888803735293, -0.15032204015024941, 1.5454073315601726, -0.14006890024093277, -0.13513891408304568, -1.2159813252458105, -1.8450844454221014, 0.4634470245535294, 0.2585251219165383, -1.567076725647452, 0.9665327517570397, -1.266071895458436, -0.6054356321755407, -0.07807402694599119, 0.5757057289250311, 0.48650570181263353, 1.0447720366865036, -0.8533957784416222, -0.030459178858456948, 0.7276407540499337, 0.03987942496074659, 1.0728454576595046, -0.8002542339693064, 0.18752301005263794, -1.021420274099691, -0.22561083473236465, 1.2400578514347544, -1.5845323502487605, -1.080061044519124, 1.167057630957205, 0.26616531409951216, 1.3096689513775894, 1.8997349790269968, 1.8608978997673593, 1.7988104009301242, 0.20714766563406606, -1.6298554863871626, 0.9617230918343997, 0.2571897792687108, 0.9834309140861408, -0.178440454615433, -1.3773480003977916, 1.9838113639526322, 1.558764345100104, 1.2149975966954583, -0.3540971556950865, -1.1473725765252176, -0.8222408630641689, 0.4917253586410606, -1.007131794968056, 1.1987237679949243, -1.9244710728552215, -0.07859443917075026], "y": [1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0], "w": [0.006733437857021726, 0.019964846361620908, -0.040806452559370626, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "l2", "loss_function": "squared-hinge", "learning_rate": "constant", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 5, "fit_intercept": true, "intercept": 0.0, "expected_w": [0.6244501112949565, 0.456344158484591, -0.21897463983698223], "expected_intercept": -0.0810075858246219}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/many_epochs.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/many_epochs.json
new file mode 100644
index 000000000000..53d7d553effc
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/many_epochs.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [1.7471477514041598, 1.3432994416386257, 1.8904744355118996, 1.2926993494848453, -1.8675855244701869, 0.27798827434883266, -1.4099397281011936, 0.32021613444193653, -1.666037581120027, -0.17885089773270213, 1.4366284347836626, -0.6976942720838455, -0.649620013238752, 1.6725460783968917, 0.5488126402431388, -1.3361973743238766, 1.4964926620003598, -1.6177325322420155, 0.36049068799231376, 0.530998784426624, -0.6693805946438705, -1.3552794891872613, 0.5630982528849886, -0.44904017672454577, 1.2661114254180412, -1.0827211504865497, 0.6604656774781046, 0.30242979222728517, -1.682511990911419, -1.830711938007695, 1.4280899882519735, -1.4098314519292345, -1.58768917598058, -1.574604990792789, -0.8269937724626386, 0.12046730035457909, 1.465302083238932, 1.4751349859050733, -0.5739867920407296, -1.6074901549600566, -0.24709085522231922, 1.7899449319618408, -1.8336199208794333, -0.7566097717276365, 1.1291476482534741, 1.1820405927148836, 1.4103225964388408, 0.17556424816204563, 0.36251428150489806, -1.4435681099064088, -1.861105350405555, -1.3789616957236013, 1.0276778945318332, -0.5248702946152539, -0.8687505464855283, -1.032805117134529, 1.4854076710795248, -0.5316224590257081, 1.55214311666063, 1.7995146370467552], "y": [1.674620526437552, 1.47477632201614, -1.6805671477377357, -0.5291076705569755, -0.5884674785166051, -2.006737079222284, -0.1436525317329071, -1.2541325708486128, 1.3193776259279213, 0.2600101567816365, 0.7862257391287131, -0.9999022309104999, 0.4994500380323206, -0.6059963981912443, -0.7515442104453247, 0.4440020355982339, 0.03894998580099387, -1.2476889296283846, 0.0848625353565381, -0.2317657945488346], "w": [0.04301825245105392, 0.020205782452563686, 0.030062544866097385, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "l2", "loss_function": "squared-epsilon-insensitive", "learning_rate": "constant", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 25, "fit_intercept": true, "intercept": 0.0, "expected_w": [0.7259824725227432, -0.25340054286191704, 0.31558534637128116], "expected_intercept": 0.024531501392368423}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/no_intercept.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/no_intercept.json
new file mode 100644
index 000000000000..67c093867606
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/no_intercept.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [-0.31961034040006675, -0.6375736827892631, -1.8209243367794872, -1.5484347443656499, -0.24783404854009028, -1.7157071839055513, 1.2649804306288175, 1.4644625931707385, -1.4755206323244727, -1.2271222013046983, -0.2500289929046797, 1.883701298707937, 1.0954438571104976, -1.47289411316231, 1.7087194547252902, 1.3111863189828354, -0.4290733385586947, -1.437717415499935, -1.7914546432285912, -1.6290827383247786, 1.5479585214540585, -1.327396131135877, -0.5484535523384086, 0.6171275430236318, 0.4192878134399822, -0.42002851101573135, -0.50157839923338, -1.7477089129261119, -0.28416388867135245, 0.8788837042156672, 1.0721235601519137, -1.2225274172742036, 1.4514830763683966, -1.8851121868811447, 1.6085152666498863, -1.0538164803065468, -1.4856629570761468, -0.7284968478825591, 1.3950451820655236, 1.3291909868449068, -0.6173945900722413, -1.040115246650318, 0.14315021395012106, -0.9141322567155492, -1.8622765022224934, 0.508342360885933, 0.08080184378274557, -1.832176743598307, 1.029891075836595, 1.9533990518220077, 1.205603832891259, -0.6240756546960364, -0.6584350299655597, -0.5937143880089435, -0.2282172826083011, 0.3179737408783514, 0.4702436369433798, -1.2915300481313587, 1.4599271541886814, 0.8410827624573156], "y": [1.4034410088861806, 2.534765439407114, 1.543029737409197, -1.3022842744138745, -3.410157847683268, 0.19860022194453505, -1.4013145234425388, -0.0028830412259241156, 0.13005974324725922, 0.26174232065233555, -2.9655720323953028, 3.383977157189304, -0.7609987936816015, -0.2846864872229031, 0.9819028418136555, 1.5897259016367142, -0.41209628150879163, 0.502212687920912, -0.14389759452009862, 1.0143193919895745], "w": [-0.03460848348445229, -0.0004104154820087427, -0.023870521982604722, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "l2", "loss_function": "squared-epsilon-insensitive", "learning_rate": "constant", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 5, "fit_intercept": false, "intercept": 0.0, "expected_w": [-0.581049115325038, 0.5912489778564128, -0.9128343325696479], "expected_intercept": 0.0}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/penalties/penalty_elasticnet.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/penalties/penalty_elasticnet.json
new file mode 100644
index 000000000000..491ecb84de8d
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/penalties/penalty_elasticnet.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [0.7693805736638444, -0.11059624371926091, 1.4274917677380032, 0.6589733356172243, -0.6664962308987019, 0.07258199702525303, -0.4212456662193098, -1.8758016065745546, 0.30735937253248347, 1.4010069813954433, 1.8059554606945802, 0.7319151884330668, -1.6953498072158881, -0.35968822891005203, -1.8323944049130532, -1.3032526736984833, 0.26160802225901403, -1.3084353176005585, 0.26644191177778476, 0.05601701179816443, 1.4754835501895074, 0.8813889917238114, 1.6143653882811932, -0.8895400070665116, -0.9733382712740482, 0.7988130514456429, 1.6062755849957577, 1.9347693004863125, 0.5636512497049799, -0.6799704458591562, 0.4267008649166404, 1.2886391543035622, 0.5118602618446464, -1.5283077699971588, -0.8564893065953747, 1.9469888613514583, -0.2727966060363025, 0.29693765513225756, 0.1089683066969207, -1.2093878024899491, -1.3371662711006636, 0.00396183168879416, 1.960816240341257, -0.4240327547654128, 0.8560530611064596, -1.296382922306909, -1.7172152849982294, -1.3695076547500107, -1.3537679459646563, -0.865451670951443, 0.14682410225626397, 1.092954859572842, 1.5213743251088174, 0.549565787829621, 1.4104089610182124, 0.39182148609770806, 0.7753866412082515, 0.1487066925864049, 1.556920333862784, -1.7909342949727214], "y": [-0.9987636598914722, 0.8247285413003103, 0.9148901941212165, -1.158247775236564, 0.9705507963532617, 0.23993786140586557, -1.1650553801867936, 0.17462069460080237, -2.6817941136706773, 1.3057441076912282, -1.1562184567568425, -1.9331796054681905, -0.41899625150687864, 0.19244106072326808, 0.6592782782754152, 1.7381927383862659, -0.32118218057278275, -0.9501921252564359, -0.12103577822443397, 0.569740440386762], "w": [0.046759148096693515, 0.04300288092605399, -0.03153201680039677, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "elasticnet", "loss_function": "squared-epsilon-insensitive", "learning_rate": "constant", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 5, "fit_intercept": true, "intercept": 0.0, "expected_w": [0.32064875418567257, -0.453539405839973, -0.7282131843967453], "expected_intercept": -0.046634523953870397}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/penalties/penalty_l1.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/penalties/penalty_l1.json
new file mode 100644
index 000000000000..80a6e8de13d4
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/penalties/penalty_l1.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [-0.5375236505312575, 1.2064103940110407, 1.130942367901505, 0.805421516946772, 0.4911063464127965, -0.02526941701155172, 1.3621508004739549, 0.8483879477745893, -0.22436407433659022, -1.8758605554666694, -0.5470409592256078, 0.9228871656413551, -0.09773370766543366, -0.6223321195119893, 0.5635217399840751, -1.4951787135424022, -1.314138956143001, 0.9483459747540866, -1.4918824257103904, -0.5214005002134927, 0.4173360193441056, -1.587582244577411, 1.2094967293488406, 1.7822129433684974, 1.9161552797357504, 1.5249289853557082, 0.5107276858559007, 1.7219461336106625, 0.8991598124097555, 0.8667115442214248, -1.8356857336632646, -0.24207289933010046, -0.8717208675356489, -0.6600161244322909, -1.6658919718223988, 1.0433965882295442, 0.03708978865581569, 0.6441896704338088, 0.5212577699371259, -0.5162926901698901, -0.21303939307662123, -0.33956711920962723, -0.0784459679463736, 1.9332942935538648, -0.5063051705858506, -1.9503720730891456, 1.6876133511961156, 1.4931042813768318, -0.593012713649645, 0.5205324500091684, -0.5686921626332357, -1.1487202494061401, -1.1067231075093913, -0.3217448330766892, -1.708359115687733, 0.6033562805467692, 1.0227445958037498, 1.728404905247249, -0.49438336167200836, -0.8122908662018662], "y": [1.7469232414307059, 0.11747490038914946, -0.003499087408005048, 0.848226470371408, 0.0454227465762615, 0.28854353012124667, 0.33107565852793136, 2.7099971198001356, 0.9561250354151642, 0.9977942235129255, -0.38047547565331, -0.13786965518954192, 0.7259933380729536, -0.22720568497289156, 0.9285355387637286, 2.9293498211949336, 0.24355091400635798, -0.6004085386845477, 1.544720047112647, -1.3403597888470205], "w": [0.028792778797953972, 0.03564774570595708, 0.022779601559861917, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "l1", "loss_function": "squared-epsilon-insensitive", "learning_rate": "constant", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 5, "fit_intercept": true, "intercept": 0.0, "expected_w": [-0.2682075068709644, 0.5856149345677873, 0.5750193229246117], "expected_intercept": 0.2083091117628858}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/penalties/penalty_l2.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/penalties/penalty_l2.json
new file mode 100644
index 000000000000..8d12b744c877
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/penalties/penalty_l2.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [0.5349030758039164, -0.2467604755102899, -1.3897089013019785, 0.27363846098876055, 0.11289711034024208, 1.8057150550143728, -0.07856328595993567, 0.010238253530201469, 0.147512771697639, 1.2768082682566333, -1.7715374476445604, 0.6776869722981953, 1.06846651351789, 0.8324614479104153, 1.1874687349007864, 0.2310433137097978, 1.8633461279685104, -1.4113724004280113, -1.8814119978583377, 0.37557397049908703, -1.54373720502935, 1.8032394003364889, -0.6971703422986111, -1.2255252393848912, -0.16875340441028985, 1.681610284372351, 1.516276646058703, -0.9895369798138791, -0.6079648285226154, -1.269645073678765, 1.6071842054839682, 0.8261126526871898, 0.906633846248563, 1.6003513472388309, 1.116655203077297, 0.39661912241716957, -0.8354990204085007, -1.3944189423702715, -0.6593013634022604, 0.6302071086312777, -1.7066298254695274, -1.7799744183751054, -0.7072207443152942, 0.3619272178519446, 1.4155942685025669, -0.851750299999964, -1.3077310927408314, -1.4639151760046287, 1.978615314577178, -1.2820085221224327, -0.7298127078912167, 0.27316561863642885, -1.962605701999022, 1.6025944846203677, 1.9089657236903483, 0.22757871654733952, -1.6609046264232394, -0.6679901370835997, 0.913714705478688, -1.4302585066327311], "y": [-1.2698992337837034, 1.7729399736158222, 0.1508151869665399, 1.5475902109796758, 0.9306260705692969, -2.085915354564297, -1.8081955641820648, -0.5927850979957924, 0.5213056119647277, -1.0014412695753345, 0.6745782822521256, 0.04645905805426469, -0.061794280735183935, -0.7169653181183582, 1.2019716284178328, -0.8971425840035512, 0.10429970555242818, 2.4775136093226, -1.6228917857078133, -1.950957483398009], "w": [0.0371423255048698, -0.028436593701160418, 0.023494518856219643, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "l2", "loss_function": "squared-epsilon-insensitive", "learning_rate": "constant", "lambda": 0.0001, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 5, "fit_intercept": true, "intercept": 0.0, "expected_w": [0.11180063226335232, -0.38460679411498216, 0.8754338312152041], "expected_intercept": -0.026089120589532073}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/penalties/penalty_none.json b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/penalties/penalty_none.json
new file mode 100644
index 000000000000..46d41e4e73b7
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/penalties/penalty_none.json
@@ -0,0 +1 @@
+{"M": 20, "N": 3, "X": [-1.2339221984844309, 0.48843508415932746, -0.24908904397154208, 1.1414343348550768, 1.119903232475214, -0.9096295788694335, -0.8941429794276132, 1.207488710140077, 1.8325574147348207, 1.5037305389683788, -0.5687309201685333, 0.003980502093834826, 0.7338517406885452, 0.8508081079316008, -0.5189969808384203, 0.24478474426249974, 0.012332661231238884, -1.944926201637271, 1.0913064864494961, 1.5305647625444663, -0.5404560643945109, 0.4615847137339748, -1.6984750334280938, -0.524703975992102, 1.7325604079300865, 0.6055125729063096, -0.4111896890953832, 1.154920571762982, -0.732655511324515, 0.2723946105042767, 1.4765095582449033, -0.2553063044172825, 1.2085905683206364, -1.4249327019417417, 0.8170438844733416, 0.8183252327582902, -1.1248315773036457, 1.6994705144622602, -0.23143697838329347, 1.63726383588989, -1.7607631088805924, -1.2628516647447454, -1.8105788847939395, 0.6995237743293208, 0.3784991197377954, 0.13324065199500223, -1.826703749220786, 0.24573232025359149, -0.6813262175163399, 0.011867332450473445, -1.5524227297023847, 0.42877482487393825, 0.2637785722021255, -1.9729437520399888, 0.4697668352171882, 1.6484915457326172, 1.1620965322281336, 1.9683258647534458, 1.835207048611466, 1.1678565411665591], "y": [0.615780567117064, -0.2924716955927201, 0.5983274388324427, -0.8535063034045541, -0.04511975114820965, -0.07232418417258707, -0.14311511736782573, -0.35195515736204436, -0.5993867245972314, -0.7266283889200774, -0.7692109548203575, 0.8682866188541212, 0.8980239768652085, -1.0863320077453502, 0.8794665202411985, -0.7023934913747021, 0.43689498777280067, -0.012164474803745749, 0.30486684746051645, -0.3491324359939706], "w": [-0.03501662840100728, 0.02460634091367167, 0.03310069924335378, 0.0], "workspace": [0.0, 0.0, 0.0], "order": "row-major", "LDX": 3, "penalty": "none", "loss_function": "squared-epsilon-insensitive", "learning_rate": "constant", "lambda": 0.0, "l1_ratio": 0.15, "eta0": 0.01, "power_t": 0.25, "epsilon": 0.1, "max_iter": 5, "fit_intercept": true, "intercept": 0.0, "expected_w": [-0.3540673727315888, 0.22097333229954338, 0.011242062522575555], "expected_intercept": -0.018616232538650853}
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/runner.py b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/runner.py
new file mode 100644
index 000000000000..970f7b74dc36
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/fixtures/python/runner.py
@@ -0,0 +1,241 @@
+#!/usr/bin/env python
+#
+# @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.
+
+"""Generate fixtures."""
+
+import os
+import json
+import numpy as np
+from sklearn.linear_model import SGDRegressor, SGDClassifier
+
+# For reproducibility:
+np.random.seed(1234)
+
+# Get the file path:
+FILE = os.path.realpath(__file__)
+
+# Extract the directory in which this file resides:
+DIR = os.path.dirname(FILE)
+
+# Map scikit-learn penalty arguments to stdlib penalty names:
+penalties = {
+ None: "none",
+ "l2": "l2",
+ "l1": "l1",
+ "elasticnet": "elasticnet"
+}
+
+# Map scikit-learn loss arguments to stdlib loss function names:
+losses = {
+ "squared_error": "squared-error",
+ "huber": "huber",
+ "epsilon_insensitive": "epsilon-insensitive",
+ "squared_epsilon_insensitive": "squared-epsilon-insensitive",
+ "hinge": "hinge",
+ "squared_hinge": "squared-hinge",
+ "perceptron": "perceptron",
+ "modified_huber": "modified-huber",
+ "log_loss": "log"
+}
+
+# Loss functions which require binary targets:
+classification = (
+ "hinge",
+ "squared_hinge",
+ "perceptron",
+ "modified_huber",
+ "log_loss"
+)
+
+
+def gen(
+ name: str,
+ loss: str = "squared_epsilon_insensitive",
+ penalty: str | None = "l2",
+ alpha: float = 1.0e-4,
+ l1_ratio: float = 0.15,
+ learning_rate: str = "constant",
+ eta0: float = 0.01,
+ power_t: float = 0.25,
+ epsilon: float = 0.1,
+ max_iter: int = 5,
+ fit_intercept: bool = True,
+ n_samples: int = 20,
+ n_features: int = 3
+ ):
+ """Generate fixture data and write to file.
+
+ # Arguments
+
+ * `name::str`: output filename
+ * `loss::str`: loss function name
+ * `penalty`: penalty name
+ * `alpha`: regularization parameter
+ * `l1_ratio`: elastic net mixing parameter
+ * `learning_rate::str`: learning rate schedule
+ * `eta0`: initial learning rate
+ * `power_t`: exponent for the inverse scaling learning rate
+ * `epsilon`: insensitivity parameter
+ * `max_iter`: number of epochs
+ * `fit_intercept`: boolean indicating whether to fit an intercept
+ * `n_samples`: number of samples
+ * `n_features`: number of features
+
+ # Examples
+
+ ``` python
+ python> gen('./data.json', penalty='l2')
+ ```
+ """
+ x = np.asarray(
+ np.random.uniform( -2.0, 2.0, ( n_samples, n_features ) ),
+ dtype=np.float64
+ )
+ beta = np.random.uniform( -1.0, 1.0, n_features )
+ y = x @ beta + np.random.normal( 0.0, 0.1, n_samples )
+
+ if loss in classification:
+ y = np.where( y > 0.0, 1.0, -1.0 ) # binary classification
+
+ y = np.asarray( y, dtype=np.float64 )
+
+ # Generate initial coefficients:
+ w = np.asarray(
+ np.random.uniform( -0.05, 0.05, n_features ),
+ dtype=np.float64
+ )
+
+ opts = {
+ "loss": loss,
+ "penalty": penalty,
+ "alpha": alpha,
+ "l1_ratio": l1_ratio,
+ "fit_intercept": fit_intercept,
+ "max_iter": max_iter,
+ "learning_rate": learning_rate,
+ "eta0": eta0,
+ "power_t": power_t,
+ "epsilon": epsilon,
+
+ # Equivalence settings to make it perform similar to stdlib implementation:
+ "tol": None,
+ "shuffle": False,
+ "early_stopping": False,
+ "warm_start": False,
+ "average": False,
+ "random_state": 0
+ }
+
+ if loss in classification:
+ model = SGDClassifier(class_weight=None, **opts)
+ model.fit(x, y, coef_init=w.reshape(1, n_features).copy(),
+ intercept_init=np.zeros(1, dtype=np.float64))
+ expected = model.coef_.ravel() # returns 2D array as it supports multi-class classification
+ else:
+ model = SGDRegressor(**opts)
+ model.fit(x, y, coef_init=w.copy(),
+ intercept_init=np.zeros(1, dtype=np.float64))
+ expected = model.coef_
+
+ # Ensure that the convergence check did not terminate training early:
+ assert model.n_iter_ == max_iter, (name, model.n_iter_, max_iter)
+
+ intercept = 0.0
+ expected_intercept = float(model.intercept_[0])
+
+ data = {
+ "M": n_samples,
+ "N": n_features,
+ "X": x.ravel().tolist(),
+ "y": y.tolist(),
+ "w": w.tolist() + [intercept],
+ "workspace": [0.0] * n_features,
+ "order": "row-major",
+ "LDX": n_features,
+ "penalty": penalties[penalty],
+ "loss_function": losses[loss],
+ "learning_rate": learning_rate,
+ "lambda": alpha,
+ "l1_ratio": l1_ratio,
+ "eta0": eta0,
+ "power_t": power_t,
+ "epsilon": epsilon,
+ "max_iter": max_iter,
+ "fit_intercept": fit_intercept,
+ "intercept": intercept,
+ "expected_w": expected.tolist(),
+ "expected_intercept": expected_intercept
+ }
+
+ # Based on the script directory, create an output filepath:
+ filepath = os.path.join(DIR, name)
+
+ # Create the output directory if it doesn't exist:
+ os.makedirs(os.path.dirname(filepath), exist_ok=True)
+
+ # Write the data to the output filepath as JSON:
+ with open(filepath, "w", encoding="utf-8") as outfile:
+ json.dump(data, outfile)
+
+ # Include trailing newline:
+ with open(filepath, "a", encoding="utf-8") as outfile:
+ outfile.write("\n")
+
+
+def main():
+ """Generate fixture data."""
+ # Penalties:
+ gen("penalties/penalty_none.json", penalty=None, alpha=0.0)
+ gen("penalties/penalty_l2.json", penalty="l2")
+ gen("penalties/penalty_l1.json", penalty="l1")
+ gen("penalties/penalty_elasticnet.json", penalty="elasticnet")
+
+ # Learning rate schedules:
+ gen("learning-rates/lr_constant.json", learning_rate="constant")
+ gen("learning-rates/lr_invscaling.json", learning_rate="invscaling")
+
+ # Intercept handling:
+ gen("no_intercept.json", fit_intercept=False)
+
+ # Large insensitivity parameter (i.e., many zero gradients):
+ gen("large_epsilon.json", loss="squared_epsilon_insensitive", epsilon=2.0)
+
+ # Loss functions (regression):
+ gen("loss-functions/loss_squared_error.json", loss="squared_error")
+ gen("loss-functions/loss_epsilon_insensitive.json", loss="epsilon_insensitive")
+ gen("loss-functions/loss_squared_epsilon_insensitive.json",
+ loss="squared_epsilon_insensitive")
+ gen("loss-functions/loss_huber.json", loss="huber")
+
+ # Loss functions (binary classification, `y` in `{-1,+1}`):
+ gen("loss-functions/loss_hinge.json", loss="hinge")
+ gen("loss-functions/loss_squared_hinge.json", loss="squared_hinge")
+ gen("loss-functions/loss_perceptron.json", loss="perceptron")
+ gen("loss-functions/loss_modified_huber.json", loss="modified_huber")
+ gen("loss-functions/loss_log.json", loss="log_loss")
+
+ # Larger number of features:
+ gen("large_nfeatures.json", penalty="elasticnet", n_samples=30,
+ n_features=8)
+
+ # Multiple epochs:
+ gen("many_epochs.json", max_iter=25)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/test.dsgd_trainer.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/test.dsgd_trainer.js
new file mode 100644
index 000000000000..ca1d3ee66580
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/test.dsgd_trainer.js
@@ -0,0 +1,1027 @@
+/**
+* @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.
+*/
+
+/* eslint-disable max-len */
+
+'use strict';
+
+// MODULES //
+
+var tape = require( 'tape' );
+var isAlmostSameValue = require( '@stdlib/number/float64/base/assert/is-almost-same-value' );
+var penalty2enum = require( '@stdlib/ml/base/sgd/penalty-str2enum' );
+var lr2enum = require( '@stdlib/ml/base/sgd/learning-rate-str2enum' );
+var loss2enum = require( '@stdlib/ml/base/sgd/loss-function-str2enum' );
+var Float64Params = require( '@stdlib/ml/base/sgd/params/float64' );
+var Float64Array = require( '@stdlib/array/float64' );
+var dsgdTrainer = require( './../lib/dsgd_trainer.js' );
+
+
+// FIXTURES //
+
+var penaltyNone = require( './fixtures/python/penalties/penalty_none.json' );
+var penaltyL2 = require( './fixtures/python/penalties/penalty_l2.json' );
+var penaltyL1 = require( './fixtures/python/penalties/penalty_l1.json' );
+var penaltyElasticnet = require( './fixtures/python/penalties/penalty_elasticnet.json' );
+var lrConstant = require( './fixtures/python/learning-rates/lr_constant.json' );
+var lrInvscaling = require( './fixtures/python/learning-rates/lr_invscaling.json' );
+var noIntercept = require( './fixtures/python/no_intercept.json' );
+var largeEpsilon = require( './fixtures/python/large_epsilon.json' );
+var lossSquaredError = require( './fixtures/python/loss-functions/loss_squared_error.json' );
+var lossEpsilonInsensitive = require( './fixtures/python/loss-functions/loss_epsilon_insensitive.json' );
+var lossSqEpsInsensitive = require( './fixtures/python/loss-functions/loss_squared_epsilon_insensitive.json' );
+var lossHuber = require( './fixtures/python/loss-functions/loss_huber.json' );
+var lossHinge = require( './fixtures/python/loss-functions/loss_hinge.json' );
+var lossSquaredHinge = require( './fixtures/python/loss-functions/loss_squared_hinge.json' );
+var lossPerceptron = require( './fixtures/python/loss-functions/loss_perceptron.json' );
+var lossModifiedHuber = require( './fixtures/python/loss-functions/loss_modified_huber.json' );
+var lossLog = require( './fixtures/python/loss-functions/loss_log.json' );
+var largeNfeatures = require( './fixtures/python/large_nfeatures.json' );
+var manyEpochs = require( './fixtures/python/many_epochs.json' );
+
+
+// TESTS //
+
+tape( 'main export is a function', function test( t ) {
+ t.ok( true, __filename );
+ t.strictEqual( typeof dsgdTrainer, 'function', 'main export is a function' );
+ t.end();
+});
+
+tape( 'the function has an arity of 12', function test( t ) {
+ t.strictEqual( dsgdTrainer.length, 12, 'returns expected value' );
+ t.end();
+});
+
+tape( 'the function throws an error if provided an invalid first argument', function test( t ) {
+ var values;
+ var params;
+ var data;
+ var i;
+
+ data = penaltyL2;
+
+ values = [
+ 'foo',
+ 'bar',
+ 'beep',
+ 'boop'
+ ];
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ params = new Float64Params(params );
+
+ for ( i = 0; i < values.length; i++ ) {
+ t.throws( badValue( values[ i ] ), TypeError, 'throws an error when provided ' + values[ i ] );
+ }
+ t.end();
+
+ function badValue( value ) {
+ return function badValue() {
+ dsgdTrainer( value, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, new Float64Array( data.N+1 ), 1, new Float64Array( data.N ), 1, params );
+ };
+ }
+});
+
+tape( 'the function throws an error if provided an invalid second argument', function test( t ) {
+ var values;
+ var params;
+ var data;
+ var i;
+
+ data = penaltyL2;
+
+ values = [
+ -1,
+ -2,
+ -3
+ ];
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ params = new Float64Params(params );
+
+ for ( i = 0; i < values.length; i++ ) {
+ t.throws( badValue( values[ i ] ), RangeError, 'throws an error when provided ' + values[ i ] );
+ }
+ t.end();
+
+ function badValue( value ) {
+ return function badValue() {
+ dsgdTrainer( data.order, value, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, new Float64Array( data.N+1 ), 1, new Float64Array( data.N ), 1, params );
+ };
+ }
+});
+
+tape( 'the function throws an error if provided an invalid third argument', function test( t ) {
+ var values;
+ var params;
+ var data;
+ var i;
+
+ data = penaltyL2;
+
+ values = [
+ -1,
+ -2,
+ -3
+ ];
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ params = new Float64Params(params );
+
+ for ( i = 0; i < values.length; i++ ) {
+ t.throws( badValue( values[ i ] ), RangeError, 'throws an error when provided ' + values[ i ] );
+ }
+ t.end();
+
+ function badValue( value ) {
+ return function badValue() {
+ dsgdTrainer( data.order, data.M, value, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, new Float64Array( data.N+1 ), 1, new Float64Array( data.N ), 1, params );
+ };
+ }
+});
+
+tape( 'the function throws an error if provided an invalid fifth argument', function test( t ) {
+ var values;
+ var params;
+ var data;
+ var i;
+
+ data = penaltyL2;
+
+ values = [
+ 0,
+ -1
+ ];
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ params = new Float64Params(params );
+
+ for ( i = 0; i < values.length; i++ ) {
+ t.throws( badValue( values[ i ] ), RangeError, 'throws an error when provided ' + values[ i ] );
+ }
+ t.end();
+
+ function badValue( value ) {
+ return function badValue() {
+ dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), value, new Float64Array( data.y ), 1, new Float64Array( data.N+1 ), 1, new Float64Array( data.N ), 1, params );
+ };
+ }
+});
+
+tape( 'the function throws an error if provided an invalid seventh argument', function test( t ) {
+ var values;
+ var params;
+ var data;
+ var i;
+
+ data = penaltyL2;
+
+ values = [
+ 0
+ ];
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ params = new Float64Params(params );
+
+ for ( i = 0; i < values.length; i++ ) {
+ t.throws( badValue( values[ i ] ), RangeError, 'throws an error when provided ' + values[ i ] );
+ }
+ t.end();
+
+ function badValue( value ) {
+ return function badValue() {
+ dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), value, new Float64Array( data.N+1 ), 1, new Float64Array( data.N ), 1, params );
+ };
+ }
+});
+
+tape( 'the function throws an error if provided an invalid ninth argument', function test( t ) {
+ var values;
+ var params;
+ var data;
+ var i;
+
+ data = penaltyL2;
+
+ values = [
+ 0
+ ];
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ params = new Float64Params(params );
+
+ for ( i = 0; i < values.length; i++ ) {
+ t.throws( badValue( values[ i ] ), RangeError, 'throws an error when provided ' + values[ i ] );
+ }
+ t.end();
+
+ function badValue( value ) {
+ return function badValue() {
+ dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, new Float64Array( data.N+1 ), value, new Float64Array( data.N ), 1, params );
+ };
+ }
+});
+
+tape( 'the function throws an error if provided an invalid eleventh argument', function test( t ) {
+ var values;
+ var params;
+ var data;
+ var i;
+
+ data = penaltyL2;
+
+ values = [
+ 0
+ ];
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ params = new Float64Params(params );
+
+ for ( i = 0; i < values.length; i++ ) {
+ t.throws( badValue( values[ i ] ), RangeError, 'throws an error when provided ' + values[ i ] );
+ }
+ t.end();
+
+ function badValue( value ) {
+ return function badValue() {
+ dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, new Float64Array( data.N+1 ), 1, new Float64Array( data.N ), value, params );
+ };
+ }
+});
+
+tape( 'the function trains a linear model via stochastic gradient descent (no penalty)', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = penaltyNone;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function trains a linear model via stochastic gradient descent (L2 penalty)', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = penaltyL2;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function trains a linear model via stochastic gradient descent (L1 penalty)', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = penaltyL1;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function trains a linear model via stochastic gradient descent (elastic net penalty)', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = penaltyElasticnet;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports a constant learning rate scheduler', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lrConstant;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports an inverse scaling learning rate scheduler', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lrInvscaling;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports a large insensitivity parameter', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = largeEpsilon;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the squared error loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossSquaredError;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the epsilon-insensitive loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossEpsilonInsensitive;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the squared epsilon-insensitive loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossSqEpsInsensitive;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the Huber loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossHuber;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the hinge loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossHinge;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the squared hinge loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossSquaredHinge;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the perceptron loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossPerceptron;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the modified Huber loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossModifiedHuber;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the log loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossLog;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports a large number of features', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = largeNfeatures;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports multiple epochs', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = manyEpochs;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, 0 ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function does not fit an intercept when `fitIntercept` is `false`', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = noIntercept;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.order, data.M, data.N, new Float64Array( data.X ), data.LDX, new Float64Array( data.y ), 1, w, 1, workspace, 1, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], 0 ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( out[ data.N ], 0.0, 'does not store an intercept' );
+
+ t.end();
+});
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/test.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/test.js
new file mode 100644
index 000000000000..a086d4b31ae6
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/test.js
@@ -0,0 +1,38 @@
+/**
+* @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 tape = require( 'tape' );
+var dsgdTrainer = require( './../lib' );
+
+
+// TESTS //
+
+tape( 'main export is a function', function test( t ) {
+ t.ok( true, __filename );
+ t.strictEqual( typeof dsgdTrainer, 'function', 'main export is a function' );
+ t.end();
+});
+
+tape( 'attached to the main export is a method providing an ndarray interface', function test( t ) {
+ t.strictEqual( typeof dsgdTrainer.ndarray, 'function', 'method is a function' );
+ t.end();
+});
diff --git a/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/test.ndarray.js b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/test.ndarray.js
new file mode 100644
index 000000000000..7f35dc290c24
--- /dev/null
+++ b/lib/node_modules/@stdlib/ml/strided/dsgd-trainer/test/test.ndarray.js
@@ -0,0 +1,1001 @@
+/**
+* @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.
+*/
+
+/* eslint-disable max-len */
+
+'use strict';
+
+// MODULES //
+
+var tape = require( 'tape' );
+var isAlmostSameValue = require( '@stdlib/number/float64/base/assert/is-almost-same-value' );
+var penalty2enum = require( '@stdlib/ml/base/sgd/penalty-str2enum' );
+var lr2enum = require( '@stdlib/ml/base/sgd/learning-rate-str2enum' );
+var loss2enum = require( '@stdlib/ml/base/sgd/loss-function-str2enum' );
+var Float64Params = require( '@stdlib/ml/base/sgd/params/float64' );
+var Float64Array = require( '@stdlib/array/float64' );
+var dsgdTrainer = require( './../lib/ndarray.js' );
+
+
+// FIXTURES //
+
+var penaltyNone = require( './fixtures/python/penalties/penalty_none.json' );
+var penaltyL2 = require( './fixtures/python/penalties/penalty_l2.json' );
+var penaltyL1 = require( './fixtures/python/penalties/penalty_l1.json' );
+var penaltyElasticnet = require( './fixtures/python/penalties/penalty_elasticnet.json' );
+var lrConstant = require( './fixtures/python/learning-rates/lr_constant.json' );
+var lrInvscaling = require( './fixtures/python/learning-rates/lr_invscaling.json' );
+var noIntercept = require( './fixtures/python/no_intercept.json' );
+var largeEpsilon = require( './fixtures/python/large_epsilon.json' );
+var lossSquaredError = require( './fixtures/python/loss-functions/loss_squared_error.json' );
+var lossEpsilonInsensitive = require( './fixtures/python/loss-functions/loss_epsilon_insensitive.json' );
+var lossSqEpsInsensitive = require( './fixtures/python/loss-functions/loss_squared_epsilon_insensitive.json' );
+var lossHuber = require( './fixtures/python/loss-functions/loss_huber.json' );
+var lossHinge = require( './fixtures/python/loss-functions/loss_hinge.json' );
+var lossSquaredHinge = require( './fixtures/python/loss-functions/loss_squared_hinge.json' );
+var lossPerceptron = require( './fixtures/python/loss-functions/loss_perceptron.json' );
+var lossModifiedHuber = require( './fixtures/python/loss-functions/loss_modified_huber.json' );
+var lossLog = require( './fixtures/python/loss-functions/loss_log.json' );
+var largeNfeatures = require( './fixtures/python/large_nfeatures.json' );
+var manyEpochs = require( './fixtures/python/many_epochs.json' );
+
+
+// VARIABLES //
+
+// Maximum allowed ULP difference when comparing against scikit-learn:
+var ULP = 16;
+
+
+// TESTS //
+
+tape( 'main export is a function', function test( t ) {
+ t.ok( true, __filename );
+ t.strictEqual( typeof dsgdTrainer, 'function', 'main export is a function' );
+ t.end();
+});
+
+tape( 'the function has an arity of 16', function test( t ) {
+ t.strictEqual( dsgdTrainer.length, 16, 'returns expected value' );
+ t.end();
+});
+
+tape( 'the function throws an error if provided an invalid first argument', function test( t ) {
+ var values;
+ var params;
+ var data;
+ var i;
+
+ data = penaltyL2;
+
+ values = [
+ -1,
+ -2,
+ -3
+ ];
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ for ( i = 0; i < values.length; i++ ) {
+ t.throws( badValue( values[ i ] ), RangeError, 'throws an error when provided ' + values[ i ] );
+ }
+ t.end();
+
+ function badValue( value ) {
+ return function badValue() {
+ dsgdTrainer( value, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, new Float64Array( data.N+1 ), 1, 0, new Float64Array( data.N ), 1, 0, params );
+ };
+ }
+});
+
+tape( 'the function throws an error if provided an invalid second argument', function test( t ) {
+ var values;
+ var params;
+ var data;
+ var i;
+
+ data = penaltyL2;
+
+ values = [
+ -1,
+ -2,
+ -3
+ ];
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ for ( i = 0; i < values.length; i++ ) {
+ t.throws( badValue( values[ i ] ), RangeError, 'throws an error when provided ' + values[ i ] );
+ }
+ t.end();
+
+ function badValue( value ) {
+ return function badValue() {
+ dsgdTrainer( data.M, value, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, new Float64Array( data.N+1 ), 1, 0, new Float64Array( data.N ), 1, 0, params );
+ };
+ }
+});
+
+tape( 'the function throws an error if provided an invalid eighth argument', function test( t ) {
+ var values;
+ var params;
+ var data;
+ var i;
+
+ data = penaltyL2;
+
+ values = [
+ 0
+ ];
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ for ( i = 0; i < values.length; i++ ) {
+ t.throws( badValue( values[ i ] ), RangeError, 'throws an error when provided ' + values[ i ] );
+ }
+ t.end();
+
+ function badValue( value ) {
+ return function badValue() {
+ dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), value, 0, new Float64Array( data.N+1 ), 1, 0, new Float64Array( data.N ), 1, 0, params );
+ };
+ }
+});
+
+tape( 'the function throws an error if provided an invalid eleventh argument', function test( t ) {
+ var values;
+ var params;
+ var data;
+ var i;
+
+ data = penaltyL2;
+
+ values = [
+ 0
+ ];
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ for ( i = 0; i < values.length; i++ ) {
+ t.throws( badValue( values[ i ] ), RangeError, 'throws an error when provided ' + values[ i ] );
+ }
+ t.end();
+
+ function badValue( value ) {
+ return function badValue() {
+ dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, new Float64Array( data.N+1 ), value, 0, new Float64Array( data.N ), 1, 0, params );
+ };
+ }
+});
+
+tape( 'the function throws an error if provided an invalid fourteenth argument', function test( t ) {
+ var values;
+ var params;
+ var data;
+ var i;
+
+ data = penaltyL2;
+
+ values = [
+ 0
+ ];
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ for ( i = 0; i < values.length; i++ ) {
+ t.throws( badValue( values[ i ] ), RangeError, 'throws an error when provided ' + values[ i ] );
+ }
+ t.end();
+
+ function badValue( value ) {
+ return function badValue() {
+ dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, new Float64Array( data.N+1 ), 1, 0, new Float64Array( data.N ), value, 0, params );
+ };
+ }
+});
+
+tape( 'the function trains a linear model via stochastic gradient descent (no penalty)', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = penaltyNone;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function trains a linear model via stochastic gradient descent (L2 penalty)', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = penaltyL2;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function trains a linear model via stochastic gradient descent (L1 penalty)', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = penaltyL1;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function trains a linear model via stochastic gradient descent (elastic net penalty)', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = penaltyElasticnet;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports a constant learning rate scheduler', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lrConstant;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports an inverse scaling learning rate scheduler', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lrInvscaling;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports a large insensitivity parameter', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = largeEpsilon;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the squared error loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossSquaredError;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the epsilon-insensitive loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossEpsilonInsensitive;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the squared epsilon-insensitive loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossSqEpsInsensitive;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the Huber loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossHuber;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the hinge loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossHinge;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the squared hinge loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossSquaredHinge;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the perceptron loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossPerceptron;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the modified Huber loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossModifiedHuber;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports the log loss function', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = lossLog;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports a large number of features', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = largeNfeatures;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function supports multiple epochs', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = manyEpochs;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( isAlmostSameValue( out[ data.N ], data.expected_intercept, ULP ), true, 'returns expected intercept' );
+
+ t.end();
+});
+
+tape( 'the function does not fit an intercept when `fitIntercept` is `false`', function test( t ) {
+ var workspace;
+ var params;
+ var data;
+ var out;
+ var w;
+ var i;
+
+ data = noIntercept;
+
+ w = new Float64Array( data.w );
+ workspace = new Float64Array( data.workspace );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( data.penalty ),
+ 'learningRate': lr2enum( data.learning_rate ),
+ 'lossFunction': loss2enum( data.loss_function ),
+ 'penaltyParams': new Float64Array( [ data.lambda, data.l1_ratio ] ),
+ 'learningRateParams': new Float64Array( [ data.eta0, data.power_t ] ),
+ 'lossFunctionParams': new Float64Array( [ data.epsilon ] ),
+ 'intercept': data.intercept,
+ 'maxIter': data.max_iter,
+ 'fitIntercept': data.fit_intercept
+ });
+
+ out = dsgdTrainer( data.M, data.N, new Float64Array( data.X ), data.LDX, 1, 0, new Float64Array( data.y ), 1, 0, w, 1, 0, workspace, 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ for ( i = 0; i < data.N; i++ ) {
+ t.strictEqual( isAlmostSameValue( out[ i ], data.expected_w[ i ], ULP ), true, 'returns expected coefficient '+i );
+ }
+ t.strictEqual( out[ 0 + ( data.N*1 ) ], 0.0, 'does not store an intercept' );
+
+ t.end();
+});
+
+tape( 'if `M` is `0`, the function returns the weight vector unchanged', function test( t ) {
+ var expected;
+ var params;
+ var out;
+ var w;
+
+ w = new Float64Array( [ 1.0, 2.0, 3.0 ] );
+ expected = new Float64Array( [ 1.0, 2.0, 3.0 ] );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( 'l2' ),
+ 'learningRate': lr2enum( 'constant' ),
+ 'lossFunction': loss2enum( 'hinge' ),
+ 'penaltyParams': new Float64Array( [ 1.0e-4, 0.0 ] ),
+ 'learningRateParams': new Float64Array( [ 0.01, 0.0 ] ),
+ 'lossFunctionParams': new Float64Array( [ 0.1 ] ),
+ 'intercept': 0.0,
+ 'maxIter': 5,
+ 'fitIntercept': true
+ });
+
+ out = dsgdTrainer( 0, 2, new Float64Array( 4 ), 2, 1, 0, new Float64Array( 2 ), 1, 0, w, 1, 0, new Float64Array( 2 ), 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ t.deepEqual( out, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'if `N` is `0`, the function returns the weight vector unchanged', function test( t ) {
+ var expected;
+ var params;
+ var out;
+ var w;
+
+ w = new Float64Array( [ 1.0, 2.0, 3.0 ] );
+ expected = new Float64Array( [ 1.0, 2.0, 3.0 ] );
+
+ params = new Float64Params({
+ 'penalty': penalty2enum( 'l2' ),
+ 'learningRate': lr2enum( 'constant' ),
+ 'lossFunction': loss2enum( 'hinge' ),
+ 'penaltyParams': new Float64Array( [ 1.0e-4, 0.0 ] ),
+ 'learningRateParams': new Float64Array( [ 0.01, 0.0 ] ),
+ 'lossFunctionParams': new Float64Array( [ 0.1 ] ),
+ 'intercept': 0.0,
+ 'maxIter': 5,
+ 'fitIntercept': true
+ });
+
+ out = dsgdTrainer( 2, 0, new Float64Array( 4 ), 2, 1, 0, new Float64Array( 2 ), 1, 0, w, 1, 0, new Float64Array( 2 ), 1, 0, params );
+
+ t.strictEqual( out, w, 'returns expected value' );
+ t.deepEqual( out, expected, 'returns expected value' );
+
+ t.end();
+});