Created
June 2, 2012 06:56
-
-
Save kaizhu256/2857043 to your computer and use it in GitHub Desktop.
javascript my.Complex2 - 2d complex array class
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//// Complex2 - core | |
my.Complex2 = my.Complex2 || function(xxyy, ll2) { | |
var self; self = this; | |
if(!(self instanceof my.Complex2)) {return new my.Complex2(xxyy, ll2);} | |
if(ll2) { | |
if(typeof ll2 === 'number') {xxyy = [my.Array2(xxyy, ll2), my.Array2(xxyy, ll2)];} | |
} | |
self[0] = xxyy[0]; self[1] = xxyy[1]; | |
my.ooEach( | |
2, | |
function(ii) { | |
if(!self[ii]) { | |
self[ii] = my.Array2(self[ii ^ 1]); | |
self[ii].arr = new window.Float64Array(self[ii].arr.length); | |
} | |
} | |
); | |
}; | |
my.Complex2.iter0 = function(self, ll2) { | |
var ii1, ii2, ll1, out, stride1, stride2, xx, yy; if(self === undefined) {return;} | |
if(typeof self === 'function') {return self;} | |
//// OPTIMIZATION - single element array | |
if(self[0].ll1 <= 1 && self[0].ll2 <= 1) { | |
self = [self[0][self[0].offset], self[1][self[1].offset]]; | |
} | |
if(Array.isArray(self)) {return function() {return self;};} | |
out = [null, null]; xx = self[0].arr; yy = self[1].arr; self = self[0]; | |
//// OPTIMIZATION - repeat single col * ll2 | |
if(self.ll2 <= 1 && 1 < ll2) { | |
stride1 = self.stride1; ii1 = self.offset; ii2 = -1; | |
return function() { | |
ii2 += 1; if(ii2 >= ll2) {ii1 += stride1; ii2 = 0;} | |
out[0] = xx[ii1]; out[1] = yy[ii1]; return out; | |
}; | |
} | |
stride1 = self.stride1; ll1 = self.offset + self.ll1 * stride1; ii1 = self.offset; | |
stride2 = self.stride2; ll2 = self.offset + self.ll2 * stride2; ii2 = self.offset - stride2; | |
//// OPTIMIZATION - repeat single row * ll1 | |
if(self.ll1 <= 1) { | |
return function() { | |
ii2 += stride2; if(ii2 >= ll2) {ii2 = ii1;} | |
out[0] = xx[ii2]; out[1] = yy[ii2]; return out; | |
}; | |
} | |
//// OPTIMIZATION - one dimensional | |
if(self.is1D()) { | |
stride2 = self.is1D(); ii2 = self.offset - stride2; | |
return function() {ii2 += stride2; out[0] = xx[ii2]; out[1] = yy[ii2]; return out;}; | |
} | |
//// default case | |
return function() { | |
ii2 += stride2; if(ii2 >= ll2) {ii1 += stride1; ii2 = ii1; ll2 += stride1;} | |
out[0] = xx[ii2]; out[1] = yy[ii2]; return out; | |
}; | |
}; | |
my.Complex2.prototype.conjugate = function() {this[0].neg(); return this;}; | |
my.Complex2.prototype.fft = function(mode) { | |
var aa, cc, ee, ee0, ii, ii1, ii2, jj, jj2, kk, ll1, ll2, mm, nn, nn1, nn2, offset, | |
self, ss, stride1, stride2, tt1, tt2, xx, yy; | |
self = this[0]; ll1 = self.ll1; ll2 = self.ll2; offset = self.offset; | |
stride1 = self.stride1; stride2 = self.stride2; xx = this[0].arr; yy = this[1].arr; | |
//// inplace bit-reverse | |
jj = 0; nn = ll2 * stride2; nn2 = nn >> 1; | |
for (ii = stride2; ii < nn - stride2; ii += stride2) { | |
nn1 = nn2; while (jj >= nn1) {jj -= nn1; nn1 >>= 1;} jj += nn1; | |
if (ii < jj) { | |
ii2 = ii + offset; jj2 = jj + offset; | |
for(ii1 = 0; ii1 < ll1; ii1 += 1) { | |
tt1 = xx[ii2]; xx[ii2] = xx[jj2]; xx[jj2] = tt1; | |
tt1 = yy[ii2]; yy[ii2] = yy[jj2]; yy[jj2] = tt1; | |
ii2 += stride1; jj2 += stride1; | |
} | |
} | |
} | |
//// inplace fft | |
ee0 = -6.283185307179586; if(mode === 'reverse') {ee0 = -ee0; this.mul(1 / ll2);} | |
for(mm = 0; (1 << mm) < ll2; mm += 1) {;} nn1 = 0; nn2 = stride2; | |
for (ii = 0; ii < mm; ii += 1) { | |
nn1 = nn2; nn2 <<= 1; ee = ee0 * (stride2 / nn2); aa = 0.0; | |
for (jj = 0; jj < nn1; jj += stride2) { | |
cc = Math.cos(aa); ss = Math.sin(aa); aa += ee; | |
for (kk = jj; kk < nn; kk += nn2) { | |
ii2 = kk + offset; jj2 = kk + nn1 + offset; | |
for(ii1 = 0; ii1 < ll1; ii1 += 1) { | |
tt1 = cc * xx[jj2] - ss * yy[jj2]; tt2 = ss * xx[jj2] + cc * yy[jj2]; | |
xx[jj2] = xx[ii2] - tt1; yy[jj2] = yy[ii2] - tt2; xx[ii2] += tt1; yy[ii2] += tt2; | |
ii2 += stride1; jj2 += stride1; | |
} | |
} | |
} | |
} | |
return this; | |
}; | |
my.Complex2.prototype.get = function(ii1, ii2) { | |
if(arguments.length <= 1) {return my.Complex2([this[0].get(ii1), this[1].get(ii1)]);} | |
return [this[0].get(ii1, ii2), this[1].get(ii1, ii2)]; | |
}; | |
my.Complex2.prototype.jsonStringify = function(mode) { | |
var out; out = [this[0].jsonStringify('checkOnly'), this[1].jsonStringify('checkOnly')]; | |
return mode === 'checkOnly' ? out : my.jsonStringify(out); | |
}; | |
my.Complex2.prototype.length = 2; | |
my.Complex2.prototype.set = function(ii1, ii2, oo) { | |
var xx, yy; xx = arguments[arguments.length - 1]; yy = xx[1]; xx = xx[0]; | |
switch(arguments.length) { | |
case 1: this[0].set(xx); this[1].set(yy); break; | |
case 2: this[0].set(ii1, xx); this[1].set(ii1, yy); break; | |
default: this[0].set(ii1, ii2, xx); this[1].set(ii1, ii2, yy); | |
} | |
return this; | |
}; | |
my.Complex2.prototype._each = function(aa, bb) { | |
var aaNext, aaXx, aaYy, bbNext, bbXx, bbYy, | |
ii1, ii2, ll1, ll2, self, stride1, stride2, tmp, xx, xx2, yy, yy2; self = this[0]; | |
aaNext = my.Complex2.iter0(aa, this[0].ll2); bbNext = my.Complex2.iter0(aa, this[0].ll2); | |
xx = this[0].arr; yy = this[1].arr; | |
//// OPTIMIZATION - one dimensional | |
if(self.is1D()) { | |
stride2 = self.is1D(); ll2 = self.offset + self.ll1 * self.ll2 * stride2; | |
for(ii2 = self.offset; ii2 < ll2; ii2 += stride2) { | |
xx2 = xx[ii2]; yy2 = yy[ii2]; this(); | |
} | |
return this; | |
} | |
stride1 = self.stride1; ll1 = self.offset + self.ll1 * stride1; | |
stride2 = self.stride2; ll2 = self.offset + self.ll2 * stride2; | |
for(ii1 = self.offset; ii1 < ll1; ii1 += stride1) { | |
for(ii2 = ii1; ii2 < ll2; ii2 += stride2) { | |
xx2 = xx[ii2]; yy2 = yy[ii2]; this(); | |
} | |
ll2 += stride1; | |
} | |
return this; | |
}; | |
my.Complex2.prototype._reduce = function(aa, bb) { | |
var aaNext, bbNext, ii1, ii2, ll1, ll2, self, stride1, tmp, xx, yy; self = this[0]; | |
stride1 = self.stride1; | |
ll1 = self.offset + self.ll1 * stride1; | |
ll2 = Math.max(aa[0].ll2 || 0, (bb && bb[0] && bb[0].ll2) || 0); | |
aaNext = my.Complex2.iter0(aa, ll2); bbNext = my.Complex2.iter0(bb, ll2); | |
xx = this[0].arr; yy = this[1].arr; | |
for(ii1 = self.offset; ii1 < ll1; ii1 += stride1) { | |
xx[ii1] = 0; for(ii2 = 0; ii2 < ll2; ii2 += 1) {this();} | |
} | |
return this; | |
}; | |
## Complex2 - extra | |
## op | |
my.ooEach();: | |
{},: | |
'abs': 'xx[ii2] = Math.sqrt(xx2 * xx2 + yy2 * yy2); yy[ii2] = 0;', | |
'abs2': 'xx[ii2] = xx2 * xx2 + yy2 * yy2; yy[ii2] = 0;', | |
'add': 'aa = aaNext(); xx[ii2] += aa[0]; yy[ii2] += aa[1];', | |
'div': | |
'aa = aaNext(); tmp = 1 / (aa[0] * aa[0] + aa[1] * aa[1]);' + | |
'xx[ii2] = tmp * (yy2 * aa[1] + xx2 * aa[0]);' + | |
'yy[ii2] = tmp * (yy2 * aa[0] - xx2 * aa[1]);', | |
'exp': | |
'xx2 = Math.exp(xx2); xx[ii2] = xx2 * Math.cos(yy2); yy[ii2] = xx2 * Math.sin(yy2);', | |
'inv': | |
'yy[ii2] = 1 / (xx2 * xx2 + yy2 * yy2);' + | |
'xx[ii2] *= yy[ii2]; yy[ii2] *= -yy2;', | |
'mul': | |
'aa = aaNext();' + | |
'xx[ii2] = xx2 * aa[0] - yy2 * aa[1]; yy[ii2] = xx2 * aa[1] + yy2 * aa[0];', | |
'sqd': 'xx[ii2] = xx2 * xx2 - yy2 * yy2; yy[ii2] = 2 * xx2 * yy2;', | |
'sub': 'aa = aaNext(); xx[ii2] -= aa[0]; yy[ii2] -= aa[1];' | |
function(vv, kk) {}: | |
my.SOURCE_EXTRA += | |
'my.Complex2.prototype.' + kk + 'C = ' + | |
my.Complex2.prototype._each.toString().replace(r'/this\(\);/g', vv) + ';\n'; | |
## reduce | |
my.ooEach();: | |
{},: | |
'dot': [],: | |
'0', '0', | |
'aa = aaNext(); bb = bbNext();' + | |
'xx[ii2] += aa[0] * bb[0] - aa[1] * bb[1]; yy[ii2] += aa[0] * bb[1] + aa[1] * bb[0];' | |
'max2': [],: | |
'-Infinity', '-1', | |
'aa = aaNext(); tmp = aa[0] * aa[0] + aa[1] * aa[1];' + | |
'if(tmp > xx[ii1]) {xx[ii1] = tmp; yy[ii1] = ii2;}' | |
'min2': [],: | |
'Infinity', '-1', | |
'aa = aaNext(); tmp = aa[0] * aa[0] + aa[1] * aa[1];' + | |
'if(tmp < xx[ii1]) {xx[ii1] = tmp; yy[ii1] = ii2;}' | |
'sum2': [],: | |
'0', '0', | |
'aa = aaNext(); xx[ii2] += aa[0] * aa[0]; yy[ii2] += aa[1] * aa[1];' | |
function(vv, kk) {}: | |
my.SOURCE_EXTRA += | |
'my.Complex2.prototype.' + kk + 'C = ' + | |
my.Complex2.prototype._reduce.toString() | |
.replace('xx[ii1] = 0', 'xx[ii1] = ' + vv[0] + '; yy[ii1] = ' + vv[1]) | |
.replace('this();', vv[2]) + ';\n'; | |
## Complex2 - extra | |
## default inherit | |
my.ooEach();: | |
Object.keys(my.Array2.prototype).sort(), | |
function(kk) {}: | |
my.closure();: | |
[kk], | |
function(kk) {}: | |
my.Complex2.prototype[kk] = my.Complex2.prototype[kk] || function() {};: | |
this[0][kk].apply(this[0], arguments); | |
this[1][kk].apply(this[1], arguments); return this; | |
## new | |
my.ooEach();: | |
['concat', 'copy', 'mean', 'sink', 'slice'], | |
function(kk) {}: | |
my.closure();: | |
[kk], | |
function(kk) {}: | |
my.Complex2.prototype[kk] = function() {};: | |
return my.Complex2();: | |
[this[0][kk].apply(this[0], arguments), this[1][kk].apply(this[1], arguments)] | |
## 0 | |
my.ooEach();: | |
['is1D', 'isContiguous', 'isTransposed'], | |
function(kk) {}: | |
my.closure();: | |
[kk], | |
function(kk) {}: | |
my.Complex2.prototype[kk] = function() {};: | |
return this[0][kk].apply(this[0], arguments); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment