gonum.org/v1/gonum@v0.14.0/dsp/fourier/internal/fftpack/rfft.go (about) 1 // Copyright ©2018 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This is a translation of the FFTPACK rfft functions by 6 // Paul N Swarztrauber, placed in the public domain at 7 // http://www.netlib.org/fftpack/. 8 9 package fftpack 10 11 import ( 12 "math" 13 "math/cmplx" 14 ) 15 16 // Rffti initializes the array work which is used in both Rfftf 17 // and Rfftb. The prime factorization of n together with a 18 // tabulation of the trigonometric functions are computed and 19 // stored in work. 20 // 21 // Input parameter: 22 // 23 // n The length of the sequence to be transformed. 24 // 25 // Output parameters: 26 // 27 // work A work array which must be dimensioned at least 2*n. 28 // The same work array can be used for both Rfftf and Rfftb 29 // as long as n remains unchanged. different work arrays 30 // are required for different values of n. The contents of 31 // work must not be changed between calls of Rfftf or Rfftb. 32 // 33 // ifac A work array containing the factors of n. ifac must have 34 // length of at least 15. 35 func Rffti(n int, work []float64, ifac []int) { 36 if len(work) < 2*n { 37 panic("fourier: short work") 38 } 39 if len(ifac) < 15 { 40 panic("fourier: short ifac") 41 } 42 if n == 1 { 43 return 44 } 45 rffti1(n, work[n:2*n], ifac[:15]) 46 } 47 48 func rffti1(n int, wa []float64, ifac []int) { 49 ntryh := [4]int{4, 2, 3, 5} 50 51 nl := n 52 nf := 0 53 54 outer: 55 for j, ntry := 0, 0; ; j++ { 56 if j < 4 { 57 ntry = ntryh[j] 58 } else { 59 ntry += 2 60 } 61 for { 62 if nl%ntry != 0 { 63 continue outer 64 } 65 66 ifac[nf+2] = ntry 67 nl /= ntry 68 nf++ 69 70 if ntry == 2 && nf != 1 { 71 for i := 1; i < nf; i++ { 72 ib := nf - i + 1 73 ifac[ib+1] = ifac[ib] 74 } 75 ifac[2] = 2 76 } 77 78 if nl == 1 { 79 break outer 80 } 81 } 82 } 83 84 ifac[0] = n 85 ifac[1] = nf 86 if nf == 1 { 87 return 88 } 89 argh := 2 * math.Pi / float64(n) 90 91 is := 0 92 l1 := 1 93 for k1 := 0; k1 < nf-1; k1++ { 94 ip := ifac[k1+2] 95 ld := 0 96 l2 := l1 * ip 97 ido := n / l2 98 for j := 0; j < ip-1; j++ { 99 ld += l1 100 i := is 101 fi := 0.0 102 argld := float64(ld) * argh 103 for ii := 2; ii < ido; ii += 2 { 104 fi++ 105 arg := fi * argld 106 wa[i] = math.Cos(arg) 107 wa[i+1] = math.Sin(arg) 108 i += 2 109 } 110 is += ido 111 } 112 l1 = l2 113 } 114 } 115 116 // Rfftf computes the Fourier coefficients of a real perodic sequence 117 // (Fourier analysis). The transform is defined below at output 118 // parameter r. 119 // 120 // Input parameters: 121 // 122 // n The length of the array r to be transformed. The method 123 // is most efficient when n is a product of small primes. 124 // n may change so long as different work arrays are provided. 125 // 126 // r A real array of length n which contains the sequence 127 // to be transformed. 128 // 129 // work a work array which must be dimensioned at least 2*n. 130 // in the program that calls Rfftf. the work array must be 131 // initialized by calling subroutine rffti(n,work,ifac) and a 132 // different work array must be used for each different 133 // value of n. This initialization does not have to be 134 // repeated so long as n remains unchanged. Thus subsequent 135 // transforms can be obtained faster than the first. 136 // The same work array can be used by Rfftf and Rfftb. 137 // 138 // ifac A work array containing the factors of n. ifac must have 139 // length of at least 15. 140 // 141 // Output parameters: 142 // 143 // r r[0] = the sum from i=0 to i=n-1 of r[i] 144 // 145 // if n is even set l=n/2, if n is odd set l = (n+1)/2 146 // then for k = 1, ..., l-1 147 // r[2*k-1] = the sum from i = 0 to i = n-1 of 148 // r[i]*cos(k*i*2*pi/n) 149 // r[2*k] = the sum from i = 0 to i = n-1 of 150 // -r[i]*sin(k*i*2*pi/n) 151 // 152 // if n is even 153 // r[n-1] = the sum from i = 0 to i = n-1 of 154 // (-1)^i*r[i] 155 // 156 // This transform is unnormalized since a call of Rfftf 157 // followed by a call of Rfftb will multiply the input 158 // sequence by n. 159 // 160 // work contains results which must not be destroyed between 161 // calls of Rfftf or Rfftb. 162 // ifac contains results which must not be destroyed between 163 // calls of Rfftf or Rfftb. 164 func Rfftf(n int, r, work []float64, ifac []int) { 165 if len(r) < n { 166 panic("fourier: short sequence") 167 } 168 if len(work) < 2*n { 169 panic("fourier: short work") 170 } 171 if len(ifac) < 15 { 172 panic("fourier: short ifac") 173 } 174 if n == 1 { 175 return 176 } 177 rfftf1(n, r[:n], work[:n], work[n:2*n], ifac[:15]) 178 } 179 180 func rfftf1(n int, c, ch, wa []float64, ifac []int) { 181 nf := ifac[1] 182 na := true 183 l2 := n 184 iw := n - 1 185 186 for k1 := 1; k1 <= nf; k1++ { 187 kh := nf - k1 188 ip := ifac[kh+2] 189 l1 := l2 / ip 190 ido := n / l2 191 idl1 := ido * l1 192 iw -= (ip - 1) * ido 193 na = !na 194 195 switch ip { 196 case 4: 197 ix2 := iw + ido 198 ix3 := ix2 + ido 199 if na { 200 radf4(ido, l1, ch, c, wa[iw:], wa[ix2:], wa[ix3:]) 201 } else { 202 radf4(ido, l1, c, ch, wa[iw:], wa[ix2:], wa[ix3:]) 203 } 204 case 2: 205 if na { 206 radf2(ido, l1, ch, c, wa[iw:]) 207 } else { 208 radf2(ido, l1, c, ch, wa[iw:]) 209 } 210 case 3: 211 ix2 := iw + ido 212 if na { 213 radf3(ido, l1, ch, c, wa[iw:], wa[ix2:]) 214 } else { 215 radf3(ido, l1, c, ch, wa[iw:], wa[ix2:]) 216 } 217 case 5: 218 ix2 := iw + ido 219 ix3 := ix2 + ido 220 ix4 := ix3 + ido 221 if na { 222 radf5(ido, l1, ch, c, wa[iw:], wa[ix2:], wa[ix3:], wa[ix4:]) 223 } else { 224 radf5(ido, l1, c, ch, wa[iw:], wa[ix2:], wa[ix3:], wa[ix4:]) 225 } 226 default: 227 if ido == 1 { 228 na = !na 229 } 230 if na { 231 radfg(ido, ip, l1, idl1, ch, ch, ch, c, c, wa[iw:]) 232 na = false 233 } else { 234 radfg(ido, ip, l1, idl1, c, c, c, ch, ch, wa[iw:]) 235 na = true 236 } 237 } 238 239 l2 = l1 240 } 241 242 if na { 243 return 244 } 245 for i := 0; i < n; i++ { 246 c[i] = ch[i] 247 } 248 } 249 250 func radf2(ido, l1 int, cc, ch, wa1 []float64) { 251 cc3 := newThreeArray(ido, l1, 2, cc) 252 ch3 := newThreeArray(ido, 2, l1, ch) 253 254 for k := 0; k < l1; k++ { 255 ch3.set(0, 0, k, cc3.at(0, k, 0)+cc3.at(0, k, 1)) 256 ch3.set(ido-1, 1, k, cc3.at(0, k, 0)-cc3.at(0, k, 1)) 257 } 258 if ido < 2 { 259 return 260 } 261 if ido > 2 { 262 idp2 := ido + 1 263 for k := 0; k < l1; k++ { 264 for i := 2; i < ido; i += 2 { 265 ic := idp2 - (i + 1) 266 267 t2 := complex(wa1[i-2], -wa1[i-1]) * cc3.atCmplx(i-1, k, 1) 268 ch3.setCmplx(i-1, 0, k, cc3.atCmplx(i-1, k, 0)+t2) 269 270 // This is left as conj(z1)-conj(z2) rather than conj(z1-z2) 271 // to retain current signed zero behaviour. 272 ch3.setCmplx(ic-1, 1, k, cmplx.Conj(cc3.atCmplx(i-1, k, 0))-cmplx.Conj(t2)) 273 } 274 } 275 if ido%2 == 1 { 276 return 277 } 278 } 279 for k := 0; k < l1; k++ { 280 ch3.set(0, 1, k, -cc3.at(ido-1, k, 1)) 281 ch3.set(ido-1, 0, k, cc3.at(ido-1, k, 0)) 282 } 283 } 284 285 func radf3(ido, l1 int, cc, ch, wa1, wa2 []float64) { 286 const ( 287 taur = -0.5 288 taui = 0.866025403784439 // sqrt(3)/2 289 ) 290 291 cc3 := newThreeArray(ido, l1, 3, cc) 292 ch3 := newThreeArray(ido, 3, l1, ch) 293 294 for k := 0; k < l1; k++ { 295 cr2 := cc3.at(0, k, 1) + cc3.at(0, k, 2) 296 ch3.set(0, 0, k, cc3.at(0, k, 0)+cr2) 297 ch3.set(0, 2, k, taui*(cc3.at(0, k, 2)-cc3.at(0, k, 1))) 298 ch3.set(ido-1, 1, k, cc3.at(0, k, 0)+taur*cr2) 299 } 300 if ido < 2 { 301 return 302 } 303 idp2 := ido + 1 304 for k := 0; k < l1; k++ { 305 for i := 2; i < ido; i += 2 { 306 ic := idp2 - (i + 1) 307 308 d2 := complex(wa1[i-2], -wa1[i-1]) * cc3.atCmplx(i-1, k, 1) 309 d3 := complex(wa2[i-2], -wa2[i-1]) * cc3.atCmplx(i-1, k, 2) 310 c2 := d2 + d3 311 ch3.setCmplx(i-1, 0, k, cc3.atCmplx(i-1, k, 0)+c2) 312 313 t2 := cc3.atCmplx(i-1, k, 0) + scale(taur, c2) 314 t3 := scale(taui, cmplx.Conj(swap(d2-d3))) 315 ch3.setCmplx(i-1, 2, k, t2+t3) 316 ch3.setCmplx(ic-1, 1, k, cmplx.Conj(t2-t3)) 317 } 318 } 319 } 320 321 func radf4(ido, l1 int, cc, ch, wa1, wa2, wa3 []float64) { 322 const hsqt2 = math.Sqrt2 / 2 323 324 cc3 := newThreeArray(ido, l1, 4, cc) 325 ch3 := newThreeArray(ido, 4, l1, ch) 326 327 for k := 0; k < l1; k++ { 328 tr1 := cc3.at(0, k, 1) + cc3.at(0, k, 3) 329 tr2 := cc3.at(0, k, 0) + cc3.at(0, k, 2) 330 ch3.set(0, 0, k, tr1+tr2) 331 ch3.set(ido-1, 3, k, tr2-tr1) 332 ch3.set(ido-1, 1, k, cc3.at(0, k, 0)-cc3.at(0, k, 2)) 333 ch3.set(0, 2, k, cc3.at(0, k, 3)-cc3.at(0, k, 1)) 334 } 335 if ido < 2 { 336 return 337 } 338 if ido > 2 { 339 idp2 := ido + 1 340 for k := 0; k < l1; k++ { 341 for i := 2; i < ido; i += 2 { 342 ic := idp2 - (i + 1) 343 344 c2 := complex(wa1[i-2], -wa1[i-1]) * cc3.atCmplx(i-1, k, 1) 345 c3 := complex(wa2[i-2], -wa2[i-1]) * cc3.atCmplx(i-1, k, 2) 346 c4 := complex(wa3[i-2], -wa3[i-1]) * cc3.atCmplx(i-1, k, 3) 347 t1 := c2 + c4 348 t2 := cc3.atCmplx(i-1, k, 0) + c3 349 t3 := cc3.atCmplx(i-1, k, 0) - c3 350 t4 := cmplx.Conj(c4 - c2) 351 ch3.setCmplx(i-1, 0, k, t1+t2) 352 ch3.setCmplx(ic-1, 3, k, cmplx.Conj(t2-t1)) 353 ch3.setCmplx(i-1, 2, k, swap(t4)+t3) 354 ch3.setCmplx(ic-1, 1, k, cmplx.Conj(t3-swap(t4))) 355 } 356 } 357 358 if ido%2 == 1 { 359 return 360 } 361 } 362 for k := 0; k < l1; k++ { 363 ti1 := -hsqt2 * (cc3.at(ido-1, k, 1) + cc3.at(ido-1, k, 3)) 364 tr1 := hsqt2 * (cc3.at(ido-1, k, 1) - cc3.at(ido-1, k, 3)) 365 ch3.set(ido-1, 0, k, tr1+cc3.at(ido-1, k, 0)) 366 ch3.set(ido-1, 2, k, cc3.at(ido-1, k, 0)-tr1) 367 ch3.set(0, 1, k, ti1-cc3.at(ido-1, k, 2)) 368 ch3.set(0, 3, k, ti1+cc3.at(ido-1, k, 2)) 369 } 370 } 371 372 func radf5(ido, l1 int, cc, ch, wa1, wa2, wa3, wa4 []float64) { 373 const ( 374 tr11 = 0.309016994374947 375 ti11 = 0.951056516295154 376 tr12 = -0.809016994374947 377 ti12 = 0.587785252292473 378 ) 379 380 cc3 := newThreeArray(ido, l1, 5, cc) 381 ch3 := newThreeArray(ido, 5, l1, ch) 382 383 for k := 0; k < l1; k++ { 384 cr2 := cc3.at(0, k, 4) + cc3.at(0, k, 1) 385 cr3 := cc3.at(0, k, 3) + cc3.at(0, k, 2) 386 ci4 := cc3.at(0, k, 3) - cc3.at(0, k, 2) 387 ci5 := cc3.at(0, k, 4) - cc3.at(0, k, 1) 388 ch3.set(0, 0, k, cc3.at(0, k, 0)+cr2+cr3) 389 ch3.set(ido-1, 1, k, cc3.at(0, k, 0)+tr11*cr2+tr12*cr3) 390 ch3.set(0, 2, k, ti11*ci5+ti12*ci4) 391 ch3.set(ido-1, 3, k, cc3.at(0, k, 0)+tr12*cr2+tr11*cr3) 392 ch3.set(0, 4, k, ti12*ci5-ti11*ci4) 393 } 394 395 if ido < 2 { 396 return 397 } 398 idp2 := ido + 1 399 for k := 0; k < l1; k++ { 400 for i := 2; i < ido; i += 2 { 401 ic := idp2 - (i + 1) 402 403 d2 := complex(wa1[i-2], -wa1[i-1]) * cc3.atCmplx(i-1, k, 1) 404 d3 := complex(wa2[i-2], -wa2[i-1]) * cc3.atCmplx(i-1, k, 2) 405 d4 := complex(wa3[i-2], -wa3[i-1]) * cc3.atCmplx(i-1, k, 3) 406 d5 := complex(wa4[i-2], -wa4[i-1]) * cc3.atCmplx(i-1, k, 4) 407 c2 := d2 + d5 408 c3 := d3 + d4 409 c4 := cmplx.Conj(swap(d3 - d4)) 410 c5 := cmplx.Conj(swap(d2 - d5)) 411 ch3.setCmplx(i-1, 0, k, cc3.atCmplx(i-1, k, 0)+c2+c3) 412 413 t2 := cc3.atCmplx(i-1, k, 0) + scale(tr11, c2) + scale(tr12, c3) 414 t3 := cc3.atCmplx(i-1, k, 0) + scale(tr12, c2) + scale(tr11, c3) 415 t4 := scale(ti12, c5) - scale(ti11, c4) 416 t5 := scale(ti11, c5) + scale(ti12, c4) 417 ch3.setCmplx(ic-1, 1, k, cmplx.Conj(t2-t5)) 418 ch3.setCmplx(i-1, 2, k, t2+t5) 419 ch3.setCmplx(ic-1, 3, k, cmplx.Conj(t3-t4)) 420 ch3.setCmplx(i-1, 4, k, t3+t4) 421 } 422 } 423 } 424 425 func radfg(ido, ip, l1, idl1 int, cc, c1, c2, ch, ch2, wa []float64) { 426 cc3 := newThreeArray(ido, ip, l1, cc) 427 c13 := newThreeArray(ido, l1, ip, c1) 428 ch3 := newThreeArray(ido, l1, ip, ch) 429 c2m := newTwoArray(idl1, ip, c2) 430 ch2m := newTwoArray(idl1, ip, ch2) 431 432 arg := 2 * math.Pi / float64(ip) 433 dcp := math.Cos(arg) 434 dsp := math.Sin(arg) 435 ipph := (ip + 1) / 2 436 nbd := (ido - 1) / 2 437 438 if ido == 1 { 439 for ik := 0; ik < idl1; ik++ { 440 c2m.set(ik, 0, ch2m.at(ik, 0)) 441 } 442 } else { 443 for ik := 0; ik < idl1; ik++ { 444 ch2m.set(ik, 0, c2m.at(ik, 0)) 445 } 446 for j := 1; j < ip; j++ { 447 for k := 0; k < l1; k++ { 448 ch3.set(0, k, j, c13.at(0, k, j)) 449 } 450 } 451 452 is := -ido - 1 453 if nbd > l1 { 454 for j := 1; j < ip; j++ { 455 is += ido 456 for k := 0; k < l1; k++ { 457 idij := is 458 for i := 2; i < ido; i += 2 { 459 idij += 2 460 ch3.setCmplx(i-1, k, j, complex(wa[idij-1], -wa[idij])*c13.atCmplx(i-1, k, j)) 461 } 462 } 463 } 464 } else { 465 for j := 1; j < ip; j++ { 466 is += ido 467 idij := is 468 for i := 2; i < ido; i += 2 { 469 idij += 2 470 for k := 0; k < l1; k++ { 471 ch3.setCmplx(i-1, k, j, complex(wa[idij-1], -wa[idij])*c13.atCmplx(i-1, k, j)) 472 } 473 } 474 } 475 } 476 if nbd < l1 { 477 for j := 1; j < ipph; j++ { 478 jc := ip - j 479 for i := 2; i < ido; i += 2 { 480 for k := 0; k < l1; k++ { 481 c13.setCmplx(i-1, k, j, ch3.atCmplx(i-1, k, j)+ch3.atCmplx(i-1, k, jc)) 482 c13.setCmplx(i-1, k, jc, cmplx.Conj(swap(ch3.atCmplx(i-1, k, j)-ch3.atCmplx(i-1, k, jc)))) 483 } 484 } 485 } 486 } else { 487 for j := 1; j < ipph; j++ { 488 jc := ip - j 489 for k := 0; k < l1; k++ { 490 for i := 2; i < ido; i += 2 { 491 c13.setCmplx(i-1, k, j, ch3.atCmplx(i-1, k, j)+ch3.atCmplx(i-1, k, jc)) 492 c13.setCmplx(i-1, k, jc, cmplx.Conj(swap(ch3.atCmplx(i-1, k, j)-ch3.atCmplx(i-1, k, jc)))) 493 } 494 } 495 } 496 } 497 } 498 499 for j := 1; j < ipph; j++ { 500 jc := ip - j 501 for k := 0; k < l1; k++ { 502 c13.set(0, k, j, ch3.at(0, k, j)+ch3.at(0, k, jc)) 503 c13.set(0, k, jc, ch3.at(0, k, jc)-ch3.at(0, k, j)) 504 } 505 } 506 ar1 := 1.0 507 ai1 := 0.0 508 for l := 1; l < ipph; l++ { 509 lc := ip - l 510 ar1h := dcp*ar1 - dsp*ai1 511 ai1 = dcp*ai1 + dsp*ar1 512 ar1 = ar1h 513 for ik := 0; ik < idl1; ik++ { 514 ch2m.set(ik, l, c2m.at(ik, 0)+ar1*c2m.at(ik, 1)) 515 ch2m.set(ik, lc, ai1*c2m.at(ik, ip-1)) 516 } 517 dc2 := ar1 518 ds2 := ai1 519 ar2 := ar1 520 ai2 := ai1 521 for j := 2; j < ipph; j++ { 522 jc := ip - j 523 ar2h := dc2*ar2 - ds2*ai2 524 ai2 = dc2*ai2 + ds2*ar2 525 ar2 = ar2h 526 for ik := 0; ik < idl1; ik++ { 527 ch2m.add(ik, l, ar2*c2m.at(ik, j)) 528 ch2m.add(ik, lc, ai2*c2m.at(ik, jc)) 529 } 530 } 531 } 532 for j := 1; j < ipph; j++ { 533 for ik := 0; ik < idl1; ik++ { 534 ch2m.add(ik, 0, c2m.at(ik, j)) 535 } 536 } 537 538 if ido < l1 { 539 for i := 0; i < ido; i++ { 540 for k := 0; k < l1; k++ { 541 cc3.set(i, 0, k, ch3.at(i, k, 0)) 542 } 543 } 544 } else { 545 for k := 0; k < l1; k++ { 546 for i := 0; i < ido; i++ { 547 cc3.set(i, 0, k, ch3.at(i, k, 0)) 548 } 549 } 550 } 551 for j := 1; j < ipph; j++ { 552 jc := ip - j 553 j2 := 2 * j 554 for k := 0; k < l1; k++ { 555 cc3.set(ido-1, j2-1, k, ch3.at(0, k, j)) 556 cc3.set(0, j2, k, ch3.at(0, k, jc)) 557 } 558 } 559 560 if ido == 1 { 561 return 562 } 563 if nbd < l1 { 564 for j := 1; j < ipph; j++ { 565 jc := ip - j 566 j2 := 2 * j 567 for i := 2; i < ido; i += 2 { 568 ic := ido - i 569 for k := 0; k < l1; k++ { 570 cc3.setCmplx(i-1, j2, k, ch3.atCmplx(i-1, k, j)+ch3.atCmplx(i-1, k, jc)) 571 cc3.setCmplx(ic-1, j2-1, k, cmplx.Conj(ch3.atCmplx(i-1, k, j)-ch3.atCmplx(i-1, k, jc))) 572 } 573 } 574 } 575 return 576 } 577 for j := 1; j < ipph; j++ { 578 jc := ip - j 579 j2 := 2 * j 580 for k := 0; k < l1; k++ { 581 for i := 2; i < ido; i += 2 { 582 ic := ido - i 583 584 cc3.setCmplx(i-1, j2, k, ch3.atCmplx(i-1, k, j)+ch3.atCmplx(i-1, k, jc)) 585 cc3.setCmplx(ic-1, j2-1, k, cmplx.Conj(ch3.atCmplx(i-1, k, j)-ch3.atCmplx(i-1, k, jc))) 586 } 587 } 588 } 589 } 590 591 // Rfftb computes the real perodic sequence from its Fourier 592 // coefficients (Fourier synthesis). The transform is defined 593 // below at output parameter r. 594 // 595 // Input parameters 596 // 597 // n The length of the array r to be transformed. The method 598 // is most efficient when n is a product of small primes. 599 // n may change so long as different work arrays are provided. 600 // 601 // r A real array of length n which contains the sequence 602 // to be transformed. 603 // 604 // work A work array which must be dimensioned at least 2*n. 605 // in the program that calls Rfftb. The work array must be 606 // initialized by calling subroutine rffti(n,work,ifac) and a 607 // different work array must be used for each different 608 // value of n. This initialization does not have to be 609 // repeated so long as n remains unchanged thus subsequent 610 // transforms can be obtained faster than the first. 611 // The same work array can be used by Rfftf and Rfftb. 612 // 613 // ifac A work array containing the factors of n. ifac must have 614 // length of at least 15. 615 // 616 // output parameters 617 // 618 // r for n even and for i = 0, ..., n 619 // r[i] = r[0]+(-1)^i*r[n-1] 620 // plus the sum from k=1 to k=n/2-1 of 621 // 2*r(2*k-1)*cos(k*i*2*pi/n) 622 // -2*r(2*k)*sin(k*i*2*pi/n) 623 // 624 // for n odd and for i = 0, ..., n-1 625 // r[i] = r[0] plus the sum from k=1 to k=(n-1)/2 of 626 // 2*r(2*k-1)*cos(k*i*2*pi/n) 627 // -2*r(2*k)*sin(k*i*2*pi/n) 628 // 629 // This transform is unnormalized since a call of Rfftf 630 // followed by a call of Rfftb will multiply the input 631 // sequence by n. 632 // 633 // work Contains results which must not be destroyed between 634 // calls of Rfftf or Rfftb. 635 // ifac Contains results which must not be destroyed between 636 // calls of Rfftf or Rfftb. 637 func Rfftb(n int, r, work []float64, ifac []int) { 638 if len(r) < n { 639 panic("fourier: short sequence") 640 } 641 if len(work) < 2*n { 642 panic("fourier: short work") 643 } 644 if len(ifac) < 15 { 645 panic("fourier: short ifac") 646 } 647 if n == 1 { 648 return 649 } 650 rfftb1(n, r[:n], work[:n], work[n:2*n], ifac[:15]) 651 } 652 653 func rfftb1(n int, c, ch, wa []float64, ifac []int) { 654 nf := ifac[1] 655 na := false 656 l1 := 1 657 iw := 0 658 659 for k1 := 1; k1 <= nf; k1++ { 660 ip := ifac[k1+1] 661 l2 := ip * l1 662 ido := n / l2 663 idl1 := ido * l1 664 665 switch ip { 666 case 4: 667 ix2 := iw + ido 668 ix3 := ix2 + ido 669 if na { 670 radb4(ido, l1, ch, c, wa[iw:], wa[ix2:], wa[ix3:]) 671 } else { 672 radb4(ido, l1, c, ch, wa[iw:], wa[ix2:], wa[ix3:]) 673 } 674 na = !na 675 case 2: 676 if na { 677 radb2(ido, l1, ch, c, wa[iw:]) 678 } else { 679 radb2(ido, l1, c, ch, wa[iw:]) 680 } 681 na = !na 682 case 3: 683 ix2 := iw + ido 684 if na { 685 radb3(ido, l1, ch, c, wa[iw:], wa[ix2:]) 686 } else { 687 radb3(ido, l1, c, ch, wa[iw:], wa[ix2:]) 688 } 689 na = !na 690 case 5: 691 ix2 := iw + ido 692 ix3 := ix2 + ido 693 ix4 := ix3 + ido 694 if na { 695 radb5(ido, l1, ch, c, wa[iw:], wa[ix2:], wa[ix3:], wa[ix4:]) 696 } else { 697 radb5(ido, l1, c, ch, wa[iw:], wa[ix2:], wa[ix3:], wa[ix4:]) 698 } 699 na = !na 700 default: 701 if na { 702 radbg(ido, ip, l1, idl1, ch, ch, ch, c, c, wa[iw:]) 703 } else { 704 radbg(ido, ip, l1, idl1, c, c, c, ch, ch, wa[iw:]) 705 } 706 if ido == 1 { 707 na = !na 708 } 709 } 710 711 l1 = l2 712 iw += (ip - 1) * ido 713 } 714 715 if na { 716 for i := 0; i < n; i++ { 717 c[i] = ch[i] 718 } 719 } 720 } 721 722 func radb2(ido, l1 int, cc, ch, wa1 []float64) { 723 cc3 := newThreeArray(ido, 2, l1, cc) 724 ch3 := newThreeArray(ido, l1, 2, ch) 725 726 for k := 0; k < l1; k++ { 727 ch3.set(0, k, 0, cc3.at(0, 0, k)+cc3.at(ido-1, 1, k)) 728 ch3.set(0, k, 1, cc3.at(0, 0, k)-cc3.at(ido-1, 1, k)) 729 } 730 731 if ido < 2 { 732 return 733 } 734 if ido > 2 { 735 idp2 := ido + 1 736 for k := 0; k < l1; k++ { 737 for i := 2; i < ido; i += 2 { 738 ic := idp2 - (i + 1) 739 740 ch3.setCmplx(i-1, k, 0, cc3.atCmplx(i-1, 0, k)+cmplx.Conj(cc3.atCmplx(ic-1, 1, k))) 741 742 t2 := cc3.atCmplx(i-1, 0, k) - cmplx.Conj(cc3.atCmplx(ic-1, 1, k)) 743 ch3.setCmplx(i-1, k, 1, complex(wa1[i-2], wa1[i-1])*t2) 744 } 745 } 746 747 if ido%2 == 1 { 748 return 749 } 750 } 751 for k := 0; k < l1; k++ { 752 ch3.set(ido-1, k, 0, 2*cc3.at(ido-1, 0, k)) 753 ch3.set(ido-1, k, 1, -2*cc3.at(0, 1, k)) 754 } 755 } 756 757 func radb3(ido, l1 int, cc, ch, wa1, wa2 []float64) { 758 const ( 759 taur = -0.5 760 taui = 0.866025403784439 // sqrt(3)/2 761 ) 762 763 cc3 := newThreeArray(ido, 3, l1, cc) 764 ch3 := newThreeArray(ido, l1, 3, ch) 765 766 for k := 0; k < l1; k++ { 767 tr2 := cc3.at(ido-1, 1, k) + cc3.at(ido-1, 1, k) 768 cr2 := cc3.at(0, 0, k) + taur*tr2 769 ch3.set(0, k, 0, cc3.at(0, 0, k)+tr2) 770 ci3 := taui * (cc3.at(0, 2, k) + cc3.at(0, 2, k)) 771 ch3.set(0, k, 1, cr2-ci3) 772 ch3.set(0, k, 2, cr2+ci3) 773 } 774 775 if ido == 1 { 776 return 777 } 778 779 idp2 := ido + 1 780 for k := 0; k < l1; k++ { 781 for i := 2; i < ido; i += 2 { 782 ic := idp2 - (i + 1) 783 784 t2 := cc3.atCmplx(i-1, 2, k) + cmplx.Conj(cc3.atCmplx(ic-1, 1, k)) 785 c2 := cc3.atCmplx(i-1, 0, k) + scale(taur, t2) 786 ch3.setCmplx(i-1, k, 0, cc3.atCmplx(i-1, 0, k)+t2) 787 788 c3 := scale(taui, cc3.atCmplx(i-1, 2, k)-cmplx.Conj(cc3.atCmplx(ic-1, 1, k))) 789 d2 := c2 - cmplx.Conj(swap(c3)) 790 d3 := c2 + cmplx.Conj(swap(c3)) 791 ch3.setCmplx(i-1, k, 1, complex(wa1[i-2], wa1[i-1])*d2) 792 ch3.setCmplx(i-1, k, 2, complex(wa2[i-2], wa2[i-1])*d3) 793 } 794 } 795 } 796 797 func radb4(ido, l1 int, cc, ch, wa1, wa2, wa3 []float64) { 798 cc3 := newThreeArray(ido, 4, l1, cc) 799 ch3 := newThreeArray(ido, l1, 4, ch) 800 801 for k := 0; k < l1; k++ { 802 tr1 := cc3.at(0, 0, k) - cc3.at(ido-1, 3, k) 803 tr2 := cc3.at(0, 0, k) + cc3.at(ido-1, 3, k) 804 tr3 := cc3.at(ido-1, 1, k) + cc3.at(ido-1, 1, k) 805 tr4 := cc3.at(0, 2, k) + cc3.at(0, 2, k) 806 ch3.set(0, k, 0, tr2+tr3) 807 ch3.set(0, k, 1, tr1-tr4) 808 ch3.set(0, k, 2, tr2-tr3) 809 ch3.set(0, k, 3, tr1+tr4) 810 } 811 812 if ido < 2 { 813 return 814 } 815 if ido > 2 { 816 idp2 := ido + 1 817 for k := 0; k < l1; k++ { 818 for i := 2; i < ido; i += 2 { 819 ic := idp2 - (i + 1) 820 821 t1 := cc3.atCmplx(i-1, 0, k) - cmplx.Conj(cc3.atCmplx(ic-1, 3, k)) 822 t2 := cc3.atCmplx(i-1, 0, k) + cmplx.Conj(cc3.atCmplx(ic-1, 3, k)) 823 t3 := cc3.atCmplx(i-1, 2, k) + cmplx.Conj(cc3.atCmplx(ic-1, 1, k)) 824 t4 := swap(cc3.atCmplx(i-1, 2, k) - cmplx.Conj(cc3.atCmplx(ic-1, 1, k))) 825 ch3.setCmplx(i-1, k, 0, t2+t3) 826 827 c2 := t1 - cmplx.Conj(t4) 828 c3 := t2 - t3 829 c4 := t1 + cmplx.Conj(t4) 830 ch3.setCmplx(i-1, k, 1, complex(wa1[i-2], wa1[i-1])*c2) 831 ch3.setCmplx(i-1, k, 2, complex(wa2[i-2], wa2[i-1])*c3) 832 ch3.setCmplx(i-1, k, 3, complex(wa3[i-2], wa3[i-1])*c4) 833 } 834 } 835 836 if ido%2 == 1 { 837 return 838 } 839 } 840 for k := 0; k < l1; k++ { 841 tr1 := cc3.at(ido-1, 0, k) - cc3.at(ido-1, 2, k) 842 ti1 := cc3.at(0, 1, k) + cc3.at(0, 3, k) 843 tr2 := cc3.at(ido-1, 0, k) + cc3.at(ido-1, 2, k) 844 ti2 := cc3.at(0, 3, k) - cc3.at(0, 1, k) 845 ch3.set(ido-1, k, 0, tr2+tr2) 846 ch3.set(ido-1, k, 1, math.Sqrt2*(tr1-ti1)) 847 ch3.set(ido-1, k, 2, ti2+ti2) 848 ch3.set(ido-1, k, 3, -math.Sqrt2*(tr1+ti1)) 849 } 850 } 851 852 func radb5(ido, l1 int, cc, ch, wa1, wa2, wa3, wa4 []float64) { 853 const ( 854 tr11 = 0.309016994374947 855 ti11 = 0.951056516295154 856 tr12 = -0.809016994374947 857 ti12 = 0.587785252292473 858 ) 859 860 cc3 := newThreeArray(ido, 5, l1, cc) 861 ch3 := newThreeArray(ido, l1, 5, ch) 862 863 for k := 0; k < l1; k++ { 864 tr2 := cc3.at(ido-1, 1, k) + cc3.at(ido-1, 1, k) 865 tr3 := cc3.at(ido-1, 3, k) + cc3.at(ido-1, 3, k) 866 ti4 := cc3.at(0, 4, k) + cc3.at(0, 4, k) 867 ti5 := cc3.at(0, 2, k) + cc3.at(0, 2, k) 868 ch3.set(0, k, 0, cc3.at(0, 0, k)+tr2+tr3) 869 870 cr2 := cc3.at(0, 0, k) + tr11*tr2 + tr12*tr3 871 872 cr3 := cc3.at(0, 0, k) + tr12*tr2 + tr11*tr3 873 874 ci4 := ti12*ti5 - ti11*ti4 875 876 ci5 := ti11*ti5 + ti12*ti4 877 878 ch3.set(0, k, 1, cr2-ci5) 879 ch3.set(0, k, 2, cr3-ci4) 880 ch3.set(0, k, 3, cr3+ci4) 881 ch3.set(0, k, 4, cr2+ci5) 882 } 883 884 if ido == 1 { 885 return 886 } 887 888 idp2 := ido + 1 889 for k := 0; k < l1; k++ { 890 for i := 2; i < ido; i += 2 { 891 ic := idp2 - (i + 1) 892 893 t2 := cc3.atCmplx(i-1, 2, k) + cmplx.Conj(cc3.atCmplx(ic-1, 1, k)) 894 t3 := cc3.atCmplx(i-1, 4, k) + cmplx.Conj(cc3.atCmplx(ic-1, 3, k)) 895 t4 := cc3.atCmplx(i-1, 4, k) - cmplx.Conj(cc3.atCmplx(ic-1, 3, k)) 896 t5 := cc3.atCmplx(i-1, 2, k) - cmplx.Conj(cc3.atCmplx(ic-1, 1, k)) 897 ch3.setCmplx(i-1, k, 0, cc3.atCmplx(i-1, 0, k)+t2+t3) 898 899 c2 := cc3.atCmplx(i-1, 0, k) + scale(tr11, t2) + scale(tr12, t3) 900 c3 := cc3.atCmplx(i-1, 0, k) + scale(tr12, t2) + scale(tr11, t3) 901 c4 := scale(ti12, t5) - scale(ti11, t4) 902 c5 := scale(ti11, t5) + scale(ti12, t4) 903 d2 := c2 - cmplx.Conj(swap(c5)) 904 d3 := c3 - cmplx.Conj(swap(c4)) 905 d4 := c3 + cmplx.Conj(swap(c4)) 906 d5 := c2 + cmplx.Conj(swap(c5)) 907 ch3.setCmplx(i-1, k, 1, complex(wa1[i-2], wa1[i-1])*d2) 908 ch3.setCmplx(i-1, k, 2, complex(wa2[i-2], wa2[i-1])*d3) 909 ch3.setCmplx(i-1, k, 3, complex(wa3[i-2], wa3[i-1])*d4) 910 ch3.setCmplx(i-1, k, 4, complex(wa4[i-2], wa4[i-1])*d5) 911 } 912 } 913 } 914 915 func radbg(ido, ip, l1, idl1 int, cc, c1, c2, ch, ch2, wa []float64) { 916 cc3 := newThreeArray(ido, ip, l1, cc) 917 c13 := newThreeArray(ido, l1, ip, c1) 918 ch3 := newThreeArray(ido, l1, ip, ch) 919 c2m := newTwoArray(idl1, ip, c2) 920 ch2m := newTwoArray(idl1, ip, ch2) 921 922 arg := 2 * math.Pi / float64(ip) 923 dcp := math.Cos(arg) 924 dsp := math.Sin(arg) 925 ipph := (ip + 1) / 2 926 nbd := (ido - 1) / 2 927 928 if ido < l1 { 929 for i := 0; i < ido; i++ { 930 for k := 0; k < l1; k++ { 931 ch3.set(i, k, 0, cc3.at(i, 0, k)) 932 } 933 } 934 } else { 935 for k := 0; k < l1; k++ { 936 for i := 0; i < ido; i++ { 937 ch3.set(i, k, 0, cc3.at(i, 0, k)) 938 } 939 } 940 } 941 942 for j := 1; j < ipph; j++ { 943 jc := ip - j 944 j2 := 2 * j 945 for k := 0; k < l1; k++ { 946 ch3.set(0, k, j, cc3.at(ido-1, j2-1, k)+cc3.at(ido-1, j2-1, k)) 947 ch3.set(0, k, jc, cc3.at(0, j2, k)+cc3.at(0, j2, k)) 948 } 949 } 950 951 if ido != 1 { 952 if nbd < l1 { 953 for j := 1; j < ipph; j++ { 954 jc := ip - j 955 j2 := 2 * j 956 for i := 2; i < ido; i += 2 { 957 ic := ido - i 958 for k := 0; k < l1; k++ { 959 ch3.setCmplx(i-1, k, j, cc3.atCmplx(i-1, j2, k)+cmplx.Conj(cc3.atCmplx(ic-1, j2-1, k))) 960 ch3.setCmplx(i-1, k, jc, cc3.atCmplx(i-1, j2, k)-cmplx.Conj(cc3.atCmplx(ic-1, j2-1, k))) 961 } 962 } 963 } 964 } else { 965 for j := 1; j < ipph; j++ { 966 jc := ip - j 967 j2 := 2 * j 968 for k := 0; k < l1; k++ { 969 for i := 2; i < ido; i += 2 { 970 ic := ido - i 971 ch3.setCmplx(i-1, k, j, cc3.atCmplx(i-1, j2, k)+cmplx.Conj(cc3.atCmplx(ic-1, j2-1, k))) 972 ch3.setCmplx(i-1, k, jc, cc3.atCmplx(i-1, j2, k)-cmplx.Conj(cc3.atCmplx(ic-1, j2-1, k))) 973 } 974 } 975 } 976 } 977 } 978 979 ar1 := 1.0 980 ai1 := 0.0 981 for l := 1; l < ipph; l++ { 982 lc := ip - l 983 ar1h := dcp*ar1 - dsp*ai1 984 ai1 = dcp*ai1 + dsp*ar1 985 ar1 = ar1h 986 for ik := 0; ik < idl1; ik++ { 987 c2m.set(ik, l, ch2m.at(ik, 0)+ar1*ch2m.at(ik, 1)) 988 c2m.set(ik, lc, ai1*ch2m.at(ik, ip-1)) 989 } 990 dc2 := ar1 991 ds2 := ai1 992 ar2 := ar1 993 ai2 := ai1 994 for j := 2; j < ipph; j++ { 995 jc := ip - j 996 ar2h := dc2*ar2 - ds2*ai2 997 ai2 = dc2*ai2 + ds2*ar2 998 ar2 = ar2h 999 for ik := 0; ik < idl1; ik++ { 1000 c2m.add(ik, l, ar2*ch2m.at(ik, j)) 1001 c2m.add(ik, lc, ai2*ch2m.at(ik, jc)) 1002 } 1003 } 1004 } 1005 1006 for j := 1; j < ipph; j++ { 1007 for ik := 0; ik < idl1; ik++ { 1008 ch2m.add(ik, 0, ch2m.at(ik, j)) 1009 } 1010 } 1011 for j := 1; j < ipph; j++ { 1012 jc := ip - j 1013 for k := 0; k < l1; k++ { 1014 ch3.set(0, k, j, c13.at(0, k, j)-c13.at(0, k, jc)) 1015 ch3.set(0, k, jc, c13.at(0, k, j)+c13.at(0, k, jc)) 1016 } 1017 } 1018 1019 if ido != 1 { 1020 if nbd < l1 { 1021 for j := 1; j < ipph; j++ { 1022 jc := ip - j 1023 for i := 2; i < ido; i += 2 { 1024 for k := 0; k < l1; k++ { 1025 ch3.setCmplx(i-1, k, j, c13.atCmplx(i-1, k, j)-cmplx.Conj(swap(c13.atCmplx(i-1, k, jc)))) 1026 ch3.setCmplx(i-1, k, jc, c13.atCmplx(i-1, k, j)+cmplx.Conj(swap(c13.atCmplx(i-1, k, jc)))) 1027 } 1028 } 1029 } 1030 } else { 1031 for j := 1; j < ipph; j++ { 1032 jc := ip - j 1033 for k := 0; k < l1; k++ { 1034 for i := 2; i < ido; i += 2 { 1035 ch3.setCmplx(i-1, k, j, c13.atCmplx(i-1, k, j)-cmplx.Conj(swap(c13.atCmplx(i-1, k, jc)))) 1036 ch3.setCmplx(i-1, k, jc, c13.atCmplx(i-1, k, j)+cmplx.Conj(swap(c13.atCmplx(i-1, k, jc)))) 1037 } 1038 } 1039 } 1040 } 1041 } 1042 1043 if ido == 1 { 1044 return 1045 } 1046 for ik := 0; ik < idl1; ik++ { 1047 c2m.set(ik, 0, ch2m.at(ik, 0)) 1048 } 1049 for j := 1; j < ip; j++ { 1050 for k := 0; k < l1; k++ { 1051 c13.set(0, k, j, ch3.at(0, k, j)) 1052 } 1053 } 1054 1055 is := -ido - 1 1056 if nbd > l1 { 1057 for j := 1; j < ip; j++ { 1058 is += ido 1059 for k := 0; k < l1; k++ { 1060 idij := is 1061 for i := 2; i < ido; i += 2 { 1062 idij += 2 1063 c13.setCmplx(i-1, k, j, complex(wa[idij-1], wa[idij])*ch3.atCmplx(i-1, k, j)) 1064 } 1065 } 1066 } 1067 return 1068 } 1069 for j := 1; j < ip; j++ { 1070 is += ido 1071 idij := is 1072 for i := 2; i < ido; i += 2 { 1073 idij += 2 1074 for k := 0; k < l1; k++ { 1075 c13.setCmplx(i-1, k, j, complex(wa[idij-1], wa[idij])*ch3.atCmplx(i-1, k, j)) 1076 } 1077 } 1078 } 1079 }