// Copyright ©2018 The Gonum Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // This is a translation and extension of the FFTPACK test // functions by Paul N Swarztrauber, placed in the public // domain at http://www.netlib.org/fftpack/. package fftpack import ( "math" "math/cmplx" "reflect" "testing" "gonum.org/v1/gonum/cmplxs" "gonum.org/v1/gonum/floats" "gonum.org/v1/gonum/floats/scalar" ) func TestRfft(t *testing.T) { t.Parallel() // Golden value cases where golden values have // been obtained from the original Fortran code. for _, test := range rfftTests { const tol = 1e-12 testRfft(t, test.n, tol, test.wantiwork, test.wantiifac) } // General cases based purely on FFT behaviour. for n := 1; n < 500; n++ { const tol = 1e-9 testRfft(t, n, tol, nil, nil) } } func testRfft(t *testing.T, n int, tol float64, wantiwork []float64, wantiifac []int) { // Compute the work and factor slices and compare to known values. work := make([]float64, 2*n) ifac := make([]int, 15) Rffti(n, work, ifac) var failed bool if wantiwork != nil && !floats.EqualApprox(work, wantiwork, 1e-6) { failed = true t.Errorf("unexpected work after call to rffti for n=%d", n) } if wantiifac != nil && !reflect.DeepEqual(ifac, wantiifac) { failed = true t.Errorf("unexpected ifac after call to rffti for n=%d", n) } if failed { return } // Construct a sequence with known a frequency spectrum and compare // the computed spectrum. modn := n % 2 fn := float64(n) nm1 := n - 1 x, y, xh := series(n) dt := 2 * math.Pi / fn ns2 := (n + 1) / 2 if ns2 >= 2 { for k := 1; k < ns2; k++ { //eek var sum1, sum2 float64 arg := float64(k) * dt for i := 0; i < n; i++ { arg1 := float64(i) * arg sum1 += x[i] * math.Cos(arg1) sum2 += x[i] * math.Sin(arg1) } y[2*k-1] = sum1 y[2*k] = -sum2 } } var sum1, sum2 float64 for i := 0; i < nm1; i += 2 { sum1 += x[i] sum2 += x[i+1] } if modn == 1 { sum1 += x[n-1] } y[0] = sum1 + sum2 if modn == 0 { y[n-1] = sum1 - sum2 } want := naiveDFTreal(x) Rfftf(n, x, work, ifac) // Compare the result to a naive DFT implementation. if got := packCoeffs(x); !cmplxs.EqualApprox(got, want, tol) { t.Errorf("unexpected coefficients for n=%d: got:%f want:%f", n, got, want) } var rftf float64 for i := 0; i < n; i++ { rftf = math.Max(rftf, math.Abs(x[i]-y[i])) x[i] = xh[i] } rftf /= fn if !scalar.EqualWithinAbsOrRel(rftf, 0, tol, tol) { t.Errorf("unexpected rftf value for n=%d: got:%f want:0", n, rftf) } // Construct a frequency spectrum and compare the computed sequence. for i := 0; i < n; i++ { sum := x[0] / 2 arg := float64(i) * dt if ns2 >= 2 { for k := 1; k < ns2; k++ { //eek arg1 := float64(k) * arg sum += x[2*k-1]*math.Cos(arg1) - x[2*k]*math.Sin(arg1) } } if modn == 0 { // This is how it was written in FFTPACK. sum += 0.5 * math.Pow(-1, float64(i)) * x[n-1] } y[i] = 2 * sum } Rfftb(n, x, work, ifac) var rftb float64 for i := 0; i < n; i++ { rftb = math.Max(rftb, math.Abs(x[i]-y[i])) x[i] = xh[i] y[i] = xh[i] } if !scalar.EqualWithinAbsOrRel(rftb, 0, tol, tol) { t.Errorf("unexpected rftb value for n=%d: got:%g want:0", n, rftb) } // Check that Rfftb and Rfftf are inverses. Rfftb(n, y, work, ifac) Rfftf(n, y, work, ifac) cf := 1.0 / fn var rftfb float64 for i := 0; i < n; i++ { rftfb = math.Max(rftfb, math.Abs(cf*y[i]-x[i])) } if !scalar.EqualWithinAbsOrRel(rftfb, 0, tol, tol) { t.Errorf("unexpected rftfb value for n=%d: got:%f want:0", n, rftfb) } } // naiveDFTreal is the naive O(n^2) DFT implementation. func naiveDFTreal(x []float64) (y []complex128) { y = make([]complex128, len(x)) dt := -2 * math.Pi / float64(len(x)) for i := range x { arg1 := float64(i) * dt for k, xv := range x { arg2 := float64(k) * arg1 y[i] += complex(xv*math.Cos(arg2), xv*math.Sin(arg2)) } } return y[:len(x)/2+1] } func packCoeffs(x []float64) []complex128 { y := make([]complex128, len(x)/2+1) y[0] = complex(x[0], 0) if len(x) < 2 { return y } if len(x)%2 == 1 { y[len(y)-1] = complex(x[len(x)-2], x[len(x)-1]) } else { y[len(y)-1] = complex(x[len(x)-1], 0) } for i := 1; i < len(y)-1; i++ { y[i] = complex(x[2*i-1], x[2*i]) } return y } var rfftTests = []struct { n int // The following two fields are added as there is no unit testing in // FFTPACK for RFFTI. // // wantiwork is obtained from the FFTPACK test.f with modification. // The W array is zeroed at each iteration and the first 2n elements // of W are printed after the call to RFFTI. wantiwork []float64 // wantiifac is obtained from the FFTPACK rffti1.f with modification. // The IFAC array is zeroed at each iteration of test.f and the 15 elements // of IFAC are printed before RFFTI1 returns. wantiifac []int }{ { n: 120, wantiwork: []float64{ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9986295, 0.5233596e-01, 0.9945219, 0.1045285, 0.9876884, 0.1564345, 0.9781476, 0.2079117, 0.9659258, 0.2588190, 0.9510565, 0.3090170, 0.9335804, 0.3583679, 0.9135454, 0.4067366, 0.8910065, 0.4539905, 0.8660254, 0.5000000, 0.8386706, 0.5446391, 0.8090170, 0.5877852, 0.7771459, 0.6293204, 0.7431448, 0.6691306, 0.7071068, 0.7071068, 0.6691306, 0.7431449, 0.6293204, 0.7771460, 0.5877852, 0.8090170, 0.5446390, 0.8386706, 0.5000000, 0.8660254, 0.4539905, 0.8910065, 0.4067366, 0.9135455, 0.3583679, 0.9335805, 0.3090170, 0.9510565, 0.2588191, 0.9659258, 0.2079117, 0.9781476, 0.1564344, 0.9876884, 0.1045284, 0.9945219, 0.5233597e-01, 0.9986295, 0.000000, 0.000000, 0.9945219, 0.1045285, 0.9781476, 0.2079117, 0.9510565, 0.3090170, 0.9135454, 0.4067366, 0.8660254, 0.5000000, 0.8090170, 0.5877852, 0.7431448, 0.6691306, 0.000000, 0.9781476, 0.2079117, 0.9135454, 0.4067366, 0.8090170, 0.5877852, 0.6691306, 0.7431449, 0.5000000, 0.8660254, 0.3090170, 0.9510565, 0.1045284, 0.9945219, 0.000000, 0.9510565, 0.3090170, 0.8090170, 0.5877852, 0.5877852, 0.8090170, 0.3090170, 0.9510565, -0.4371139e-07, 1.000000, -0.3090170, 0.9510565, -0.5877852, 0.8090170, 0.000000, 0.9135454, 0.4067366, 0.6691306, 0.7431449, 0.000000, 0.6691306, 0.7431449, -0.1045285, 0.9945219, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{120, 4, 2, 4, 3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 54, wantiwork: []float64{ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9932383, 0.1160929, 0.9730449, 0.2306159, 0.9396926, 0.3420201, 0.8936327, 0.4487992, 0.8354878, 0.5495090, 0.7660444, 0.6427876, 0.6862416, 0.7273737, 0.5971586, 0.8021232, 0.5000000, 0.8660254, 0.3960797, 0.9182161, 0.2868032, 0.9579895, 0.1736482, 0.9848077, 0.5814485e-01, 0.9983082, 0.000000, 0.9730449, 0.2306159, 0.8936327, 0.4487992, 0.7660444, 0.6427876, 0.5971586, 0.8021232, 0.000000, 0.8936327, 0.4487992, 0.5971586, 0.8021232, 0.1736482, 0.9848077, -0.2868032, 0.9579895, 0.000000, 0.7660444, 0.6427876, 0.000000, 0.1736482, 0.9848077, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{54, 4, 2, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 49, wantiwork: []float64{ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9917900, 0.1278772, 0.9672949, 0.2536546, 0.9269168, 0.3752670, 0.000000, 0.9672949, 0.2536546, 0.8713187, 0.4907176, 0.7183493, 0.6956826, 0.000000, 0.9269168, 0.3752670, 0.7183493, 0.6956826, 0.4047833, 0.9144127, 0.000000, 0.8713187, 0.4907176, 0.5183925, 0.8551428, 0.3205151e-01, 0.9994862, 0.000000, 0.8014136, 0.5981106, 0.2845275, 0.9586679, -0.3453652, 0.9384683, 0.000000, 0.7183493, 0.6956826, 0.3205151e-01, 0.9994862, -0.6723010, 0.7402779, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{49, 2, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 32, wantiwork: []float64{ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9807853, 0.1950903, 0.9238795, 0.3826835, 0.8314696, 0.5555702, 0.7071068, 0.7071068, 0.5555702, 0.8314697, 0.3826834, 0.9238795, 0.1950902, 0.9807853, 0.000000, 0.000000, 0.9238795, 0.3826835, 0.000000, 0.000000, 0.7071068, 0.7071068, 0.000000, 0.000000, 0.3826834, 0.9238795, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{32, 3, 2, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 25, wantiwork: []float64{ 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.968583, 0.248690, 0.876307, 0.481754, 0.00000, 0.876307, 0.481754, 0.535827, 0.844328, 0.00000, 0.728969, 0.684547, 0.627904e-01, 0.998027, 0.00000, 0.535827, 0.844328, -0.425779, 0.904827, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, }, wantiifac: []int{25, 2, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 4, wantiwork: []float64{ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{4, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 3, wantiwork: []float64{ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{3, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 2, wantiwork: []float64{ 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, } func TestCfft(t *testing.T) { t.Parallel() const tol = 1e-12 // Golden value cases where golden values have // been obtained from the original Fortran code. for _, test := range cfftTests { testCfft(t, test.n, tol, test.wantiwork, test.wantiifac) } // General cases based purely on FFT behaviour. for n := 1; n < 500; n++ { testCfft(t, n, tol, nil, nil) } } func testCfft(t *testing.T, n int, tol float64, wantiwork []float64, wantiifac []int) { // Compute the work and factor slices and compare to known values. work := make([]float64, 4*n) ifac := make([]int, 15) Cffti(n, work, ifac) var failed bool if wantiwork != nil && !floats.EqualApprox(work, wantiwork, 1e-6) { failed = true t.Errorf("unexpected work after call to cffti for n=%d", n) } if wantiifac != nil && !reflect.DeepEqual(ifac, wantiifac) { failed = true t.Errorf("unexpected ifac after call to cffti for n=%d", n) } if failed { return } // Construct a sequence with known a frequency spectrum and compare // the computed spectrum. fn := float64(n) cn := complex(fn, 0) x, y1 := cmplxSeries(n) want := naiveDFT(x) cx := cmplxAsFloat(x) Cfftf(n, cx, work, ifac) x = floatAsCmplx(cx) // Compare the result to a naive DFT implementation. if !cmplxs.EqualApprox(x, want, tol*10) { t.Errorf("unexpected coefficients for n=%d: got:%f want:%f", n, x, want) } var cftf float64 for i := 0; i < n; i++ { cftf = math.Max(cftf, cmplx.Abs(x[i]-y1[i])) x[i] /= cn } cftf /= fn if !scalar.EqualWithinAbsOrRel(cftf, 0, tol, tol) { t.Errorf("unexpected cftf value for n=%d: got:%f want:0", n, cftf) } // Construct a frequency spectrum and compare the computed sequence. y2 := updatedCmplxSeries(x) cx = cmplxAsFloat(x) Cfftb(n, cx, work, ifac) x = floatAsCmplx(cx) var cftb float64 for i := 0; i < n; i++ { cftb = math.Max(cftb, cmplx.Abs(x[i]-y2[i])) x[i] = y2[i] } if !scalar.EqualWithinAbsOrRel(cftb, 0, tol, tol) { t.Errorf("unexpected cftb value for n=%d: got:%f want:0", n, cftb) } // Check that Cfftb and Cfftf are inverses. cx = cmplxAsFloat(x) Cfftf(n, cx, work, ifac) Cfftb(n, cx, work, ifac) x = floatAsCmplx(cx) var cftfb float64 for i := 0; i < n; i++ { cftfb = math.Max(cftfb, cmplx.Abs(x[i]/cn-y2[i])) } if !scalar.EqualWithinAbsOrRel(cftfb, 0, tol, tol) { t.Errorf("unexpected cftfb value for n=%d: got:%f want:0", n, cftfb) } } // naiveDFT is the naive O(n^2) DFT implementation. func naiveDFT(x []complex128) (y []complex128) { y = make([]complex128, len(x)) dt := -2 * math.Pi / float64(len(x)) for i := range x { arg1 := float64(i) * dt for k, xv := range x { arg2 := float64(k) * arg1 y[i] += complex(math.Cos(arg2), math.Sin(arg2)) * xv } } return y } func cmplxSeries(n int) (x, y []complex128) { x = make([]complex128, n) for i := 0; i < n; i++ { x[i] = complex(math.Cos(math.Sqrt2*float64(i+1)), math.Sin(math.Sqrt2*float64((i+1)*(i+1)))) } y = make([]complex128, n) dt := 2 * math.Pi / float64(n) for i := 0; i < n; i++ { arg1 := -float64(i) * dt for k := 0; k < n; k++ { arg2 := float64(k) * arg1 y[i] += complex(math.Cos(arg2), math.Sin(arg2)) * x[k] } } return x, y } func updatedCmplxSeries(x []complex128) (y []complex128) { y = make([]complex128, len(x)) dt := 2 * math.Pi / float64(len(x)) for i := range x { arg1 := float64(i) * dt for k, xv := range x { arg2 := float64(k) * arg1 y[i] += complex(math.Cos(arg2), math.Sin(arg2)) * xv } } return y } func cmplxAsFloat(c []complex128) []float64 { f := make([]float64, 2*len(c)) for i, v := range c { f[2*i] = real(v) f[2*i+1] = imag(v) } return f } func floatAsCmplx(f []float64) []complex128 { c := make([]complex128, len(f)/2) for i := range c { c[i] = complex(f[2*i], f[2*i+1]) } return c } var cfftTests = []struct { n int // The following two fields are added as there is no unit testing in // FFTPACK for RFFTI. // // wantiwork is obtained from the FFTPACK test.f with modification. // The W array is zeroed at each iteration and the first 4n elements // of W are printed after the call to RFFTI. wantiwork []float64 // wantiifac is obtained from the FFTPACK rffti1.f with modification. // The IFAC array is zeroed at each iteration of test.f and the 15 elements // of IFAC are printed before RFFTI1 returns. wantiifac []int }{ { n: 120, wantiwork: []float64{ 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 1.00000, 0.00000, 0.998630, 0.523360e-01, 0.994522, 0.104528, 0.987688, 0.156434, 0.978148, 0.207912, 0.965926, 0.258819, 0.951057, 0.309017, 0.933580, 0.358368, 0.913545, 0.406737, 0.891007, 0.453991, 0.866025, 0.500000, 0.838671, 0.544639, 0.809017, 0.587785, 0.777146, 0.629320, 0.743145, 0.669131, 0.707107, 0.707107, 0.669131, 0.743145, 0.629320, 0.777146, 0.587785, 0.809017, 0.544639, 0.838671, 0.500000, 0.866025, 0.453991, 0.891007, 0.406737, 0.913545, 0.358368, 0.933580, 0.309017, 0.951057, 0.258819, 0.965926, 0.207912, 0.978148, 0.156434, 0.987688, 0.104528, 0.994522, 0.523360e-01, 0.998630, -0.437114e-07, 1.00000, -0.523361e-01, 0.998630, -0.104529, 0.994522, -0.156434, 0.987688, -0.207912, 0.978148, -0.258819, 0.965926, -0.309017, 0.951056, -0.358368, 0.933580, -0.406737, 0.913545, -0.453991, 0.891006, -0.500000, 0.866025, -0.544639, 0.838671, -0.587785, 0.809017, -0.629321, 0.777146, -0.669131, 0.743145, -0.707107, 0.707107, -0.743145, 0.669130, -0.777146, 0.629320, -0.809017, 0.587785, -0.838671, 0.544639, -0.866025, 0.500000, -0.891007, 0.453990, -0.913545, 0.406737, -0.933580, 0.358368, -0.951057, 0.309017, -0.965926, 0.258819, -0.978148, 0.207912, -0.987688, 0.156434, -0.994522, 0.104528, -0.998630, 0.523358e-01, 1.00000, 0.00000, 0.994522, 0.104528, 0.978148, 0.207912, 0.951057, 0.309017, 0.913545, 0.406737, 0.866025, 0.500000, 0.809017, 0.587785, 0.743145, 0.669131, 0.669131, 0.743145, 0.587785, 0.809017, 0.500000, 0.866025, 0.406737, 0.913545, 0.309017, 0.951057, 0.207912, 0.978148, 0.104528, 0.994522, -0.437114e-07, 1.00000, -0.104529, 0.994522, -0.207912, 0.978148, -0.309017, 0.951056, -0.406737, 0.913545, 1.00000, 0.00000, 0.978148, 0.207912, 0.913545, 0.406737, 0.809017, 0.587785, 0.669131, 0.743145, 0.500000, 0.866025, 0.309017, 0.951057, 0.104528, 0.994522, -0.104529, 0.994522, -0.309017, 0.951056, -0.500000, 0.866025, -0.669131, 0.743145, -0.809017, 0.587785, -0.913545, 0.406737, -0.978148, 0.207912, -1.00000, -0.874228e-07, -0.978148, -0.207912, -0.913545, -0.406737, -0.809017, -0.587785, -0.669131, -0.743145, 1.00000, 0.00000, 0.951057, 0.309017, 0.809017, 0.587785, 0.587785, 0.809017, 0.309017, 0.951057, 1.00000, 0.00000, 0.809017, 0.587785, 0.309017, 0.951057, -0.309017, 0.951056, -0.809017, 0.587785, 1.00000, 0.00000, 0.587785, 0.809017, -0.309017, 0.951056, -0.951057, 0.309017, -0.809017, -0.587785, 1.00000, 0.00000, 1.00000, 0.00000, 1.00000, 0.00000, 1.00000, 0.00000, 0.309017, -0.951056, }, wantiifac: []int{120, 4, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 54, wantiwork: []float64{ 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 1.00000, 0.00000, 0.993238, 0.116093, 0.973045, 0.230616, 0.939693, 0.342020, 0.893633, 0.448799, 0.835488, 0.549509, 0.766044, 0.642788, 0.686242, 0.727374, 0.597159, 0.802123, 0.500000, 0.866025, 0.396080, 0.918216, 0.286803, 0.957990, 0.173648, 0.984808, 0.581449e-01, 0.998308, -0.581448e-01, 0.998308, -0.173648, 0.984808, -0.286803, 0.957990, -0.396080, 0.918216, -0.500000, 0.866025, -0.597159, 0.802123, -0.686242, 0.727374, -0.766044, 0.642788, -0.835488, 0.549509, -0.893633, 0.448799, -0.939693, 0.342020, -0.973045, 0.230616, -0.993238, 0.116093, 1.00000, 0.00000, 0.973045, 0.230616, 0.893633, 0.448799, 0.766044, 0.642788, 0.597159, 0.802123, 0.396080, 0.918216, 0.173648, 0.984808, -0.581448e-01, 0.998308, -0.286803, 0.957990, 1.00000, 0.00000, 0.893633, 0.448799, 0.597159, 0.802123, 0.173648, 0.984808, -0.286803, 0.957990, -0.686242, 0.727374, -0.939693, 0.342020, -0.993238, -0.116093, -0.835488, -0.549509, 1.00000, 0.00000, 0.766044, 0.642788, 0.173648, 0.984808, 1.00000, 0.00000, 0.173648, 0.984808, -0.939693, 0.342020, 1.00000, 0.00000, 1.00000, 0.00000, -0.500000, -0.866025, }, wantiifac: []int{54, 4, 2, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 49, wantiwork: []float64{ 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.623490, 0.781832, 0.991790, 0.127877, 0.967295, 0.253655, 0.926917, 0.375267, 0.871319, 0.490718, 0.801414, 0.598111, 0.718349, 0.695683, -0.222521, 0.974928, 0.967295, 0.253655, 0.871319, 0.490718, 0.718349, 0.695683, 0.518393, 0.855143, 0.284527, 0.958668, 0.320515e-01, 0.999486, -0.900969, 0.433884, 0.926917, 0.375267, 0.718349, 0.695683, 0.404783, 0.914413, 0.320515e-01, 0.999486, -0.345365, 0.938468, -0.672301, 0.740278, -0.900969, -0.433884, 0.871319, 0.490718, 0.518393, 0.855143, 0.320515e-01, 0.999486, -0.462538, 0.886599, -0.838088, 0.545535, -0.997945, 0.640701e-01, -0.222521, -0.974928, 0.801414, 0.598111, 0.284527, 0.958668, -0.345365, 0.938468, -0.838088, 0.545535, -0.997945, -0.640705e-01, -0.761446, -0.648229, 0.623490, -0.781831, 0.718349, 0.695683, 0.320515e-01, 0.999486, -0.672301, 0.740278, -0.997945, 0.640701e-01, -0.761446, -0.648228, -0.960227e-01, -0.995379, 0.623490, 0.781832, -0.222521, 0.974928, -0.900969, 0.433884, -0.900969, -0.433884, -0.222521, -0.974928, 0.623490, -0.781831, 0.623490, -0.781831, }, wantiifac: []int{49, 2, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 32, wantiwork: []float64{ 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 1.00000, 0.00000, 0.980785, 0.195090, 0.923880, 0.382683, 0.831470, 0.555570, 0.707107, 0.707107, 0.555570, 0.831470, 0.382683, 0.923880, 0.195090, 0.980785, -0.437114e-07, 1.00000, -0.195090, 0.980785, -0.382684, 0.923880, -0.555570, 0.831470, -0.707107, 0.707107, -0.831470, 0.555570, -0.923880, 0.382683, -0.980785, 0.195090, 1.00000, 0.00000, 0.923880, 0.382683, 0.707107, 0.707107, 0.382683, 0.923880, 1.00000, 0.00000, 0.707107, 0.707107, -0.437114e-07, 1.00000, -0.707107, 0.707107, 1.00000, 0.00000, 0.382683, 0.923880, -0.707107, 0.707107, -0.923880, -0.382683, 1.00000, 0.00000, 1.00000, 0.00000, 1.00000, 0.00000, 0.119249e-07, -1.00000, }, wantiifac: []int{32, 3, 2, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 25, wantiwork: []float64{ 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 1.00000, 0.00000, 0.968583, 0.248690, 0.876307, 0.481754, 0.728969, 0.684547, 0.535827, 0.844328, 1.00000, 0.00000, 0.876307, 0.481754, 0.535827, 0.844328, 0.627904e-01, 0.998027, -0.425779, 0.904827, 1.00000, 0.00000, 0.728969, 0.684547, 0.627904e-01, 0.998027, -0.637424, 0.770513, -0.992115, 0.125333, 1.00000, 0.00000, 0.535827, 0.844328, -0.425779, 0.904827, -0.992115, 0.125333, -0.637424, -0.770513, 1.00000, 0.00000, 1.00000, 0.00000, 1.00000, 0.00000, 1.00000, 0.00000, 0.309017, -0.951056, }, wantiifac: []int{25, 2, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 4, wantiwork: []float64{ 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 1.00000, 0.00000, 1.00000, 0.00000, 1.00000, 0.00000, 0.119249e-07, -1.00000, }, wantiifac: []int{4, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 3, wantiwork: []float64{ 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 1.00000, 0.00000, 1.00000, 0.00000, -0.500000, -0.866025, }, wantiifac: []int{3, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 2, wantiwork: []float64{ 0.00000, 0.00000, 0.00000, 0.00000, 1.00000, 0.00000, -1.00000, -0.874228e-07, }, wantiifac: []int{2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, } func TestSint(t *testing.T) { t.Parallel() const tol = 1e-12 for _, test := range sintTests { // Compute the work and factor slices and compare to known values. work := make([]float64, 5*(test.n)/2) ifac := make([]int, 15) Sinti(test.n-1, work, ifac) var failed bool if !floats.EqualApprox(work, test.wantiwork, 1e-6) { failed = true t.Errorf("unexpected work after call to sinti for n=%d", test.n) } if !reflect.DeepEqual(ifac, test.wantiifac) { failed = true t.Errorf("unexpected ifac after call to sinti for n=%d", test.n) } if failed { continue } // Construct a sequence with known a frequency spectrum and compare // the computed spectrum. fn := float64(test.n) x, _, xh := series(test.n - 1) y := make([]float64, test.n-1) dt := math.Pi / fn for i := 0; i < test.n-1; i++ { arg1 := float64(i+1) * dt for k := 0; k < test.n-1; k++ { //eek y[i] += x[k] * math.Sin(float64(k+1)*arg1) } y[i] *= 2 } Sint(test.n-1, x, work, ifac) cf := 0.5 / fn var sintt float64 for i := 0; i < test.n-1; i++ { sintt = math.Max(sintt, math.Abs(x[i]-y[i])) x[i] = xh[i] y[i] = x[i] } sintt *= cf if !scalar.EqualWithinAbsOrRel(sintt, 0, tol, tol) { t.Errorf("unexpected sintt value for n=%d: got:%f want:0", test.n, sintt) } // Check that the transform is its own inverse. Sint(test.n-1, x, work, ifac) Sint(test.n-1, x, work, ifac) var sintfb float64 for i := 0; i < test.n-1; i++ { sintfb = math.Max(sintfb, math.Abs(cf*x[i]-y[i])) } if !scalar.EqualWithinAbsOrRel(sintfb, 0, tol, tol) { t.Errorf("unexpected sintfb value for n=%d: got:%f want:0", test.n, sintfb) } } } var sintTests = []struct { n int // The following two fields are added as there is no unit testing in // FFTPACK for SINTI. // // wantiwork is obtained from the FFTPACK test.f with modification. // The W array is zeroed at each iteration and the first 2.5n elements // of W are printed after the call to RFFTI. wantiwork []float64 // wantiifac is obtained from the FFTPACK sint.f with modification. // The IFAC array is zeroed at each iteration of test.f and the 15 elements // of IFAC are printed before RFFTI returns. wantiifac []int }{ { n: 120, wantiwork: []float64{ 0.5235390e-01, 0.1046719, 0.1569182, 0.2090569, 0.2610524, 0.3128690, 0.3644710, 0.4158234, 0.4668908, 0.5176381, 0.5680307, 0.6180340, 0.6676137, 0.7167359, 0.7653669, 0.8134733, 0.8610222, 0.9079810, 0.9543176, 1.000000, 1.044997, 1.089278, 1.132812, 1.175570, 1.217523, 1.258641, 1.298896, 1.338261, 1.376709, 1.414214, 1.450749, 1.486290, 1.520812, 1.554292, 1.586707, 1.618034, 1.648252, 1.677341, 1.705280, 1.732051, 1.757634, 1.782013, 1.805171, 1.827091, 1.847759, 1.867161, 1.885283, 1.902113, 1.917639, 1.931852, 1.944740, 1.956295, 1.966510, 1.975377, 1.982890, 1.989044, 1.993835, 1.997259, 1.999315, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9986295, 0.5233596e-01, 0.9945219, 0.1045285, 0.9876884, 0.1564345, 0.9781476, 0.2079117, 0.9659258, 0.2588190, 0.9510565, 0.3090170, 0.9335804, 0.3583679, 0.9135454, 0.4067366, 0.8910065, 0.4539905, 0.8660254, 0.5000000, 0.8386706, 0.5446391, 0.8090170, 0.5877852, 0.7771459, 0.6293204, 0.7431448, 0.6691306, 0.7071068, 0.7071068, 0.6691306, 0.7431449, 0.6293204, 0.7771460, 0.5877852, 0.8090170, 0.5446390, 0.8386706, 0.5000000, 0.8660254, 0.4539905, 0.8910065, 0.4067366, 0.9135455, 0.3583679, 0.9335805, 0.3090170, 0.9510565, 0.2588191, 0.9659258, 0.2079117, 0.9781476, 0.1564344, 0.9876884, 0.1045284, 0.9945219, 0.5233597e-01, 0.9986295, 0.000000, 0.000000, 0.9945219, 0.1045285, 0.9781476, 0.2079117, 0.9510565, 0.3090170, 0.9135454, 0.4067366, 0.8660254, 0.5000000, 0.8090170, 0.5877852, 0.7431448, 0.6691306, 0.000000, 0.9781476, 0.2079117, 0.9135454, 0.4067366, 0.8090170, 0.5877852, 0.6691306, 0.7431449, 0.5000000, 0.8660254, 0.3090170, 0.9510565, 0.1045284, 0.9945219, 0.000000, 0.9510565, 0.3090170, 0.8090170, 0.5877852, 0.5877852, 0.8090170, 0.3090170, 0.9510565, -0.4371139e-07, 1.000000, -0.3090170, 0.9510565, -0.5877852, 0.8090170, 0.000000, 0.9135454, 0.4067366, 0.6691306, 0.7431449, 0.000000, 0.6691306, 0.7431449, -0.1045285, 0.9945219, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.1681558e-42, }, wantiifac: []int{120, 4, 2, 4, 3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 54, wantiwork: []float64{ 0.1162897, 0.2321858, 0.3472964, 0.4612317, 0.5736065, 0.6840402, 0.7921596, 0.8975984, 1.000000, 1.099018, 1.194317, 1.285575, 1.372483, 1.454747, 1.532089, 1.604246, 1.670976, 1.732051, 1.787265, 1.836432, 1.879385, 1.915979, 1.946090, 1.969615, 1.986477, 1.996616, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9932383, 0.1160929, 0.9730449, 0.2306159, 0.9396926, 0.3420201, 0.8936327, 0.4487992, 0.8354878, 0.5495090, 0.7660444, 0.6427876, 0.6862416, 0.7273737, 0.5971586, 0.8021232, 0.5000000, 0.8660254, 0.3960797, 0.9182161, 0.2868032, 0.9579895, 0.1736482, 0.9848077, 0.5814485e-01, 0.9983082, 0.000000, 0.9730449, 0.2306159, 0.8936327, 0.4487992, 0.7660444, 0.6427876, 0.5971586, 0.8021232, 0.000000, 0.8936327, 0.4487992, 0.5971586, 0.8021232, 0.1736482, 0.9848077, -0.2868032, 0.9579895, 0.000000, 0.7660444, 0.6427876, 0.000000, 0.1736482, 0.9848077, 0.000000, 0.000000, 0.000000, 0.000000, 0.7567012e-43, }, wantiifac: []int{54, 4, 2, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 49, wantiwork: []float64{ 0.1281404, 0.2557543, 0.3823173, 0.5073092, 0.6302165, 0.7505341, 0.8677675, 0.9814351, 1.091070, 1.196221, 1.296457, 1.391365, 1.480556, 1.563663, 1.640345, 1.710286, 1.773199, 1.828825, 1.876937, 1.917336, 1.949856, 1.974364, 1.990758, 1.998972, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9917900, 0.1278772, 0.9672949, 0.2536546, 0.9269168, 0.3752670, 0.000000, 0.9672949, 0.2536546, 0.8713187, 0.4907176, 0.7183493, 0.6956826, 0.000000, 0.9269168, 0.3752670, 0.7183493, 0.6956826, 0.4047833, 0.9144127, 0.000000, 0.8713187, 0.4907176, 0.5183925, 0.8551428, 0.3205151e-01, 0.9994862, 0.000000, 0.8014136, 0.5981106, 0.2845275, 0.9586679, -0.3453652, 0.9384683, 0.000000, 0.7183493, 0.6956826, 0.3205151e-01, 0.9994862, -0.6723010, 0.7402779, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{49, 2, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 32, wantiwork: []float64{ 0.1960343, 0.3901806, 0.5805693, 0.7653669, 0.9427935, 1.111140, 1.268787, 1.414214, 1.546021, 1.662939, 1.763843, 1.847759, 1.913881, 1.961571, 1.990369, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9807853, 0.1950903, 0.9238795, 0.3826835, 0.8314696, 0.5555702, 0.7071068, 0.7071068, 0.5555702, 0.8314697, 0.3826834, 0.9238795, 0.1950902, 0.9807853, 0.000000, 0.000000, 0.9238795, 0.3826835, 0.000000, 0.000000, 0.7071068, 0.7071068, 0.000000, 0.000000, 0.3826834, 0.9238795, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.4484155e-43, }, wantiifac: []int{32, 3, 2, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 25, wantiwork: []float64{ 0.2506665, 0.4973798, 0.7362491, 0.9635074, 1.175570, 1.369094, 1.541027, 1.688656, 1.809654, 1.902113, 1.964575, 1.996053, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9685832, 0.2486899, 0.8763067, 0.4817537, 0.000000, 0.8763067, 0.4817537, 0.5358267, 0.8443279, 0.000000, 0.7289686, 0.6845471, 0.6279038e-01, 0.9980267, 0.000000, 0.5358267, 0.8443279, -0.4257794, 0.9048270, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{25, 2, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 4, wantiwork: []float64{ 1.414214, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{4, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 3, wantiwork: []float64{ 1.732051, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{3, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 2, wantiwork: []float64{ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, } func TestCost(t *testing.T) { t.Parallel() const tol = 1e-12 for _, test := range costTests { // Compute the work and factor slices and compare to known values. work := make([]float64, 3*(test.n+1)) ifac := make([]int, 15) Costi(test.n+1, work, ifac) var failed bool if !floats.EqualApprox(work, test.wantiwork, 1e-6) { failed = true t.Errorf("unexpected work after call to costi for n=%d", test.n) } if !reflect.DeepEqual(ifac, test.wantiifac) { failed = true t.Errorf("unexpected ifac after call to costi for n=%d", test.n) } if failed { continue } // Construct a sequence with known a frequency spectrum and compare // the computed spectrum. fn := float64(test.n) x, _, xh := series(test.n + 1) y := make([]float64, test.n+1) dt := math.Pi / fn for i := 0; i < test.n+1; i++ { y[i] = 0.5 * (x[0] + math.Pow(-1, float64(i))*x[test.n]) arg1 := float64(i) * dt for k := 1; k < test.n; k++ { //eek y[i] += x[k] * math.Cos(float64(k)*arg1) } y[i] *= 2 } Cost(test.n+1, x, work, ifac) cf := 0.5 / fn var costt float64 for i := 0; i < test.n; i++ { costt = math.Max(costt, math.Abs(x[i]-y[i])) x[i] = xh[i] y[i] = x[i] } costt *= cf if !scalar.EqualWithinAbsOrRel(costt, 0, tol, tol) { t.Errorf("unexpected costt value for n=%d: got:%f want:0", test.n, costt) } // Check that the transform is its own inverse. Cost(test.n+1, x, work, ifac) Cost(test.n+1, x, work, ifac) var costfb float64 for i := 0; i < test.n-1; i++ { costfb = math.Max(costfb, math.Abs(cf*x[i]-y[i])) } if !scalar.EqualWithinAbsOrRel(costfb, 0, tol, tol) { t.Errorf("unexpected costfb value for n=%d: got:%f want:0", test.n, costfb) } } } var costTests = []struct { n int // The following two fields are added as there is no unit testing in // FFTPACK for SINTI. // // wantiwork is obtained from the FFTPACK test.f with modification. // The W array is zeroed at each iteration and the first 3n elements // of W are printed after the call to RFFTI. wantiwork []float64 // wantiifac is obtained from the FFTPACK sint.f with modification. // The IFAC array is zeroed at each iteration of test.f and the 15 elements // of IFAC are printed before RFFTI returns. wantiifac []int }{ { n: 120, wantiwork: []float64{ 0.000000, 0.5235390e-01, 0.1046719, 0.1569182, 0.2090569, 0.2610524, 0.3128690, 0.3644710, 0.4158234, 0.4668908, 0.5176381, 0.5680307, 0.6180340, 0.6676137, 0.7167359, 0.7653669, 0.8134733, 0.8610222, 0.9079810, 0.9543176, 1.000000, 1.044997, 1.089278, 1.132812, 1.175570, 1.217523, 1.258641, 1.298896, 1.338261, 1.376709, 1.414214, 1.450749, 1.486290, 1.520812, 1.554292, 1.586707, 1.618034, 1.648252, 1.677341, 1.705280, 1.732051, 1.757634, 1.782013, 1.805171, 1.827091, 1.847759, 1.867161, 1.885283, 1.902113, 1.917639, 1.931852, 1.944740, 1.956295, 1.966510, 1.975377, 1.982890, 1.989044, 1.993835, 1.997259, 1.999315, 0.000000, 0.5235375e-01, 0.1046719, 0.1569182, 0.2090568, 0.2610523, 0.3128687, 0.3644710, 0.4158233, 0.4668906, 0.5176381, 0.5680307, 0.6180339, 0.6676136, 0.7167357, 0.7653669, 0.8134732, 0.8610221, 0.9079810, 0.9543175, 1.000000, 1.044997, 1.089278, 1.132812, 1.175570, 1.217523, 1.258641, 1.298896, 1.338261, 1.376709, 1.414214, 1.450749, 1.486290, 1.520812, 1.554292, 1.586707, 1.618034, 1.648252, 1.677341, 1.705280, 1.732051, 1.757634, 1.782013, 1.805171, 1.827091, 1.847759, 1.867161, 1.885283, 1.902113, 1.917639, 1.931852, 1.944740, 1.956295, 1.966510, 1.975377, 1.982890, 1.989044, 1.993835, 1.997259, 1.999315, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9986295, 0.5233596e-01, 0.9945219, 0.1045285, 0.9876884, 0.1564345, 0.9781476, 0.2079117, 0.9659258, 0.2588190, 0.9510565, 0.3090170, 0.9335804, 0.3583679, 0.9135454, 0.4067366, 0.8910065, 0.4539905, 0.8660254, 0.5000000, 0.8386706, 0.5446391, 0.8090170, 0.5877852, 0.7771459, 0.6293204, 0.7431448, 0.6691306, 0.7071068, 0.7071068, 0.6691306, 0.7431449, 0.6293204, 0.7771460, 0.5877852, 0.8090170, 0.5446390, 0.8386706, 0.5000000, 0.8660254, 0.4539905, 0.8910065, 0.4067366, 0.9135455, 0.3583679, 0.9335805, 0.3090170, 0.9510565, 0.2588191, 0.9659258, 0.2079117, 0.9781476, 0.1564344, 0.9876884, 0.1045284, 0.9945219, 0.5233597e-01, 0.9986295, 0.000000, 0.000000, 0.9945219, 0.1045285, 0.9781476, 0.2079117, 0.9510565, 0.3090170, 0.9135454, 0.4067366, 0.8660254, 0.5000000, 0.8090170, 0.5877852, 0.7431448, 0.6691306, 0.000000, 0.9781476, 0.2079117, 0.9135454, 0.4067366, 0.8090170, 0.5877852, 0.6691306, 0.7431449, 0.5000000, 0.8660254, 0.3090170, 0.9510565, 0.1045284, 0.9945219, 0.000000, 0.9510565, 0.3090170, 0.8090170, 0.5877852, 0.5877852, 0.8090170, 0.3090170, 0.9510565, -0.4371139e-07, 1.000000, -0.3090170, 0.9510565, -0.5877852, 0.8090170, 0.000000, 0.9135454, 0.4067366, 0.6691306, 0.7431449, 0.000000, 0.6691306, 0.7431449, -0.1045285, 0.9945219, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.1681558e-42, 0.5605194e-44, }, wantiifac: []int{120, 4, 2, 4, 3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 54, wantiwork: []float64{ 0.000000, 0.1162897, 0.2321858, 0.3472964, 0.4612317, 0.5736065, 0.6840402, 0.7921596, 0.8975984, 1.000000, 1.099018, 1.194317, 1.285575, 1.372483, 1.454747, 1.532089, 1.604246, 1.670976, 1.732051, 1.787265, 1.836432, 1.879385, 1.915979, 1.946090, 1.969615, 1.986477, 1.996616, 0.000000, 0.1162897, 0.2321858, 0.3472964, 0.4612317, 0.5736064, 0.6840403, 0.7921594, 0.8975984, 1.000000, 1.099018, 1.194317, 1.285575, 1.372483, 1.454747, 1.532089, 1.604246, 1.670976, 1.732051, 1.787265, 1.836432, 1.879385, 1.915979, 1.946090, 1.969615, 1.986477, 1.996616, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9932383, 0.1160929, 0.9730449, 0.2306159, 0.9396926, 0.3420201, 0.8936327, 0.4487992, 0.8354878, 0.5495090, 0.7660444, 0.6427876, 0.6862416, 0.7273737, 0.5971586, 0.8021232, 0.5000000, 0.8660254, 0.3960797, 0.9182161, 0.2868032, 0.9579895, 0.1736482, 0.9848077, 0.5814485e-01, 0.9983082, 0.000000, 0.9730449, 0.2306159, 0.8936327, 0.4487992, 0.7660444, 0.6427876, 0.5971586, 0.8021232, 0.000000, 0.8936327, 0.4487992, 0.5971586, 0.8021232, 0.1736482, 0.9848077, -0.2868032, 0.9579895, 0.000000, 0.7660444, 0.6427876, 0.000000, 0.1736482, 0.9848077, 0.000000, 0.000000, 0.000000, 0.000000, 0.7567012e-43, 0.5605194e-44, }, wantiifac: []int{54, 4, 2, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 49, wantiwork: []float64{ 0.000000, 0.1281404, 0.2557543, 0.3823173, 0.5073092, 0.6302165, 0.7505341, 0.8677675, 0.9814351, 1.091070, 1.196221, 1.296457, 1.391365, 1.480556, 1.563663, 1.640345, 1.710286, 1.773199, 1.828825, 1.876937, 1.917336, 1.949856, 1.974364, 1.990758, 1.998972, 0.6410302e-01, 0.1920458, 0.3191997, 0.4450417, 0.5690550, 0.6907300, 0.8095666, 0.9250766, 1.036785, 1.144233, 1.246980, 1.344602, 1.436699, 1.522892, 1.602827, 1.676176, 1.742637, 1.801938, 1.853834, 1.898111, 1.934590, 1.963118, 1.983580, 1.995891, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9917900, 0.1278772, 0.9672949, 0.2536546, 0.9269168, 0.3752670, 0.000000, 0.9672949, 0.2536546, 0.8713187, 0.4907176, 0.7183493, 0.6956826, 0.000000, 0.9269168, 0.3752670, 0.7183493, 0.6956826, 0.4047833, 0.9144127, 0.000000, 0.8713187, 0.4907176, 0.5183925, 0.8551428, 0.3205151e-01, 0.9994862, 0.000000, 0.8014136, 0.5981106, 0.2845275, 0.9586679, -0.3453652, 0.9384683, 0.000000, 0.7183493, 0.6956826, 0.3205151e-01, 0.9994862, -0.6723010, 0.7402779, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.6866362e-43, 0.2802597e-44, }, wantiifac: []int{49, 2, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 32, wantiwork: []float64{ 0.000000, 0.1960343, 0.3901806, 0.5805693, 0.7653669, 0.9427935, 1.111140, 1.268787, 1.414214, 1.546021, 1.662939, 1.763843, 1.847759, 1.913881, 1.961571, 1.990369, 0.000000, 0.1960343, 0.3901805, 0.5805693, 0.7653669, 0.9427933, 1.111140, 1.268787, 1.414214, 1.546021, 1.662939, 1.763842, 1.847759, 1.913881, 1.961571, 1.990369, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9807853, 0.1950903, 0.9238795, 0.3826835, 0.8314696, 0.5555702, 0.7071068, 0.7071068, 0.5555702, 0.8314697, 0.3826834, 0.9238795, 0.1950902, 0.9807853, 0.000000, 0.000000, 0.9238795, 0.3826835, 0.000000, 0.000000, 0.7071068, 0.7071068, 0.000000, 0.000000, 0.3826834, 0.9238795, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.4484155e-43, 0.4203895e-44, }, wantiifac: []int{32, 3, 2, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 25, wantiwork: []float64{ 0.000000, 0.2506665, 0.4973798, 0.7362491, 0.9635074, 1.175570, 1.369094, 1.541027, 1.688656, 1.809654, 1.902113, 1.964575, 1.996053, 0.1255808, 0.3747624, 0.6180339, 0.8515584, 1.071653, 1.274848, 1.457937, 1.618034, 1.752613, 1.859553, 1.937166, 1.984229, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9685832, 0.2486899, 0.8763067, 0.4817537, 0.000000, 0.8763067, 0.4817537, 0.5358267, 0.8443279, 0.000000, 0.7289686, 0.6845471, 0.6279038e-01, 0.9980267, 0.000000, 0.5358267, 0.8443279, -0.4257794, 0.9048270, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.3503246e-43, 0.2802597e-44, }, wantiifac: []int{25, 2, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 4, wantiwork: []float64{ 0.000000, 1.414214, 0.000000, 1.414214, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.5605194e-44, 0.1401298e-44, }, wantiifac: []int{4, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 3, wantiwork: []float64{ 0.000000, 1.732051, 1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.4203895e-44, 0.1401298e-44, }, wantiifac: []int{3, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 2, wantiwork: []float64{ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, } func TestCosq(t *testing.T) { t.Parallel() const tol = 1e-12 for _, test := range sincosqTests { // Compute the work and factor slices and compare to known values. work := make([]float64, 3*test.n) ifac := make([]int, 15) Cosqi(test.n, work, ifac) var failed bool if !floats.EqualApprox(work, test.wantiwork, 1e-6) { failed = true t.Errorf("unexpected work after call to cosqi for n=%d", test.n) t.Logf("\n%v\n%v", work, test.wantiwork) } if !reflect.DeepEqual(ifac, test.wantiifac) { failed = true t.Errorf("unexpected ifac after call to cosqi for n=%d", test.n) } if failed { continue } // Construct a sequence with known a frequency spectrum and compare // the computed spectrum. fn := float64(test.n) x := make([]float64, test.n) y, _, xh := series(test.n) dt := math.Pi / (2 * fn) for i := 0; i < test.n; i++ { arg := float64(i) * dt for k := 0; k < test.n; k++ { x[i] += y[k] * math.Cos(float64(2*k+1)*arg) } x[i] *= 4 } Cosqb(test.n, y, work, ifac) cf := 0.25 / fn var cosqbt float64 for i := 0; i < test.n; i++ { cosqbt = math.Max(cosqbt, math.Abs(x[i]-y[i])) x[i] = xh[i] } cosqbt *= cf if !scalar.EqualWithinAbsOrRel(cosqbt, 0, tol, tol) { t.Errorf("unexpected cosqbt value for n=%d: got:%f want:0", test.n, cosqbt) } // Construct a frequency spectrum and compare the computed sequence. for i := 0; i < test.n; i++ { y[i] = 0.5 * x[0] arg := float64(2*i+1) * dt for k := 1; k < test.n; k++ { y[i] += x[k] * math.Cos(float64(k)*arg) } y[i] *= 2 } Cosqf(test.n, x, work, ifac) var cosqft float64 for i := 0; i < test.n; i++ { cosqft = math.Max(cosqft, math.Abs(x[i]-y[i])) x[i] = xh[i] y[i] = xh[i] } cosqft *= cf if !scalar.EqualWithinAbsOrRel(cosqft, 0, tol, tol) { t.Errorf("unexpected cosqft value for n=%d: got:%f want:0", test.n, cosqft) } // Check that Cosqb and Cosqf are inverses. Cosqb(test.n, x, work, ifac) Cosqf(test.n, x, work, ifac) var cosqfb float64 for i := 0; i < test.n; i++ { cosqfb = math.Max(cosqfb, math.Abs(cf*x[i]-y[i])) } if !scalar.EqualWithinAbsOrRel(cosqfb, 0, tol, tol) { t.Errorf("unexpected cosqfb value for n=%d: got:%f want:0", test.n, cosqfb) } } } func TestSinq(t *testing.T) { t.Parallel() const tol = 1e-12 for _, test := range sincosqTests { // Compute the work and factor slices and compare to known values. work := make([]float64, 3*test.n) ifac := make([]int, 15) Sinqi(test.n, work, ifac) var failed bool if !floats.EqualApprox(work, test.wantiwork, 1e-6) { failed = true t.Errorf("unexpected work after call to sinqi for n=%d", test.n) t.Logf("\n%v\n%v", work, test.wantiwork) } if !reflect.DeepEqual(ifac, test.wantiifac) { failed = true t.Errorf("unexpected ifac after call to sinqi for n=%d", test.n) } if failed { continue } // Construct a sequence with known a frequency spectrum and compare // the computed spectrum. fn := float64(test.n) x := make([]float64, test.n) y, _, xh := series(test.n) dt := math.Pi / (2 * fn) for i := 0; i < test.n; i++ { arg := float64(i+1) * dt for k := 0; k < test.n; k++ { x[i] += y[k] * math.Sin(float64(2*k+1)*arg) } x[i] *= 4 } Sinqb(test.n, y, work, ifac) cf := 0.25 / fn var sinqbt float64 for i := 0; i < test.n; i++ { sinqbt = math.Max(sinqbt, math.Abs(x[i]-y[i])) x[i] = xh[i] } sinqbt *= cf if !scalar.EqualWithinAbsOrRel(sinqbt, 0, tol, tol) { t.Errorf("unexpected sinqbt value for n=%d: got:%f want:0", test.n, sinqbt) } // Construct a frequency spectrum and compare the computed sequence. for i := 0; i < test.n; i++ { arg := float64(2*i+1) * dt y[i] = 0.5 * math.Pow(-1, float64(i)) * x[test.n-1] for k := 0; k < test.n-1; k++ { y[i] += x[k] * math.Sin(float64(k+1)*arg) } y[i] *= 2 } Sinqf(test.n, x, work, ifac) var sinqft float64 for i := 0; i < test.n; i++ { sinqft = math.Max(sinqft, math.Abs(x[i]-y[i])) x[i] = xh[i] y[i] = xh[i] } sinqft *= cf if !scalar.EqualWithinAbsOrRel(sinqft, 0, tol, tol) { t.Errorf("unexpected sinqft value for n=%d: got:%f want:0", test.n, sinqft) } // Check that Sinqb and Sinqf are inverses. Sinqb(test.n, x, work, ifac) Sinqf(test.n, x, work, ifac) var sinqfb float64 for i := 0; i < test.n; i++ { sinqfb = math.Max(sinqfb, math.Abs(cf*x[i]-y[i])) } if !scalar.EqualWithinAbsOrRel(sinqfb, 0, tol, tol) { t.Errorf("unexpected sinqfb value for n=%d: got:%f want:0", test.n, sinqfb) } } } var sincosqTests = []struct { n int // The following two fields are added as there is no unit testing in // FFTPACK for SINTI. // // wantiwork is obtained from the FFTPACK test.f with modification. // The W array is zeroed at each iteration and the first 3n elements // of W are printed after the call to RFFTI. wantiwork []float64 // wantiifac is obtained from the FFTPACK sint.f with modification. // The IFAC array is zeroed at each iteration of test.f and the 15 elements // of IFAC are printed before RFFTI returns. wantiifac []int }{ { n: 120, wantiwork: []float64{ 0.9999143, 0.9996573, 0.9992290, 0.9986295, 0.9978589, 0.9969173, 0.9958049, 0.9945219, 0.9930685, 0.9914449, 0.9896514, 0.9876884, 0.9855561, 0.9832549, 0.9807853, 0.9781476, 0.9753423, 0.9723699, 0.9692309, 0.9659258, 0.9624552, 0.9588197, 0.9550200, 0.9510565, 0.9469301, 0.9426415, 0.9381914, 0.9335804, 0.9288096, 0.9238795, 0.9187912, 0.9135454, 0.9081432, 0.9025853, 0.8968728, 0.8910065, 0.8849877, 0.8788171, 0.8724960, 0.8660254, 0.8594064, 0.8526402, 0.8457278, 0.8386706, 0.8314696, 0.8241262, 0.8166415, 0.8090170, 0.8012538, 0.7933533, 0.7853169, 0.7771459, 0.7688418, 0.7604060, 0.7518398, 0.7431448, 0.7343225, 0.7253744, 0.7163019, 0.7071068, 0.6977904, 0.6883546, 0.6788007, 0.6691306, 0.6593458, 0.6494480, 0.6394390, 0.6293204, 0.6190940, 0.6087614, 0.5983246, 0.5877852, 0.5771452, 0.5664062, 0.5555702, 0.5446390, 0.5336145, 0.5224985, 0.5112931, 0.5000000, 0.4886212, 0.4771588, 0.4656145, 0.4539905, 0.4422887, 0.4305110, 0.4186597, 0.4067366, 0.3947438, 0.3826834, 0.3705574, 0.3583679, 0.3461170, 0.3338068, 0.3214395, 0.3090170, 0.2965415, 0.2840153, 0.2714404, 0.2588191, 0.2461533, 0.2334453, 0.2206974, 0.2079117, 0.1950902, 0.1822355, 0.1693494, 0.1564344, 0.1434926, 0.1305261, 0.1175374, 0.1045284, 0.9150153e-01, 0.7845908e-01, 0.6540307e-01, 0.5233597e-01, 0.3925979e-01, 0.2617688e-01, 0.1308960e-01, -0.4371139e-07, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9986295, 0.5233596e-01, 0.9945219, 0.1045285, 0.9876884, 0.1564345, 0.9781476, 0.2079117, 0.9659258, 0.2588190, 0.9510565, 0.3090170, 0.9335804, 0.3583679, 0.9135454, 0.4067366, 0.8910065, 0.4539905, 0.8660254, 0.5000000, 0.8386706, 0.5446391, 0.8090170, 0.5877852, 0.7771459, 0.6293204, 0.7431448, 0.6691306, 0.7071068, 0.7071068, 0.6691306, 0.7431449, 0.6293204, 0.7771460, 0.5877852, 0.8090170, 0.5446390, 0.8386706, 0.5000000, 0.8660254, 0.4539905, 0.8910065, 0.4067366, 0.9135455, 0.3583679, 0.9335805, 0.3090170, 0.9510565, 0.2588191, 0.9659258, 0.2079117, 0.9781476, 0.1564344, 0.9876884, 0.1045284, 0.9945219, 0.5233597e-01, 0.9986295, 0.000000, 0.000000, 0.9945219, 0.1045285, 0.9781476, 0.2079117, 0.9510565, 0.3090170, 0.9135454, 0.4067366, 0.8660254, 0.5000000, 0.8090170, 0.5877852, 0.7431448, 0.6691306, 0.000000, 0.9781476, 0.2079117, 0.9135454, 0.4067366, 0.8090170, 0.5877852, 0.6691306, 0.7431449, 0.5000000, 0.8660254, 0.3090170, 0.9510565, 0.1045284, 0.9945219, 0.000000, 0.9510565, 0.3090170, 0.8090170, 0.5877852, 0.5877852, 0.8090170, 0.3090170, 0.9510565, -0.4371139e-07, 1.000000, -0.3090170, 0.9510565, -0.5877852, 0.8090170, 0.000000, 0.9135454, 0.4067366, 0.6691306, 0.7431449, 0.000000, 0.6691306, 0.7431449, -0.1045285, 0.9945219, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{120, 4, 2, 4, 3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 54, wantiwork: []float64{ 0.9995769, 0.9983082, 0.9961947, 0.9932383, 0.9894416, 0.9848077, 0.9793406, 0.9730449, 0.9659258, 0.9579895, 0.9492427, 0.9396926, 0.9293475, 0.9182161, 0.9063078, 0.8936327, 0.8802014, 0.8660254, 0.8511167, 0.8354878, 0.8191521, 0.8021232, 0.7844157, 0.7660444, 0.7470251, 0.7273737, 0.7071068, 0.6862416, 0.6647958, 0.6427876, 0.6202354, 0.5971586, 0.5735765, 0.5495090, 0.5249766, 0.5000000, 0.4746003, 0.4487992, 0.4226182, 0.3960797, 0.3692062, 0.3420202, 0.3145447, 0.2868032, 0.2588191, 0.2306159, 0.2022175, 0.1736482, 0.1449319, 0.1160929, 0.8715568e-01, 0.5814485e-01, 0.2908471e-01, -0.4371139e-07, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9932383, 0.1160929, 0.9730449, 0.2306159, 0.9396926, 0.3420201, 0.8936327, 0.4487992, 0.8354878, 0.5495090, 0.7660444, 0.6427876, 0.6862416, 0.7273737, 0.5971586, 0.8021232, 0.5000000, 0.8660254, 0.3960797, 0.9182161, 0.2868032, 0.9579895, 0.1736482, 0.9848077, 0.5814485e-01, 0.9983082, 0.000000, 0.9730449, 0.2306159, 0.8936327, 0.4487992, 0.7660444, 0.6427876, 0.5971586, 0.8021232, 0.000000, 0.8936327, 0.4487992, 0.5971586, 0.8021232, 0.1736482, 0.9848077, -0.2868032, 0.9579895, 0.000000, 0.7660444, 0.6427876, 0.000000, 0.1736482, 0.9848077, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{54, 4, 2, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 49, wantiwork: []float64{ 0.9994862, 0.9979454, 0.9953791, 0.9917900, 0.9871818, 0.9815592, 0.9749279, 0.9672949, 0.9586679, 0.9490557, 0.9384684, 0.9269168, 0.9144126, 0.9009688, 0.8865993, 0.8713187, 0.8551428, 0.8380881, 0.8201723, 0.8014136, 0.7818314, 0.7614459, 0.7402779, 0.7183493, 0.6956825, 0.6723009, 0.6482283, 0.6234898, 0.5981105, 0.5721166, 0.5455348, 0.5183925, 0.4907175, 0.4625383, 0.4338836, 0.4047833, 0.3752669, 0.3453650, 0.3151082, 0.2845275, 0.2536545, 0.2225209, 0.1911586, 0.1595999, 0.1278771, 0.9602292e-01, 0.6407014e-01, 0.3205151e-01, -0.4371139e-07, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9917900, 0.1278772, 0.9672949, 0.2536546, 0.9269168, 0.3752670, 0.000000, 0.9672949, 0.2536546, 0.8713187, 0.4907176, 0.7183493, 0.6956826, 0.000000, 0.9269168, 0.3752670, 0.7183493, 0.6956826, 0.4047833, 0.9144127, 0.000000, 0.8713187, 0.4907176, 0.5183925, 0.8551428, 0.3205151e-01, 0.9994862, 0.000000, 0.8014136, 0.5981106, 0.2845275, 0.9586679, -0.3453652, 0.9384683, 0.000000, 0.7183493, 0.6956826, 0.3205151e-01, 0.9994862, -0.6723010, 0.7402779, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{49, 2, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 32, wantiwork: []float64{ 0.9987954, 0.9951847, 0.9891765, 0.9807853, 0.9700313, 0.9569404, 0.9415441, 0.9238795, 0.9039893, 0.8819212, 0.8577286, 0.8314696, 0.8032075, 0.7730104, 0.7409511, 0.7071068, 0.6715589, 0.6343933, 0.5956993, 0.5555702, 0.5141027, 0.4713967, 0.4275551, 0.3826834, 0.3368898, 0.2902846, 0.2429801, 0.1950902, 0.1467305, 0.9801713e-01, 0.4906765e-01, -0.4371139e-07, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9807853, 0.1950903, 0.9238795, 0.3826835, 0.8314696, 0.5555702, 0.7071068, 0.7071068, 0.5555702, 0.8314697, 0.3826834, 0.9238795, 0.1950902, 0.9807853, 0.000000, 0.000000, 0.9238795, 0.3826835, 0.000000, 0.000000, 0.7071068, 0.7071068, 0.000000, 0.000000, 0.3826834, 0.9238795, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{32, 3, 2, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 25, wantiwork: []float64{ 0.9980267, 0.9921147, 0.9822872, 0.9685832, 0.9510565, 0.9297765, 0.9048271, 0.8763067, 0.8443279, 0.8090170, 0.7705132, 0.7289686, 0.6845471, 0.6374239, 0.5877852, 0.5358267, 0.4817536, 0.4257792, 0.3681245, 0.3090170, 0.2486898, 0.1873812, 0.1253331, 0.6279038e-01, -0.4371139e-07, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.9685832, 0.2486899, 0.8763067, 0.4817537, 0.000000, 0.8763067, 0.4817537, 0.5358267, 0.8443279, 0.000000, 0.7289686, 0.6845471, 0.6279038e-01, 0.9980267, 0.000000, 0.5358267, 0.8443279, -0.4257794, 0.9048270, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{25, 2, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 4, wantiwork: []float64{ 0.9238795, 0.7071068, 0.3826834, -0.4371139e-07, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{4, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 3, wantiwork: []float64{ 0.8660254, 0.5000000, -0.4371139e-07, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{3, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { n: 2, wantiwork: []float64{ 0.7071068, -0.4371139e-07, 0.000000, 0.000000, 0.000000, 0.000000, }, wantiifac: []int{2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, } // series returns three copies of a sinusoidal sequence n samples long. func series(n int) (x, y, xh []float64) { x = make([]float64, n) y = make([]float64, n) xh = make([]float64, n) for i := 0; i < n; i++ { x[i] = math.Sin(float64(i+1) * math.Sqrt2) y[i] = x[i] xh[i] = x[i] } return x, y, xh }