Skip to content

Instantly share code, notes, and snippets.

@kaizhu256
Created June 2, 2012 06:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kaizhu256/2857043 to your computer and use it in GitHub Desktop.
Save kaizhu256/2857043 to your computer and use it in GitHub Desktop.
javascript my.Complex2 - 2d complex array class
//// 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