Skip to content

Commit

Permalink
Merge pull request #1 from compute-io/develop
Browse files Browse the repository at this point in the history
Adds accessor and copy options. Updates according to module spec.
  • Loading branch information
kgryte committed Mar 16, 2015
2 parents c9e4353 + 7ce2ebe commit a909493
Show file tree
Hide file tree
Showing 6 changed files with 327 additions and 75 deletions.
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2014 Rebekah Smith.
Copyright (c) 2014-2015 Rebekah Smith.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.
64 changes: 49 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Moving Sum
===
[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Coverage Status][coveralls-image]][coveralls-url] [![Dependencies][dependencies-image]][dependencies-url]

> Computes a moving sum over a numeric array.
> Computes a moving sum over an array.

## Installation
Expand All @@ -20,36 +20,70 @@ For use in the browser, use [browserify](https://github.com/substack/node-browse
var msum = require( 'compute-msum' );
```

#### msum( arr, window )
#### msum( arr, window[, options] )

Slides a `window` over a numeric `array` to compute a moving sum.
Slides a `window` over an `array` to compute a moving sum. For numeric `arrays`,

``` javascript
var data = [ 1, 2, 3, 4, 5 ];
var arr = [ 1, 2, 3, 4, 5 ];

msum( data, 2 );
var values = msum( arr, 2 );
// returns [ 3, 5, 7, 9 ]
```

The function accepts two `options`:

* __copy__: `boolean` indicating whether to return a new `array` containing the computed sums. Default: `true`.
* __accessor__: accessor `function` for accessing values in object `arrays`.

To mutate the input `array` (e.g., when input values can be discarded or when optimizing memory usage), set the `copy` option to `false`.

``` javascript
var arr = [ 1, 2, 3, 4, 5 ];

var values = msum( arr, 2, {
'copy': false
});
// returns [ 3, 5, 7, 9 ]

console.log( arr === values );
// returns true
```

Note: the returned `array` has length `L - W + 1`, where `L` is the length of the input `array` and `W` is the `window` size.
For non-numeric `arrays`, provide an accessor `function` for accessing numeric `array` values.

``` javascript
var arr = [
{'x':1},
{'x':2},
{'x':3},
{'x':4}
];

function getValue( d ) {
return d.x;
}

var values = msum( arr, 2, {
'accessor': getValue
});
// returns [ 3, 5, 7 ]
```

__Note__: the returned `array` has length `L - W + 1`, where `L` is the length of the input `array` and `W` is the `window` size.


## Examples

``` javascript
var msum = require( 'compute-msum' );

// Simulate some data...
var data = new Array( 50 );

for ( var i = 0; i < data.length; i++ ) {
data[ i ] = Math.random() * 100;
}

// Compute the moving sum:
var arr = msum( data, 7 );

console.log( arr.join( '\n' ) );
var values = msum( data, 8 );
console.log( values.join( '\n' ) );
```

To run the example code from the top-level application directory,
Expand Down Expand Up @@ -95,7 +129,7 @@ $ make view-cov

## Copyright

Copyright &copy; 2014. Rebekah Smith.
Copyright &copy; 2014-2015. Rebekah Smith.


[npm-image]: http://img.shields.io/npm/v/compute-msum.svg
Expand All @@ -114,4 +148,4 @@ Copyright &copy; 2014. Rebekah Smith.
[dev-dependencies-url]: https://david-dm.org/dev/compute-io/msum

[github-issues-image]: http://img.shields.io/github/issues/compute-io/msum.svg
[github-issues-url]: https://github.com/compute-io/msum/issues
[github-issues-url]: https://github.com/compute-io/msum/issues
11 changes: 4 additions & 7 deletions examples/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
'use strict';

var msum = require( './../lib' );

// Simulate some data...
var data = new Array( 50 );

for ( var i = 0; i < data.length; i++ ) {
data[ i ] = Math.random() * 100;
}

// Compute the moving sum:
var arr = msum( data, 7 );

console.log( arr.join( '\n' ) );
var values = msum( data, 8 );
console.log( values.join( '\n' ) );
151 changes: 111 additions & 40 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
*
*
* DESCRIPTION:
* - Compute a moving sum over a numeric array.
* - Compute a moving sum over an array.
*
*
* NOTES:
* [1]
* [1]
*
*
* TODO:
* [1]
* [1]
*
*
* LICENSE:
Expand All @@ -26,55 +26,126 @@
*
*/

(function() {
'use strict';
'use strict';

// MOVING SUM //
// MODULES //

/**
* FUNCTION: msum( arr , window )
* Computes a moving sum over an array of numeric values.
*
* @param {Array} arr - array of data values
* @param {Number} window - size of moving window
* @returns {Array} array of window sum values
*/
function msum( arr , W ) {
if ( !Array.isArray( arr ) ) {
throw new TypeError( 'msum()::invalid input argument. Must provide an array.' );
var isArray = require( 'validate.io-array' ),
isObject = require( 'validate.io-object' ),
isBoolean = require( 'validate.io-boolean-primitive' ),
isPositiveInteger = require( 'validate.io-positive-integer' ),
isFunction = require( 'validate.io-function' );


// MOVING SUM //

/**
* FUNCTION: msum( arr, W[, options] )
* Computes a moving sum over an array.
*
* @param {Array} arr - input array
* @param {Number} W - size of moving window
* @param {Object} [options] - function options
* @param {Function} [options.accessor] - accessor function for accessing numeric values
* @param {Boolean} [options.copy=true] - boolean indicating whether to return a new array of window sums
* @returns {Array} array of window sum values
*/
function msum( arr, W, options ) {
var copy = true,
clbk,
len,
sum,
dropVal,
out,
i;
if ( !isArray( arr ) ) {
throw new TypeError( 'msum()::invalid input argument. Must provide an array. Value: `' + arr + '`.' );
}
if ( !isPositiveInteger( W ) ) {
throw new TypeError( 'msum()::invalid input argument. Window must be a positive integer. Value: `' + W + '`.' );
}
if ( arguments.length > 2 ) {
if ( !isObject( options ) ) {
throw new TypeError( 'msum()::invalid input argument. Options must be an object. Value: `' + options + '`.' );
}
if ( typeof W !== 'number' || W !== W ) {
throw new TypeError( 'msum()::invalid input argument. Window must be numeric.' );
}
if ( Math.floor( W ) !== W || W < 1 ) {
throw new TypeError( 'msum()::invalid input argument. Window must be a positive integer.' );
}
if ( W > arr.length ) {
throw new Error( 'msum()::invalid input argument. Window cannot exceed the array length.' );
if ( options.hasOwnProperty( 'accessor' ) ) {
clbk = options.accessor;
if ( !isFunction( clbk ) ) {
throw new TypeError( 'msum()::invalid option. Accessor option must be a function. Value: `' + clbk + '`.' );
}
}
var len = arr.length,
out = new Array( len - W + 1 ),
sum = 0,
k;
if ( options.hasOwnProperty( 'copy' ) ) {
copy = options.copy;
if ( !isBoolean( copy ) ) {
throw new TypeError( 'msum()::invalid option. Copy option must be a boolean primitive. Value: `' + copy + '`.' );
}
}
}
if ( W > arr.length ) {
throw new Error( 'msum()::invalid input argument. Window cannot exceed the array length.' );
}
len = arr.length;
sum = 0;

if ( copy && !clbk ) {
// Case 1: numeric array and return a copy...
len = len - W + 1;
out = new Array( len );

// Compute the sum for the first window...
for ( var i = 0; i < W; i++ ) {
// Calculate the sum for the first window...
for ( i = 0; i < W; i++ ) {
sum += arr[ i ];
}
out[ 0 ] = sum;

// Compute the sum for the remaining windows...
for ( var j = W; j < len; j++ ) {
k = j - W;
sum += arr[ j ] - arr[ k ];
out[ k+1 ] = sum;
// Calculate sums for the remaining windows...
for ( i = 0; i < len-1; i++ ){
sum += arr[ i+W ] - arr[ i ];
out[ i+1 ] = sum;
}
return out;
} // end FUNCTION msum()
}
else if ( clbk ) {
if ( copy ) {
// Case 2: non-numeric array and return a copy...
out = new Array( len );
for ( i = 0; i < len; i++ ){
out[ i ] = clbk( arr[i] );
}
} else {
// Case 3: non-numeric array and mutate the input array...
out = arr;
for ( i = 0; i < len; i++ ) {
out[ i ] = clbk( arr[i] );
}
}
}
else {
// Case 4: numeric array and mutate the input array...
out = arr;
}
len = len - W + 1;

// Calculate the sum for the first window...
for ( i = 0; i < W; i++ ) {
sum += out[ i ];
}
dropVal = out[ 0 ];
out[ 0 ] = sum;

// Calculate sums for the remaining windows...
for ( i = 1; i < len; i++ ){
sum += out[ i+W-1 ] - dropVal;
dropVal = out[ i ];
out[ i ] = sum;
}
// Trim the output array:
out.length = len;
return out;
} // end FUNCTION msum()


// EXPORTS //
// EXPORTS //

module.exports = msum;
module.exports = msum;

})();
12 changes: 9 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "compute-msum",
"version": "1.0.0",
"description": "Computes a moving sum over a numeric array.",
"description": "Computes a moving sum over an array.",
"author": {
"name": "Rebekah Smith",
"email": "rebekahjs17@gmail.com"
Expand Down Expand Up @@ -38,13 +38,19 @@
"sum",
"moving",
"window",
"sliding"
"sliding",
"array",
"numeric array"
],
"bugs": {
"url": "https://github.com/compute-io/msum/issues"
},
"dependencies": {
"validate.io-array": "^1.0.3"
"validate.io-array": "^1.0.3",
"validate.io-boolean-primitive": "^1.0.0",
"validate.io-function": "^1.0.2",
"validate.io-object": "^1.0.3",
"validate.io-positive-integer": "^1.0.0"
},
"devDependencies": {
"chai": "2.x.x",
Expand Down

0 comments on commit a909493

Please sign in to comment.