Skip to content

Commit 055e192

Browse files
committed
test(math/base/special/boxcoxf): add test fixtures and native tests
--- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: na - task: lint_package_json status: na - task: lint_repl_help status: na - task: lint_javascript_src status: na - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - task: lint_javascript_tests status: passed - task: lint_javascript_benchmarks status: na - task: lint_python status: missing_dependencies - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: passed - task: lint_typescript_tests status: na - task: lint_license_headers status: passed ---
1 parent 4edebf7 commit 055e192

6 files changed

Lines changed: 179 additions & 49 deletions

File tree

lib/node_modules/@stdlib/math/base/special/boxcoxf/test/fixtures/python/medium_positive.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/usr/bin/env python
2+
#
3+
# @license Apache-2.0
4+
#
5+
# Copyright (c) 2025 The Stdlib Authors.
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
19+
"""Generate fixtures."""
20+
21+
from os import path
22+
import json
23+
from scipy.special import boxcox
24+
import numpy as np
25+
26+
# Get the file path.
27+
FILE = path.realpath(__file__)
28+
29+
# Get the file's directory.
30+
DIR = path.dirname(FILE)
31+
32+
33+
def generate(x, y, filename):
34+
"""Generate fixture data and write to file.
35+
36+
# Arguments
37+
38+
* `x`: domain
39+
* `y`: domain
40+
* `name::str`: filename of the output file
41+
42+
# Examples
43+
44+
```python
45+
python> x = np.linspace(1.0, 10.0, 2001).astype(np.float32)
46+
python> y = np.linspace(-5.0, 5.0, 2001).astype(np.float32)
47+
python> generate(x, y, './data.json')
48+
```
49+
"""
50+
z = []
51+
for xi, yi in zip(x, y):
52+
z.append(np.float32(boxcox(float(xi), float(yi))))
53+
z = np.array(z, dtype=np.float32)
54+
55+
data = dict(
56+
x=x.tolist(),
57+
y=y.tolist(),
58+
expected=z.tolist()
59+
)
60+
61+
filepath = path.join(DIR, filename)
62+
63+
with open(filepath, 'w') as out:
64+
json.dump(data, out)
65+
66+
67+
def main():
68+
"""Generate fixture data."""
69+
# Medium positive values:
70+
x = np.linspace(1.0, 10.0, 500).astype(np.float32)
71+
lmda = np.linspace(-5.0, 5.0, 500).astype(np.float32)
72+
generate(x, lmda, "medium_positive.json")
73+
74+
# Small positive values:
75+
x = np.linspace(np.float32(2.0**-20), 1.0, 500).astype(np.float32)
76+
lmda = np.linspace(-5.0, 5.0, 500).astype(np.float32)
77+
generate(x, lmda, "small_positive.json")
78+
79+
# Tiny values:
80+
x = np.linspace(
81+
np.float32(1.9**-20), np.float32(2.0**-20), 500
82+
).astype(np.float32)
83+
lmda = np.linspace(-5.0, 5.0, 500).astype(np.float32)
84+
generate(x, lmda, "tiny.json")
85+
86+
# Tiny lambda:
87+
x = np.linspace(1.0, 10.0, 500).astype(np.float32)
88+
lmda = np.linspace(-5.0e-15, 5.0e-15, 500).astype(np.float32)
89+
generate(x, lmda, "tiny_lambda.json")
90+
91+
92+
if __name__ == "__main__":
93+
main()

lib/node_modules/@stdlib/math/base/special/boxcoxf/test/fixtures/python/small_positive.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

lib/node_modules/@stdlib/math/base/special/boxcoxf/test/fixtures/python/tiny.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

lib/node_modules/@stdlib/math/base/special/boxcoxf/test/fixtures/python/tiny_lambda.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

lib/node_modules/@stdlib/math/base/special/boxcoxf/test/test.native.js

Lines changed: 82 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ var resolve = require( 'path' ).resolve;
2424
var tape = require( 'tape' );
2525
var isnanf = require( '@stdlib/math/base/assert/is-nanf' );
2626
var randu = require( '@stdlib/random/base/randu' );
27-
var absf = require( '@stdlib/math/base/special/absf' );
27+
var abs = require( '@stdlib/math/base/special/abs' );
2828
var float64ToFloat32 = require( '@stdlib/number/float64/base/to-float32' );
2929
var NINF = require( '@stdlib/constants/float32/ninf' );
3030
var EPS = require( '@stdlib/constants/float32/eps' );
@@ -39,6 +39,14 @@ var opts = {
3939
};
4040

4141

42+
// FIXTURES //
43+
44+
var mediumPositive = require( './fixtures/python/medium_positive.json' );
45+
var smallPositive = require( './fixtures/python/small_positive.json' );
46+
var tiny = require( './fixtures/python/tiny.json' );
47+
var tinyLambda = require( './fixtures/python/tiny_lambda.json' );
48+
49+
4250
// TESTS //
4351

4452
tape( 'main export is a function', opts, function test( t ) {
@@ -62,16 +70,19 @@ tape( 'the function returns `NaN` if provided `NaN`', opts, function test( t ) {
6270
t.end();
6371
});
6472

65-
tape( 'the function returns `-Infinity` if lambda is negative and `x` is +0', opts, function test( t ) {
73+
tape( 'the function returns `-Infinity` if lambda is negative and `x` is +-0', opts, function test( t ) {
6674
var lambda;
6775
var b;
6876
var i;
6977

7078
for ( i = 0; i < 1e3; i++ ) {
71-
lambda = float64ToFloat32( -1.0 * ( ( randu() * 100.0 ) + 1.0 ) );
79+
lambda = float64ToFloat32( -1.0 * ( (randu()*100.0) + 1.0 ) );
7280

7381
b = boxcoxf( +0.0, lambda );
74-
t.strictEqual( b, NINF, 'returns -Infinity when lambda is negative and x is positive zero' );
82+
t.strictEqual( b, NINF, 'returns -Infinity when lambda is negative and `x` is positive zero' );
83+
84+
b = boxcoxf( -0.0, lambda );
85+
t.strictEqual( b, NINF, 'returns -Infinity when lambda is negative and `x` is negative zero' );
7586
}
7687
t.end();
7788
});
@@ -83,15 +94,15 @@ tape( 'the function returns `NaN` if `x` is negative', opts, function test( t )
8394
var i;
8495

8596
for ( i = 0; i < 1e3; i++ ) {
86-
x = float64ToFloat32( -1.0 * ( ( randu() * 100.0 ) + 1.0 ) );
97+
x = float64ToFloat32( -1.0 * ( (randu()*100.0) + 1.0 ) );
8798
y = float64ToFloat32( randu() * 10.0 );
8899
b = boxcoxf( x, y );
89100
t.strictEqual( isnanf( b ), true, 'returns expected value' );
90101
}
91102
t.end();
92103
});
93104

94-
tape( 'the function computes a one-parameter Box-Cox transformation for positive numbers', opts, function test( t ) {
105+
tape( 'the function computes a one-parameter Box-Cox transformation for positive medium numbers', opts, function test( t ) {
95106
var expected;
96107
var delta;
97108
var tol;
@@ -100,70 +111,92 @@ tape( 'the function computes a one-parameter Box-Cox transformation for positive
100111
var b;
101112
var i;
102113

103-
x = [
104-
float64ToFloat32( 1.0 ),
105-
float64ToFloat32( 4.0 ),
106-
float64ToFloat32( 10.0 ),
107-
float64ToFloat32( 2.0 ),
108-
float64ToFloat32( 5.0 )
109-
];
110-
y = [
111-
float64ToFloat32( 2.5 ),
112-
float64ToFloat32( 2.5 ),
113-
float64ToFloat32( 2.5 ),
114-
float64ToFloat32( 1.0 ),
115-
float64ToFloat32( 0.5 )
116-
];
117-
expected = [
118-
float64ToFloat32( 0.0 ),
119-
float64ToFloat32( 12.4 ),
120-
float64ToFloat32( 126.09114837646484 ),
121-
float64ToFloat32( 1.0 ),
122-
float64ToFloat32( 2.4721359014511108 )
123-
];
114+
expected = mediumPositive.expected;
115+
x = mediumPositive.x;
116+
y = mediumPositive.y;
117+
for ( i = 0; i < expected.length; i++ ) {
118+
b = boxcoxf( x[ i ], y[ i ] );
119+
if ( b === expected[ i ] ) {
120+
t.strictEqual( b, expected[ i ], 'returns '+b+' when provided '+x[i]+' and '+y[i]+'.' );
121+
} else {
122+
delta = abs( expected[ i ] - b );
123+
tol = 16.0 * EPS * abs( expected[ i ] );
124+
t.ok( delta <= tol, 'within tolerance. returns '+b+' when provided '+x[i]+' and '+y[i]+'. expected: '+expected[i]+'. delta: '+delta+'. tol: ' +tol+'.' );
125+
}
126+
}
127+
t.end();
128+
});
129+
130+
tape( 'the function computes a one-parameter Box-Cox transformation for positive small numbers', opts, function test( t ) {
131+
var expected;
132+
var delta;
133+
var tol;
134+
var x;
135+
var y;
136+
var b;
137+
var i;
124138

139+
expected = smallPositive.expected;
140+
x = smallPositive.x;
141+
y = smallPositive.y;
125142
for ( i = 0; i < expected.length; i++ ) {
126143
b = boxcoxf( x[ i ], y[ i ] );
127144
if ( b === expected[ i ] ) {
128-
t.strictEqual( b, expected[ i ], 'returns ' + b + ' when provided ' + x[ i ] + ' and ' + y[ i ] + '.' );
145+
t.strictEqual( b, expected[ i ], 'returns '+b+' when provided '+x[i]+' and '+y[i]+'.' );
129146
} else {
130-
delta = absf( expected[ i ] - b );
131-
tol = 20.0 * EPS * absf( expected[ i ] );
132-
t.ok( delta <= tol, 'within tolerance. returns ' + b + ' when provided ' + x[ i ] + ' and ' + y[ i ] + '. expected: ' + expected[ i ] + '. delta: ' + delta + '. tol: ' + tol + '.' );
147+
delta = abs( expected[ i ] - b );
148+
tol = 16.0 * EPS * abs( expected[ i ] );
149+
t.ok( delta <= tol, 'within tolerance. returns '+b+' when provided '+x[i]+' and '+y[i]+'. expected: '+expected[i]+'. delta: '+delta+'. tol: ' +tol+'.' );
133150
}
134151
}
135152
t.end();
136153
});
137154

138-
tape( 'the function computes a one-parameter Box-Cox transformation when lambda is zero (returns natural log)', opts, function test( t ) {
155+
tape( 'the function computes a one-parameter Box-Cox transformation for tiny numbers', opts, function test( t ) {
139156
var expected;
140157
var delta;
141158
var tol;
142159
var x;
160+
var y;
143161
var b;
144162
var i;
145163

146-
x = [
147-
float64ToFloat32( 1.0 ),
148-
float64ToFloat32( 2.0 ),
149-
float64ToFloat32( 4.0 ),
150-
float64ToFloat32( 10.0 )
151-
];
152-
expected = [
153-
float64ToFloat32( 0.0 ),
154-
float64ToFloat32( 0.6931471805599453 ),
155-
float64ToFloat32( 1.3862943611198906 ),
156-
float64ToFloat32( 2.302585092994046 )
157-
];
164+
expected = tiny.expected;
165+
x = tiny.x;
166+
y = tiny.y;
167+
for ( i = 0; i < expected.length; i++ ) {
168+
b = boxcoxf( x[ i ], y[ i ] );
169+
if ( b === expected[ i ] ) {
170+
t.strictEqual( b, expected[ i ], 'returns '+b+' when provided '+x[i]+' and '+y[i]+'.' );
171+
} else {
172+
delta = abs( expected[ i ] - b );
173+
tol = 70.0 * EPS * abs( expected[ i ] );
174+
t.ok( delta <= tol, 'within tolerance. returns '+b+' when provided '+x[i]+' and '+y[i]+'. expected: '+expected[i]+'. delta: '+delta+'. tol: ' +tol+'.' );
175+
}
176+
}
177+
t.end();
178+
});
158179

180+
tape( 'the function computes a one-parameter Box-Cox transformation for tiny lambda', opts, function test( t ) {
181+
var expected;
182+
var delta;
183+
var tol;
184+
var x;
185+
var y;
186+
var b;
187+
var i;
188+
189+
expected = tinyLambda.expected;
190+
x = tinyLambda.x;
191+
y = tinyLambda.y;
159192
for ( i = 0; i < expected.length; i++ ) {
160-
b = boxcoxf( x[ i ], 0.0 );
193+
b = boxcoxf( x[ i ], y[ i ] );
161194
if ( b === expected[ i ] ) {
162-
t.strictEqual( b, expected[ i ], 'returns ' + b + ' when provided ' + x[ i ] + ' and lambda=0.' );
195+
t.strictEqual( b, expected[ i ], 'returns '+b+' when provided '+x[i]+' and '+y[i]+'.' );
163196
} else {
164-
delta = absf( expected[ i ] - b );
165-
tol = 2.0 * EPS * absf( expected[ i ] );
166-
t.ok( delta <= tol, 'within tolerance. returns ' + b + ' when provided ' + x[ i ] + ' and lambda=0. expected: ' + expected[ i ] + '. delta: ' + delta + '. tol: ' + tol + '.' );
197+
delta = abs( expected[ i ] - b );
198+
tol = 1.0 * EPS * abs( expected[ i ] );
199+
t.ok( delta <= tol, 'within tolerance. returns '+b+' when provided '+x[i]+' and '+y[i]+'. expected: '+expected[i]+'. delta: '+delta+'. tol: ' +tol+'.' );
167200
}
168201
}
169202
t.end();

0 commit comments

Comments
 (0)