Skip to content

Repository files navigation

Matrix

NPM versionBuild StatusCoverage StatusDependencies

Matrices.

Sponsor

This module exports a Matrix data structure for efficient storage and computation of numeric values. The data structure provides an interface for accessing and modifying one or more stored values. Matrices find common use in linear algebra, numerical analysis, image manipulation, machine learning, and data processing.


  1. Installation
  2. Usage
  3. Notes
  4. Examples
  5. Tests
  6. License

Installation

$ npm install dstructs-matrix

For use in the browser, use browserify.

Usage

varmatrix=require('dstructs-matrix');

matrix( [data,] shape[, dtype] )

Creates a new Matrix having a specified shape (dimensions => [rows,cols]).

varmat=matrix([3,2]);/*	[ 0 0 0 0 0 0 ]*/

By default, the matrix elements are floating-point 64-bit numbers (float64). To specify a different data type, provide a dtype.

varmat=matrix([2,2],'int8');/*	[ 0 0 0 0 ]*/

The following dtypes are accepted:

  • int8
  • uint8
  • uint8_clamped
  • int16
  • uint16
  • int32
  • uint32
  • float32
  • float64

If a linearnumeric array is not provided, the function initializes a zero-filled matrix. To initialize a matrix, provide a typed input data array, whose length matches the specified shape.

vardata=newInt8Array(6);for(vari=0;i<data.length;i++){data[i]=i;}varmat=matrix(data,[2,3]);// 2*3 = 6/*	[ 0 1 2 3 4 5 ]*/

To cast an input data array to a different data type, provide a dtype.

varmat=matrix(data,[2,2],'uint32');/*	[ 0 1 2 3 ]*/

If provided an Array instead of a typed array and no dtype is specified, the input data array is cast to float64.

vardata=[10,20,30,40,50,60];varmat=matrix(data,[3,2]);/*	[ 10 20 30 40 50 60 ]*/vardtype=mat.dtype;// returns 'float64'

Properties

A Matrix has the following properties...

dtype

A read-only property returning the underlying storage data type.

vardtype=mat.dtype;// returns <string>

ndims

A read-only property returning the number of dimensions.

varndims=mat.ndims;// returns 2

shape

A read-only property returning the matrix shape.

varshape=mat.shape;// returns [...]

offset

A property returning the offset used to index into the underlying data store.

varoffset=mat.offset;// returns 0

By default, the offset is 0. While not read-only, most consumers should treat the offset as a read-only property.

strides

A read-only property returning the strides used to index into the underlying data store.

varstrides=mat.strides;// returns [...]

While not frozen, most consumers should treat the strides elements as read-only elements.

length

A read-only property returning the matrix length; i.e., how many elements are in the Matrix, similar to Array#length.

varlen=mat.length;// returns <number>

Note: while a Matrix has a length property, a Matrix should not be considered array-like, as array indexing with not work as expected.

vardata=newFloat32Array(10);varmat=matrix(data,[1,10]);/* [ 0 0 0 0 0 0 0 0 0 0 ]*/varvalue=mat.get(1,3);// returns 0value=mat[3];// returns undefined

nbytes

A read-only property returning the number of bytes consumed by the Matrix elements.

varnbytes=mat.nbytes;// returns <number>

data

A read-only property pointing to the underlying storage array.

vardata=mat.data;// returns <TypedArray>

Methods

A Matrix has the following methods...

Set Methods

These methods mutate a Matrix:

Matrix.prototype.set( i, j, value )

Sets a Matrix element located at a row and column index.

mat.set(3,1,20);/*	[ 0 1 2 3 4 5 6 20 8 9 ]*/

Set methods return the Matrix instance and are thus chainable.

mat.set(3,1,21).set(3,1,22).set(3,1,23).set(3,1,24).get(3,1);// returns 24

Note: out-of-bounds row and column indices will silently fail.

Matrix.prototype.iset( index, value )

Sets a Matrix element located at a specified index. If index < 0, the index refers to a position relative to the Matrix length, where index = -1 corresponds to the last element.

mat.iset(7,25);/*	[ 0 1 2 3 4 5 6 25 8 9 ]*/mat.iset(-3,20);/*	[ 0 1 2 3 4 5 6 20 8 9 ]*/

Note: out-of-bounds indices will silently fail.

Matrix.prototype.mset( idx[, cols], value[, thisArg] )

Sets multiple Matrix elements. If provided a single array, idx is treated as an array of linear indices. The value argument may be either a number primitive, a Matrix containing values to set, or a callback function.

vardata=newInt8Array(10*10);for(vari=0;i<data.length;i++){data[i]=i;}// Create a 10x10 matrix:varmat=matrix(data,[10,10]);varsubmat=mat.mget([0,2,4],[1,4,5]);/*	[ 1 4 5 21 24 25 41 44 45 ]*/mat.mset([1,4,5,21,24,25,41,44,45],5);submat=mat.mget([0,2,4],[1,4,5]);/*	[ 5 5 5 5 5 5 5 5 5 ]*/varzeros=matrix([1,3],'int8');/*	[ 0 0 0 ]*/mat.mset([2],[1,4,5],zeros);submat=mat.mget([0,2,4],[1,4,5]);/*	[ 5 5 5 0 0 0 5 5 5 ]*/

A callback is provided four arguments:

  • d: current value
  • i: row index
  • j: column index
  • idx: linear index

and is expected to return a number primitive or a value which can be cast to a number primitive.

functionset(d,i,j,idx){return''+j+i;}mat.mset([0],[1,4,5],set);mat.mget([0,2,4],[1,4,5]);/*	[ 10 40 50 0 0 0 5 5 5 ]*/

By default, the callback this context is set to the Matrix instance. To specify a different this context, provide a thisArg.

functionset(d,i,j,idx){console.log(this);// returns nullreturn''+j+i;}mat.mset([0],[1,4,5],set,null);

Notes:

  • Negative indices are not permitted.
  • Out-of-bounds row and column indices will silently fail.
  • Values which are set are cast to the target Matrix data type.
  • A value Matrix must have dimensions which match the submatrix defined by row and column indices.
  • If linear indices are provided, a value Matrix must have a length equal to the number of provided indices.

Matrix.prototype.sset( subsequence, value[, thisArg] )

Sets Matrix elements according to a specified subsequence. The subsequence must specify both row and column subsequences; e.g., '3:7,5:9', where 3:7 corresponds to row indices 3,4,5,6 and 5:9 corresponds to column indices 5,6,7,8. The second argument may be either a number primitive, a Matrix containing values to set, or a callback function.

vardata=newFloat32Array(10*10);for(vari=0;i<data.length;i++){data[i]=i;}// Create a 10x10 matrix:varmat=matrix(data,[10,10]);varsubmat=mat.sget('3:7,5:9');/*	[ 35 36 37 38 45 46 47 48 55 56 57 58 65 66 67 68 ]*/varzeros=matrix([2,2],'float32');/*	[ 0 0 0 0 ]*/mat.sset('4:6,6:8',zeros);submat=mat.sget('3:7,5:9');/*	[ 35 36 37 38 45 0 0 48 55 0 0 58 65 66 67 68 ]*/

A callback is provided four arguments:

  • d: value at a subsequence index
  • i: row index
  • j: column index
  • idx: linear index

and is expected to return a number primitive or a value which can be cast to a number primitive.

functionset(d,i,j,idx){return''+j+i;}mat.sset('4:6,6:8',set);submat=mat.sget('3:7,5:9');/*	[ 35 36 37 38 45 64 74 48 55 65 75 58 65 66 67 68 ]*/

By default, the callback this context is set to the Matrix instance. To specify a different this context, provide a thisArg.

functionset(d,i,j,idx){console.log(this);// returns nullreturn''+j+i;}mat.sset('4:6,6:8',set,null);

Notes:

  • Values which are set are cast to the target Matrix data type.
  • Out-of-bounds row and column indices will silently fail.
  • A provided Matrix must have dimensions which match the submatrix defined by row and column subsequences.
  • For further subsequence documentation, see compute-indexspace.

===

Get Methods

These methods provide access to Matrix elements:

Matrix.prototype.get( i, j )

Returns a Matrix element located at a row and column index.

vardata=newFloat32Array(10);for(vari=0;i<data.length;i++){data[i]=i;}varmat=matrix(data,[5,2]);/*	[ 0 1 2 3 4 5 6 7 8 9 ]*/varvalues=mat.get(3,1);// returns 7

Note: out-of-bounds row and column indices will return a value of undefined.

Matrix.prototype.iget( index )

Returns a Matrix element located at a specified index. If index < 0, the index refers to a position relative to the Matrix length, where index = -1 corresponds to the last element.

varvalue=mat.iget(7);// returns 7value=mat.iget(-3);// returns 7

Note: out-of-bounds indices will return a value of undefined.

Matrix.prototype.mget( idx[, cols] )

Returns multiple Matrix elements. If provided a single argument, the method treats idx as an array of linear indices (idx[i] >= 0) and returns a new Matrix instance having a single row. Otherwise, idx and cols are integer arrays which specify row and column indices and the method returns a new Matrix instance having dimensions determined by the number of defined rows and columns.

vardata=newInt8Array(10);for(vari=0;i<data.length;i++){data[i]=i*2;}varmat=matrix(data,[5,2]);/*	[ 0 2 4 6 8 10 12 14 16 18 ]*/// Scramble the second column:varvals=mat.mget([1,5,3,9,7]);/*	[ 2, 10, 6, 18, 14 ]*/// Extract select rows and columns in arbitrary order:varmat1=mat.mget([1,3,2],[1]);/*	[ 4 14 8 ]*/

If idx and/or cols is null, all rows (columns) are extracted.

// Replicate a column:varrep=mat.mget(null,[1,1,1,1,1]);/*	[ 2 2 2 2 2 6 6 6 6 6 10 10 10 10 10 14 14 14 14 14 18 18 18 18 18 ]*/// Tile select rows and columns:vartile=mat.mget([1,2,1,2],[0,1,0,1]);/*	[ 4 6 4 6 8 10 8 10 4 6 4 6 8 10 8 10	]*/

Note: out-of-bounds indices are ignored.

Matrix.prototype.sget( subsequence )

Returns Matrix elements in a new Matrix according to a specified subsequence. The subsequence must specify both row and column subsequences; e.g., '3:7,5:9', where 3:7 corresponds to row indices 3,4,5,6 and 5:9 corresponds to column indices 5,6,7,8. If a subsequence does not correspond to any Matrix elements, the method returns an empty Matrix.

varsubmatrix;submatrix=mat.sget(':,:');// Copy a matrix/*	[ 0 1 2 3 4 5 6 7 8 9 ]*/submatrix=mat.sget('1:4,:');/*	[ 2 3 4 5 6 7 ]*/submatrix=mat.sget('::-1,:');// flip top-to-bottom/*	[ 8 9 6 7 4 5 2 3 0 1 ]*/submatrix=mat.sget(':,::-1');// flip left-to-right/*	[ 1 0 3 2 5 4 7 6 9 8 ]*/submatrix=mat.sget('50:100,:');/*	[]*/

Notes:

  • Out-of-bounds indices are ignored.
  • For further subsequence documentation, see compute-indexspace.

===

Accessor Methods

These methods do not mutate a Matrix and return some representation of a Matrix:

Matrix.prototype.toString()

Returns a string representation of a Matrix. This method is similar to Array#toString, except that rows are delineated by semicolons and column values are delineated by commas.

vardata=newInt8Array(10);for(vari=0;i<data.length;i++){data[i]=i;}varmat=matrix(data,[5,2]);varstr=mat.toString();// 0,1;2,3;4,5;6,7;8,9

To construct an array of arrays from the string representation,

varrows,cols,i,j;rows=str.split(';');for(i=0;i<rows.length;i++){cols=rows[i].split(',');rows[i]=newArray(cols.length);for(j=0;j<cols.length;j++){rows[i][j]=parseFloat(cols[j]);}}

Matrix.prototype.toJSON()

Returns a JSON representation of a Matrix. JSON#stringify implicitly calls this method when stringifying a Matrix instance.

vardata=newInt8Array(10);for(vari=0;i<data.length;i++){data[i]=i;}varmat=matrix(data,[5,2]);/*	[ 0 1 2 3 4 5 6 7 8 9 ]*/varjson=mat.toJSON();/*	{ "type": "Matrix", "dtype": "int8", "shape": [5,2], "offset": 0, "strides": [2,1], "raw": false, "data": [0,1,2,3,4,5,6,7,8,9]	}*/

To a revive a Matrix from a JSON string,

// Matrix reviver:varreviver=require('dstructs-matrix-reviver');// Stringify a matrix (implicitly calls `.toJSON`):varstr=JSON.stringify(mat);// returns '{"type":"Matrix","dtype":"int8","shape":[5,2],"offset":0,"strides":[2,1],"raw":false,"data":[0,1,2,3,4,5,6,7,8,9]}'// Revive a Matrix from a JSON string:varmat=JSON.parse(str,reviver);/*	[ 0 1 2 3 4 5 6 7 8 9 ]*/

Constructor

A Matrix has a constructor having the following interface...

mat.constructor( data, dtype, shape, offset, strides )

Creates a new Matrix having a specified shape, offset, strides, dtype, and underlying typed data store.

vardata=newFloat32Array(10);varmat1=matrix(data,[5,2]);/*	[ 0 0 0 0 0 0 0 0 0 0 ]*/varmat2=newmat1.constructor(data,mat1.dtype,[2,5],0,[5,1]);/*	[ 0 0 0 0 0 0 0 0 0 0 ]*/

Note: while more performant, constructing a Matrix in this manner should be carefully considered. Arguments are not validated or sanity checked.


Raw

For performance, a lower-level interface is provided which forgoes some of the guarantees of the above API, such as input argument validation and measures to prevent Matrices from becoming corrupted. While use of the above API is encouraged in REPL environments, use of the lower-level interface may be warranted when arguments are of a known type or when many Matrices must be created.

matrix.raw( [data,] shape[, dtype] )

Creates a new Matrix having a specified shape.

vardata=newFloat32Array(10);varmat=matrix.raw(data,[5,2]);/*	[ 0 0 0 0 0 0 0 0 0 0 ]*/

If the input data type is known, Matrix creation is significantly faster.

varmat=matrix.raw(data,[5,2],'float32');/*	[ 0 0 0 0 0 0 0 0 0 0 ]*/

Notes:

  • The shape and dtype parameters are the same as for the higher-level Matrix interface.
  • Specifying a dtype does not cast the data to a different storage type. Instead, providing the argument circumvents the need to determine the input data type, resulting in increased performance.
  • Input datamust be a typed array. Unlike the higher-level Matrix interface, plain arrays are not cast to float64. Providing a plain array can lead to subtle bugs and affect performance.
  • Matrix properties and methods are the same as for the higher-level API, with the exception that Matrix properties are no longer read-only and methods do not perform input argument validation.
  • Setting properties is not recommended as the Matrix can become corrupted; e.g., incompatible dimensions, out-of-bounds indexing, etc. In contrast to the strict API above, setting Matrix properties will not result in an error being thrown. Accordingly, property modification may introduce silent bugs.
  • The lower-level Matrix constructor has the same interface as the higher-level Matrix constructor.

Notes

Linear Indexing

A linear index corresponds to an element position in a flattened Matrix arranged in row-major order. For example, consider a zero-filled 5x2 matrix, its subscripts, and its corresponding linear indices.

/*	Matrix Subscripts Indices	[ 0 0 [ a00 a01 [ 0 1 0 0 a10 a11 2 3A = 0 0 => a20 a21 => 4 5 0 0 a30 a31 6 7 0 0 ] a40 a41 ] 8 9 ]*/

Examples

varmatrix=require('dstructs-matrix');// Create a new 2x2 matrix:varmat=matrix([2,2]);console.log(mat);// Inspect the initialized matrix elements:console.log(mat.get(1,1));// Set a matrix element:console.log(mat.set(1,1,5));// Confirm that the matrix element was set:console.log(mat.get(1,1));// Convert the matrix to a string:console.log(mat.toString());// Convert the matrix to JSON:console.log(mat.toJSON());

To run the example code from the top-level application directory,

$ node ./examples/index.js

Tests

Unit

Unit tests use the Mocha test framework with Chai assertions. To run the tests, execute the following command in the top-level application directory:

$ make test

All new feature development should have corresponding unit tests to validate correct functionality.

Test Coverage

This repository uses Istanbul as its code coverage tool. To generate a test coverage report, execute the following command in the top-level application directory:

$ make test-cov

Istanbul creates a ./reports/coverage directory. To access an HTML version of the report,

$ make view-cov

License

MIT license.

Copyright

Copyright © 2015. The Compute.io Authors.

Releases

Packages

Used by

Contributors

Languages