Chris@25: 'use strict'; Chris@25: Chris@25: !function(exports, undefined) { Chris@25: Chris@25: var Chris@25: // If the typed array is unspecified, use this. Chris@25: DefaultArrayType = Float32Array, Chris@25: // Simple math functions we need. Chris@25: sqrt = Math.sqrt, Chris@25: sqr = function(number) {return Math.pow(number, 2)}, Chris@25: // Internal convenience copies of the exported functions Chris@25: isComplexArray, Chris@25: ComplexArray Chris@25: Chris@25: exports.isComplexArray = isComplexArray = function(obj) { Chris@25: return obj !== undefined && Chris@25: obj.hasOwnProperty !== undefined && Chris@25: obj.hasOwnProperty('real') && Chris@25: obj.hasOwnProperty('imag') Chris@25: } Chris@25: Chris@25: exports.ComplexArray = ComplexArray = function(other, opt_array_type){ Chris@25: if (isComplexArray(other)) { Chris@25: // Copy constuctor. Chris@25: this.ArrayType = other.ArrayType Chris@25: this.real = new this.ArrayType(other.real) Chris@25: this.imag = new this.ArrayType(other.imag) Chris@25: } else { Chris@25: this.ArrayType = opt_array_type || DefaultArrayType Chris@25: // other can be either an array or a number. Chris@25: this.real = new this.ArrayType(other) Chris@25: this.imag = new this.ArrayType(this.real.length) Chris@25: } Chris@25: Chris@25: this.length = this.real.length Chris@25: } Chris@25: Chris@25: ComplexArray.prototype.toString = function() { Chris@25: var components = [] Chris@25: Chris@25: this.forEach(function(c_value, i) { Chris@25: components.push( Chris@25: '(' + Chris@25: c_value.real.toFixed(2) + ',' + Chris@25: c_value.imag.toFixed(2) + Chris@25: ')' Chris@25: ) Chris@25: }) Chris@25: Chris@25: return '[' + components.join(',') + ']' Chris@25: } Chris@25: Chris@25: // In-place mapper. Chris@25: ComplexArray.prototype.map = function(mapper) { Chris@25: var Chris@25: i, Chris@25: n = this.length, Chris@25: // For GC efficiency, pass a single c_value object to the mapper. Chris@25: c_value = {} Chris@25: Chris@25: for (i = 0; i < n; i++) { Chris@25: c_value.real = this.real[i] Chris@25: c_value.imag = this.imag[i] Chris@25: mapper(c_value, i, n) Chris@25: this.real[i] = c_value.real Chris@25: this.imag[i] = c_value.imag Chris@25: } Chris@25: Chris@25: return this Chris@25: } Chris@25: Chris@25: ComplexArray.prototype.forEach = function(iterator) { Chris@25: var Chris@25: i, Chris@25: n = this.length, Chris@25: // For consistency with .map. Chris@25: c_value = {} Chris@25: Chris@25: for (i = 0; i < n; i++) { Chris@25: c_value.real = this.real[i] Chris@25: c_value.imag = this.imag[i] Chris@25: iterator(c_value, i, n) Chris@25: } Chris@25: } Chris@25: Chris@25: ComplexArray.prototype.conjugate = function() { Chris@25: return (new ComplexArray(this)).map(function(value) { Chris@25: value.imag *= -1 Chris@25: }) Chris@25: } Chris@25: Chris@25: // Helper so we can make ArrayType objects returned have similar interfaces Chris@25: // to ComplexArrays. Chris@25: function iterable(obj) { Chris@25: if (!obj.forEach) Chris@25: obj.forEach = function(iterator) { Chris@25: var i, n = this.length Chris@25: Chris@25: for (i = 0; i < n; i++) Chris@25: iterator(this[i], i, n) Chris@25: } Chris@25: Chris@25: return obj Chris@25: } Chris@25: Chris@25: ComplexArray.prototype.magnitude = function() { Chris@25: var mags = new this.ArrayType(this.length) Chris@25: Chris@25: this.forEach(function(value, i) { Chris@25: mags[i] = sqrt(sqr(value.real) + sqr(value.imag)) Chris@25: }) Chris@25: Chris@25: // ArrayType will not necessarily be iterable: make it so. Chris@25: return iterable(mags) Chris@25: } Chris@25: }(typeof exports === 'undefined' && (this.complex_array = {}) || exports)