UNPKG

ts-scikit

Version:

A scientific toolkit written in Typescript

215 lines 8.28 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FftComplex = void 0; const utils_1 = require("../utils"); const fft_pfa_1 = require("./fft-pfa"); const array_math_1 = require("../utils/array-math"); /** * A fast Fourier transform of complex-valued arrays. * <p> * The FFT length nfft equals the number of <em>complex</em> numbers * transformed. The transform of nfft complex numbers yields nfft compplex * numbers. Those complex numbers are packed into arrays as [real_0, imag_0, * real-1, imag_1, ...]. Here, real_k and imag_k correspond to the real and * imaginary parts, respectively, of the complex number with array index k. * <p> * When input and output arrays are the same array, transforms are * performed in-place. For example, an input array cx[2*nfft] of nfft * complex numbers may be the same as an output array cy[2*nfft] of * nfft complex numbers. By "the same array", we mean that cx==cy. * <p> * Transforms may be performed for any dimension of a multi-dimensional * array. For example, we may transform the 1st dimension of an input * array cx[n2][2*nfft] of n2*nfft complex numbers to an output array * cy[n2][2*nfft] of n2*nfft complex numbers. Or, we may transform the * 2nd dimension of an input array cx[nfft][2*n1] of nfft*n1 complex * numbers to an output array cy[nfft][2*n1] of nfft*n1 complex numbers. * In either case, the input array cx and the output array cy may be the * same array, such that the transform may be performed in-place. */ class FftComplex { /** * Constructs a new FFT, with specified length. * <p> * Valid FFT lengths an be obtained by calling the methods * {@link SmallNFFT} and {@link FastNFFT}. * @param nfft the FFT length, which must be valid. */ constructor(nfft) { utils_1.Check.argument(fft_pfa_1.FftPfa.IsValidNFFT(nfft), `nfft = ${nfft} is valid FFT length`); this._nfft = nfft; } /** * Returns an FFT length optimized for speed. * <p> * The FFT length will be the fastest valid length that is not less than * the specified length n. * @param n the lower bound on FFT length. * @returns the FFT length. */ static FastNFFT(n) { utils_1.Check.argument(n <= 720720, 'n does not exceed 720720'); return fft_pfa_1.FftPfa.FastNFFT(n); } /** * Returns an FFT length optimized for memory. * <p> * The FFT length will be the smallest valid length that is not less than * the specified length n. * @param n the lower bound on FFT length. * @return the FFT length. */ static SmallNFFT(n) { utils_1.Check.argument(n <= 720720, 'n does not exceed 720720'); return fft_pfa_1.FftPfa.SmallNFFT(n); } static _checkSign(sign) { utils_1.Check.argument(sign === 1 || sign === -1, 'sign equals 1 or -1'); } static _checkArray(a, name, n1, n2, n3) { if (a[0] instanceof Array) { if (a[0][0] instanceof Array) { let ok = a.length >= n3; for (let i3 = 0; i3 < n3 && ok; ++i3) { ok = a[i3].length >= n2; for (let i2 = 0; i2 < n2 && ok; ++i2) { ok = a[i3][i2].length >= n1; } } utils_1.Check.argument(ok, `dimensions of ${name} are valid`); } else { let ok = a.length >= n2; for (let i2 = 0; i2 < n2 && ok; ++i2) { ok = a[i2].length >= n1; } utils_1.Check.argument(ok, `dimensions of ${name} are valid`); } } else { utils_1.Check.argument(a.length >= n1, `dimensions of ${name} are valid`); } } /** * The FFT length for this FFT. */ get nfft() { return this._nfft; } /** * Computes a complex-to-complex fast Fourier transform. * Transforms a 1-D input array cx[2*nfft] of nfft complex numbers * to a 1-D output array cy[2*nfft] of nfft complex numbers. * @param sign the sign (1 or -1) of the exponent used in the FFT. * @param cx the input array. * @param cy the output array. */ complexToComplex(sign, cx, cy) { FftComplex._checkSign(sign); FftComplex._checkArray(cx, 'cx', 2 * this._nfft); FftComplex._checkArray(cy, 'cy', 2 * this._nfft); if (cx !== cy) { cy = array_math_1.ccopy(cx, this._nfft); } fft_pfa_1.FftPfa.Transform(sign, this._nfft, cy); } complexToComplex1(sign, cx, cy, n2, n3) { FftComplex._checkSign(sign); if (cx[0] instanceof Array) { if (cx[0][0] instanceof Array) { cx = cx; cy = cy; FftComplex._checkArray(cx, 'cx', 2 * this._nfft, n2, n3); FftComplex._checkArray(cy, 'cy', 2 * this._nfft, n2, n3); for (let i3 = 0; i3 < n3; ++i3) { this.complexToComplex1(sign, cx[i3], cy[i3], n2); } } else { cx = cx; cy = cy; FftComplex._checkArray(cx, 'cx', 2 * this._nfft, n2); FftComplex._checkArray(cy, 'cy', 2 * this._nfft, n2); for (let i2 = 0; i2 < n3; ++i2) { this.complexToComplex(sign, cx[i2], cy[i2]); } } } } complexToComplex2(sign, cx, cy, n1, n3) { FftComplex._checkSign(sign); if (cx[0] instanceof Array) { if (cx[0][0] instanceof Array) { cx = cx; cy = cy; FftComplex._checkArray(cx, 'cx', 2 * n1, this._nfft, n3); FftComplex._checkArray(cy, 'cy', 2 * n1, this._nfft, n3); for (let i3 = 0; i3 < n3; ++i3) { this.complexToComplex2(sign, cx[i3], cy[i3], n1); } } else { cx = cx; cy = cy; FftComplex._checkArray(cx, 'cx', 2 * n1, this._nfft); FftComplex._checkArray(cy, 'cy', 2 * n1, this._nfft); if (cx !== cy) { for (let i1 = 0; i1 < 2 * this._nfft; ++i1) { cy[i1] = cx[i1]; } } fft_pfa_1.FftPfa.Transform2a(sign, n1, this._nfft, cy); } } } /** * Computes a complex-to-complex dimension-3 fast Fourier transform. * <p> * Transforms a 3-D input array cx[nfft][n2][2*n1] of nfft*n2*n1 complex * numbers to a 3-D output array cy[nfft][n2][2*n1] of nfft*n2*n1 complex * numbers. * @param sign the sign (1 or -1) of the exponent used in the FFT. * @param n1 the 1st dimension of arrays. * @param n2 the 2nd dimension of arrays. * @param cx the input array. * @param cy the output array. */ complexToComplex3(sign, cx, cy, n1, n2) { FftComplex._checkSign(sign); FftComplex._checkArray(cx, 'cx', 2 * n1, n2, this._nfft); FftComplex._checkArray(cy, 'cy', 2 * n1, n2, this._nfft); const cxi2 = new Array(this._nfft); const cyi2 = new Array(this._nfft); for (let i2 = 0; i2 < n2; ++i2) { for (let i3 = 0; i3 < this._nfft; ++i3) { cxi2[i3] = cx[i3][i2]; cyi2[i3] = cy[i3][i2]; } this.complexToComplex2(sign, cxi2, cyi2, n1); } } scale(cx, n1, n2, n3) { if (cx[0] instanceof Array) { if (cx[0][0] instanceof Array) { cx = cx; for (let i3 = 0; i3 < n3; ++i3) { this.scale(cx[i3], n1, n2); } } else { cx = cx; for (let i2 = 0; i2 < n2; ++i2) { this.scale(cx[i2], n1); } } } else { cx = cx; const s = 1.0 / this._nfft; let n = 2 * n1; while (--n >= 0) { cx[n] *= s; } } } } exports.FftComplex = FftComplex; //# sourceMappingURL=fft-complex.js.map