Chris@19: (* Chris@19: * Copyright (c) 1997-1999 Massachusetts Institute of Technology Chris@19: * Copyright (c) 2003, 2007-14 Matteo Frigo Chris@19: * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology Chris@19: * Chris@19: * This program is free software; you can redistribute it and/or modify Chris@19: * it under the terms of the GNU General Public License as published by Chris@19: * the Free Software Foundation; either version 2 of the License, or Chris@19: * (at your option) any later version. Chris@19: * Chris@19: * This program is distributed in the hope that it will be useful, Chris@19: * but WITHOUT ANY WARRANTY; without even the implied warranty of Chris@19: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Chris@19: * GNU General Public License for more details. Chris@19: * Chris@19: * You should have received a copy of the GNU General Public License Chris@19: * along with this program; if not, write to the Free Software Chris@19: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Chris@19: * Chris@19: *) Chris@19: Chris@19: (* trigonometric transforms *) Chris@19: open Util Chris@19: Chris@19: (* DFT of real input *) Chris@19: let rdft sign n input = Chris@19: Fft.dft sign n (Complex.real @@ input) Chris@19: Chris@19: (* DFT of hermitian input *) Chris@19: let hdft sign n input = Chris@19: Fft.dft sign n (Complex.hermitian n input) Chris@19: Chris@19: (* DFT real transform of vectors of two real numbers, Chris@19: multiplication by (NaN I), and summation *) Chris@19: let dft_via_rdft sign n input = Chris@19: let f = rdft sign n input Chris@19: in fun i -> Chris@19: Complex.plus Chris@19: [Complex.real (f i); Chris@19: Complex.times (Complex.nan Expr.I) (Complex.imag (f i))] Chris@19: Chris@19: (* Discrete Hartley Transform *) Chris@19: let dht sign n input = Chris@19: let f = Fft.dft sign n (Complex.real @@ input) in Chris@19: (fun i -> Chris@19: Complex.plus [Complex.real (f i); Complex.imag (f i)]) Chris@19: Chris@19: let trigI n input = Chris@19: let twon = 2 * n in Chris@19: let input' = Complex.hermitian twon input Chris@19: in Chris@19: Fft.dft 1 twon input' Chris@19: Chris@19: let interleave_zero input = fun i -> Chris@19: if (i mod 2) == 0 Chris@19: then Complex.zero Chris@19: else Chris@19: input ((i - 1) / 2) Chris@19: Chris@19: let trigII n input = Chris@19: let fourn = 4 * n in Chris@19: let input' = Complex.hermitian fourn (interleave_zero input) Chris@19: in Chris@19: Fft.dft 1 fourn input' Chris@19: Chris@19: let trigIII n input = Chris@19: let fourn = 4 * n in Chris@19: let twon = 2 * n in Chris@19: let input' = Complex.hermitian fourn Chris@19: (fun i -> Chris@19: if (i == 0) then Chris@19: Complex.real (input 0) Chris@19: else if (i == twon) then Chris@19: Complex.uminus (Complex.real (input 0)) Chris@19: else Chris@19: Complex.antihermitian twon input i) Chris@19: in Chris@19: let dft = Fft.dft 1 fourn input' Chris@19: in fun k -> dft (2 * k + 1) Chris@19: Chris@19: let zero_extend n input = fun i -> Chris@19: if (i >= 0 && i < n) Chris@19: then input i Chris@19: else Complex.zero Chris@19: Chris@19: let trigIV n input = Chris@19: let fourn = 4 * n Chris@19: and eightn = 8 * n in Chris@19: let input' = Complex.hermitian eightn Chris@19: (zero_extend fourn (Complex.antihermitian fourn Chris@19: (interleave_zero input))) Chris@19: in Chris@19: let dft = Fft.dft 1 eightn input' Chris@19: in fun k -> dft (2 * k + 1) Chris@19: Chris@19: let make_dct scale nshift trig = Chris@19: fun n input -> Chris@19: trig (n - nshift) (Complex.real @@ (Complex.times scale) @@ Chris@19: (zero_extend n input)) Chris@19: (* Chris@19: * DCT-I: y[k] = sum x[j] cos(pi * j * k / n) Chris@19: *) Chris@19: let dctI = make_dct Complex.one 1 trigI Chris@19: Chris@19: (* Chris@19: * DCT-II: y[k] = sum x[j] cos(pi * (j + 1/2) * k / n) Chris@19: *) Chris@19: let dctII = make_dct Complex.one 0 trigII Chris@19: Chris@19: (* Chris@19: * DCT-III: y[k] = sum x[j] cos(pi * j * (k + 1/2) / n) Chris@19: *) Chris@19: let dctIII = make_dct Complex.half 0 trigIII Chris@19: Chris@19: (* Chris@19: * DCT-IV y[k] = sum x[j] cos(pi * (j + 1/2) * (k + 1/2) / n) Chris@19: *) Chris@19: let dctIV = make_dct Complex.half 0 trigIV Chris@19: Chris@19: let shift s input = fun i -> input (i - s) Chris@19: Chris@19: (* DST-x input := TRIG-x (input / i) *) Chris@19: let make_dst scale nshift kshift jshift trig = Chris@19: fun n input -> Chris@19: Complex.real @@ Chris@19: (shift (- jshift) Chris@19: (trig (n + nshift) (Complex.uminus @@ Chris@19: (Complex.times Complex.i) @@ Chris@19: (Complex.times scale) @@ Chris@19: Complex.real @@ Chris@19: (shift kshift (zero_extend n input))))) Chris@19: Chris@19: (* Chris@19: * DST-I: y[k] = sum x[j] sin(pi * j * k / n) Chris@19: *) Chris@19: let dstI = make_dst Complex.one 1 1 1 trigI Chris@19: Chris@19: (* Chris@19: * DST-II: y[k] = sum x[j] sin(pi * (j + 1/2) * k / n) Chris@19: *) Chris@19: let dstII = make_dst Complex.one 0 0 1 trigII Chris@19: Chris@19: (* Chris@19: * DST-III: y[k] = sum x[j] sin(pi * j * (k + 1/2) / n) Chris@19: *) Chris@19: let dstIII = make_dst Complex.half 0 1 0 trigIII Chris@19: Chris@19: (* Chris@19: * DST-IV y[k] = sum x[j] sin(pi * (j + 1/2) * (k + 1/2) / n) Chris@19: *) Chris@19: let dstIV = make_dst Complex.half 0 0 0 trigIV Chris@19: