From 62b2acde95a6198a5c9ef4cb206e335b3e7a8727 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 22 Sep 2026 21:31:19 +0000 Subject: [PATCH] test: migrate `blas/base/zaxpy` to ULP-based assertions Resolves a part of #11352. Migrates the tests for blas/base/zaxpy from computed relative-tolerance comparisons (delta = abs(actual[i] - expected[i]) / tol = rtol * EPS * abs(expected[i]), asserted via t.ok(delta <= tol, ...)) to ULP-difference assertions using @stdlib/assert/is-almost-same-value, mirroring the established idiom in blas/base/drot: the shared isApprox(t, actual, expected, ulp) helper collapses to a single isAlmostSameValue assertion, and each test body declares a single named ULP constant sized to the minimum integer bound that passes for that test. Applies to all four test files (test.zaxpy.js, test.ndarray.js, and their .native.js counterparts, including the native-only "dcabs1(alpha) === 0.0" test in test.ndarray.native.js). ULP bounds were determined by measuring the exact per-element ULP distance for every fixture via @stdlib/number/float64/base/ulp-difference, run directly against the implementation. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01PLAefATEDhsbjEiq9xEYN4 --- .../blas/base/zaxpy/test/test.ndarray.js | 49 +++++++++-------- .../base/zaxpy/test/test.ndarray.native.js | 53 +++++++++++-------- .../blas/base/zaxpy/test/test.zaxpy.js | 45 +++++++++------- .../blas/base/zaxpy/test/test.zaxpy.native.js | 45 +++++++++------- 4 files changed, 109 insertions(+), 83 deletions(-) diff --git a/lib/node_modules/@stdlib/blas/base/zaxpy/test/test.ndarray.js b/lib/node_modules/@stdlib/blas/base/zaxpy/test/test.ndarray.js index bc313d9c0b05..d02e3deaea3c 100644 --- a/lib/node_modules/@stdlib/blas/base/zaxpy/test/test.ndarray.js +++ b/lib/node_modules/@stdlib/blas/base/zaxpy/test/test.ndarray.js @@ -24,8 +24,7 @@ var tape = require( 'tape' ); var Float64Array = require( '@stdlib/array/float64' ); var Complex128Array = require( '@stdlib/array/complex128' ); var Complex128 = require( '@stdlib/complex/float64/ctor' ); -var EPS = require( '@stdlib/constants/float64/eps' ); -var abs = require( '@stdlib/math/base/special/abs' ); +var isAlmostSameValue = require( '@stdlib/assert/is-almost-same-value' ); var zaxpy = require( './../lib/ndarray.js' ); @@ -38,22 +37,14 @@ var zaxpy = require( './../lib/ndarray.js' ); * @param {Object} t - test object * @param {Collection} actual - actual values * @param {Collection} expected - expected values -* @param {number} rtol - relative tolerance +* @param {NonNegativeInteger} ulp - maximum allowed ULP difference */ -function isApprox( t, actual, expected, rtol ) { - var delta; - var tol; +function isApprox( t, actual, expected, ulp ) { var i; t.strictEqual( actual.length, expected.length, 'returns expected value' ); for ( i = 0; i < expected.length; i++ ) { - if ( actual[ i ] === expected[ i ] ) { - t.strictEqual( actual[ i ], expected[ i ], 'returns expected value' ); - } else { - delta = abs( actual[ i ] - expected[ i ] ); - tol = rtol * EPS * abs( expected[ i ] ); - t.ok( delta <= tol, 'within tolerance. actual: '+actual[ i ]+'. expected: '+expected[ i ]+'. delta: '+delta+'. tol: '+tol+'.' ); - } + t.strictEqual( isAlmostSameValue( actual[ i ], expected[ i ], ulp ), true, 'returns expected value' ); } } @@ -75,6 +66,7 @@ tape( 'the function scales elements from `x` by `alpha` and adds the result to ` var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -131,7 +123,8 @@ tape( 'the function scales elements from `x` by `alpha` and adds the result to ` 0.8, -0.7 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 24; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -139,6 +132,7 @@ tape( 'the function supports an `x` stride', function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -195,7 +189,8 @@ tape( 'the function supports an `x` stride', function test( t ) { 0.8, -0.7 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 8; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -203,6 +198,7 @@ tape( 'the function supports an `x` offset', function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -259,7 +255,8 @@ tape( 'the function supports an `x` offset', function test( t ) { 0.8, -0.7 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 11; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -267,6 +264,7 @@ tape( 'the function supports a `y` stride', function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -323,7 +321,8 @@ tape( 'the function supports a `y` stride', function test( t ) { 0.32, // 4 -1.16 // 4 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 6; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -331,6 +330,7 @@ tape( 'the function supports a `y` offset', function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -387,7 +387,8 @@ tape( 'the function supports a `y` offset', function test( t ) { 0.8, -0.7 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 1; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -457,6 +458,7 @@ tape( 'the function supports a negative `x` stride', function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -513,7 +515,8 @@ tape( 'the function supports a negative `x` stride', function test( t ) { 0.8, -0.7 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 24; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -521,6 +524,7 @@ tape( 'the function supports a negative `y` stride', function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -577,7 +581,8 @@ tape( 'the function supports a negative `y` stride', function test( t ) { 0.52, // 1 -1.51 // 1 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 8; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -585,6 +590,7 @@ tape( 'the function supports complex access patterns', function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -641,6 +647,7 @@ tape( 'the function supports complex access patterns', function test( t ) { 0.32, // 1 -1.16 // 1 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 6; + isApprox( t, viewY, expected, ULP ); t.end(); }); diff --git a/lib/node_modules/@stdlib/blas/base/zaxpy/test/test.ndarray.native.js b/lib/node_modules/@stdlib/blas/base/zaxpy/test/test.ndarray.native.js index c0951fb971ad..72c3ae68d167 100644 --- a/lib/node_modules/@stdlib/blas/base/zaxpy/test/test.ndarray.native.js +++ b/lib/node_modules/@stdlib/blas/base/zaxpy/test/test.ndarray.native.js @@ -25,8 +25,7 @@ var tape = require( 'tape' ); var Float64Array = require( '@stdlib/array/float64' ); var Complex128Array = require( '@stdlib/array/complex128' ); var Complex128 = require( '@stdlib/complex/float64/ctor' ); -var EPS = require( '@stdlib/constants/float64/eps' ); -var abs = require( '@stdlib/math/base/special/abs' ); +var isAlmostSameValue = require( '@stdlib/assert/is-almost-same-value' ); var tryRequire = require( '@stdlib/utils/try-require' ); @@ -47,22 +46,14 @@ var opts = { * @param {Object} t - test object * @param {Collection} actual - actual values * @param {Collection} expected - expected values -* @param {number} rtol - relative tolerance +* @param {NonNegativeInteger} ulp - maximum allowed ULP difference */ -function isApprox( t, actual, expected, rtol ) { - var delta; - var tol; +function isApprox( t, actual, expected, ulp ) { var i; t.strictEqual( actual.length, expected.length, 'returns expected value' ); for ( i = 0; i < expected.length; i++ ) { - if ( actual[ i ] === expected[ i ] ) { - t.strictEqual( actual[ i ], expected[ i ], 'returns expected value' ); - } else { - delta = abs( actual[ i ] - expected[ i ] ); - tol = rtol * EPS * abs( expected[ i ] ); - t.ok( delta <= tol, 'within tolerance. actual: '+actual[ i ]+'. expected: '+expected[ i ]+'. delta: '+delta+'. tol: '+tol+'.' ); - } + t.strictEqual( isAlmostSameValue( actual[ i ], expected[ i ], ulp ), true, 'returns expected value' ); } } @@ -84,6 +75,7 @@ tape( 'the function scales elements from `x` by `alpha` and adds the result to ` var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -140,7 +132,8 @@ tape( 'the function scales elements from `x` by `alpha` and adds the result to ` 0.8, -0.7 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 24; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -148,6 +141,7 @@ tape( 'if dcabs1( alpha ) === 0.0; the function returns the second input array u var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -204,7 +198,8 @@ tape( 'if dcabs1( alpha ) === 0.0; the function returns the second input array u 0.8, -0.7 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 0; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -212,6 +207,7 @@ tape( 'the function supports an `x` stride', opts, function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -268,7 +264,8 @@ tape( 'the function supports an `x` stride', opts, function test( t ) { 0.8, -0.7 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 8; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -276,6 +273,7 @@ tape( 'the function supports an `x` offset', opts, function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -332,7 +330,8 @@ tape( 'the function supports an `x` offset', opts, function test( t ) { 0.8, -0.7 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 11; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -340,6 +339,7 @@ tape( 'the function supports a `y` stride', opts, function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -396,7 +396,8 @@ tape( 'the function supports a `y` stride', opts, function test( t ) { 0.32, // 4 -1.16 // 4 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 6; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -404,6 +405,7 @@ tape( 'the function supports a `y` offset', opts, function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -460,7 +462,8 @@ tape( 'the function supports a `y` offset', opts, function test( t ) { 0.8, -0.7 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 1; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -507,6 +510,7 @@ tape( 'the function supports a negative `x` stride', opts, function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -563,7 +567,8 @@ tape( 'the function supports a negative `x` stride', opts, function test( t ) { 0.8, -0.7 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 24; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -571,6 +576,7 @@ tape( 'the function supports a negative `y` stride', opts, function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -627,7 +633,8 @@ tape( 'the function supports a negative `y` stride', opts, function test( t ) { 0.52, // 1 -1.51 // 1 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 8; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -635,6 +642,7 @@ tape( 'the function supports complex access patterns', opts, function test( t ) var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -691,6 +699,7 @@ tape( 'the function supports complex access patterns', opts, function test( t ) 0.32, // 1 -1.16 // 1 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 6; + isApprox( t, viewY, expected, ULP ); t.end(); }); diff --git a/lib/node_modules/@stdlib/blas/base/zaxpy/test/test.zaxpy.js b/lib/node_modules/@stdlib/blas/base/zaxpy/test/test.zaxpy.js index c02ccd798e51..4a3c390ee675 100644 --- a/lib/node_modules/@stdlib/blas/base/zaxpy/test/test.zaxpy.js +++ b/lib/node_modules/@stdlib/blas/base/zaxpy/test/test.zaxpy.js @@ -24,8 +24,7 @@ var tape = require( 'tape' ); var Float64Array = require( '@stdlib/array/float64' ); var Complex128Array = require( '@stdlib/array/complex128' ); var Complex128 = require( '@stdlib/complex/float64/ctor' ); -var EPS = require( '@stdlib/constants/float64/eps' ); -var abs = require( '@stdlib/math/base/special/abs' ); +var isAlmostSameValue = require( '@stdlib/assert/is-almost-same-value' ); var zaxpy = require( './../lib/zaxpy.js' ); @@ -38,22 +37,14 @@ var zaxpy = require( './../lib/zaxpy.js' ); * @param {Object} t - test object * @param {Collection} actual - actual values * @param {Collection} expected - expected values -* @param {number} rtol - relative tolerance +* @param {NonNegativeInteger} ulp - maximum allowed ULP difference */ -function isApprox( t, actual, expected, rtol ) { - var delta; - var tol; +function isApprox( t, actual, expected, ulp ) { var i; t.strictEqual( actual.length, expected.length, 'returns expected value' ); for ( i = 0; i < expected.length; i++ ) { - if ( actual[ i ] === expected[ i ] ) { - t.strictEqual( actual[ i ], expected[ i ], 'returns expected value' ); - } else { - delta = abs( actual[ i ] - expected[ i ] ); - tol = rtol * EPS * abs( expected[ i ] ); - t.ok( delta <= tol, 'within tolerance. actual: '+actual[ i ]+'. expected: '+expected[ i ]+'. delta: '+delta+'. tol: '+tol+'.' ); - } + t.strictEqual( isAlmostSameValue( actual[ i ], expected[ i ], ulp ), true, 'returns expected value' ); } } @@ -75,6 +66,7 @@ tape( 'the function scales elements from `x` by `alpha` and adds the result to ` var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -131,7 +123,8 @@ tape( 'the function scales elements from `x` by `alpha` and adds the result to ` 0.8, -0.7 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 24; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -139,6 +132,7 @@ tape( 'the function supports an `x` stride', function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -195,7 +189,8 @@ tape( 'the function supports an `x` stride', function test( t ) { 0.8, -0.7 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 8; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -203,6 +198,7 @@ tape( 'the function supports a `y` stride', function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -259,7 +255,8 @@ tape( 'the function supports a `y` stride', function test( t ) { 0.32, // 4 -1.16 // 4 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 6; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -329,6 +326,7 @@ tape( 'the function supports negative `x` strides', function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -385,7 +383,8 @@ tape( 'the function supports negative `x` strides', function test( t ) { 0.8, -0.7 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 24; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -393,6 +392,7 @@ tape( 'the function supports negative `y` strides', function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -449,7 +449,8 @@ tape( 'the function supports negative `y` strides', function test( t ) { 0.52, // 1 -1.51 // 1 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 8; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -457,6 +458,7 @@ tape( 'the function supports complex access patterns', function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -513,7 +515,8 @@ tape( 'the function supports complex access patterns', function test( t ) { 0.32, // 1 -1.16 // 1 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 6; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -521,6 +524,7 @@ tape( 'the function supports view offsets', function test( t ) { var expected; var viewY; var alpha; + var ULP; var x0; var y0; var x1; @@ -579,6 +583,7 @@ tape( 'the function supports view offsets', function test( t ) { -0.96 // 4 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 24; + isApprox( t, viewY, expected, ULP ); t.end(); }); diff --git a/lib/node_modules/@stdlib/blas/base/zaxpy/test/test.zaxpy.native.js b/lib/node_modules/@stdlib/blas/base/zaxpy/test/test.zaxpy.native.js index d3e7808edfb8..b4749c09c50d 100644 --- a/lib/node_modules/@stdlib/blas/base/zaxpy/test/test.zaxpy.native.js +++ b/lib/node_modules/@stdlib/blas/base/zaxpy/test/test.zaxpy.native.js @@ -25,8 +25,7 @@ var tape = require( 'tape' ); var Float64Array = require( '@stdlib/array/float64' ); var Complex128Array = require( '@stdlib/array/complex128' ); var Complex128 = require( '@stdlib/complex/float64/ctor' ); -var EPS = require( '@stdlib/constants/float64/eps' ); -var abs = require( '@stdlib/math/base/special/abs' ); +var isAlmostSameValue = require( '@stdlib/assert/is-almost-same-value' ); var tryRequire = require( '@stdlib/utils/try-require' ); @@ -47,22 +46,14 @@ var opts = { * @param {Object} t - test object * @param {Collection} actual - actual values * @param {Collection} expected - expected values -* @param {number} rtol - relative tolerance +* @param {NonNegativeInteger} ulp - maximum allowed ULP difference */ -function isApprox( t, actual, expected, rtol ) { - var delta; - var tol; +function isApprox( t, actual, expected, ulp ) { var i; t.strictEqual( actual.length, expected.length, 'returns expected value' ); for ( i = 0; i < expected.length; i++ ) { - if ( actual[ i ] === expected[ i ] ) { - t.strictEqual( actual[ i ], expected[ i ], 'returns expected value' ); - } else { - delta = abs( actual[ i ] - expected[ i ] ); - tol = rtol * EPS * abs( expected[ i ] ); - t.ok( delta <= tol, 'within tolerance. actual: '+actual[ i ]+'. expected: '+expected[ i ]+'. delta: '+delta+'. tol: '+tol+'.' ); - } + t.strictEqual( isAlmostSameValue( actual[ i ], expected[ i ], ulp ), true, 'returns expected value' ); } } @@ -84,6 +75,7 @@ tape( 'the function scales elements from `x` by `alpha` and adds the result to ` var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -140,7 +132,8 @@ tape( 'the function scales elements from `x` by `alpha` and adds the result to ` 0.8, -0.7 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 24; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -148,6 +141,7 @@ tape( 'the function supports an `x` stride', opts, function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -204,7 +198,8 @@ tape( 'the function supports an `x` stride', opts, function test( t ) { 0.8, -0.7 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 8; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -212,6 +207,7 @@ tape( 'the function supports a `y` stride', opts, function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -268,7 +264,8 @@ tape( 'the function supports a `y` stride', opts, function test( t ) { 0.32, // 4 -1.16 // 4 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 6; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -338,6 +335,7 @@ tape( 'the function supports negative `x` strides', opts, function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -394,7 +392,8 @@ tape( 'the function supports negative `x` strides', opts, function test( t ) { 0.8, -0.7 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 24; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -402,6 +401,7 @@ tape( 'the function supports negative `y` strides', opts, function test( t ) { var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -458,7 +458,8 @@ tape( 'the function supports negative `y` strides', opts, function test( t ) { 0.52, // 1 -1.51 // 1 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 8; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -466,6 +467,7 @@ tape( 'the function supports complex access patterns', opts, function test( t ) var expected; var viewY; var alpha; + var ULP; var x; var y; @@ -522,7 +524,8 @@ tape( 'the function supports complex access patterns', opts, function test( t ) 0.32, // 1 -1.16 // 1 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 6; + isApprox( t, viewY, expected, ULP ); t.end(); }); @@ -530,6 +533,7 @@ tape( 'the function supports view offsets', opts, function test( t ) { var expected; var viewY; var alpha; + var ULP; var x0; var y0; var x1; @@ -588,6 +592,7 @@ tape( 'the function supports view offsets', opts, function test( t ) { -0.96 // 4 ]); - isApprox( t, viewY, expected, 14.0 ); + ULP = 24; + isApprox( t, viewY, expected, ULP ); t.end(); });