From c0d11b031e7f228812264fadbdba5fd1663b0545 Mon Sep 17 00:00:00 2001 From: stdlib-bot Date: Tue, 17 Dec 2024 01:18:51 +0000 Subject: [PATCH] Auto-generated commit --- CHANGELOG.md | 52 ++++- CONTRIBUTORS | 15 +- base/ctor/lib/tojson.js | 2 +- base/docs/types/index.d.ts | 155 ++++++++++++ lib/index.js | 9 + to-json/README.md | 155 ++++++++++++ to-json/benchmark/benchmark.js | 98 ++++++++ to-json/docs/repl.txt | 26 +++ to-json/docs/types/index.d.ts | 142 +++++++++++ to-json/docs/types/test.ts | 48 ++++ to-json/examples/index.js | 57 +++++ to-json/lib/index.js | 50 ++++ to-json/lib/main.js | 139 +++++++++++ to-json/package.json | 69 ++++++ to-json/test/test.js | 414 +++++++++++++++++++++++++++++++++ 15 files changed, 1422 insertions(+), 9 deletions(-) create mode 100644 to-json/README.md create mode 100644 to-json/benchmark/benchmark.js create mode 100644 to-json/docs/repl.txt create mode 100644 to-json/docs/types/index.d.ts create mode 100644 to-json/docs/types/test.ts create mode 100644 to-json/examples/index.js create mode 100644 to-json/lib/index.js create mode 100644 to-json/lib/main.js create mode 100644 to-json/package.json create mode 100644 to-json/test/test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index b68fd058..be68803d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@
-## Unreleased (2024-12-16) +## Unreleased (2024-12-17)
@@ -20,6 +20,7 @@ ##### Features +- [`9d912a3`](https://github.com/stdlib-js/stdlib/commit/9d912a3e992cb9c5fe272a3aecc55293efbc0647) - add `ndarray2json` to namespace - [`1a202e3`](https://github.com/stdlib-js/stdlib/commit/1a202e3605b10cd01bf9654f8356c72c5c8a8186) - update namespace TypeScript declarations [(#3916)](https://github.com/stdlib-js/stdlib/pull/3916) - [`dbfd8f5`](https://github.com/stdlib-js/stdlib/commit/dbfd8f5c81d11be2142ebfc4f2f0bb0316ba7478) - add `filterMap` to namespace - [`cbc4d3f`](https://github.com/stdlib-js/stdlib/commit/cbc4d3f7514b7213cad4f9d2ca5d916e13eeffa5) - add `reject` to namespace @@ -58,6 +59,7 @@ ##### Features +- [`58e795d`](https://github.com/stdlib-js/stdlib/commit/58e795db467b7bd1d3dc6c5847f91a97fed2ccff) - update namespace TypeScript declarations [(#3937)](https://github.com/stdlib-js/stdlib/pull/3937) - [`14427c7`](https://github.com/stdlib-js/stdlib/commit/14427c79bc62f82b16cbadc9d34749901e48d105) - add `fill`, `map`, and `toReversed` to namespace - [`a0d6619`](https://github.com/stdlib-js/stdlib/commit/a0d66193409576538d0f16aa89cbaeedec7898be) - add `minSignedIntegerDataType` and `minUnsignedIntegerDataType` to namespace - [`8b1548f`](https://github.com/stdlib-js/stdlib/commit/8b1548fb45c1ff131f5edac20cb984344a2d28ec) - update namespace TypeScript declarations [(#3190)](https://github.com/stdlib-js/stdlib/pull/3190) @@ -118,6 +120,28 @@ +
+ +#### [@stdlib/ndarray/base/ctor](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ndarray/base/ctor) + +
+ +
+ +##### Bug Fixes + +- [`aea44c9`](https://github.com/stdlib-js/stdlib/commit/aea44c9c8699a4d748c0db70d4a60801bfc03c40) - update loop limit + +
+ + + +
+ +
+ + +
#### [@stdlib/ndarray/base/map](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ndarray/base/map) @@ -350,6 +374,28 @@ +
+ +#### [@stdlib/ndarray/to-json](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ndarray/to-json) + +
+ +
+ +##### Features + +- [`ae80da2`](https://github.com/stdlib-js/stdlib/commit/ae80da29fdbfd1be7541df6607715b77b06f1019) - add `ndarray/to-json` + +
+ + + +
+ +
+ + +
@@ -386,6 +432,10 @@ A total of 3 people contributed to this release. Thank you to the following cont
+- [`9d912a3`](https://github.com/stdlib-js/stdlib/commit/9d912a3e992cb9c5fe272a3aecc55293efbc0647) - **feat:** add `ndarray2json` to namespace _(by Athan Reines)_ +- [`ae80da2`](https://github.com/stdlib-js/stdlib/commit/ae80da29fdbfd1be7541df6607715b77b06f1019) - **feat:** add `ndarray/to-json` _(by Athan Reines)_ +- [`aea44c9`](https://github.com/stdlib-js/stdlib/commit/aea44c9c8699a4d748c0db70d4a60801bfc03c40) - **fix:** update loop limit _(by Athan Reines)_ +- [`58e795d`](https://github.com/stdlib-js/stdlib/commit/58e795db467b7bd1d3dc6c5847f91a97fed2ccff) - **feat:** update namespace TypeScript declarations [(#3937)](https://github.com/stdlib-js/stdlib/pull/3937) _(by stdlib-bot, Philipp Burckhardt)_ - [`c106b69`](https://github.com/stdlib-js/stdlib/commit/c106b69cc141efc8c32e79d55ad8acf07f3c9c0a) - **docs:** update namespace table of contents [(#3939)](https://github.com/stdlib-js/stdlib/pull/3939) _(by stdlib-bot, Philipp Burckhardt)_ - [`58f02bf`](https://github.com/stdlib-js/stdlib/commit/58f02bf605d6879cd80152f11f913451df2ad494) - **docs:** fix comment _(by Athan Reines)_ - [`baffefb`](https://github.com/stdlib-js/stdlib/commit/baffefb25177147fa3bafa5c1d0562a7528d5054) - **docs:** fix comment _(by Athan Reines)_ diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 1ba9b590..f7b71a85 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -2,12 +2,14 @@ # # Contributors listed in alphabetical order. +Aadish Jain Aayush Khanna Abhijit Raut Adarsh Palaskar Aditya Sapra Ahmed Atwa Ahmed Kashkoush +Ahmed Khaled Aleksandr <112382387+alextes90@users.noreply.github.com> Ali Salesi Aman Bhansali @@ -46,11 +48,10 @@ Jordan Gallivan <115050475+Jordan-Gallivan@users.noreply.github.com> Joris Labie Justin Dennison Karthik Prakash <116057817+skoriop@users.noreply.github.com> -Khaldon Kohantika Nath <145763549+kohantikanath@users.noreply.github.com> Krishnendu Das <86651039+itskdhere@users.noreply.github.com> Kshitij-Dale <152467202+Kshitij-Dale@users.noreply.github.com> -Lovelin <100030865+lovelindhoni@users.noreply.github.com> +Lovelin Dhoni J B <100030865+lovelindhoni@users.noreply.github.com> Manik Sharma Manvith M <148960168+manvith2003@users.noreply.github.com> Marcus Fantham @@ -61,6 +62,7 @@ Mohammad Kaif Momtchil Momtchev Muhammad Haris Naresh Jagadeesan +Naveen Kumar Neeraj Pathak Nishant Shinde <97207366+nishant-s7@users.noreply.github.com> Nithin Katta <88046362+nithinkatta@users.noreply.github.com> @@ -71,10 +73,10 @@ Ori Miles <97595296+orimiles5@users.noreply.github.com> Philipp Burckhardt Prajwal Kulkarni Pranav Goswami -Praneki <97080887+PraneGIT@users.noreply.github.com> -Pratik <97464067+Pratik772846@users.noreply.github.com> +Pranjal Jha <97080887+PraneGIT@users.noreply.github.com> +Pratik Singh <97464067+Pratik772846@users.noreply.github.com> Pratyush Kumar Chouhan -Priyansh <88396544+itsspriyansh@users.noreply.github.com> +Priyansh Prajapati <88396544+itsspriyansh@users.noreply.github.com> Priyanshu Agarwal <113460573+AgPriyanshu18@users.noreply.github.com> Pushpendra Chandravanshi Raunak Kumar Gupta @@ -93,7 +95,7 @@ Sarthak Paandey <145528240+SarthakPaandey@users.noreply.github.com> Saurabh Singh Seyyed Parsa Neshaei Shashank Shekhar Singh -Shivam <11shivam00@gmail.com> +Shivam Ahir <11shivam00@gmail.com> Shraddheya Shendre Shubh Mehta <93862397+Shubh942@users.noreply.github.com> Shubham Mishra @@ -116,7 +118,6 @@ Vivek maurya <155618190+vivekmaurya001@users.noreply.github.com> Xiaochuan Ye Yaswanth Kosuru <116426380+yaswanthkosuru@users.noreply.github.com> Yernar Yergaziyev -naveen olenkabilonizhka <62379231+olenkabilonizhka@users.noreply.github.com> rainn <88160429+AmCodesLame@users.noreply.github.com> rei2hu diff --git a/base/ctor/lib/tojson.js b/base/ctor/lib/tojson.js index 9cc4b67a..9429edb9 100644 --- a/base/ctor/lib/tojson.js +++ b/base/ctor/lib/tojson.js @@ -57,7 +57,7 @@ function toJSON() { out.strides = this._strides.slice(); // Flip the signs of negative strides: - for ( i = 0; i < len; i++ ) { + for ( i = 0; i < out.strides.length; i++ ) { if ( out.strides[ i ] < 0 ) { out.strides[ i ] *= -1; } diff --git a/base/docs/types/index.d.ts b/base/docs/types/index.d.ts index 9a82e659..b19dd8ab 100644 --- a/base/docs/types/index.d.ts +++ b/base/docs/types/index.d.ts @@ -50,6 +50,7 @@ import dtypes2signatures = require( './../../../base/dtypes2signatures' ); import empty = require( './../../../base/empty' ); import emptyLike = require( './../../../base/empty-like' ); import expandDimensions = require( './../../../base/expand-dimensions' ); +import fill = require( './../../../base/fill' ); import flag = require( './../../../base/flag' ); import flags = require( './../../../base/flags' ); import fliplr = require( './../../../base/fliplr' ); @@ -59,10 +60,13 @@ import scalar2ndarray = require( './../../../base/from-scalar' ); import ind = require( './../../../base/ind' ); import ind2sub = require( './../../../base/ind2sub' ); import iterationOrder = require( './../../../base/iteration-order' ); +import map = require( './../../../base/map' ); import maxViewBufferIndex = require( './../../../base/max-view-buffer-index' ); import maybeBroadcastArray = require( './../../../base/maybe-broadcast-array' ); import maybeBroadcastArrays = require( './../../../base/maybe-broadcast-arrays' ); import metaDataProps = require( './../../../base/meta-data-props' ); +import minSignedIntegerDataType = require( './../../../base/min-signed-integer-dtype' ); +import minUnsignedIntegerDataType = require( './../../../base/min-unsigned-integer-dtype' ); import minViewBufferIndex = require( './../../../base/min-view-buffer-index' ); import minmaxViewBufferIndex = require( './../../../base/minmax-view-buffer-index' ); import ndarraylike2ndarray = require( './../../../base/ndarraylike2ndarray' ); @@ -103,6 +107,7 @@ import strides2offset = require( './../../../base/strides2offset' ); import strides2order = require( './../../../base/strides2order' ); import sub2ind = require( './../../../base/sub2ind' ); import ndarray2array = require( './../../../base/to-array' ); +import toReversed = require( './../../../base/to-reversed' ); import transpose = require( './../../../base/transpose' ); import unary = require( './../../../base/unary' ); import unaryBy = require( './../../../base/unary-by' ); @@ -938,6 +943,44 @@ interface Namespace { */ expandDimensions: typeof expandDimensions; + /** + * Fills an input ndarray with a specified value. + * + * @param x - input ndarray + * @param value - scalar value + * + * @example + * var Float64Array = require( '@stdlib/array/float64' ); + * + * // Create a data buffer: + * var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] ); + * + * // Define the shape of the input array: + * var shape = [ 3, 1, 2 ]; + * + * // Define the array strides: + * var sx = [ 2, 2, 1 ]; + * + * // Define the index offset: + * var ox = 0; + * + * // Create the input ndarray-like object: + * var x = { + * 'dtype': 'float64', + * 'data': xbuf, + * 'shape': shape, + * 'strides': sx, + * 'offset': ox, + * 'order': 'row-major' + * }; + * + * ns.fill( x, 10.0 ); + * + * console.log( x.data ); + * // => [ 10.0, 10.0, 10.0, 10.0, 10.0, 10.0 ] + */ + fill: typeof fill; + /** * Returns a specified flag for a provided ndarray. * @@ -1291,6 +1334,50 @@ interface Namespace { */ iterationOrder: typeof iterationOrder; + /** + * Applies a callback function to the elements in an input ndarray and assigns results to the elements in an output ndarray. + * + * @param arrays - array-like object containing one input ndarray and one output ndarray + * @param fcn - callback function + * @param thisArg - callback function execution context + * @throws arrays must have the same number of dimensions + * @throws arrays must have the same shape + * + * @example + * var Float64Array = require( '@stdlib/array/float64' ); + * var ndarray = require( './../../../ctor' ); + * + * function scale( x ) { + * return x * 10.0; + * } + * + * // Create data buffers: + * var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); + * var ybuf = new Float64Array( 6 ); + * + * // Define the shape of the input and output arrays: + * var shape = [ 3, 1, 2 ]; + * + * // Define the array strides: + * var sx = [ 4, 4, 1 ]; + * var sy = [ 2, 2, 1 ]; + * + * // Define the index offsets: + * var ox = 1; + * var oy = 0; + * + * // Create the input and output ndarrays: + * var x = ndarray( 'float64', xbuf, shape, sx, ox, 'row-major' ); + * var y = ndarray( 'float64', ybuf, shape, sy, oy, 'row-major' ); + * + * // Apply the ns.map function: + * ns.map( [ x, y ], scale ); + * + * console.log( y.data ); + * // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] + */ + map: typeof map; + /** * Computes the maximum linear index in an underlying data buffer accessible to an array view. * @@ -1484,6 +1571,38 @@ interface Namespace { */ metaDataProps: typeof metaDataProps; + /** + * Returns the minimum ndarray data type for storing a provided signed integer value. + * + * @param value - scalar value + * @returns ndarray data type + * + * @example + * var dt = ns.minSignedIntegerDataType( 1280 ); + * // returns 'int16' + * + * @example + * var dt = ns.minSignedIntegerDataType( 3 ); + * // returns 'int8' + */ + minSignedIntegerDataType: typeof minSignedIntegerDataType; + + /** + * Returns the minimum ndarray data type for storing a provided unsigned integer value. + * + * @param value - scalar value + * @returns ndarray data type + * + * @example + * var dt = ns.minUnsignedIntegerDataType( 1280 ); + * // returns 'uint16' + * + * @example + * var dt = ns.minUnsignedIntegerDataType( 3 ); + * // returns 'uint8' + */ + minUnsignedIntegerDataType: typeof minUnsignedIntegerDataType; + /** * Computes the minimum linear index in an underlying data buffer accessible to an array view. * @@ -2718,6 +2837,42 @@ interface Namespace { */ ndarray2array: typeof ndarray2array; + /** + * Returns a new ndarray where the order of elements of an input ndarray is reversed along each dimension. + * + * @param x - input array + * @returns output array + * + * @example + * var typedarray = require( '@stdlib/array/typed' ); + * var ndarray = require( './../../../ctor' ); + * var ndarray2array = require( './../../../to-array' ); + * + * var buffer = typedarray( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ], 'float64' ); + * var shape = [ 3, 2 ]; + * var strides = [ 2, 1 ]; + * var offset = 0; + * + * var x = ndarray( 'float64', buffer, shape, strides, offset, 'row-major' ); + * // returns + * + * var sh = x.shape; + * // returns [ 3, 2 ] + * + * var arr = ndarray2array( x ); + * // returns [ [ 1.0, 2.0 ], [ 3.0, 4.0 ], [ 5.0, 6.0 ] ] + * + * var y = ns.toReversed( x ); + * // returns + * + * sh = y.shape; + * // returns [ 3, 2 ] + * + * arr = ndarray2array( y ); + * // returns [ [ 6.0, 5.0 ], [ 4.0, 3.0 ], [ 2.0, 1.0 ] ] + */ + toReversed: typeof toReversed; + /** * Transposes a matrix (or a stack of matrices). * diff --git a/lib/index.js b/lib/index.js index dd36e14a..d1cce23f 100644 --- a/lib/index.js +++ b/lib/index.js @@ -513,6 +513,15 @@ setReadOnly( ns, 'sub2ind', require( './../sub2ind' ) ); */ setReadOnly( ns, 'ndarray2array', require( './../to-array' ) ); +/** +* @name ndarray2json +* @memberof ns +* @readonly +* @type {Function} +* @see {@link module:@stdlib/ndarray/to-json} +*/ +setReadOnly( ns, 'ndarray2json', require( './../to-json' ) ); + /** * @name zeros * @memberof ns diff --git a/to-json/README.md b/to-json/README.md new file mode 100644 index 00000000..1087fd9e --- /dev/null +++ b/to-json/README.md @@ -0,0 +1,155 @@ + + +# ndarray2json + +> Serialize an [ndarray][@stdlib/ndarray/ctor] as a JSON object. + + + +
+ +
+ + + + + +
+ +## Usage + +```javascript +var ndarray2json = require( '@stdlib/ndarray/to-json' ); +``` + +#### ndarray2json( x ) + +Serializes an [ndarray][@stdlib/ndarray/ctor] as a JSON object. + +```javascript +var ndarray = require( '@stdlib/ndarray/ctor' ); + +var buffer = [ 1, 2, 3, 4 ]; +var shape = [ 2, 2 ]; +var order = 'row-major'; +var strides = [ 2, 1 ]; +var offset = 0; + +var x = ndarray( 'generic', buffer, shape, strides, offset, order ); +// returns + +var out = ndarray2json( x ); +// returns { 'type': 'ndarray', 'dtype': 'generic', 'flags': {...}, 'offset': 0, 'order': 'row-major', 'shape': [ 3, 2 ], 'strides': [ 2, 1 ], 'data': [ 1.0, 2.0, 3.0, 4.0 ] } +``` + +
+ + + + + +
+ +## Notes + +- The function does **not** serialize data outside of the buffer defined by the [ndarray][@stdlib/ndarray/ctor] view. + +
+ + + + + +
+ +## Examples + + + +```javascript +var shape2strides = require( '@stdlib/ndarray/base/shape2strides' ); +var strides2offset = require( '@stdlib/ndarray/base/strides2offset' ); +var discreteUniform = require( '@stdlib/random/base/discrete-uniform' ); +var zeroTo = require( '@stdlib/array/base/zero-to' ); +var ndarray = require( '@stdlib/ndarray/ctor' ); +var ndarray2json = require( '@stdlib/ndarray/to-json' ); + +// Create a data buffer: +var buffer = zeroTo( 27 ); + +// Specify array meta data: +var shape = [ 3, 3, 3 ]; +var order = 'column-major'; +var ndims = shape.length; + +// Compute array meta data: +var strides = shape2strides( shape, order ); +var offset = strides2offset( shape, strides ); + +// Print array information: +console.log( '' ); +console.log( 'Dims: %s', shape.join( 'x' ) ); + +// Randomly flip strides and convert an ndarray to JSON... +var arr; +var i; +for ( i = 0; i < 20; i++ ) { + strides[ discreteUniform( 0, ndims-1 ) ] *= -1; + offset = strides2offset( shape, strides ); + + console.log( '' ); + console.log( 'Strides: %s', strides.join( ',' ) ); + console.log( 'Offset: %d', offset ); + + arr = ndarray( 'generic', buffer, shape, strides, offset, order ); + console.log( JSON.stringify( ndarray2json( arr ) ) ); +} +``` + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + diff --git a/to-json/benchmark/benchmark.js b/to-json/benchmark/benchmark.js new file mode 100644 index 00000000..ab386b55 --- /dev/null +++ b/to-json/benchmark/benchmark.js @@ -0,0 +1,98 @@ +/** +* @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 bench = require( '@stdlib/bench' ); +var isPlainObject = require( '@stdlib/assert/is-plain-object' ); +var shape2strides = require( './../../base/shape2strides' ); +var strides2offset = require( './../../base/strides2offset' ); +var numel = require( './../../base/numel' ); +var zeroTo = require( '@stdlib/array/base/zero-to' ); +var ndarray = require( './../../ctor' ); +var pkg = require( './../package.json' ).name; +var ndarray2json = require( './../lib' ); + + +// MAIN // + +bench( pkg+':order=row-major', function benchmark( b ) { + var strides; + var buffer; + var offset; + var order; + var shape; + var arr; + var out; + var i; + + shape = [ 10, 10, 10 ]; + order = 'row-major'; + buffer = zeroTo( numel( shape ) ); + strides = shape2strides( shape, order ); + offset = strides2offset( shape, strides ); + arr = ndarray( 'generic', buffer, shape, strides, offset, order ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + out = ndarray2json( arr ); + if ( typeof out !== 'object' ) { + b.fail( 'should return an object' ); + } + } + b.toc(); + if ( !isPlainObject( out ) ) { + b.fail( 'should return a JSON object' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':order=column-major', function benchmark( b ) { + var strides; + var buffer; + var offset; + var order; + var shape; + var arr; + var out; + var i; + + shape = [ 10, 10, 10 ]; + order = 'column-major'; + buffer = zeroTo( numel( shape ) ); + strides = shape2strides( shape, order ); + offset = strides2offset( shape, strides ); + arr = ndarray( 'generic', buffer, shape, strides, offset, order ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + out = ndarray2json( arr ); + if ( typeof out !== 'object' ) { + b.fail( 'should return an object' ); + } + } + b.toc(); + if ( !isPlainObject( out ) ) { + b.fail( 'should return a JSON object' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/to-json/docs/repl.txt b/to-json/docs/repl.txt new file mode 100644 index 00000000..b5216172 --- /dev/null +++ b/to-json/docs/repl.txt @@ -0,0 +1,26 @@ + +{{alias}}( x ) + Serializes an ndarray as a JSON object. + + This function does *not* serialize data outside of the buffer region defined + by the ndarray view. + + Parameters + ---------- + x: ndarray + Input ndarray. + + Returns + ------- + out: Object + JSON object. + + Examples + -------- + > var arr = {{alias:@stdlib/ndarray/array}}( [ [ 1, 2 ], [ 3, 4 ] ] ); + > var out = {{alias}}( arr ) + {...} + + See Also + -------- + diff --git a/to-json/docs/types/index.d.ts b/to-json/docs/types/index.d.ts new file mode 100644 index 00000000..7d6b1809 --- /dev/null +++ b/to-json/docs/types/index.d.ts @@ -0,0 +1,142 @@ +/* +* @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 { typedndarray, realcomplexndarray, boolndarray, DataType, Order } from '@stdlib/types/ndarray'; + +/** +* Interface describing serialized ndarray flags. +*/ +interface Flags { + /** + * Boolean indicating if an ndarray is read-only. + */ + READONLY: boolean; +} + +/** +* Interface describing a returned JSON representation of an ndarray. +*/ +interface JSONObject { + /** + * Serialized object type. + */ + type: 'ndarray'; + + /** + * Underlying data type. + */ + dtype: DataType; + + /** + * Configuration flags. + */ + flags: Flags; + + /** + * Memory layout order. + */ + order: Order; + + /** + * Array dimensions. + */ + shape: Array; + + /** + * Index strides. + */ + strides: Array; + + /** + * Data. + */ + data: Array; +} + +/** +* Serializes an ndarray as a JSON object. +* +* ## Notes +* +* - The function does **not** serialize data outside of the buffer region defined by the ndarray view. +* +* @param x - input ndarray +* @returns JSON object +* +* @example +* var array = require( '@stdlib/ndarray/array' ); +* +* var x = array( [ [ 1.0, 2.0 ], [ 3.0, 4.0 ] ] ); +* // returns +* +* var o = ndarray2json( x ); +* // returns {...} +*/ +declare function ndarray2json( x: realcomplexndarray ): JSONObject; + +/** +* Serializes an ndarray as a JSON object. +* +* ## Notes +* +* - The function does **not** serialize data outside of the buffer region defined by the ndarray view. +* +* @param x - input ndarray +* @returns JSON object +* +* @example +* var BooleanArray = require( '@stdlib/array/bool' ); +* var array = require( '@stdlib/ndarray/array' ); +* +* var x = array( new BooleanArray( 4 ) ); +* // returns +* +* var o = ndarray2json( x ); +* // returns {...} +*/ +declare function ndarray2json( x: boolndarray ): JSONObject; + +/** +* Serializes an ndarray as a JSON object. +* +* ## Notes +* +* - The function does **not** serialize data outside of the buffer region defined by the ndarray view. +* +* @param x - input ndarray +* @returns JSON object +* +* @example +* var array = require( '@stdlib/ndarray/array' ); +* +* var x = array( [ [ 1.0, 2.0 ], [ 3.0, 4.0 ] ] ); +* // returns +* +* var o = ndarray2json( x ); +* // returns {...} +*/ +declare function ndarray2json( x: typedndarray ): JSONObject; + + +// EXPORTS // + +export = ndarray2json; diff --git a/to-json/docs/types/test.ts b/to-json/docs/types/test.ts new file mode 100644 index 00000000..8900effc --- /dev/null +++ b/to-json/docs/types/test.ts @@ -0,0 +1,48 @@ +/* +* @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 array = require( './../../../array' ); +import ndarray2json = require( './index' ); + + +// TESTS // + +// The function returns a JSON object... +{ + ndarray2json( array( [ [ 1, 2 ], [ 3, 4 ] ] ) ); // $ExpectType JSONObject +} + +// The compiler throws an error if the function is provided a first argument which is not an ndarray... +{ + ndarray2json( 123 ); // $ExpectError + ndarray2json( true ); // $ExpectError + ndarray2json( false ); // $ExpectError + ndarray2json( null ); // $ExpectError + ndarray2json( undefined ); // $ExpectError + ndarray2json( [ 1, 2 ] ); // $ExpectError + ndarray2json( {} ); // $ExpectError + ndarray2json( ( x: number ): number => x ); // $ExpectError +} + +// The compiler throws an error if the function is provided an unsupported number of arguments... +{ + const arr = array( [ [ 1, 2 ], [ 3, 4 ] ] ); + + ndarray2json(); // $ExpectError + ndarray2json( arr, {} ); // $ExpectError +} diff --git a/to-json/examples/index.js b/to-json/examples/index.js new file mode 100644 index 00000000..352d6cc1 --- /dev/null +++ b/to-json/examples/index.js @@ -0,0 +1,57 @@ +/** +* @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'; + +var shape2strides = require( './../../base/shape2strides' ); +var strides2offset = require( './../../base/strides2offset' ); +var discreteUniform = require( '@stdlib/random/base/discrete-uniform' ); +var zeroTo = require( '@stdlib/array/base/zero-to' ); +var ndarray = require( './../../ctor' ); +var ndarray2json = require( './../lib' ); + +// Create a data buffer: +var buffer = zeroTo( 27 ); + +// Specify array meta data: +var shape = [ 3, 3, 3 ]; +var order = 'column-major'; +var ndims = shape.length; + +// Compute array meta data: +var strides = shape2strides( shape, order ); +var offset = strides2offset( shape, strides ); + +// Print array information: +console.log( '' ); +console.log( 'Dims: %s', shape.join( 'x' ) ); + +// Randomly flip strides and convert an ndarray to JSON... +var arr; +var i; +for ( i = 0; i < 20; i++ ) { + strides[ discreteUniform( 0, ndims-1 ) ] *= -1; + offset = strides2offset( shape, strides ); + + console.log( '' ); + console.log( 'Strides: %s', strides.join( ',' ) ); + console.log( 'Offset: %d', offset ); + + arr = ndarray( 'generic', buffer, shape, strides, offset, order ); + console.log( JSON.stringify( ndarray2json( arr ) ) ); +} diff --git a/to-json/lib/index.js b/to-json/lib/index.js new file mode 100644 index 00000000..e2b0b4de --- /dev/null +++ b/to-json/lib/index.js @@ -0,0 +1,50 @@ +/** +* @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'; + +/** +* Serialize an ndarray to JSON. +* +* @module @stdlib/ndarray/to-json +* +* @example +* var ndarray = require( '@stdlib/ndarray/ctor' ); +* var ndarray2json = require( '@stdlib/ndarray/to-json' ); +* +* var buffer = [ 1, 2, 3, 4 ]; +* var shape = [ 2, 2 ]; +* var order = 'row-major'; +* var strides = [ 2, 1 ]; +* var offset = 0; +* +* var arr = ndarray( 'generic', buffer, shape, strides, offset, order ); +* // returns +* +* var out = ndarray2json( arr ); +* // returns {...} +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/to-json/lib/main.js b/to-json/lib/main.js new file mode 100644 index 00000000..36e957ae --- /dev/null +++ b/to-json/lib/main.js @@ -0,0 +1,139 @@ + +/** +* @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 isComplexDataType = require( './../../base/assert/is-complex-floating-point-data-type' ); +var isndarrayLike = require( '@stdlib/assert/is-ndarray-like' ); +var isReadOnly = require( './../../base/assert/is-read-only' ); +var getDType = require( './../../dtype' ); +var getShape = require( './../../shape' ); +var getStrides = require( './../../strides' ); +var getOffset = require( './../../offset' ); +var getOrder = require( './../../order' ); +var numel = require( './../../base/numel' ); +var ind2sub = require( './../../base/ind2sub' ); +var real = require( '@stdlib/complex/float64/real' ); +var imag = require( '@stdlib/complex/float64/imag' ); +var format = require( '@stdlib/string/format' ); + + +// FUNCTIONS // + +/** +* Tests whether an object has a specified method. +* +* @private +* @param {Object} obj - input object +* @param {string} method - method name +* @returns {boolean} boolean indicating whether an object has a specified method +* +* @example +* var bool = hasMethod( [], 'toJSON' ); +* // returns false +*/ +function hasMethod( obj, method ) { + return ( typeof obj[ method ] === 'function' ); +} + + +// MAIN // + +/** +* Serializes an ndarray as a JSON object. +* +* ## Notes +* +* - The function does **not** serialize data outside of the buffer region defined by the ndarray view. +* +* @param {ndarrayLike} x - input ndarray +* @throws {TypeError} must provide an ndarray-like object +* @returns {Object} JSON representation +* +* @example +* var array = require( '@stdlib/ndarray/array' ); +* +* var x = array( [ [ 1.0, 2.0 ], [ 3.0, 4.0 ] ] ); +* // returns +* +* var o = toJSON( x ); +* // returns {...} +*/ +function toJSON( x ) { + var out; + var len; + var sh; + var st; + var o; + var v; + var i; + + if ( !isndarrayLike( x ) ) { + throw new TypeError( format( 'invalid argument. Must provide an ndarray. Value: `%s`.', x ) ); + } + // Defer to input argument's custom implementation, if already defined... + if ( hasMethod( x, 'toJSON' ) ) { + return x.toJSON(); + } + // Build an object containing all ndarray properties needed to revive a serialized ndarray... + out = {}; + out.type = 'ndarray'; + out.dtype = getDType( x ); + out.flags = { + 'READONLY': isReadOnly( x ) + }; + out.order = getOrder( x ); + + sh = getShape( x ); + out.shape = sh; + + st = getStrides( x ); + out.strides = st.slice(); + + o = getOffset( x ); + + len = numel( out.shape ); + + // Flip the signs of negative strides: + for ( i = 0; i < st.length; i++ ) { + if ( out.strides[ i ] < 0 ) { + out.strides[ i ] *= -1; + } + } + // Cast data to generic array... + out.data = []; + if ( isComplexDataType( out.dtype ) ) { + for ( i = 0; i < len; i++ ) { + v = x.get.apply( x, ind2sub( sh, st, o, out.order, i, 'throw' ) ); + out.data.push( real( v ), imag( v ) ); + } + } else { + for ( i = 0; i < len; i++ ) { + out.data.push( x.get.apply( x, ind2sub( sh, st, o, out.order, i, 'throw' ) ) ); + } + } + return out; +} + + +// EXPORTS // + +module.exports = toJSON; diff --git a/to-json/package.json b/to-json/package.json new file mode 100644 index 00000000..0ba19b26 --- /dev/null +++ b/to-json/package.json @@ -0,0 +1,69 @@ +{ + "name": "@stdlib/ndarray/to-json", + "version": "0.0.0", + "description": "Serialize an ndarray as a JSON object.", + "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": { + "benchmark": "./benchmark", + "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", + "stdtypes", + "types", + "ndarray", + "multidimensional", + "array", + "utilities", + "utility", + "utils", + "util", + "view", + "convert", + "tojson", + "transform", + "json" + ], + "__stdlib__": {} +} diff --git a/to-json/test/test.js b/to-json/test/test.js new file mode 100644 index 00000000..181c6f5f --- /dev/null +++ b/to-json/test/test.js @@ -0,0 +1,414 @@ +/** +* @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 tape = require( 'tape' ); +var Float64Array = require( '@stdlib/array/float64' ); +var Complex64Array = require( '@stdlib/array/complex64' ); +var ndarray = require( './../../ctor' ); +var sub2ind = require( './../../sub2ind' ); +var noop = require( '@stdlib/utils/noop' ); +var ndarray2json = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof ndarray2json, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function throws an error if not provided an ndarray-like object', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + NaN, + true, + false, + null, + void 0, + [], + {}, + function noop() {} + ]; + 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() { + ndarray2json( value ); + }; + } +}); + +tape( 'the function serializes an ndarray to JSON (row-major)', function test( t ) { + var expected; + var strides; + var actual; + var buffer; + var offset; + var dtype; + var order; + var shape; + var arr; + + dtype = 'float64'; + buffer = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); + shape = [ 2, 2 ]; + order = 'row-major'; + strides = [ 2, 1 ]; + offset = 2; + + arr = ndarray( dtype, buffer, shape, strides, offset, order ); + + expected = { + 'type': 'ndarray', + 'dtype': 'float64', + 'data': [ 3.0, 4.0, 5.0, 6.0 ], + 'shape': [ 2, 2 ], + 'strides': [ 2, 1 ], + 'order': 'row-major', + 'flags': { + 'READONLY': false + } + }; + actual = ndarray2json( arr ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function serializes an ndarray to JSON (row-major, negative strides)', function test( t ) { + var expected; + var strides; + var actual; + var buffer; + var offset; + var dtype; + var order; + var shape; + var arr; + + dtype = 'float64'; + buffer = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); + shape = [ 2, 2 ]; + order = 'row-major'; + strides = [ -2, -1 ]; + offset = 5; + + arr = ndarray( dtype, buffer, shape, strides, offset, order ); + + expected = { + 'type': 'ndarray', + 'dtype': 'float64', + 'data': [ 6.0, 5.0, 4.0, 3.0 ], + 'shape': [ 2, 2 ], + 'strides': [ 2, 1 ], + 'order': 'row-major', + 'flags': { + 'READONLY': false + } + }; + actual = ndarray2json( arr ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function serializes an ndarray to JSON (column-major)', function test( t ) { + var expected; + var strides; + var actual; + var buffer; + var offset; + var dtype; + var order; + var shape; + var arr; + + dtype = 'generic'; + buffer = [ 1.0, 2.0, 3.0, 4.0 ]; + shape = [ 2, 2 ]; + order = 'column-major'; + strides = [ 1, 2 ]; + offset = 0; + + arr = ndarray( dtype, buffer, shape, strides, offset, order ); + + expected = { + 'type': 'ndarray', + 'dtype': 'generic', + 'data': [ 1.0, 2.0, 3.0, 4.0 ], + 'shape': [ 2, 2 ], + 'strides': [ 1, 2 ], + 'order': 'column-major', + 'flags': { + 'READONLY': false + } + }; + actual = ndarray2json( arr ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function serializes an ndarray to JSON (column-major, negative strides)', function test( t ) { + var expected; + var strides; + var actual; + var buffer; + var offset; + var dtype; + var order; + var shape; + var arr; + + dtype = 'float64'; + buffer = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); + shape = [ 2, 2 ]; + order = 'column-major'; + strides = [ -1, -2 ]; + offset = 5; + + arr = ndarray( dtype, buffer, shape, strides, offset, order ); + + expected = { + 'type': 'ndarray', + 'dtype': 'float64', + 'data': [ 6.0, 5.0, 4.0, 3.0 ], + 'shape': [ 2, 2 ], + 'strides': [ 1, 2 ], + 'order': 'column-major', + 'flags': { + 'READONLY': false + } + }; + actual = ndarray2json( arr ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function serializes an ndarray to JSON (0d)', function test( t ) { + var expected; + var strides; + var actual; + var buffer; + var offset; + var dtype; + var order; + var shape; + var arr; + + dtype = 'generic'; + buffer = [ 1.0, 2.0, 3.0, 4.0 ]; + shape = []; + order = 'column-major'; + strides = [ 0 ]; + offset = 2; + + arr = ndarray( dtype, buffer, shape, strides, offset, order ); + + expected = { + 'type': 'ndarray', + 'dtype': 'generic', + 'data': [ 3.0 ], + 'shape': [], + 'strides': [ 0 ], + 'order': 'column-major', + 'flags': { + 'READONLY': false + } + }; + actual = ndarray2json( arr ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function serializes an ndarray to JSON (dtype=complex)', function test( t ) { + var expected; + var strides; + var actual; + var buffer; + var offset; + var dtype; + var order; + var shape; + var arr; + + dtype = 'complex64'; + buffer = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); + shape = [ 2, 2 ]; + order = 'row-major'; + strides = [ 2, 1 ]; + offset = 0; + + arr = ndarray( dtype, buffer, shape, strides, offset, order ); + + expected = { + 'type': 'ndarray', + 'dtype': 'complex64', + 'data': [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ], + 'shape': [ 2, 2 ], + 'strides': [ 2, 1 ], + 'order': 'row-major', + 'flags': { + 'READONLY': false + } + }; + actual = ndarray2json( arr ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function serializes an ndarray-like object to JSON (row-major)', function test( t ) { + var expected; + var actual; + var arr; + + arr = { + 'dtype': 'float64', + 'data': new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ), + 'shape': [ 2, 2 ], + 'strides': [ 2, 1 ], + 'offset': 2, + 'order': 'row-major', + 'ndims': 2, + 'length': 4, + 'flags': { + 'READONLY': true + }, + 'get': getter, + 'set': noop + }; + + expected = { + 'type': 'ndarray', + 'dtype': 'float64', + 'data': [ 3.0, 4.0, 5.0, 6.0 ], + 'shape': [ 2, 2 ], + 'strides': [ 2, 1 ], + 'order': 'row-major', + 'flags': { + 'READONLY': true + } + }; + actual = ndarray2json( arr ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); + + function getter( i, j ) { + return arr.data[ arr.offset+sub2ind( [ 2, 2 ], i, j ) ]; + } +}); + +tape( 'the function serializes an ndarray-like object to JSON (column-major)', function test( t ) { + var expected; + var actual; + var arr; + + arr = { + 'dtype': 'float64', + 'data': new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ), + 'shape': [ 2, 2 ], + 'strides': [ 1, 2 ], + 'offset': 2, + 'order': 'column-major', + 'ndims': 2, + 'length': 4, + 'flags': { + 'READONLY': true + }, + 'get': getter, + 'set': noop + }; + + expected = { + 'type': 'ndarray', + 'dtype': 'float64', + 'data': [ 3.0, 5.0, 4.0, 6.0 ], + 'shape': [ 2, 2 ], + 'strides': [ 1, 2 ], + 'order': 'column-major', + 'flags': { + 'READONLY': true + } + }; + actual = ndarray2json( arr ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); + + function getter( i, j ) { + return arr.data[ arr.offset+sub2ind( [ 2, 2 ], i, j ) ]; + } +}); + +tape( 'the function serializes an ndarray-like object to JSON (row-major, dtype=complex)', function test( t ) { + var expected; + var actual; + var arr; + + arr = { + 'dtype': 'complex64', + 'data': new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ), + 'shape': [ 2, 2 ], + 'strides': [ 2, 1 ], + 'offset': 0, + 'order': 'row-major', + 'ndims': 2, + 'length': 4, + 'flags': { + 'READONLY': true + }, + 'get': getter, + 'set': noop + }; + + expected = { + 'type': 'ndarray', + 'dtype': 'complex64', + 'data': [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ], + 'shape': [ 2, 2 ], + 'strides': [ 2, 1 ], + 'order': 'row-major', + 'flags': { + 'READONLY': true + } + }; + actual = ndarray2json( arr ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); + + function getter( i, j ) { + return arr.data.get( arr.offset+sub2ind( [ 2, 2 ], i, j ) ); + } +});