1 /* Automatically generated from Squeak on 30 July 2012 4:52:39 pm
2 by VMMaker 4.9.8
3 */
4
5 #include <math.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <time.h>
10
11 /* Default EXPORT macro that does nothing (see comment in sq.h): */
12 #define EXPORT(returnType) returnType
13
14 /* Do not include the entire sq.h file but just those parts needed. */
15 /* The virtual machine proxy definition */
16 #include "sqVirtualMachine.h"
17 /* Configuration options */
18 #include "sqConfig.h"
19 /* Platform specific definitions */
20 #include "sqPlatformSpecific.h"
21
22 #define true 1
23 #define false 0
24 #define null 0 /* using 'null' because nil is predefined in Think C */
25 #ifdef SQUEAK_BUILTIN_PLUGIN
26 #undef EXPORT
27 // was #undef EXPORT(returnType) but screws NorCroft cc
28 #define EXPORT(returnType) static returnType
29 #endif
30
31 #include "sqMemoryAccess.h"
32
33
34 /*** Constants ***/
35
36 /*** Function Prototypes ***/
37 #pragma export on
38 EXPORT(const char*) getModuleName(void);
39 #pragma export off
40 static sqInt halt(void);
41 static sqInt loadFFTFrom(sqInt fftOop);
42 static sqInt permuteData(void);
43 #pragma export on
44 EXPORT(sqInt) primitiveFFTPermuteData(void);
45 EXPORT(sqInt) primitiveFFTScaleData(void);
46 EXPORT(sqInt) primitiveFFTTransformData(void);
47 #pragma export off
48 static sqInt scaleData(void);
49 #pragma export on
50 EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter);
51 #pragma export off
52 static sqInt transformForward(sqInt forward);
53 /*** Variables ***/
54 static sqInt fftSize;
55 static float * imagData;
56 static sqInt imagDataSize;
57
58 #ifdef SQUEAK_BUILTIN_PLUGIN
59 extern
60 #endif
61 struct VirtualMachine* interpreterProxy;
62 static const char *moduleName =
63 #ifdef SQUEAK_BUILTIN_PLUGIN
64 "FFTPlugin 30 July 2012 (i)"
65 #else
66 "FFTPlugin 30 July 2012 (e)"
67 #endif
68 ;
69 static sqInt nu;
70 static unsigned int * permTable;
71 static sqInt permTableSize;
72 static float * realData;
73 static sqInt realDataSize;
74 static float * sinTable;
75 static sqInt sinTableSize;
76
77
78
79 /* Note: This is hardcoded so it can be run from Squeak.
80 The module name is used for validating a module *after*
81 it is loaded to check if it does really contain the module
82 we're thinking it contains. This is important! */
83
getModuleName(void)84 EXPORT(const char*) getModuleName(void) {
85 return moduleName;
86 }
87
halt(void)88 static sqInt halt(void) {
89 ;
90 }
91
loadFFTFrom(sqInt fftOop)92 static sqInt loadFFTFrom(sqInt fftOop) {
93 sqInt oop;
94
95 interpreterProxy->success((interpreterProxy->slotSizeOf(fftOop)) >= 6);
96 if (interpreterProxy->failed()) {
97 return 0;
98 }
99 nu = interpreterProxy->fetchIntegerofObject(0, fftOop);
100 fftSize = interpreterProxy->fetchIntegerofObject(1, fftOop);
101 oop = interpreterProxy->fetchPointerofObject(2, fftOop);
102 sinTableSize = interpreterProxy->stSizeOf(oop);
103 /* begin checkedFloatPtrOf: */
104 interpreterProxy->success(interpreterProxy->isWords(oop));
105 if (interpreterProxy->failed()) {
106 sinTable = 0;
107 goto l1;
108 }
109 sinTable = ((float *) (interpreterProxy->firstIndexableField(oop)));
110 l1: /* end checkedFloatPtrOf: */;
111 oop = interpreterProxy->fetchPointerofObject(3, fftOop);
112 permTableSize = interpreterProxy->stSizeOf(oop);
113 /* begin checkedWordPtrOf: */
114 interpreterProxy->success(interpreterProxy->isWords(oop));
115 permTable = ((unsigned int *) (interpreterProxy->firstIndexableField(oop)));
116 oop = interpreterProxy->fetchPointerofObject(4, fftOop);
117 realDataSize = interpreterProxy->stSizeOf(oop);
118 /* begin checkedFloatPtrOf: */
119 interpreterProxy->success(interpreterProxy->isWords(oop));
120 if (interpreterProxy->failed()) {
121 realData = 0;
122 goto l2;
123 }
124 realData = ((float *) (interpreterProxy->firstIndexableField(oop)));
125 l2: /* end checkedFloatPtrOf: */;
126 oop = interpreterProxy->fetchPointerofObject(5, fftOop);
127 imagDataSize = interpreterProxy->stSizeOf(oop);
128 /* begin checkedFloatPtrOf: */
129 interpreterProxy->success(interpreterProxy->isWords(oop));
130 if (interpreterProxy->failed()) {
131 imagData = 0;
132 goto l3;
133 }
134 imagData = ((float *) (interpreterProxy->firstIndexableField(oop)));
135 l3: /* end checkedFloatPtrOf: */;
136 interpreterProxy->success((((((1 << nu) == fftSize) && (((((sqInt) fftSize >> 2)) + 1) == sinTableSize)) && (fftSize == realDataSize)) && (fftSize == imagDataSize)) && (realDataSize == imagDataSize));
137 return (interpreterProxy->failed()) == 0;
138 }
139
permuteData(void)140 static sqInt permuteData(void) {
141 sqInt a;
142 sqInt b;
143 sqInt end;
144 sqInt i;
145 float tmp;
146
147 i = 0;
148 end = permTableSize;
149 while (i < end) {
150 a = (permTable[i]) - 1;
151 b = (permTable[i + 1]) - 1;
152 if (!((a < realDataSize) && (b < realDataSize))) {
153 return interpreterProxy->success(0);
154 }
155 tmp = realData[a];
156 realData[a] = (realData[b]);
157 realData[b] = tmp;
158 tmp = imagData[a];
159 imagData[a] = (imagData[b]);
160 imagData[b] = tmp;
161 i += 2;
162 }
163 }
164
primitiveFFTPermuteData(void)165 EXPORT(sqInt) primitiveFFTPermuteData(void) {
166 sqInt rcvr;
167
168 rcvr = interpreterProxy->stackObjectValue(0);
169 if (!(loadFFTFrom(rcvr))) {
170 return null;
171 }
172 permuteData();
173 if (interpreterProxy->failed()) {
174 permuteData();
175 }
176 }
177
primitiveFFTScaleData(void)178 EXPORT(sqInt) primitiveFFTScaleData(void) {
179 sqInt rcvr;
180
181 rcvr = interpreterProxy->stackObjectValue(0);
182 if (!(loadFFTFrom(rcvr))) {
183 return null;
184 }
185 scaleData();
186 }
187
primitiveFFTTransformData(void)188 EXPORT(sqInt) primitiveFFTTransformData(void) {
189 sqInt forward;
190 sqInt rcvr;
191
192 forward = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0));
193 rcvr = interpreterProxy->stackObjectValue(1);
194 if (!(loadFFTFrom(rcvr))) {
195 return null;
196 }
197 /* begin transformData: */
198 permuteData();
199 if (interpreterProxy->failed()) {
200 permuteData();
201 goto l1;
202 }
203 transformForward(forward);
204 if (!(forward)) {
205 scaleData();
206 }
207 l1: /* end transformData: */;
208 if (!(interpreterProxy->failed())) {
209 interpreterProxy->pop(1);
210 }
211 }
212
213
214 /* Scale all elements by 1/n when doing inverse */
215
scaleData(void)216 static sqInt scaleData(void) {
217 sqInt i;
218 float realN;
219
220 if (fftSize <= 1) {
221 return null;
222 }
223 realN = ((float) (1.0 / (((double) fftSize))));
224 for (i = 0; i <= (fftSize - 1); i += 1) {
225 realData[i] = ((realData[i]) * realN);
226 imagData[i] = ((imagData[i]) * realN);
227 }
228 }
229
230
231 /* Note: This is coded so that is can be run from Squeak. */
232
setInterpreter(struct VirtualMachine * anInterpreter)233 EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) {
234 sqInt ok;
235
236 interpreterProxy = anInterpreter;
237 ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR;
238 if (ok == 0) {
239 return 0;
240 }
241 ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR;
242 return ok;
243 }
244
transformForward(sqInt forward)245 static sqInt transformForward(sqInt forward) {
246 sqInt fftScale;
247 sqInt fftSize2;
248 sqInt fftSize4;
249 sqInt i;
250 sqInt ii;
251 float imagT;
252 float imagU;
253 sqInt ip;
254 sqInt j;
255 sqInt lev;
256 sqInt lev1;
257 sqInt level;
258 float realT;
259 float realU;
260 sqInt theta;
261
262 fftSize2 = ((sqInt) fftSize >> 1);
263 fftSize4 = ((sqInt) fftSize >> 2);
264 for (level = 1; level <= nu; level += 1) {
265 lev = ((level < 0) ? ((usqInt) 1 >> -level) : ((usqInt) 1 << level));
266 lev1 = ((sqInt) lev >> 1);
267 fftScale = fftSize / lev;
268 for (j = 1; j <= lev1; j += 1) {
269
270 /* pi * (j-1) / lev1 mapped onto 0..n/2 */
271
272 theta = (j - 1) * fftScale;
273 if (theta < fftSize4) {
274
275 /* Compute U, the complex multiplier for each level */
276
277 realU = sinTable[(sinTableSize - theta) - 1];
278 imagU = sinTable[theta];
279 } else {
280 realU = 0.0 - (sinTable[theta - fftSize4]);
281 imagU = sinTable[fftSize2 - theta];
282 }
283 if (!(forward)) {
284 imagU = 0.0 - imagU;
285 }
286 i = j;
287 while (i <= fftSize) {
288 ip = (i + lev1) - 1;
289 ii = i - 1;
290 realT = ((realData[ip]) * realU) - ((imagData[ip]) * imagU);
291 imagT = ((realData[ip]) * imagU) + ((imagData[ip]) * realU);
292 realData[ip] = ((realData[ii]) - realT);
293 imagData[ip] = ((imagData[ii]) - imagT);
294 realData[ii] = ((realData[ii]) + realT);
295 imagData[ii] = ((imagData[ii]) + imagT);
296 i += lev;
297 }
298 }
299 }
300 }
301
302
303 #ifdef SQUEAK_BUILTIN_PLUGIN
304
305
306 void* FFTPlugin_exports[][3] = {
307 {"FFTPlugin", "primitiveFFTTransformData", (void*)primitiveFFTTransformData},
308 {"FFTPlugin", "setInterpreter", (void*)setInterpreter},
309 {"FFTPlugin", "primitiveFFTPermuteData", (void*)primitiveFFTPermuteData},
310 {"FFTPlugin", "primitiveFFTScaleData", (void*)primitiveFFTScaleData},
311 {"FFTPlugin", "getModuleName", (void*)getModuleName},
312 {NULL, NULL, NULL}
313 };
314
315
316 #endif /* ifdef SQ_BUILTIN_PLUGIN */
317
318