Skip to content

Commit

Permalink
[UPDATE] subseq get/set. Allow setting a single numeric value, matrix…
Browse files Browse the repository at this point in the history
… of values, or via a clbk.
  • Loading branch information
kgryte committed May 30, 2015
1 parent ed858a4 commit d5419c1
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 36 deletions.
15 changes: 12 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,17 @@ mat.iset( 7, 25 );
*/
```

__Note__: out-of-bounds subscripts will silently fail.
__Note__: out-of-bounds indices will silently fail.


<a name="matrix-sset"></a>
#### mat.sset( subsequence, value[, thisArg] )

Sets `Matrix` elements according to a specified [subsequence](https://github.com/compute-io/indexspace).

``` javascript

```


<a name="matrix-get"></a>
Expand Down Expand Up @@ -258,7 +267,7 @@ var value = mat.iget( 7 );
// returns 7
```

__Note__: out-of-bounds subscripts will return a value of `undefined`.
__Note__: out-of-bounds indices will return a value of `undefined`.


===
Expand Down Expand Up @@ -347,7 +356,7 @@ var mat = matrix.raw( data, [5,2], 'float32' );

#### Linear Indexing

A linear `index` corresponds to an element position in a flattened `Matrix` arranged in __row-major__ order. For example, consider an empty 5x2 matrix, its subscripts, and its corresponding linear indices.
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.

``` javascript
/*
Expand Down
8 changes: 6 additions & 2 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ TODO
3. if provided `data` and not a `dtype`, should determine the type from the `data`
4. set/get api
- `sset`, `sget`
- handle empty subsequence; empty matrix?
- warn that set values get cast to target matrix dtype
- `mset`, `mget`
- use linear index
5.
5. `toString` method
6. `toArray` method (???)
7.
8. should we allow negative indices for `iset`, `iget`, etc?
9. should `set` methods return the `Matrix` instance to allow for method chaining?
10.

2 changes: 1 addition & 1 deletion examples/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ console.log( mat );
console.log( mat.get( 1, 1 ) );

// Set a matrix element:
console.log( mat.set( 1, 1, 5 ) );
mat.set( 1, 1, 5 );

// Confirm that the matrix element was set:
console.log( mat.get( 1, 1 ) );
Expand Down
6 changes: 3 additions & 3 deletions lib/matrix.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// MODULES //

var isString = require( 'validate.io-string-primitive' ),
isPositiveIntegerArray = require( 'validate.io-positive-integer-array' ),
isNonNegativeIntegerArray = require( 'validate.io-nonnegative-integer-array' ),
contains = require( 'validate.io-contains' ),
getType = require( './getType.js' ),
Matrix = require( './ctor.js' );
Expand Down Expand Up @@ -61,8 +61,8 @@ function matrix() {
}

// Input argument validation...
if ( !isPositiveIntegerArray( shape ) ) {
throw new TypeError( 'matrix()::invalid input argument. A matrix shape must be an array of positive integers. Value: `' + shape + '`.' );
if ( !isNonNegativeIntegerArray( shape ) ) {
throw new TypeError( 'matrix()::invalid input argument. A matrix shape must be an array of nonnegative integers. Value: `' + shape + '`.' );
}
ndims = shape.length;
if ( ndims !== 2 ) {
Expand Down
18 changes: 9 additions & 9 deletions lib/sget.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,19 @@ function sget( seq ) {
nCols = cols.length;
len = nRows * nCols;

// TODO: handle empty results. Return empty matrix?

d = new BTYPES[ this.dtype ]( len );
mat = new this.constructor( d, [nRows,nCols], this.dtype );

s0 = this.strides[ 0 ];
s1 = this.strides[ 1 ];
s2 = mat.strides[ 0 ];
s3 = mat.strides[ 1 ];
if ( len ) {
s0 = this.strides[ 0 ];
s1 = this.strides[ 1 ];
s2 = mat.strides[ 0 ];
s3 = mat.strides[ 1 ];

for ( i = 0; i < nRows; i++ ) {
for ( j = 0; j < nCols; j++ ) {
d[ i*s2 + j*s3 ] = this.data[ rows[i]*s0 + cols[j]*s1 ];
for ( i = 0; i < nRows; i++ ) {
for ( j = 0; j < nCols; j++ ) {
d[ i*s2 + j*s3 ] = this.data[ rows[i]*s0 + cols[j]*s1 ];
}
}
}
return mat;
Expand Down
70 changes: 53 additions & 17 deletions lib/sset.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,33 @@
// MODULES //

var isString = require( 'validate.io-string-primitive' ),
isNumber = require( 'validate.io-number-primitive' ),
isFunction = require( 'validate.io-function' ),
ispace = require( 'compute-indexspace' );


// SUBSEQUENCE SET //

/**
* FUNCTION: sset( subsequence, matrix )
* FUNCTION: sset( subsequence, value[, thisArg] )
* Sets matrix elements according to a specified subsequence.
*
* @param {String} subsequence - subsequence string
* @param {Matrix} matrix - matrix containing the values to set
* @param {Number|Matrix|Function} value - either a single numeric value, a matrix containing the values to set, or a function which returns a numeric value
* @returns {Matrix} Matrix instance
*/
function sset( seq, mat ) {
function sset( seq, val, thisArg ) {
/* jshint validthis: true */
var nRows,
nCols,
clbk,
rows,
cols,
seqs,
mat,
ctx,
s0, s1, s2, s3,
idx,
i, j;

if ( !isString( seq ) ) {
Expand All @@ -33,30 +39,60 @@ function sset( seq, mat ) {
if ( seqs.length !== 2 ) {
throw new Error( 'sset()::invalid input argument. Subsequence string must specify row and column subsequences. Value: `' + seq + '`.' );
}

// TODO: handle empty input matrix?

if ( isFunction( val ) ) {
clbk = val;
}
else if ( !isNumber( val ) ) {
mat = val;
}
rows = ispace( seqs[ 0 ], this.shape[ 0 ] );
cols = ispace( seqs[ 1 ], this.shape[ 1 ] );

nRows = rows.length;
nCols = cols.length;

if ( nRows !== mat.shape[ 0 ] ) {
throw new Error( 'sset()::invalid input arguments. Row subsequence does not match input matrix dimensions. Expected a [' + nRows + ',' + nCols + '] matrix and instead received a [' + mat.shape.join( ',' ) + '] matrix.' );
if ( !( nRows && nCols ) ) {
return this;
}
if ( nCols !== mat.shape[ 1 ] ) {
throw new Error( 'sset()::invalid input arguments. Column subsequence does not match input matrix dimensions. Expected a [' + nRows + ',' + nCols + '] matrix and instead received a [' + mat.shape.join( ',' ) + '] matrix.' );
}

s0 = this.strides[ 0 ];
s1 = this.strides[ 1 ];
s2 = mat.strides[ 0 ];
s3 = mat.strides[ 1 ];

for ( i = 0; i < nRows; i++ ) {
for ( j = 0; j < nCols; j++ ) {
this.data[ rows[i]*s0 + cols[j]*s1 ] = mat.data[ i*s2 + j*s3 ];
// Callback...
if ( clbk ) {
if ( arguments.length > 3 ) {
ctx = thisArg;
} else {
ctx = this;
}
for ( i = 0; i < nRows; i++ ) {
for ( j = 0; j < nCols; j++ ) {
idx = rows[i]*s0 + cols[j]*s1;
this.data[ idx ] = clbk.call( ctx, this.data[ idx ], rows[i], cols[j], idx );
}
}
}
// Input matrix...
else if ( mat ) {
if ( nRows !== mat.shape[ 0 ] ) {
throw new Error( 'sset()::invalid input arguments. Row subsequence does not match input matrix dimensions. Expected a [' + nRows + ',' + nCols + '] matrix and instead received a [' + mat.shape.join( ',' ) + '] matrix.' );
}
if ( nCols !== mat.shape[ 1 ] ) {
throw new Error( 'sset()::invalid input arguments. Column subsequence does not match input matrix dimensions. Expected a [' + nRows + ',' + nCols + '] matrix and instead received a [' + mat.shape.join( ',' ) + '] matrix.' );
}
s2 = mat.strides[ 0 ];
s3 = mat.strides[ 1 ];
for ( i = 0; i < nRows; i++ ) {
for ( j = 0; j < nCols; j++ ) {
this.data[ rows[i]*s0 + cols[j]*s1 ] = mat.data[ i*s2 + j*s3 ];
}
}
}
// Single numeric value...
else {
for ( i = 0; i < nRows; i++ ) {
for ( j = 0; j < nCols; j++ ) {
this.data[ rows[i]*s0 + cols[j]*s1 ] = val;
}
}
}
return this;
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@
"compute-indexspace": "^1.0.1",
"type-name": "^1.0.1",
"validate.io-contains": "^1.0.0",
"validate.io-positive-integer-array": "^1.0.0",
"validate.io-function": "^1.0.2",
"validate.io-nonnegative-integer-array": "^1.0.1",
"validate.io-number-primitive": "^1.0.0",
"validate.io-string-primitive": "^1.0.0"
},
"devDependencies": {
Expand Down

0 comments on commit d5419c1

Please sign in to comment.