github.com/gopherd/gonum@v0.0.4/dsp/fourier/internal/fftpack/cost.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 cost 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  // Costi initializes the array work which is used in subroutine
    14  // Cost. The prime factorization of n together with a tabulation
    15  // of the trigonometric functions are computed and stored in work.
    16  //
    17  // Input parameter
    18  //
    19  // n       The length of the sequence to be transformed. The method
    20  //         is most efficient when n-1 is a product of small primes.
    21  //
    22  // Output parameters
    23  //
    24  // work    A work array which must be dimensioned at least 3*n.
    25  //         Different work arrays are required for different values
    26  //         of n. The contents of work must not be changed between
    27  //         calls of Cost.
    28  //
    29  // ifac    An integer work array of length at least 15.
    30  func Costi(n int, work []float64, ifac []int) {
    31  	if len(work) < 3*n {
    32  		panic("fourier: short work")
    33  	}
    34  	if len(ifac) < 15 {
    35  		panic("fourier: short ifac")
    36  	}
    37  	if n < 4 {
    38  		return
    39  	}
    40  	dt := math.Pi / float64(n-1)
    41  	for k := 1; k < n/2; k++ {
    42  		fk := float64(k)
    43  		work[k] = 2 * math.Sin(fk*dt)
    44  		work[n-k-1] = 2 * math.Cos(fk*dt)
    45  	}
    46  	Rffti(n-1, work[n:], ifac)
    47  }
    48  
    49  // Cost computes the Discrete Fourier Cosine Transform of an even
    50  // sequence x(i). The transform is defined below at output parameter x.
    51  //
    52  // Cost is the unnormalized inverse of itself since a call of Cost
    53  // followed by another call of Cost will multiply the input sequence
    54  // x by 2*(n-1). The transform is defined below at output parameter x
    55  //
    56  // The array work which is used by subroutine Cost must be
    57  // initialized by calling subroutine Costi(n,work).
    58  //
    59  // Input parameters
    60  //
    61  // n       The length of the sequence x. n must be greater than 1.
    62  //         The method is most efficient when n-1 is a product of
    63  //         small primes.
    64  //
    65  // x       An array which contains the sequence to be transformed.
    66  //
    67  // work    A work array which must be dimensioned at least 3*n
    68  //         in the program that calls Cost. The work array must be
    69  //         initialized by calling subroutine Costi(n,work) and a
    70  //         different work array must be used for each different
    71  //         value of n. This initialization does not have to be
    72  //         repeated so long as n remains unchanged thus subsequent
    73  //         transforms can be obtained faster than the first.
    74  //
    75  // ifac    An integer work array of length at least 15.
    76  //
    77  // Output parameters
    78  //
    79  // x       for i=1,...,n
    80  //           x(i) = x(1)+(-1)**(i-1)*x(n)
    81  //             + the sum from k=2 to k=n-1
    82  //               2*x(k)*cos((k-1)*(i-1)*pi/(n-1))
    83  //
    84  //         A call of Cost followed by another call of
    85  //         Cost will multiply the sequence x by 2*(n-1).
    86  //         Hence Cost is the unnormalized inverse
    87  //         of itself.
    88  //
    89  // work    Contains initialization calculations which must not be
    90  //         destroyed between calls of Cost.
    91  //
    92  // ifac    An integer work array of length at least 15.
    93  func Cost(n int, x, work []float64, ifac []int) {
    94  	if len(x) < n {
    95  		panic("fourier: short sequence")
    96  	}
    97  	if len(work) < 3*n {
    98  		panic("fourier: short work")
    99  	}
   100  	if len(ifac) < 15 {
   101  		panic("fourier: short ifac")
   102  	}
   103  	if n < 2 {
   104  		return
   105  	}
   106  	switch n {
   107  	case 2:
   108  		x[0], x[1] = x[0]+x[1], x[0]-x[1]
   109  	case 3:
   110  		x1p3 := x[0] + x[2]
   111  		tx2 := 2 * x[1]
   112  		x[1] = x[0] - x[2]
   113  		x[0] = x1p3 + tx2
   114  		x[2] = x1p3 - tx2
   115  	default:
   116  		c1 := x[0] - x[n-1]
   117  		x[0] += x[n-1]
   118  		for k := 1; k < n/2; k++ {
   119  			kc := n - k - 1
   120  			t1 := x[k] + x[kc]
   121  			t2 := x[k] - x[kc]
   122  			c1 += work[kc] * t2
   123  			t2 *= work[k]
   124  			x[k] = t1 - t2
   125  			x[kc] = t1 + t2
   126  		}
   127  		if n%2 != 0 {
   128  			x[n/2] *= 2
   129  		}
   130  		Rfftf(n-1, x, work[n:], ifac)
   131  		xim2 := x[1]
   132  		x[1] = c1
   133  		for i := 3; i < n; i += 2 {
   134  			xi := x[i]
   135  			x[i] = x[i-2] - x[i-1]
   136  			x[i-1] = xim2
   137  			xim2 = xi
   138  		}
   139  		if n%2 != 0 {
   140  			x[n-1] = xim2
   141  		}
   142  	}
   143  }