github.com/gopherd/gonum@v0.0.4/dsp/fourier/internal/fftpack/sint.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 sint 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  // Sinti initializes the array work which is used in subroutine Sint.
    14  // The prime factorization of n together with a tabulation of the
    15  // 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 parameter
    23  //
    24  // work    A work array with at least ceil(2.5*n) locations.
    25  //         Different work arrays are required for different values
    26  //         of n. The contents of work must not be changed between
    27  //         calls of Sint.
    28  //
    29  // ifac    An integer work array of length at least 15.
    30  func Sinti(n int, work []float64, ifac []int) {
    31  	if len(work) < 5*(n+1)/2 {
    32  		panic("fourier: short work")
    33  	}
    34  	if len(ifac) < 15 {
    35  		panic("fourier: short ifac")
    36  	}
    37  	if n <= 1 {
    38  		return
    39  	}
    40  	dt := math.Pi / float64(n+1)
    41  	for k := 0; k < n/2; k++ {
    42  		work[k] = 2 * math.Sin(float64(k+1)*dt)
    43  	}
    44  	Rffti(n+1, work[n/2:], ifac)
    45  }
    46  
    47  // Sint computes the Discrete Fourier Sine Transform of an odd
    48  // sequence x(i). The transform is defined below at output parameter x.
    49  //
    50  // Sint is the unnormalized inverse of itself since a call of Sint
    51  // followed by another call of Sint will multiply the input sequence
    52  // x by 2*(n+1).
    53  //
    54  // The array work which is used by subroutine Sint must be
    55  // initialized by calling subroutine Sinti(n,work).
    56  //
    57  // Input parameters
    58  //
    59  // n       The length of the sequence to be transformed. The method
    60  //         is most efficient when n+1 is the product of small primes.
    61  //
    62  // x       An array which contains the sequence to be transformed.
    63  //
    64  //
    65  // work    A work array with dimension at least ceil(2.5*n)
    66  //         in the program that calls Sint. The work array must be
    67  //         initialized by calling subroutine Sinti(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=1,...,n
    78  //           x(i)= the sum from k=1 to k=n
    79  //             2*x(k)*sin(k*i*pi/(n+1))
    80  //
    81  //         A call of Sint followed by another call of
    82  //         Sint will multiply the sequence x by 2*(n+1).
    83  //         Hence Sint is the unnormalized inverse
    84  //         of itself.
    85  //
    86  // work    Contains initialization calculations which must not be
    87  //         destroyed between calls of Sint.
    88  // ifac    Contains initialization calculations which must not be
    89  //         destroyed between calls of Sint.
    90  func Sint(n int, x, work []float64, ifac []int) {
    91  	if len(x) < n {
    92  		panic("fourier: short sequence")
    93  	}
    94  	if len(work) < 5*(n+1)/2 {
    95  		panic("fourier: short work")
    96  	}
    97  	if len(ifac) < 15 {
    98  		panic("fourier: short ifac")
    99  	}
   100  	if n == 0 {
   101  		return
   102  	}
   103  	sint1(n, x, work, work[n/2:], work[n/2+n+1:], ifac)
   104  }
   105  
   106  func sint1(n int, war, was, xh, x []float64, ifac []int) {
   107  	const sqrt3 = 1.73205080756888
   108  
   109  	for i := 0; i < n; i++ {
   110  		xh[i] = war[i]
   111  		war[i] = x[i]
   112  	}
   113  
   114  	switch n {
   115  	case 1:
   116  		xh[0] *= 2
   117  	case 2:
   118  		xh[0], xh[1] = sqrt3*(xh[0]+xh[1]), sqrt3*(xh[0]-xh[1])
   119  	default:
   120  		x[0] = 0
   121  		for k := 0; k < n/2; k++ {
   122  			kc := n - k - 1
   123  			t1 := xh[k] - xh[kc]
   124  			t2 := was[k] * (xh[k] + xh[kc])
   125  			x[k+1] = t1 + t2
   126  			x[kc+1] = t2 - t1
   127  		}
   128  		if n%2 != 0 {
   129  			x[n/2+1] = 4 * xh[n/2]
   130  		}
   131  		rfftf1(n+1, x, xh, war, ifac)
   132  		xh[0] = 0.5 * x[0]
   133  		for i := 2; i < n; i += 2 {
   134  			xh[i-1] = -x[i]
   135  			xh[i] = xh[i-2] + x[i-1]
   136  		}
   137  		if n%2 == 0 {
   138  			xh[n-1] = -x[n]
   139  		}
   140  	}
   141  
   142  	for i := 0; i < n; i++ {
   143  		x[i] = war[i]
   144  		war[i] = xh[i]
   145  	}
   146  }