gonum.org/v1/gonum@v0.14.0/dsp/fourier/internal/fftpack/cfft.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 cfft 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  // Cffti initializes the array work which is used in both Cfftf
    17  // and Cfftb. 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 4*n.
    28  //	       the same work array can be used for both Cfftf and Cfftb
    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 Cfftf or Cfftb.
    32  //
    33  //	ifac   A work array containing the factors of n. ifac must have
    34  //	       length 15.
    35  func Cffti(n int, work []float64, ifac []int) {
    36  	if len(work) < 4*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  	cffti1(n, work[2*n:4*n], ifac[:15])
    46  }
    47  
    48  func cffti1(n int, wa []float64, ifac []int) {
    49  	ntryh := [4]int{3, 4, 2, 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  
    87  	argh := 2 * math.Pi / float64(n)
    88  	i := 1
    89  	l1 := 1
    90  	for k1 := 0; k1 < nf; k1++ {
    91  		ip := ifac[k1+2]
    92  		ld := 0
    93  		l2 := l1 * ip
    94  		ido := n / l2
    95  		idot := 2*ido + 2
    96  		for j := 0; j < ip-1; j++ {
    97  			i1 := i
    98  			wa[i-1] = 1
    99  			wa[i] = 0
   100  			ld += l1
   101  			var fi float64
   102  			argld := float64(ld) * argh
   103  			for ii := 3; ii < idot; ii += 2 {
   104  				i += 2
   105  				fi++
   106  				arg := fi * argld
   107  				wa[i-1] = math.Cos(arg)
   108  				wa[i] = math.Sin(arg)
   109  			}
   110  			if ip > 5 {
   111  				wa[i1-1] = wa[i-1]
   112  				wa[i1] = wa[i]
   113  			}
   114  		}
   115  		l1 = l2
   116  	}
   117  }
   118  
   119  // Cfftf computes the forward complex Discrete Fourier transform
   120  // (the Fourier analysis). Equivalently, Cfftf computes the
   121  // Fourier coefficients of a complex periodic sequence. The
   122  // transform is defined below at output parameter c.
   123  //
   124  //	Input parameters:
   125  //
   126  //	n      The length of the array c to be transformed. The method
   127  //	       is most efficient when n is a product of small primes.
   128  //	       n may change so long as different work arrays are provided.
   129  //
   130  //	c      A complex array of length n which contains the sequence
   131  //	       to be transformed.
   132  //
   133  //	work   A real work array which must be dimensioned at least 4*n.
   134  //	       in the program that calls Cfftf. The work array must be
   135  //	       initialized by calling subroutine Cffti(n,work,ifac) and a
   136  //	       different work array must be used for each different
   137  //	       value of n. This initialization does not have to be
   138  //	       repeated so long as n remains unchanged thus subsequent
   139  //	       transforms can be obtained faster than the first.
   140  //	       the same work array can be used by Cfftf and Cfftb.
   141  //
   142  //	ifac   A work array containing the factors of n. ifac must have
   143  //	       length of at least 15.
   144  //
   145  //	Output parameters:
   146  //
   147  //	 c     for j=0, ..., n-1
   148  //	         c[j]=the sum from k=0, ..., n-1 of
   149  //	           c[k]*exp(-i*j*k*2*pi/n)
   150  //
   151  //	       where i=sqrt(-1)
   152  //
   153  //	This transform is unnormalized since a call of Cfftf
   154  //	followed by a call of Cfftb will multiply the input
   155  //	sequence by n.
   156  //
   157  //	The n elements of c are represented in n pairs of real
   158  //	values in r where c[j] = r[j*2]+r[j*2+1]i.
   159  //
   160  //	work   Contains results which must not be destroyed between
   161  //	       calls of Cfftf or Cfftb.
   162  //	ifac   Contains results which must not be destroyed between
   163  //	       calls of Cfftf or Cfftb.
   164  func Cfftf(n int, r, work []float64, ifac []int) {
   165  	if len(r) < 2*n {
   166  		panic("fourier: short sequence")
   167  	}
   168  	if len(work) < 4*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  	cfft1(n, r[:2*n], work[:2*n], work[2*n:4*n], ifac[:15], -1)
   178  }
   179  
   180  // Cfftb computes the backward complex Discrete Fourier Transform
   181  // (the Fourier synthesis). Equivalently, Cfftf computes the computes
   182  // a complex periodic sequence from its Fourier coefficients. The
   183  // transform is defined below at output parameter c.
   184  //
   185  //	Input parameters:
   186  //
   187  //	n      The length of the array c to be transformed. The method
   188  //	       is most efficient when n is a product of small primes.
   189  //	       n may change so long as different work arrays are provided.
   190  //
   191  //	c      A complex array of length n which contains the sequence
   192  //	       to be transformed.
   193  //
   194  //	work   A real work array which must be dimensioned at least 4*n.
   195  //	       in the program that calls Cfftb. The work array must be
   196  //	       initialized by calling subroutine Cffti(n,work,ifac) and a
   197  //	       different work array must be used for each different
   198  //	       value of n. This initialization does not have to be
   199  //	       repeated so long as n remains unchanged thus subsequent
   200  //	       transforms can be obtained faster than the first.
   201  //	       The same work array can be used by Cfftf and Cfftb.
   202  //
   203  //	ifac   A work array containing the factors of n. ifac must have
   204  //	       length of at least 15.
   205  //
   206  //	Output parameters:
   207  //
   208  //	c      for j=0, ..., n-1
   209  //	         c[j]=the sum from k=0, ..., n-1 of
   210  //	           c[k]*exp(i*j*k*2*pi/n)
   211  //
   212  //	       where i=sqrt(-1)
   213  //
   214  //	This transform is unnormalized since a call of Cfftf
   215  //	followed by a call of Cfftb will multiply the input
   216  //	sequence by n.
   217  //
   218  //	The n elements of c are represented in n pairs of real
   219  //	values in r where c[j] = r[j*2]+r[j*2+1]i.
   220  //
   221  //	work   Contains results which must not be destroyed between
   222  //	       calls of Cfftf or Cfftb.
   223  //	ifac   Contains results which must not be destroyed between
   224  //	       calls of Cfftf or Cfftb.
   225  func Cfftb(n int, c, work []float64, ifac []int) {
   226  	if len(c) < 2*n {
   227  		panic("fourier: short sequence")
   228  	}
   229  	if len(work) < 4*n {
   230  		panic("fourier: short work")
   231  	}
   232  	if len(ifac) < 15 {
   233  		panic("fourier: short ifac")
   234  	}
   235  	if n == 1 {
   236  		return
   237  	}
   238  	cfft1(n, c[:2*n], work[:2*n], work[2*n:4*n], ifac[:15], 1)
   239  }
   240  
   241  // cfft1 implements cfftf1 and cfftb1 depending on sign.
   242  func cfft1(n int, c, ch, wa []float64, ifac []int, sign float64) {
   243  	nf := ifac[1]
   244  	na := false
   245  	l1 := 1
   246  	iw := 0
   247  
   248  	for k1 := 1; k1 <= nf; k1++ {
   249  		ip := ifac[k1+1]
   250  		l2 := ip * l1
   251  		ido := n / l2
   252  		idot := 2 * ido
   253  		idl1 := idot * l1
   254  
   255  		switch ip {
   256  		case 4:
   257  			ix2 := iw + idot
   258  			ix3 := ix2 + idot
   259  			if na {
   260  				pass4(idot, l1, ch, c, wa[iw:], wa[ix2:], wa[ix3:], sign)
   261  			} else {
   262  				pass4(idot, l1, c, ch, wa[iw:], wa[ix2:], wa[ix3:], sign)
   263  			}
   264  			na = !na
   265  		case 2:
   266  			if na {
   267  				pass2(idot, l1, ch, c, wa[iw:], sign)
   268  			} else {
   269  				pass2(idot, l1, c, ch, wa[iw:], sign)
   270  			}
   271  			na = !na
   272  		case 3:
   273  			ix2 := iw + idot
   274  			if na {
   275  				pass3(idot, l1, ch, c, wa[iw:], wa[ix2:], sign)
   276  			} else {
   277  				pass3(idot, l1, c, ch, wa[iw:], wa[ix2:], sign)
   278  			}
   279  			na = !na
   280  		case 5:
   281  			ix2 := iw + idot
   282  			ix3 := ix2 + idot
   283  			ix4 := ix3 + idot
   284  			if na {
   285  				pass5(idot, l1, ch, c, wa[iw:], wa[ix2:], wa[ix3:], wa[ix4:], sign)
   286  			} else {
   287  				pass5(idot, l1, c, ch, wa[iw:], wa[ix2:], wa[ix3:], wa[ix4:], sign)
   288  			}
   289  			na = !na
   290  		default:
   291  			var nac bool
   292  			if na {
   293  				nac = pass(idot, ip, l1, idl1, ch, ch, ch, c, c, wa[iw:], sign)
   294  			} else {
   295  				nac = pass(idot, ip, l1, idl1, c, c, c, ch, ch, wa[iw:], sign)
   296  			}
   297  			if nac {
   298  				na = !na
   299  			}
   300  		}
   301  
   302  		l1 = l2
   303  		iw += (ip - 1) * idot
   304  	}
   305  
   306  	if na {
   307  		for i := 0; i < 2*n; i++ {
   308  			c[i] = ch[i]
   309  		}
   310  	}
   311  }
   312  
   313  // pass2 implements passf2 and passb2 depending on sign.
   314  func pass2(ido, l1 int, cc, ch, wa1 []float64, sign float64) {
   315  	cc3 := newThreeArray(ido, 2, l1, cc)
   316  	ch3 := newThreeArray(ido, l1, 2, ch)
   317  
   318  	if ido <= 2 {
   319  		for k := 0; k < l1; k++ {
   320  			ch3.setCmplx(0, k, 0, cc3.atCmplx(0, 0, k)+cc3.atCmplx(0, 1, k))
   321  			ch3.setCmplx(0, k, 1, cc3.atCmplx(0, 0, k)-cc3.atCmplx(0, 1, k))
   322  		}
   323  		return
   324  	}
   325  	for k := 0; k < l1; k++ {
   326  		for i := 1; i < ido; i += 2 {
   327  			ch3.setCmplx(i-1, k, 0, cc3.atCmplx(i-1, 0, k)+cc3.atCmplx(i-1, 1, k))
   328  			t2 := cc3.atCmplx(i-1, 0, k) - cc3.atCmplx(i-1, 1, k)
   329  			ch3.setCmplx(i-1, k, 1, complex(wa1[i-1], sign*wa1[i])*t2)
   330  		}
   331  	}
   332  }
   333  
   334  // pass3 implements passf3 and passb3 depending on sign.
   335  func pass3(ido, l1 int, cc, ch, wa1, wa2 []float64, sign float64) {
   336  	const (
   337  		taur = -0.5
   338  		taui = 0.866025403784439 // sqrt(3)/2
   339  	)
   340  
   341  	cc3 := newThreeArray(ido, 3, l1, cc)
   342  	ch3 := newThreeArray(ido, l1, 3, ch)
   343  
   344  	if ido == 2 {
   345  		for k := 0; k < l1; k++ {
   346  			t2 := cc3.atCmplx(0, 1, k) + cc3.atCmplx(0, 2, k)
   347  			ch3.setCmplx(0, k, 0, cc3.atCmplx(0, 0, k)+t2)
   348  
   349  			c2 := cc3.atCmplx(0, 0, k) + scale(taur, t2)
   350  			c3 := cmplx.Conj(swap(scale(sign*taui, cc3.atCmplx(0, 1, k)-cc3.atCmplx(0, 2, k))))
   351  			ch3.setCmplx(0, k, 1, c2-c3)
   352  			ch3.setCmplx(0, k, 2, c2+c3)
   353  		}
   354  		return
   355  	}
   356  	for k := 0; k < l1; k++ {
   357  		for i := 1; i < ido; i += 2 {
   358  			t2 := cc3.atCmplx(i-1, 1, k) + cc3.atCmplx(i-1, 2, k)
   359  			ch3.setCmplx(i-1, k, 0, cc3.atCmplx(i-1, 0, k)+t2)
   360  
   361  			c2 := cc3.atCmplx(i-1, 0, k) + scale(taur, t2)
   362  			c3 := cmplx.Conj(swap(scale(sign*taui, cc3.atCmplx(i-1, 1, k)-cc3.atCmplx(i-1, 2, k))))
   363  			d2 := c2 - c3
   364  			d3 := c2 + c3
   365  			ch3.setCmplx(i-1, k, 1, complex(wa1[i-1], sign*wa1[i])*d2)
   366  			ch3.setCmplx(i-1, k, 2, complex(wa2[i-1], sign*wa2[i])*d3)
   367  		}
   368  	}
   369  }
   370  
   371  // pass4 implements passf4 and passb4 depending on sign.
   372  func pass4(ido, l1 int, cc, ch, wa1, wa2, wa3 []float64, sign float64) {
   373  	cc3 := newThreeArray(ido, 4, l1, cc)
   374  	ch3 := newThreeArray(ido, l1, 4, ch)
   375  
   376  	if ido == 2 {
   377  		for k := 0; k < l1; k++ {
   378  			t1 := cc3.atCmplx(0, 0, k) - cc3.atCmplx(0, 2, k)
   379  			t2 := cc3.atCmplx(0, 0, k) + cc3.atCmplx(0, 2, k)
   380  			t3 := cc3.atCmplx(0, 1, k) + cc3.atCmplx(0, 3, k)
   381  			t4 := cmplx.Conj(swap(scale(sign, cc3.atCmplx(0, 3, k)-cc3.atCmplx(0, 1, k))))
   382  
   383  			ch3.setCmplx(0, k, 0, t2+t3)
   384  			ch3.setCmplx(0, k, 1, t1+t4)
   385  			ch3.setCmplx(0, k, 2, t2-t3)
   386  			ch3.setCmplx(0, k, 3, t1-t4)
   387  		}
   388  		return
   389  	}
   390  	for k := 0; k < l1; k++ {
   391  		for i := 1; i < ido; i += 2 {
   392  			t1 := cc3.atCmplx(i-1, 0, k) - cc3.atCmplx(i-1, 2, k)
   393  			t2 := cc3.atCmplx(i-1, 0, k) + cc3.atCmplx(i-1, 2, k)
   394  			t3 := cc3.atCmplx(i-1, 1, k) + cc3.atCmplx(i-1, 3, k)
   395  			t4 := cmplx.Conj(swap(scale(sign, cc3.atCmplx(i-1, 3, k)-cc3.atCmplx(i-1, 1, k))))
   396  			ch3.setCmplx(i-1, k, 0, t2+t3)
   397  
   398  			c2 := t1 + t4
   399  			c3 := t2 - t3
   400  			c4 := t1 - t4
   401  			ch3.setCmplx(i-1, k, 1, complex(wa1[i-1], sign*wa1[i])*c2)
   402  			ch3.setCmplx(i-1, k, 2, complex(wa2[i-1], sign*wa2[i])*c3)
   403  			ch3.setCmplx(i-1, k, 3, complex(wa3[i-1], sign*wa3[i])*c4)
   404  		}
   405  	}
   406  }
   407  
   408  // pass5 implements passf5 and passb5 depending on sign.
   409  func pass5(ido, l1 int, cc, ch, wa1, wa2, wa3, wa4 []float64, sign float64) {
   410  	const (
   411  		tr11 = 0.309016994374947
   412  		ti11 = 0.951056516295154
   413  		tr12 = -0.809016994374947
   414  		ti12 = 0.587785252292473
   415  	)
   416  
   417  	cc3 := newThreeArray(ido, 5, l1, cc)
   418  	ch3 := newThreeArray(ido, l1, 5, ch)
   419  
   420  	if ido == 2 {
   421  		for k := 0; k < l1; k++ {
   422  			t2 := cc3.atCmplx(0, 1, k) + cc3.atCmplx(0, 4, k)
   423  			t3 := cc3.atCmplx(0, 2, k) + cc3.atCmplx(0, 3, k)
   424  			t4 := cc3.atCmplx(0, 2, k) - cc3.atCmplx(0, 3, k)
   425  			t5 := cc3.atCmplx(0, 1, k) - cc3.atCmplx(0, 4, k)
   426  			ch3.setCmplx(0, k, 0, cc3.atCmplx(0, 0, k)+t2+t3)
   427  
   428  			c2 := cc3.atCmplx(0, 0, k) + scale(tr11, t2) + scale(tr12, t3)
   429  			c3 := cc3.atCmplx(0, 0, k) + scale(tr12, t2) + scale(tr11, t3)
   430  			c4 := cmplx.Conj(swap(scale(sign, scale(ti12, t5)-scale(ti11, t4))))
   431  			c5 := cmplx.Conj(swap(scale(sign, scale(ti11, t5)+scale(ti12, t4))))
   432  			ch3.setCmplx(0, k, 1, c2-c5)
   433  			ch3.setCmplx(0, k, 2, c3-c4)
   434  			ch3.setCmplx(0, k, 3, c3+c4)
   435  			ch3.setCmplx(0, k, 4, c2+c5)
   436  		}
   437  		return
   438  	}
   439  	for k := 0; k < l1; k++ {
   440  		for i := 1; i < ido; i += 2 {
   441  			t2 := cc3.atCmplx(i-1, 1, k) + cc3.atCmplx(i-1, 4, k)
   442  			t3 := cc3.atCmplx(i-1, 2, k) + cc3.atCmplx(i-1, 3, k)
   443  			t4 := cc3.atCmplx(i-1, 2, k) - cc3.atCmplx(i-1, 3, k)
   444  			t5 := cc3.atCmplx(i-1, 1, k) - cc3.atCmplx(i-1, 4, k)
   445  			ch3.setCmplx(i-1, k, 0, cc3.atCmplx(i-1, 0, k)+t2+t3)
   446  
   447  			c2 := cc3.atCmplx(i-1, 0, k) + scale(tr11, t2) + scale(tr12, t3)
   448  			c3 := cc3.atCmplx(i-1, 0, k) + scale(tr12, t2) + scale(tr11, t3)
   449  			c4 := cmplx.Conj(swap(scale(sign, scale(ti12, t5)-scale(ti11, t4))))
   450  			c5 := cmplx.Conj(swap(scale(sign, scale(ti11, t5)+scale(ti12, t4))))
   451  			d2 := c2 - c5
   452  			d3 := c3 - c4
   453  			d4 := c3 + c4
   454  			d5 := c2 + c5
   455  			ch3.setCmplx(i-1, k, 1, complex(wa1[i-1], sign*wa1[i])*d2)
   456  			ch3.setCmplx(i-1, k, 2, complex(wa2[i-1], sign*wa2[i])*d3)
   457  			ch3.setCmplx(i-1, k, 3, complex(wa3[i-1], sign*wa3[i])*d4)
   458  			ch3.setCmplx(i-1, k, 4, complex(wa4[i-1], sign*wa4[i])*d5)
   459  		}
   460  	}
   461  }
   462  
   463  // pass implements passf and passb depending on sign.
   464  func pass(ido, ip, l1, idl1 int, cc, c1, c2, ch, ch2, wa []float64, sign float64) (nac bool) {
   465  	cc3 := newThreeArray(ido, ip, l1, cc)
   466  	c13 := newThreeArray(ido, l1, ip, c1)
   467  	ch3 := newThreeArray(ido, l1, ip, ch)
   468  	c2m := newTwoArray(idl1, ip, c2)
   469  	ch2m := newTwoArray(idl1, ip, ch2)
   470  
   471  	idot := ido / 2
   472  	ipph := (ip + 1) / 2
   473  	idp := ip * ido
   474  
   475  	if ido < l1 {
   476  		for j := 1; j < ipph; j++ {
   477  			jc := ip - j
   478  			for i := 0; i < ido; i++ {
   479  				for k := 0; k < l1; k++ {
   480  					ch3.set(i, k, j, cc3.at(i, j, k)+cc3.at(i, jc, k))
   481  					ch3.set(i, k, jc, cc3.at(i, j, k)-cc3.at(i, jc, k))
   482  				}
   483  			}
   484  		}
   485  		for i := 0; i < ido; i++ {
   486  			for k := 0; k < l1; k++ {
   487  				ch3.set(i, k, 0, cc3.at(i, 0, k))
   488  			}
   489  		}
   490  	} else {
   491  		for j := 1; j < ipph; j++ {
   492  			jc := ip - j
   493  			for k := 0; k < l1; k++ {
   494  				for i := 0; i < ido; i++ {
   495  					ch3.set(i, k, j, cc3.at(i, j, k)+cc3.at(i, jc, k))
   496  					ch3.set(i, k, jc, cc3.at(i, j, k)-cc3.at(i, jc, k))
   497  				}
   498  			}
   499  		}
   500  		for k := 0; k < l1; k++ {
   501  			for i := 0; i < ido; i++ {
   502  				ch3.set(i, k, 0, cc3.at(i, 0, k))
   503  			}
   504  		}
   505  	}
   506  
   507  	idl := 1 - ido
   508  	inc := 0
   509  	for l := 1; l < ipph; l++ {
   510  		lc := ip - l
   511  		idl += ido
   512  		for ik := 0; ik < idl1; ik++ {
   513  			c2m.set(ik, l, ch2m.at(ik, 0)+wa[idl-1]*ch2m.at(ik, 1))
   514  			c2m.set(ik, lc, sign*wa[idl]*ch2m.at(ik, ip-1))
   515  		}
   516  		idlj := idl
   517  		inc += ido
   518  		for j := 2; j < ipph; j++ {
   519  			jc := ip - j
   520  			idlj += inc
   521  			if idlj > idp {
   522  				idlj -= idp
   523  			}
   524  			war := wa[idlj-1]
   525  			wai := wa[idlj]
   526  			for ik := 0; ik < idl1; ik++ {
   527  				c2m.add(ik, l, war*ch2m.at(ik, j))
   528  				c2m.add(ik, lc, sign*wai*ch2m.at(ik, jc))
   529  			}
   530  		}
   531  	}
   532  
   533  	for j := 1; j < ipph; j++ {
   534  		for ik := 0; ik < idl1; ik++ {
   535  			ch2m.add(ik, 0, ch2m.at(ik, j))
   536  		}
   537  	}
   538  
   539  	for j := 1; j < ipph; j++ {
   540  		jc := ip - j
   541  		for ik := 1; ik < idl1; ik += 2 {
   542  			ch2m.setCmplx(ik-1, j, c2m.atCmplx(ik-1, j)-cmplx.Conj(swap(c2m.atCmplx(ik-1, jc))))
   543  			ch2m.setCmplx(ik-1, jc, c2m.atCmplx(ik-1, j)+cmplx.Conj(swap(c2m.atCmplx(ik-1, jc))))
   544  		}
   545  	}
   546  
   547  	if ido == 2 {
   548  		return true
   549  	}
   550  
   551  	for ik := 0; ik < idl1; ik++ {
   552  		c2m.set(ik, 0, ch2m.at(ik, 0))
   553  	}
   554  
   555  	for j := 1; j < ip; j++ {
   556  		for k := 0; k < l1; k++ {
   557  			c13.setCmplx(0, k, j, ch3.atCmplx(0, k, j))
   558  		}
   559  	}
   560  
   561  	if idot > l1 {
   562  		idj := 1 - ido
   563  		for j := 1; j < ip; j++ {
   564  			idj += ido
   565  			for k := 0; k < l1; k++ {
   566  				idij := idj
   567  				for i := 3; i < ido; i += 2 {
   568  					idij += 2
   569  					c13.setCmplx(i-1, k, j, complex(wa[idij-1], sign*wa[idij])*ch3.atCmplx(i-1, k, j))
   570  				}
   571  			}
   572  		}
   573  
   574  		return false
   575  	}
   576  
   577  	idij := -1
   578  	for j := 1; j < ip; j++ {
   579  		idij += 2
   580  		for i := 3; i < ido; i += 2 {
   581  			idij += 2
   582  			for k := 0; k < l1; k++ {
   583  				c13.setCmplx(i-1, k, j, complex(wa[idij-1], sign*wa[idij])*ch3.atCmplx(i-1, k, j))
   584  			}
   585  		}
   586  	}
   587  	return false
   588  }