Matrix
Matrices.
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.
Installation
$ npm install dstructs-matrix
For use in the browser, use browserify.
Usage
var matrix = ;
matrix( [data,] shape[, dtype] )
Creates a new Matrix
having a specified shape
(dimensions => [rows,cols]
).
var mat = ;/*[ 0 00 00 0 ]*/
By default, the matrix elements are floating-point 64-bit numbers (float64
). To specify a different data type, provide a dtype
.
var mat = ;/*[ 0 00 0 ]*/
The following dtypes
are accepted:
int8
uint8
uint8_clamped
int16
uint16
int32
uint32
float32
float64
If a linear numeric 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
.
var data = 6 ;for var i = 0; i < datalength; i++data i = i;var mat = ; // 2*3 = 6/*[ 0 1 23 4 5 ]*/
To cast an input data
array to a different data type, provide a dtype
.
var mat = ;/*[ 0 12 3 ]*/
If provided an Array
instead of a typed array and no dtype
is specified, the input data
array is cast to float64
.
var data = 10 20 30 40 50 60 ;var mat = ;/*[ 10 2030 4050 60 ]*/var dtype = matdtype;// returns 'float64'
Properties
A Matrix
has the following properties...
dtype
A read-only property returning the underlying storage data type.
var dtype = matdtype;// returns <string>
ndims
A read-only property returning the number of dimensions.
var ndims = matndims;// returns 2
shape
A read-only property returning the matrix shape
.
var shape = matshape;// returns [...]
offset
A property returning the offset
used to index into the underlying data store.
var offset = matoffset;// 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.
var strides = matstrides;// 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
.
var len = matlength;// 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.
var data = 10 ;var mat = ;/*[ 0 0 0 0 0 0 0 0 0 0 ]*/var value = mat;// returns 0value = mat 3 ;// returns undefined
nbytes
A read-only property returning the number of bytes consumed by the Matrix
elements.
var nbytes = matnbytes;// returns <number>
data
A read-only property pointing to the underlying storage array.
var data = matdata;// 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;/*[ 0 12 34 56 208 9 ]*/
Set methods return the Matrix
instance and are thus chainable.
mat;// 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;/*[ 0 12 34 56 258 9 ]*/mat;/*[ 0 12 34 56 208 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
.
var data = 10*10 ;for var i = 0; i < datalength; i++data i = i;// Create a 10x10 matrix:var mat = ;var submat = mat;/*[ 1 4 521 24 2541 44 45 ]*/mat;submat = mat;/*[ 5 5 55 5 55 5 5 ]*/var zeros = ;/*[ 0 0 0 ]*/mat;submat = mat;/*[ 5 5 50 0 05 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.
{return '' + j + i;}mat;mat;/*[ 10 40 500 0 05 5 5 ]*/
By default, the callback this
context is set to the Matrix
instance. To specify a different this
context, provide a thisArg
.
{console;// returns nullreturn '' + j + i;}mat;
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 alength
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
.
var data = 10*10 ;for var i = 0; i < datalength; i++data i = i;// Create a 10x10 matrix:var mat = ;var submat = mat;/*[ 35 36 37 3845 46 47 4855 56 57 5865 66 67 68 ]*/var zeros = ;/*[ 0 00 0 ]*/mat;submat = mat;/*[ 35 36 37 3845 0 0 4855 0 0 5865 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.
{return '' + j + i;}mat;submat = mat;/*[ 35 36 37 3845 64 74 4855 65 75 5865 66 67 68 ]*/
By default, the callback this
context is set to the Matrix
instance. To specify a different this
context, provide a thisArg
.
{console;// returns nullreturn '' + j + i;}mat;
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.
var data = 10 ;for var i = 0; i < datalength; i++data i = i;var mat = ;/*[ 0 12 34 56 78 9 ]*/var values = mat;// 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.
var value = mat;// returns 7value = mat;// 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.
var data = 10 ;for var i = 0; i < datalength; i++data i = i*2;var mat = ;/*[ 0 24 68 1012 1416 18 ]*/// Scramble the second column:var vals = mat;/*[ 2, 10, 6, 18, 14 ]*/// Extract select rows and columns in arbitrary order:var mat1 = mat;/*[ 4148 ]*/
If idx
and/or cols
is null
, all rows (columns) are extracted.
// Replicate a column:var rep = mat;/*[ 2 2 2 2 26 6 6 6 610 10 10 10 1014 14 14 14 1418 18 18 18 18 ]*/// Tile select rows and columns:var tile = mat;/*[4 6 4 68 10 8 104 6 4 68 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
.
var submatrix;submatrix = mat; // Copy a matrix/*[ 0 12 34 56 78 9 ]*/submatrix = mat;/*[ 2 34 56 7 ]*/submatrix = mat; // flip top-to-bottom/*[ 8 96 74 52 30 1 ]*/submatrix = mat; // flip left-to-right/*[ 1 03 25 47 69 8 ]*/submatrix = mat;/*[]*/
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.
var data = 10 ;for var i = 0; i < datalength; i++data i = i;var mat = ;var str = mat;// 0,1;2,3;4,5;6,7;8,9
To construct an array
of arrays
from the string
representation,
var rowscolsi j;rows = str;for i = 0; i < rowslength; i++cols = rows i ;rows i = colslength ;for j = 0; j < colslength; j++rows i j = ;
Matrix.prototype.toJSON()
Returns a JSON
representation of a Matrix
. JSON#stringify
implicitly calls this method when stringifying a Matrix
instance.
var data = 10 ;for var i = 0; i < datalength; i++data i = i;var mat = ;/*[ 0 12 34 56 78 9 ]*/var json = mat;/*{"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:var reviver = ;// Stringify a matrix (implicitly calls `.toJSON`):var str = JSON;// 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:var mat = JSON;/*[ 0 12 34 56 78 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.
var data = 10 ;var mat1 = ;/*[ 0 00 00 00 00 0 ]*/var mat2 = data mat1dtype 25 0 51 ;/*[ 0 0 0 0 00 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
.
var data = 10 ;var mat = matrix;/*[ 0 00 00 00 00 0 ]*/
If the input data
type is known, Matrix
creation is significantly faster.
var mat = matrix;/*[ 0 00 00 00 00 0 ]*/
Notes:
- The
shape
anddtype
parameters are the same as for the higher-levelMatrix
interface. - Specifying a
dtype
does not cast the data to a different storage type. Instead, providing the argument circumvents the need to determine the inputdata
type, resulting in increased performance. - Input
data
must be a typed array. Unlike the higher-levelMatrix
interface, plainarrays
are not cast tofloat64
. Providing a plainarray
can lead to subtle bugs and affect performance. Matrix
properties and methods are the same as for the higher-level API, with the exception thatMatrix
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, settingMatrix
properties will not result in anerror
being thrown. Accordingly, property modification may introduce silent bugs. - The lower-level
Matrix
constructor has the same interface as the higher-levelMatrix
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 10 0 a10 a11 2 3A = 0 0 => a20 a21 => 4 50 0 a30 a31 6 70 0 ] a40 a41 ] 8 9 ]*/
Examples
var matrix = ;// Create a new 2x2 matrix:var mat = ;console;// Inspect the initialized matrix elements:console;// Set a matrix element:console;// Confirm that the matrix element was set:console;// Convert the matrix to a string:console;// Convert the matrix to JSON:console;
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
Copyright
Copyright © 2015. The Compute.io Authors.