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