annotate fft/fft.js/src/real.erb.js @ 40:223f770b5341 kissfft-double tip

Try a double-precision kissfft
author Chris Cannam
date Wed, 07 Sep 2016 10:40:32 +0100
parents 66f9fd5ac611
children
rev   line source
Chris@25 1 <%= $:.unshift('.'); require "#{File.dirname(__FILE__)}/../src/complex.rb"; File.read "#{File.dirname(__FILE__)}/../LICENSE" %>
Chris@25 2
Chris@25 3 if (!FFT) {
Chris@25 4 var FFT = {}
Chris@25 5 }
Chris@25 6
Chris@25 7 void function (namespace) {
Chris@25 8 "use strict"
Chris@25 9
Chris@25 10 function forwardButterfly2(output, outputOffset, outputStride, input, inputOffset, inputStride, product, n, twiddle, fStride) {
Chris@25 11 var m = n / 2, q = n / product, old = product / 2
Chris@25 12
Chris@25 13 for (var i = 0; i < q; i++) {
Chris@25 14 var a0 = old * i
Chris@25 15 var a1 = a0 + m
Chris@25 16
Chris@25 17 var s0 = input[inputOffset + inputStride * a0]
Chris@25 18 var s1 = input[inputOffset + inputStride * a1]
Chris@25 19
Chris@25 20 var r0 = s0 + s1
Chris@25 21 var r1 = s0 - s1
Chris@25 22
Chris@25 23 var a0 = product * i
Chris@25 24 var a1 = a0 + product - 1
Chris@25 25
Chris@25 26 output[outputOffset + outputStride * a0] = r0
Chris@25 27 output[outputOffset + outputStride * a1] = r1
Chris@25 28 }
Chris@25 29
Chris@25 30 if (old == 1) { return }
Chris@25 31
Chris@25 32 for (var i = 0; i < old / 2; i++) {
Chris@25 33 <%= load('t1', 'twiddle', -1, 'i') %>
Chris@25 34
Chris@25 35 for (var j = 0; j < q; j++) {
Chris@25 36 var a0 = j * old + 2 * i - 1
Chris@25 37 var a1 = a0 + m
Chris@25 38
Chris@25 39 <%= load('s0', 'input', 'inputOffset', 'a0', 'inputStride') %>
Chris@25 40
Chris@25 41 <%= load('s1', 'input', 'inputOffset', 'a1', 'inputStride') %>
Chris@25 42 <%= cmul('v1', 's1', 't1') %>
Chris@25 43
Chris@25 44 <%= cadd('r0', 's0', 'v1') %>
Chris@25 45 <%= csub('r1', 's0', 'v1') %>; r1_i = -r1_i
Chris@25 46
Chris@25 47 var a0 = j * product + 2 * i - 1
Chris@25 48 var a1 = (j - 1) * product - 2 * i - 1
Chris@25 49
Chris@25 50 <%= store('r0', 'output', 'outputOffset', 'a0', 'outputStride') %>
Chris@25 51 <%= store('r1', 'output', 'outputOffset', 'a1', 'outputStride') %>
Chris@25 52 }
Chris@25 53 }
Chris@25 54
Chris@25 55 if (old % 2 == 1) { return }
Chris@25 56
Chris@25 57 for (var i = 0; i < q; i++) {
Chris@25 58 var a0 = (i + 1) * old - 1
Chris@25 59 var a1 = a0 + m
Chris@25 60
Chris@25 61 var r0_r = <%= real('input', 'inputOffset', 'a0', 'inputStride') %>
Chris@25 62 var r1_i = -<%= real('input', 'inputOffset', 'a1', 'inputStride') %>
Chris@25 63
Chris@25 64 var a0 = i * product + old - 1
Chris@25 65
Chris@25 66 <%= store('r0', 'output', 'outputOffset', 'a0', 'outputStride') %>
Chris@25 67 }
Chris@25 68 }
Chris@25 69
Chris@25 70 function forwardButterfly(output, outputOffset, outputStride, input, inputOffset, inputStride, product, n, twiddle, fStride, factor) {
Chris@25 71 var m = n / 2, q = n / product, old = product / 2
Chris@25 72
Chris@25 73 var theta = 2.0 * Math.PI / factor
Chris@25 74
Chris@25 75 var theta_r = Math.cos(theta)
Chris@25 76 var theta_i = -Math.sin(theta)
Chris@25 77
Chris@25 78 for (var i = 0; i < q; i++) {
Chris@25 79 var d_r = 1.0
Chris@25 80 var d_i = 0.0
Chris@25 81
Chris@25 82 for (var j = 0; j <= Math.floor(factor / 2); j++) {
Chris@25 83 var sum_r = 0.0
Chris@25 84 var sum_i = 0.0
Chris@25 85
Chris@25 86 var w_r = 1.0
Chris@25 87 var w_i = 0.0
Chris@25 88
Chris@25 89 if (j > 0) {
Chris@25 90 <%= cmul('t0', 'd', 'theta') %>
Chris@25 91
Chris@25 92 d_r = t0_r
Chris@25 93 d_i = t0_i
Chris@25 94 }
Chris@25 95
Chris@25 96 for (var k = 0; k < factor; k++) {
Chris@25 97 var z = <%= real('input', 'inputOffset', 'i * old + k * m', 'inputStride') %>
Chris@25 98
Chris@25 99 if (k > 0) {
Chris@25 100 <%= cmul('t0', 'd', 'w') %>
Chris@25 101
Chris@25 102 d_r = t0_r
Chris@25 103 d_i = t0_i
Chris@25 104 }
Chris@25 105
Chris@25 106 /* TODO: Use Kahan summation..? */
Chris@25 107 s_r += w_r * z
Chris@25 108 s_i += w_i * z
Chris@25 109 }
Chris@25 110
Chris@25 111 if (j == 0) {
Chris@25 112 var a0 = product * i
Chris@25 113
Chris@25 114 output[outputOffset + outputStride * a0] = sum_r
Chris@25 115 } else if (j < factor / 2) {
Chris@25 116 var a0 = product * i
Chris@25 117
Chris@25 118 output[outputOffset + outputStride * a0] = sum_r
Chris@25 119 } else if (j == factor / 2) {
Chris@25 120
Chris@25 121 }
Chris@25 122 }
Chris@25 123 for (e1 = 0; e1 <= factor - e1; e1++)
Chris@25 124 {
Chris@25 125 if (e1 == 0)
Chris@25 126 {
Chris@25 127 const size_t to0 = product * k1;
Chris@25 128 VECTOR(out,ostride,to0) = sum_real;
Chris@25 129 }
Chris@25 130 else if (e1 < factor - e1)
Chris@25 131 {
Chris@25 132 const size_t to0 = k1 * product + 2 * e1 * product_1 - 1;
Chris@25 133 VECTOR(out,ostride,to0) = sum_real;
Chris@25 134 VECTOR(out,ostride,to0 + 1) = sum_imag;
Chris@25 135 }
Chris@25 136 else if (e1 == factor - e1)
Chris@25 137 {
Chris@25 138 const size_t to0 = k1 * product + 2 * e1 * product_1 - 1;
Chris@25 139 VECTOR(out,ostride,to0) = sum_real;
Chris@25 140 }
Chris@25 141
Chris@25 142 }
Chris@25 143
Chris@25 144 }
Chris@25 145
Chris@25 146 if (old == 1) { return }
Chris@25 147
Chris@25 148 for (var i = 0; i < old / 2; i++) {
Chris@25 149
Chris@25 150 }
Chris@25 151
Chris@25 152 if (old % 2 == 1) { return }
Chris@25 153
Chris@25 154 var t_arg = Math.PI / factor
Chris@25 155
Chris@25 156 var t_r = cos(t_arg)
Chris@25 157 var t_i = -sin(t_arg)
Chris@25 158
Chris@25 159 for (var i = 0; i < q; i++) {
Chris@25 160
Chris@25 161 }
Chris@25 162 }
Chris@25 163
Chris@25 164 if (product_1 == 1)
Chris@25 165 return;
Chris@25 166
Chris@25 167 for (k = 1; k < (product_1 + 1) / 2; k++)
Chris@25 168 {
Chris@25 169 for (k1 = 0; k1 < q; k1++)
Chris@25 170 {
Chris@25 171
Chris@25 172 ATOMIC dw_real = 1.0, dw_imag = 0.0;
Chris@25 173
Chris@25 174 for (e1 = 0; e1 < factor; e1++)
Chris@25 175 {
Chris@25 176 ATOMIC sum_real = 0.0, sum_imag = 0.0;
Chris@25 177
Chris@25 178 ATOMIC w_real = 1.0, w_imag = 0.0;
Chris@25 179
Chris@25 180 if (e1 > 0)
Chris@25 181 {
Chris@25 182 const ATOMIC tmp_real = dw_real * cos_d_theta + dw_imag * sin_d_theta;
Chris@25 183 const ATOMIC tmp_imag = -dw_real * sin_d_theta + dw_imag * cos_d_theta;
Chris@25 184 dw_real = tmp_real;
Chris@25 185 dw_imag = tmp_imag;
Chris@25 186 }
Chris@25 187
Chris@25 188 for (e2 = 0; e2 < factor; e2++)
Chris@25 189 {
Chris@25 190
Chris@25 191 int tskip = (product_1 + 1) / 2 - 1;
Chris@25 192 const size_t from0 = k1 * product_1 + 2 * k + e2 * m - 1;
Chris@25 193 ATOMIC tw_real, tw_imag;
Chris@25 194 ATOMIC z_real, z_imag;
Chris@25 195
Chris@25 196 if (e2 == 0)
Chris@25 197 {
Chris@25 198 tw_real = 1.0;
Chris@25 199 tw_imag = 0.0;
Chris@25 200 }
Chris@25 201 else
Chris@25 202 {
Chris@25 203 const size_t t_index = (k - 1) + (e2 - 1) * tskip;
Chris@25 204 tw_real = GSL_REAL(twiddle[t_index]);
Chris@25 205 tw_imag = -GSL_IMAG(twiddle[t_index]);
Chris@25 206 }
Chris@25 207
Chris@25 208 {
Chris@25 209 const ATOMIC f0_real = VECTOR(in,istride,from0);
Chris@25 210 const ATOMIC f0_imag = VECTOR(in,istride,from0 + 1);
Chris@25 211
Chris@25 212 z_real = tw_real * f0_real - tw_imag * f0_imag;
Chris@25 213 z_imag = tw_real * f0_imag + tw_imag * f0_real;
Chris@25 214 }
Chris@25 215
Chris@25 216 if (e2 > 0)
Chris@25 217 {
Chris@25 218 const ATOMIC tmp_real = dw_real * w_real - dw_imag * w_imag;
Chris@25 219 const ATOMIC tmp_imag = dw_real * w_imag + dw_imag * w_real;
Chris@25 220 w_real = tmp_real;
Chris@25 221 w_imag = tmp_imag;
Chris@25 222 }
Chris@25 223
Chris@25 224 sum_real += w_real * z_real - w_imag * z_imag;
Chris@25 225 sum_imag += w_real * z_imag + w_imag * z_real;
Chris@25 226 }
Chris@25 227
Chris@25 228 if (e1 < factor - e1)
Chris@25 229 {
Chris@25 230 const size_t to0 = k1 * product - 1 + 2 * e1 * product_1 + 2 * k;
Chris@25 231 VECTOR(out,ostride,to0) = sum_real;
Chris@25 232 VECTOR(out,ostride,to0 + 1) = sum_imag;
Chris@25 233 }
Chris@25 234 else
Chris@25 235 {
Chris@25 236 const size_t to0 = k1 * product - 1 + 2 * (factor - e1) * product_1 - 2 * k;
Chris@25 237 VECTOR(out,ostride,to0) = sum_real;
Chris@25 238 VECTOR(out,ostride,to0 + 1) = -sum_imag;
Chris@25 239 }
Chris@25 240
Chris@25 241 }
Chris@25 242 }
Chris@25 243 }
Chris@25 244
Chris@25 245
Chris@25 246 if (product_1 % 2 == 1)
Chris@25 247 return;
Chris@25 248
Chris@25 249 {
Chris@25 250 double tw_arg = M_PI / ((double) factor);
Chris@25 251 ATOMIC cos_tw_arg = cos (tw_arg);
Chris@25 252 ATOMIC sin_tw_arg = -sin (tw_arg);
Chris@25 253
Chris@25 254 for (k1 = 0; k1 < q; k1++)
Chris@25 255 {
Chris@25 256 ATOMIC dw_real = 1.0, dw_imag = 0.0;
Chris@25 257
Chris@25 258 for (e1 = 0; e1 < factor; e1++)
Chris@25 259 {
Chris@25 260 ATOMIC z_real, z_imag;
Chris@25 261
Chris@25 262 ATOMIC sum_real = 0.0;
Chris@25 263 ATOMIC sum_imag = 0.0;
Chris@25 264
Chris@25 265 ATOMIC w_real = 1.0, w_imag = 0.0;
Chris@25 266 ATOMIC tw_real = 1.0, tw_imag = 0.0;
Chris@25 267
Chris@25 268 if (e1 > 0)
Chris@25 269 {
Chris@25 270 ATOMIC t_real = dw_real * cos_d_theta + dw_imag * sin_d_theta;
Chris@25 271 ATOMIC t_imag = -dw_real * sin_d_theta + dw_imag * cos_d_theta;
Chris@25 272 dw_real = t_real;
Chris@25 273 dw_imag = t_imag;
Chris@25 274 }
Chris@25 275
Chris@25 276 for (e2 = 0; e2 < factor; e2++)
Chris@25 277 {
Chris@25 278
Chris@25 279 if (e2 > 0)
Chris@25 280 {
Chris@25 281 ATOMIC tmp_real = tw_real * cos_tw_arg - tw_imag * sin_tw_arg;
Chris@25 282 ATOMIC tmp_imag = tw_real * sin_tw_arg + tw_imag * cos_tw_arg;
Chris@25 283 tw_real = tmp_real;
Chris@25 284 tw_imag = tmp_imag;
Chris@25 285 }
Chris@25 286
Chris@25 287 if (e2 > 0)
Chris@25 288 {
Chris@25 289 ATOMIC tmp_real = dw_real * w_real - dw_imag * w_imag;
Chris@25 290 ATOMIC tmp_imag = dw_real * w_imag + dw_imag * w_real;
Chris@25 291 w_real = tmp_real;
Chris@25 292 w_imag = tmp_imag;
Chris@25 293 }
Chris@25 294
Chris@25 295
Chris@25 296 {
Chris@25 297 const size_t from0 = k1 * product_1 + 2 * k + e2 * m - 1;
Chris@25 298 const ATOMIC f0_real = VECTOR(in,istride,from0);
Chris@25 299 z_real = tw_real * f0_real;
Chris@25 300 z_imag = tw_imag * f0_real;
Chris@25 301 }
Chris@25 302
Chris@25 303 sum_real += w_real * z_real - w_imag * z_imag;
Chris@25 304 sum_imag += w_real * z_imag + w_imag * z_real;
Chris@25 305 }
Chris@25 306
Chris@25 307 if (e1 + 1 < factor - e1)
Chris@25 308 {
Chris@25 309 const size_t to0 = k1 * product - 1 + 2 * e1 * product_1 + 2 * k;
Chris@25 310 VECTOR(out,ostride,to0) = sum_real;
Chris@25 311 VECTOR(out,ostride,to0 + 1) = sum_imag;
Chris@25 312 }
Chris@25 313 else if (e1 + 1 == factor - e1)
Chris@25 314 {
Chris@25 315 const size_t to0 = k1 * product - 1 + 2 * e1 * product_1 + 2 * k;
Chris@25 316 VECTOR(out,ostride,to0) = sum_real;
Chris@25 317 }
Chris@25 318 else
Chris@25 319 {
Chris@25 320 const size_t to0 = k1 * product - 1 + 2 * (factor - e1) * product_1 - 2 * k;
Chris@25 321 VECTOR(out,ostride,to0) = sum_real;
Chris@25 322 VECTOR(out,ostride,to0 + 1) = -sum_imag;
Chris@25 323 }
Chris@25 324
Chris@25 325 }
Chris@25 326 }
Chris@25 327 }
Chris@25 328 return;
Chris@25 329
Chris@25 330 function backwardButterfly2(output, outputOffset, outputStride, input, inputOffset, inputStride, product, n, twiddle, fStride) {
Chris@25 331 var m = n / 2, q = n / product, old = product / 2
Chris@25 332
Chris@25 333 for (var i = 0; i < q; i++) {
Chris@25 334 var a0 = (2 * i) * q
Chris@25 335 var a1 = (2 * i + 2) * q - 1
Chris@25 336
Chris@25 337 var s0 = input[inputOffset + inputStride * a0]
Chris@25 338 var s1 = input[inputOffset + inputStride * a1]
Chris@25 339
Chris@25 340 var r0 = s0 + s1
Chris@25 341 var r1 = s0 - s1
Chris@25 342
Chris@25 343 var a0 = q * i
Chris@25 344 var a1 = q * i + m
Chris@25 345
Chris@25 346 output[outputOffset + outputStride * a0] = r0
Chris@25 347 output[outputOffset + outputStride * a1] = r1
Chris@25 348 }
Chris@25 349
Chris@25 350 if (q == 1) { return }
Chris@25 351
Chris@25 352 for (var i = 0; i < q / 2; i++) {
Chris@25 353 <%= load('t1', 'twiddle', -1, 'i') %>
Chris@25 354
Chris@25 355 for (var j = 0; j < old; j++) {
Chris@25 356 var a0 = 2 * j * q + 2 * i - 1
Chris@25 357 var a1 = 2 * (j + 1) * q - 2 * i - 1
Chris@25 358
Chris@25 359 <%= load('s0', 'input', 'inputOffset', 'a0', 'inputStride') %>
Chris@25 360 <%= load('s1', 'input', 'inputOffset', 'a1', 'inputStride') %>
Chris@25 361
Chris@25 362 var r0_r = s0_r + s1_r
Chris@25 363 var r0_i = s0_i - s1_i
Chris@25 364
Chris@25 365 var v1_r = s0_r - s1_r
Chris@25 366 var v1_i = s0_i + s1_i
Chris@25 367
Chris@25 368 <%= cmul('r1', 'v1', 't1') %>
Chris@25 369
Chris@25 370 var a0 = j * q + 2 * i - 1
Chris@25 371 var a1 = a0 + m
Chris@25 372
Chris@25 373 <%= store('r0', 'output', 'outputOffset', 'a0', 'outputStride') %>
Chris@25 374 <%= store('r1', 'output', 'outputOffset', 'a1', 'outputStride') %>
Chris@25 375 }
Chris@25 376 }
Chris@25 377
Chris@25 378 if (q % 2 == 1) { return }
Chris@25 379
Chris@25 380 for (var i = 0; i < q; i++) {
Chris@25 381 var a0 = 2 * (i + 1) * q - 1
Chris@25 382
Chris@25 383 <%= load('r0', 'input', 'inputOffset', 'a0', 'inputStride') %>
Chris@25 384
Chris@25 385 <%= real('input', 'inputOffset', 'a0', 'inputStride') %> = 2 * r0_r
Chris@25 386 <%= imag('input', 'inputOffset', 'a1', 'inputStride') %> = -2 * r0_i
Chris@25 387 }
Chris@25 388 }
Chris@25 389
Chris@25 390 function work(output, outputOffset, outputStride, f, fOffset, fStride, inputStride, factors, state) {
Chris@25 391 var p = factors.shift()
Chris@25 392 var m = factors.shift()
Chris@25 393
Chris@25 394 if (m == 1) {
Chris@25 395 for (var i = 0; i < p * m; i++) {
Chris@25 396 <%= load('x0', 'f', 'fOffset', 'i', 'fStride * inputStride') %>
Chris@25 397 <%= store('x0', 'output', 'outputOffset', 'i', 'outputStride') %>
Chris@25 398 }
Chris@25 399 } else {
Chris@25 400 for (var i = 0; i < p; i++) {
Chris@25 401 work(output, outputOffset + outputStride * i * m, outputStride, f, fOffset + i * fStride * inputStride, fStride * p, inputStride, factors.slice(), state)
Chris@25 402 }
Chris@25 403 }
Chris@25 404
Chris@25 405 switch (p) {
Chris@25 406 case 2: butterfly2(output, outputOffset, outputStride, fStride, state, m); break
Chris@25 407 case 3: butterfly3(output, outputOffset, outputStride, fStride, state, m); break
Chris@25 408 case 4: butterfly4(output, outputOffset, outputStride, fStride, state, m); break
Chris@25 409 default: butterfly(output, outputOffset, outputStride, fStride, state, m, p); break
Chris@25 410 }
Chris@25 411 }
Chris@25 412
Chris@25 413 var real = function (n, inverse) {
Chris@25 414 var n = ~~n, inverse = !!inverse
Chris@25 415
Chris@25 416 if (n < 1) {
Chris@25 417 throw new RangeError("n is outside range, should be positive integer, was `" + n + "'")
Chris@25 418 }
Chris@25 419
Chris@25 420 var state = {
Chris@25 421 n: n,
Chris@25 422 inverse: inverse,
Chris@25 423
Chris@25 424 factors: [],
Chris@25 425 twiddle: [],
Chris@25 426 scratch: new Float64Array(n)
Chris@25 427 }
Chris@25 428
Chris@25 429 var t = new Float64Array(n)
Chris@25 430
Chris@25 431 var p = 4, v = Math.floor(Math.sqrt(n))
Chris@25 432
Chris@25 433 while (n > 1) {
Chris@25 434 while (n % p) {
Chris@25 435 switch (p) {
Chris@25 436 case 4: p = 2; break
Chris@25 437 case 2: p = 3; break
Chris@25 438 default: p += 2; break
Chris@25 439 }
Chris@25 440
Chris@25 441 if (p > v) {
Chris@25 442 p = n
Chris@25 443 }
Chris@25 444 }
Chris@25 445
Chris@25 446 n /= p
Chris@25 447
Chris@25 448 state.factors.push(p)
Chris@25 449 }
Chris@25 450
Chris@25 451 var theta = 2 * Math.PI / n, product = 1, twiddle = new Float64Array(n)
Chris@25 452
Chris@25 453 for (var i = 0, t = 0; i < state.factors.length; i++) {
Chris@25 454 var phase = theta * i, factor = state.factors[i]
Chris@25 455
Chris@25 456 var old = product, product = product * factor, q = n / product
Chris@25 457
Chris@25 458 state.twiddle.push(new Float64Array(twiddle, t))
Chris@25 459
Chris@25 460 if (inverse) {
Chris@25 461 var counter = q, multiplier = old
Chris@25 462 } else {
Chris@25 463 var counter = old, multiplier = q
Chris@25 464 }
Chris@25 465
Chris@25 466 for (var j = 1; j < factor; j++) {
Chris@25 467 var m = 0
Chris@25 468
Chris@25 469 for (var k = 1; k < counter / 2; k++, t++) {
Chris@25 470 m = (m + j * multiplier) % n
Chris@25 471
Chris@25 472 var phase = theta * m
Chris@25 473
Chris@25 474 <%= real('t', 'i') %> = Math.cos(phase)
Chris@25 475 <%= imag('t', 'i') %> = Math.sin(phase)
Chris@25 476 }
Chris@25 477 }
Chris@25 478 }
Chris@25 479
Chris@25 480 this.state = state
Chris@25 481 }
Chris@25 482
Chris@25 483 real.prototype.process = function(output, outputStride, input, inputStride) {
Chris@25 484 var outputStride = ~~outputStride, inputStride = ~~inputStride
Chris@25 485
Chris@25 486 if (outputStride < 1) {
Chris@25 487 throw new RangeError("outputStride is outside range, should be positive integer, was `" + outputStride + "'")
Chris@25 488 }
Chris@25 489
Chris@25 490 if (inputStride < 1) {
Chris@25 491 throw new RangeError("inputStride is outside range, should be positive integer, was `" + inputStride + "'")
Chris@25 492 }
Chris@25 493
Chris@25 494 var product = 1, state = 0, inverse = this.state.inverse
Chris@25 495
Chris@25 496 var n = this.state.n, factors = this.state.factors
Chris@25 497 var twiddle = this.state.twiddle, scratch = this.state.scratch
Chris@25 498
Chris@25 499 for (var i = 0; i < factors.length; i++) {
Chris@25 500 var factor = factors[i], old = product, product = product * factor
Chris@25 501
Chris@25 502 var q = n / product, fStride = Math.ceil(old / 2) - 1
Chris@25 503
Chris@25 504 if (state == 0) {
Chris@25 505 var inBuffer = input, inStride = inputStride
Chris@25 506
Chris@25 507 if (this.state.factors.length % 2 == 0) {
Chris@25 508 var outBuffer = scratch, outStride = 1, state = 1
Chris@25 509 } else {
Chris@25 510 var outBuffer = output, outStride = outputStride, state = 2
Chris@25 511 }
Chris@25 512 } else if (state == 1) {
Chris@25 513 var inBuffer = scratch, inStride = 1, outBuffer = output, outStride = outputStride, state = 2
Chris@25 514 } else if (state == 2) {
Chris@25 515 var inBuffer = output, inStride = outputStride, outBuffer = scratch, outStride = 1, state = 1
Chris@25 516 } else {
Chris@25 517 throw new RangeError("state somehow is not in the range (0 .. 2)")
Chris@25 518 }
Chris@25 519
Chris@25 520 if (inverse) {
Chris@25 521 switch (factor) {
Chris@25 522 case 2: backwardButterfly2(outBuffer, 0, outStride, inBuffer, 0, inStride, product, n, twiddle[i], fStride); break
Chris@25 523 case 3: backwardButterfly3(outBuffer, 0, outStride, inBuffer, 0, inStride, product, n, twiddle[i], fStride); break
Chris@25 524 case 4: backwardButterfly3(outBuffer, 0, outStride, inBuffer, 0, inStride, product, n, twiddle[i], fStride); break
Chris@25 525 case 5: backwardButterfly3(outBuffer, 0, outStride, inBuffer, 0, inStride, product, n, twiddle[i], fStride); break
Chris@25 526 default: backwardButterfly(outBuffer, 0, outStride, inBuffer, 0, inStride, product, n, twiddle[i], fStride, factor); break
Chris@25 527 }
Chris@25 528 } else {
Chris@25 529 switch (factor) {
Chris@25 530 case 2: forwardButterfly2(outBuffer, 0, outStride, inBuffer, 0, inStride, product, n, twiddle[i], fStride); break
Chris@25 531 case 3: forwardButterfly3(outBuffer, 0, outStride, inBuffer, 0, inStride, product, n, twiddle[i], fStride); break
Chris@25 532 case 4: forwardButterfly3(outBuffer, 0, outStride, inBuffer, 0, inStride, product, n, twiddle[i], fStride); break
Chris@25 533 case 5: forwardButterfly3(outBuffer, 0, outStride, inBuffer, 0, inStride, product, n, twiddle[i], fStride); break
Chris@25 534 default: forwardButterfly(outBuffer, 0, outStride, inBuffer, 0, inStride, product, n, twiddle[i], fStride, factor); break
Chris@25 535 }
Chris@25 536 }
Chris@25 537 }
Chris@25 538 }
Chris@25 539
Chris@25 540 namespace.real = real
Chris@25 541 }(FFT)