Spaces:
Running
Running
/* Smalltalk from Squeak4.5 with VMMaker 4.13.6 translated as JS source on 3 November 2014 1:52:20 pm */ | |
/* Automatically generated by | |
JSPluginCodeGenerator VMMakerJS-bf.15 uuid: fd4e10f2-3773-4e80-8bb5-c4b471a014e5 | |
from | |
FFTPlugin VMMaker-bf.353 uuid: 8ae25e7e-8d2c-451e-8277-598b30e9c002 | |
*/ | |
(function FFTPlugin() { | |
; | |
var VM_PROXY_MAJOR = 1; | |
var VM_PROXY_MINOR = 11; | |
/*** Functions ***/ | |
function CLASSOF(obj) { return typeof obj === "number" ? interpreterProxy.classSmallInteger() : obj.sqClass } | |
function SIZEOF(obj) { return obj.pointers ? obj.pointers.length : obj.words ? obj.words.length : obj.bytes ? obj.bytes.length : 0 } | |
function BYTESIZEOF(obj) { return obj.bytes ? obj.bytes.length : obj.words ? obj.words.length * 4 : 0 } | |
function DIV(a, b) { return Math.floor(a / b) | 0; } // integer division | |
function MOD(a, b) { return a - DIV(a, b) * b | 0; } // signed modulus | |
function SHL(a, b) { return b > 31 ? 0 : a << b; } // fix JS shift | |
function SHR(a, b) { return b > 31 ? 0 : a >>> b; } // fix JS shift | |
function SHIFT(a, b) { return b < 0 ? (b < -31 ? 0 : a >>> (0-b) ) : (b > 31 ? 0 : a << b); } | |
/*** Variables ***/ | |
var fftSize = 0; | |
var imagData = null; | |
var imagDataSize = 0; | |
var interpreterProxy = null; | |
var moduleName = "FFTPlugin 3 November 2014 (e)"; | |
var nu = 0; | |
var permTable = null; | |
var permTableSize = 0; | |
var realData = null; | |
var realDataSize = 0; | |
var sinTable = null; | |
var sinTableSize = 0; | |
/* Return the first indexable word of oop which is assumed to be variableWordSubclass */ | |
function checkedFloatPtrOf(oop) { | |
interpreterProxy.success(interpreterProxy.isWords(oop)); | |
if (interpreterProxy.failed()) { | |
return 0; | |
} | |
return oop.wordsAsFloat32Array(); | |
} | |
/* Return the first indexable word of oop which is assumed to be variableWordSubclass */ | |
function checkedWordPtrOf(oop) { | |
interpreterProxy.success(interpreterProxy.isWords(oop)); | |
return oop.words; | |
} | |
/* Note: This is hardcoded so it can be run from Squeak. | |
The module name is used for validating a module *after* | |
it is loaded to check if it does really contain the module | |
we're thinking it contains. This is important! */ | |
function getModuleName() { | |
return moduleName; | |
} | |
function halt() { | |
; | |
} | |
function loadFFTFrom(fftOop) { | |
var oop; | |
interpreterProxy.success(SIZEOF(fftOop) >= 6); | |
if (interpreterProxy.failed()) { | |
return false; | |
} | |
nu = interpreterProxy.fetchIntegerofObject(0, fftOop); | |
fftSize = interpreterProxy.fetchIntegerofObject(1, fftOop); | |
oop = interpreterProxy.fetchPointerofObject(2, fftOop); | |
sinTableSize = SIZEOF(oop); | |
sinTable = checkedFloatPtrOf(oop); | |
oop = interpreterProxy.fetchPointerofObject(3, fftOop); | |
permTableSize = SIZEOF(oop); | |
permTable = checkedWordPtrOf(oop); | |
oop = interpreterProxy.fetchPointerofObject(4, fftOop); | |
realDataSize = SIZEOF(oop); | |
realData = checkedFloatPtrOf(oop); | |
oop = interpreterProxy.fetchPointerofObject(5, fftOop); | |
imagDataSize = SIZEOF(oop); | |
/* Check assumptions about sizes */ | |
imagData = checkedFloatPtrOf(oop); | |
interpreterProxy.success((((((SHL(1, nu)) === fftSize) && (((fftSize >> 2) + 1) === sinTableSize)) && (fftSize === realDataSize)) && (fftSize === imagDataSize)) && (realDataSize === imagDataSize)); | |
return interpreterProxy.failed() === false; | |
} | |
function permuteData() { | |
var a; | |
var b; | |
var end; | |
var i; | |
var tmp; | |
i = 0; | |
end = permTableSize; | |
while (i < end) { | |
a = permTable[i] - 1; | |
b = permTable[i + 1] - 1; | |
if (!((a < realDataSize) && (b < realDataSize))) { | |
return interpreterProxy.success(false); | |
} | |
tmp = realData[a]; | |
realData[a] = realData[b]; | |
realData[b] = tmp; | |
tmp = imagData[a]; | |
imagData[a] = imagData[b]; | |
imagData[b] = tmp; | |
i += 2; | |
} | |
} | |
function primitiveFFTPermuteData() { | |
var rcvr; | |
rcvr = interpreterProxy.stackObjectValue(0); | |
if (!loadFFTFrom(rcvr)) { | |
return null; | |
} | |
permuteData(); | |
if (interpreterProxy.failed()) { | |
/* permuteData went wrong. Do the permutation again -- this will restore the original order */ | |
permuteData(); | |
} | |
} | |
function primitiveFFTScaleData() { | |
var rcvr; | |
rcvr = interpreterProxy.stackObjectValue(0); | |
if (!loadFFTFrom(rcvr)) { | |
return null; | |
} | |
scaleData(); | |
} | |
function primitiveFFTTransformData() { | |
var forward; | |
var rcvr; | |
forward = interpreterProxy.booleanValueOf(interpreterProxy.stackValue(0)); | |
rcvr = interpreterProxy.stackObjectValue(1); | |
if (!loadFFTFrom(rcvr)) { | |
return null; | |
} | |
transformData(forward); | |
if (!interpreterProxy.failed()) { | |
interpreterProxy.pop(1); | |
} | |
} | |
/* Scale all elements by 1/n when doing inverse */ | |
function scaleData() { | |
var i; | |
var realN; | |
if (fftSize <= 1) { | |
return null; | |
} | |
realN = (1.0 / fftSize); | |
for (i = 0; i <= (fftSize - 1); i++) { | |
realData[i] = (realData[i] * realN); | |
imagData[i] = (imagData[i] * realN); | |
} | |
} | |
/* Note: This is coded so that is can be run from Squeak. */ | |
function setInterpreter(anInterpreter) { | |
var ok; | |
interpreterProxy = anInterpreter; | |
ok = interpreterProxy.majorVersion() == VM_PROXY_MAJOR; | |
if (ok === false) { | |
return false; | |
} | |
ok = interpreterProxy.minorVersion() >= VM_PROXY_MINOR; | |
return ok; | |
} | |
function transformData(forward) { | |
permuteData(); | |
if (interpreterProxy.failed()) { | |
/* permuteData went wrong. Do the permutation again -- this will restore the original order */ | |
permuteData(); | |
return null; | |
} | |
transformForward(forward); | |
if (!forward) { | |
scaleData(); | |
} | |
} | |
function transformForward(forward) { | |
var fftScale; | |
var fftSize2; | |
var fftSize4; | |
var i; | |
var ii; | |
var imagT; | |
var imagU; | |
var ip; | |
var j; | |
var lev; | |
var lev1; | |
var level; | |
var realT; | |
var realU; | |
var theta; | |
fftSize2 = fftSize >> 1; | |
fftSize4 = fftSize >> 2; | |
for (level = 1; level <= nu; level++) { | |
lev = SHL(1, level); | |
lev1 = lev >> 1; | |
fftScale = DIV(fftSize, lev); | |
for (j = 1; j <= lev1; j++) { | |
/* pi * (j-1) / lev1 mapped onto 0..n/2 */ | |
theta = (j - 1) * fftScale; | |
if (theta < fftSize4) { | |
/* Compute U, the complex multiplier for each level */ | |
realU = sinTable[(sinTableSize - theta) - 1]; | |
imagU = sinTable[theta]; | |
} else { | |
realU = 0.0 - sinTable[theta - fftSize4]; | |
imagU = sinTable[fftSize2 - theta]; | |
} | |
if (!forward) { | |
imagU = 0.0 - imagU; | |
} | |
i = j; | |
while (i <= fftSize) { | |
ip = (i + lev1) - 1; | |
ii = i - 1; | |
realT = (realData[ip] * realU) - (imagData[ip] * imagU); | |
imagT = (realData[ip] * imagU) + (imagData[ip] * realU); | |
realData[ip] = (realData[ii] - realT); | |
imagData[ip] = (imagData[ii] - imagT); | |
realData[ii] = (realData[ii] + realT); | |
imagData[ii] = (imagData[ii] + imagT); | |
i += lev; | |
} | |
} | |
} | |
} | |
function registerPlugin() { | |
if (typeof Squeak === "object" && Squeak.registerExternalModule) { | |
Squeak.registerExternalModule("FFTPlugin", { | |
primitiveFFTTransformData: primitiveFFTTransformData, | |
setInterpreter: setInterpreter, | |
primitiveFFTPermuteData: primitiveFFTPermuteData, | |
primitiveFFTScaleData: primitiveFFTScaleData, | |
getModuleName: getModuleName, | |
}); | |
} else self.setTimeout(registerPlugin, 100); | |
} | |
registerPlugin(); | |
})(); // Register module/plugin | |