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 | |