Skip to content

Commit 754cbf3

Browse files
committed
Add implementation for generic interface to compute the absolute value
1 parent 3aeee6a commit 754cbf3

File tree

4 files changed

+356
-0
lines changed

4 files changed

+356
-0
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2020 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
var Float64Array = require( '@stdlib/array/float64' );
22+
var array = require( '@stdlib/ndarray/array' );
23+
var ind2sub = require( '@stdlib/ndarray/ind2sub' );
24+
var abs = require( './../lib' );
25+
26+
var sub;
27+
var sh;
28+
var x;
29+
var y;
30+
var i;
31+
32+
// Provide a number...
33+
y = abs( -1.0 );
34+
console.log( 'x = %d => abs(x) = %d', -1.0, y );
35+
36+
// Provide an array-like object...
37+
x = new Float64Array( [ -1.0, -2.0, -3.0 ] );
38+
y = abs( x );
39+
for ( i = 0; i < x.length; i++ ) {
40+
console.log( 'x_%d = %d => abs(x_%d) = %d', i, x[ i ], i, y.iget( i ) );
41+
}
42+
43+
// Provide an ndarray...
44+
x = array( [ [ -1.0, -2.0 ], [ -3.0, -4.0 ] ] );
45+
sh = x.shape;
46+
47+
y = abs( x );
48+
for ( i = 0; i < x.length; i++ ) {
49+
sub = ind2sub( sh, i );
50+
console.log( 'x_%d%d = %d => abs(x_%d%d) = %d', sub[ 0 ], sub[ 1 ], x.iget( i ), sub[ 0 ], sub[ 1 ], y.iget( i ) );
51+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2020 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
/**
22+
* Compute the absolute value.
23+
*
24+
* @module @stdlib/math/special/abs
25+
*
26+
* @example
27+
* var abs = require( '@stdlib/math/special/abs' );
28+
*
29+
* var y = abs( -1.0 );
30+
* // returns 1.0
31+
*
32+
* @example
33+
* var Float64Array = require( '@stdlib/array/float64' );
34+
* var abs = require( '@stdlib/math/special/abs' );
35+
*
36+
* var x = new Float64Array( [ 1.0, -1.0, 0.0 ] );
37+
*
38+
* var y = abs( x );
39+
* // returns <Float64Array>[ 1.0, 1.0, 0.0 ]
40+
*
41+
* @example
42+
* var array = require( '@stdlib/ndarray/array' );
43+
* var abs = require( '@stdlib/math/special/abs' );
44+
*
45+
* var x = array( [ [ 1.0, -2.0 ], [ -3.0, 4.0 ] ] );
46+
* // returns <ndarray>
47+
*
48+
* var y = abs( x );
49+
* // returns <ndarray>
50+
*
51+
* var v = y.get( 0, 1 );
52+
* // 2.0
53+
*/
54+
55+
// MAIN //
56+
57+
var main = require( './main.js' );
58+
59+
60+
// EXPORTS //
61+
62+
module.exports = main;
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2020 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MODULES //
22+
23+
var isNumber = require( '@stdlib/assert/is-number' ).isPrimitive;
24+
var isndarrayLike = require( '@stdlib/assert/is-ndarray-like' );
25+
var isArrayLikeObject = require( '@stdlib/assert/is-array-like-object' );
26+
var isSingleSegmentCompatible = require( '@stdlib/ndarray/base/assert/is-single-segment-compatible' );
27+
var isFloat64Array = require( '@stdlib/assert/is-float64array' );
28+
var isFloat32Array = require( '@stdlib/assert/is-float32array' );
29+
var ndarray = require( '@stdlib/ndarray/ctor' );
30+
var buffer = require( '@stdlib/ndarray/base/buffer' );
31+
var shape2strides = require( '@stdlib/ndarray/base/shape2strides' );
32+
var iterationOrder = require( '@stdlib/ndarray/base/iteration-order' );
33+
var dtype = require( '@stdlib/ndarray/base/buffer-dtype' );
34+
var base = require( '@stdlib/math/base/special/abs' );
35+
var dabs = require( '@stdlib/math/strided/special/dabs' );
36+
var sabs = require( '@stdlib/math/strided/special/sabs' );
37+
var gabs = require( '@stdlib/math/strided/special/abs' );
38+
39+
40+
// MAIN //
41+
42+
/**
43+
* Computes the absolute value.
44+
*
45+
* @param {(ndarray|ArrayLikeObject|number)} x - input value
46+
* @param {(ndarray|ArrayLikeObject)} [mask] - array mask
47+
* @throws {TypeError} first argument must be either an ndarray, array-like object, or number
48+
* @throws {TypeError} second argument must be either an ndarray or array-like object
49+
* @throws {Error} second argument must have the same shape as the first argument
50+
* @returns {(ndarray|number)} results
51+
*
52+
* @example
53+
* var y = abs( -1.0 );
54+
* // returns 1.0
55+
*
56+
* @example
57+
* var Float64Array = require( '@stdlib/array/float64' );
58+
*
59+
* var x = new Float64Array( [ 1.0, -1.0, 0.0 ] );
60+
*
61+
* var y = abs( x );
62+
* // returns <ndarray>
63+
*
64+
* var d = y.data;
65+
* // returns <Float64Array>[ 1.0, 1.0, 0.0 ]
66+
*
67+
* @example
68+
* var array = require( '@stdlib/ndarray/array' );
69+
*
70+
* var x = array( [ [ 1.0, -2.0 ], [ -3.0, 4.0 ] ] );
71+
* // returns <ndarray>
72+
*
73+
* var y = abs( x );
74+
* // returns <ndarray>
75+
*
76+
* var v = y.get( 0, 1 );
77+
* // 2.0
78+
*/
79+
function abs( x ) {
80+
var strides;
81+
var offset;
82+
var order;
83+
var ndims;
84+
var shape;
85+
var data;
86+
var ctor;
87+
var buf;
88+
var xc;
89+
var dt;
90+
var N;
91+
var s;
92+
var y;
93+
var i;
94+
95+
if ( isNumber( x ) ) {
96+
return base( x );
97+
}
98+
// TODO: add complex number support; should probably coincide with complex number array support
99+
100+
if ( isndarrayLike( x ) ) {
101+
// Cache ndarray properties to avoid repeatedly calling ndarray accessors...
102+
N = x.length;
103+
ndims = x.ndims;
104+
shape = x.shape;
105+
strides = x.strides;
106+
offset = x.offset;
107+
order = x.order;
108+
data = x.data;
109+
dt = x.dtype;
110+
111+
// Create an output ndarray...
112+
ctor = ndarray( dt, ndims );
113+
buf = buffer( dt, N );
114+
y = ctor( buf, shape, shape2strides( shape, order ), 0, order );
115+
116+
// Determine whether we can use one-dimensional type-optimized implementations...
117+
if ( ndims === 1 ) {
118+
if ( dt === 'float64' ) {
119+
dabs.ndarray( N, data, strides[ 0 ], offset, buf, 1, 0 );
120+
} else if ( dt === 'float32' ) {
121+
sabs.ndarray( N, data, strides[ 0 ], offset, buf, 1, 0 );
122+
} else {
123+
gabs.ndarray( N, data, strides[ 0 ], offset, buf, 1, 0 );
124+
}
125+
return y;
126+
}
127+
// Determine whether we can ignore shape (and strides) and treat `x` as a linear array...
128+
s = iterationOrder( strides ); // +/-1
129+
if ( s !== 0 && isSingleSegmentCompatible( shape, strides, offset ) ) { // Note: equivalent to @stdlib/ndarray/base/assert/is-contiguous, but in-lined so we can retain iteration order
130+
if ( dt === 'float64' ) {
131+
dabs.ndarray( N, data, s, offset, buf, 1, 0 );
132+
} else if ( dt === 'float32' ) {
133+
sabs.ndarray( N, data, s, offset, buf, 1, 0 );
134+
} else {
135+
gabs.ndarray( N, data, s, offset, buf, 1, 0 );
136+
}
137+
return y;
138+
}
139+
// At this point, `x` is a non-contiguous n-dimensional array, so we cannot directly use lower-level strided array functionality...
140+
141+
// TODO: consider cache oblivious iteration, rather than data copy...
142+
xc = buffer( dt, N );
143+
for ( i = 0; i < N; i++ ) {
144+
xc[ i ] = x.iget( i );
145+
}
146+
// The buffer copy is contiguous so we can now use lower-level strided array functionality...
147+
if ( dt === 'float64' ) {
148+
dabs( N, xc, 1, buf, 1 );
149+
} else if ( dt === 'float32' ) {
150+
sabs( N, xc, 1, buf, 1 );
151+
} else {
152+
gabs( N, xc, 1, buf, 1 );
153+
}
154+
return y;
155+
}
156+
if ( !isArrayLikeObject( x ) ) {
157+
throw new TypeError( 'invalid argument. First argument must be either a number, array-like object, or ndarray. Value: `' + x + '`.' );
158+
}
159+
N = x.length;
160+
dt = dtype( x ) || 'generic';
161+
162+
// Create an output array...
163+
ctor = ndarray( dt, 1 );
164+
buf = buffer( dt, N );
165+
y = ctor( buf, [ N ], [ 1 ], 0, 'row-major' );
166+
167+
if ( isFloat64Array( x ) ) {
168+
dabs( x.length, x, 1, buf, 1 );
169+
} else if ( isFloat32Array( x ) ) {
170+
sabs( x.length, x, 1, buf, 1 );
171+
} else {
172+
gabs( x.length, x, 1, buf, 1 );
173+
}
174+
return y;
175+
}
176+
177+
178+
// EXPORTS //
179+
180+
module.exports = abs;
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"name": "@stdlib/math/special/abs",
3+
"version": "0.0.0",
4+
"description": "Compute the absolute value.",
5+
"license": "Apache-2.0",
6+
"author": {
7+
"name": "The Stdlib Authors",
8+
"url": "https://github.com/stdlib-js/stdlib/graphs/contributors"
9+
},
10+
"contributors": [
11+
{
12+
"name": "The Stdlib Authors",
13+
"url": "https://github.com/stdlib-js/stdlib/graphs/contributors"
14+
}
15+
],
16+
"main": "./lib",
17+
"directories": {
18+
"benchmark": "./benchmark",
19+
"doc": "./docs",
20+
"example": "./examples",
21+
"lib": "./lib",
22+
"test": "./test"
23+
},
24+
"types": "./docs/types",
25+
"scripts": {},
26+
"homepage": "https://github.com/stdlib-js/stdlib",
27+
"repository": {
28+
"type": "git",
29+
"url": "git://github.com/stdlib-js/stdlib.git"
30+
},
31+
"bugs": {
32+
"url": "https://github.com/stdlib-js/stdlib/issues"
33+
},
34+
"dependencies": {},
35+
"devDependencies": {},
36+
"engines": {
37+
"node": ">=0.10.0",
38+
"npm": ">2.7.0"
39+
},
40+
"os": [
41+
"aix",
42+
"darwin",
43+
"freebsd",
44+
"linux",
45+
"macos",
46+
"openbsd",
47+
"sunos",
48+
"win32",
49+
"windows"
50+
],
51+
"keywords": [
52+
"stdlib",
53+
"stdmath",
54+
"mathematics",
55+
"math",
56+
"math.abs",
57+
"abs",
58+
"absolute",
59+
"magnitude",
60+
"value"
61+
],
62+
"__stdlib__": {}
63+
}

0 commit comments

Comments
 (0)