gonum.org/v1/gonum@v0.14.0/dsp/fourier/internal/fftpack/cosq.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 cosq 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 "math" 12 13 // Cosqi initializes the array work which is used in both Cosqf 14 // and Cosqb. The prime factorization of n together with a 15 // tabulation of the trigonometric functions are computed and 16 // stored in work. 17 // 18 // Input parameter: 19 // 20 // n The length of the sequence to be transformed. the method 21 // is most efficient when n+1 is a product of small primes. 22 // 23 // Output parameters: 24 // 25 // work A work array which must be dimensioned at least 3*n. 26 // The same work array can be used for both Cosqf and Cosqb 27 // as long as n remains unchanged. Different work arrays 28 // are required for different values of n. The contents of 29 // work must not be changed between calls of Cosqf or Cosqb. 30 // 31 // ifac An integer work array of length at least 15. 32 func Cosqi(n int, work []float64, ifac []int) { 33 if len(work) < 3*n { 34 panic("fourier: short work") 35 } 36 if len(ifac) < 15 { 37 panic("fourier: short ifac") 38 } 39 dt := 0.5 * math.Pi / float64(n) 40 for k := range work[:n] { 41 work[k] = math.Cos(float64(k+1) * dt) 42 } 43 Rffti(n, work[n:], ifac) 44 } 45 46 // Cosqf computes the Fast Fourier Transform of quarter wave data. 47 // That is, Cosqf computes the coefficients in a cosine series 48 // representation with only odd wave numbers. The transform is 49 // defined below at output parameter x. 50 // 51 // Cosqb is the unnormalized inverse of Cosqf since a call of Cosqf 52 // followed by a call of Cosqb will multiply the input sequence x 53 // by 4*n. 54 // 55 // The array work which is used by subroutine Cosqf must be 56 // initialized by calling subroutine Cosqi(n,work). 57 // 58 // Input parameters: 59 // 60 // n The length of the array x to be transformed. The method 61 // is most efficient when n is a product of small primes. 62 // 63 // x An array which contains the sequence to be transformed. 64 // 65 // work A work array which must be dimensioned at least 3*n 66 // in the program that calls Cosqf. The work array must be 67 // initialized by calling subroutine Cosqi(n,work) and a 68 // different work array must be used for each different 69 // value of n. This initialization does not have to be 70 // repeated so long as n remains unchanged thus subsequent 71 // transforms can be obtained faster than the first. 72 // 73 // ifac An integer work array of length at least 15. 74 // 75 // Output parameters: 76 // 77 // x for i=0, ..., n-1 78 // x[i] = x[i] + the sum from k=0 to k=n-2 of 79 // 2*x[k]*cos((2*i+1)*k*pi/(2*n)) 80 // 81 // A call of Cosqf followed by a call of 82 // Cosqb will multiply the sequence x by 4*n. 83 // Therefore Cosqb is the unnormalized inverse 84 // of Cosqf. 85 // 86 // work Contains initialization calculations which must not 87 // be destroyed between calls of Cosqf or Cosqb. 88 func Cosqf(n int, x, work []float64, ifac []int) { 89 if len(x) < n { 90 panic("fourier: short sequence") 91 } 92 if len(work) < 3*n { 93 panic("fourier: short work") 94 } 95 if len(ifac) < 15 { 96 panic("fourier: short ifac") 97 } 98 if n < 2 { 99 return 100 } 101 if n == 2 { 102 tsqx := math.Sqrt2 * x[1] 103 x[1] = x[0] - tsqx 104 x[0] += tsqx 105 return 106 } 107 cosqf1(n, x, work, work[n:], ifac) 108 } 109 110 func cosqf1(n int, x, w, xh []float64, ifac []int) { 111 for k := 1; k < (n+1)/2; k++ { 112 kc := n - k 113 xh[k] = x[k] + x[kc] 114 xh[kc] = x[k] - x[kc] 115 } 116 if n%2 == 0 { 117 xh[(n+1)/2] = 2 * x[(n+1)/2] 118 } 119 for k := 1; k < (n+1)/2; k++ { 120 kc := n - k 121 x[k] = w[k-1]*xh[kc] + w[kc-1]*xh[k] 122 x[kc] = w[k-1]*xh[k] - w[kc-1]*xh[kc] 123 } 124 if n%2 == 0 { 125 x[(n+1)/2] = w[(n-1)/2] * xh[(n+1)/2] 126 } 127 Rfftf(n, x, xh, ifac) 128 for i := 2; i < n; i += 2 { 129 x[i-1], x[i] = x[i-1]-x[i], x[i-1]+x[i] 130 } 131 } 132 133 // Cosqb computes the Fast Fourier Transform of quarter wave data. 134 // That is, Cosqb computes a sequence from its representation in 135 // terms of a cosine series with odd wave numbers. The transform 136 // is defined below at output parameter x. 137 // 138 // Cosqf is the unnormalized inverse of Cosqb since a call of Cosqb 139 // followed by a call of Cosqf will multiply the input sequence x 140 // by 4*n. 141 // 142 // The array work which is used by subroutine Cosqb must be 143 // initialized by calling subroutine Cosqi(n,work). 144 // 145 // Input parameters: 146 // 147 // n The length of the array x to be transformed. The method 148 // is most efficient when n is a product of small primes. 149 // 150 // x An array which contains the sequence to be transformed. 151 // 152 // work A work array which must be dimensioned at least 3*n 153 // in the program that calls Cosqb. The work array must be 154 // initialized by calling subroutine Cosqi(n,work) and a 155 // different work array must be used for each different 156 // value of n. This initialization does not have to be 157 // repeated so long as n remains unchanged thus subsequent 158 // transforms can be obtained faster than the first. 159 // 160 // ifac An integer work array of length at least 15. 161 // 162 // Output parameters: 163 // 164 // x for i=0, ..., n-1 165 // x[i]= the sum from k=0 to k=n-1 of 166 // 4*x[k]*cos((2*k+1)*i*pi/(2*n)) 167 // 168 // A call of Cosqb followed by a call of 169 // Cosqf will multiply the sequence x by 4*n. 170 // Therefore Cosqf is the unnormalized inverse 171 // of Cosqb. 172 // 173 // work Contains initialization calculations which must not 174 // be destroyed between calls of Cosqb or Cosqf. 175 func Cosqb(n int, x, work []float64, ifac []int) { 176 if len(x) < n { 177 panic("fourier: short sequence") 178 } 179 if len(work) < 3*n { 180 panic("fourier: short work") 181 } 182 if len(ifac) < 15 { 183 panic("fourier: short ifac") 184 } 185 186 if n < 2 { 187 x[0] *= 4 188 return 189 } 190 if n == 2 { 191 x[0], x[1] = 4*(x[0]+x[1]), 2*math.Sqrt2*(x[0]-x[1]) 192 return 193 } 194 cosqb1(n, x, work, work[n:], ifac) 195 } 196 197 func cosqb1(n int, x, w, xh []float64, ifac []int) { 198 for i := 2; i < n; i += 2 { 199 x[i-1], x[i] = x[i-1]+x[i], x[i]-x[i-1] 200 } 201 x[0] *= 2 202 if n%2 == 0 { 203 x[n-1] *= 2 204 } 205 Rfftb(n, x, xh, ifac) 206 for k := 1; k < (n+1)/2; k++ { 207 kc := n - k 208 xh[k] = w[k-1]*x[kc] + w[kc-1]*x[k] 209 xh[kc] = w[k-1]*x[k] - w[kc-1]*x[kc] 210 } 211 if n%2 == 0 { 212 x[(n+1)/2] *= 2 * w[(n-1)/2] 213 } 214 for k := 1; k < (n+1)/2; k++ { 215 x[k] = xh[k] + xh[n-k] 216 x[n-k] = xh[k] - xh[n-k] 217 } 218 x[0] *= 2 219 }