view src/fftw-3.3.3/genfft/trig.ml @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents 37bf6b4a2645
children
line wrap: on
line source
(*
 * Copyright (c) 1997-1999 Massachusetts Institute of Technology
 * Copyright (c) 2003, 2007-11 Matteo Frigo
 * Copyright (c) 2003, 2007-11 Massachusetts Institute of Technology
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *)

(* trigonometric transforms *)
open Util

(* DFT of real input *)
let rdft sign n input =
  Fft.dft sign n (Complex.real @@ input)

(* DFT of hermitian input *)
let hdft sign n input =
  Fft.dft sign n (Complex.hermitian n input)

(* DFT real transform of vectors of two real numbers,
   multiplication by (NaN I), and summation *)
let dft_via_rdft sign n input =
  let f = rdft sign n input
  in fun i -> 
    Complex.plus
      [Complex.real (f i); 
       Complex.times (Complex.nan Expr.I) (Complex.imag (f i))]

(* Discrete Hartley Transform *)
let dht sign n input =
  let f = Fft.dft sign n (Complex.real @@ input) in
  (fun i ->
    Complex.plus [Complex.real (f i); Complex.imag (f i)])

let trigI n input = 
  let twon = 2 * n in
  let input' = Complex.hermitian twon input
  in
  Fft.dft 1 twon input'

let interleave_zero input = fun i -> 
  if (i mod 2) == 0
      then Complex.zero
  else
    input ((i - 1) / 2)

let trigII n input =
  let fourn = 4 * n in
  let input' = Complex.hermitian fourn (interleave_zero input)
  in
  Fft.dft 1 fourn input'

let trigIII n input =
  let fourn = 4 * n in
  let twon = 2 * n in
  let input' = Complex.hermitian fourn
      (fun i -> 
	if (i == 0) then
	  Complex.real (input 0)
	else if (i == twon) then
	  Complex.uminus (Complex.real (input 0))
	else
	  Complex.antihermitian twon input i)
  in
  let dft = Fft.dft 1 fourn input'
  in fun k -> dft (2 * k + 1)

let zero_extend n input = fun i ->
  if (i >= 0 && i < n)
  then input i
  else Complex.zero

let trigIV n input =
  let fourn = 4 * n
  and eightn = 8 * n in
  let input' = Complex.hermitian eightn 
      (zero_extend fourn (Complex.antihermitian fourn 
			 (interleave_zero input)))
  in
  let dft = Fft.dft 1 eightn input'
  in fun k -> dft (2 * k + 1)

let make_dct scale nshift trig =
  fun n input ->
    trig (n - nshift) (Complex.real @@ (Complex.times scale) @@ 
		       (zero_extend n input))
(*
 * DCT-I:  y[k] = sum x[j] cos(pi * j * k / n)
 *)
let dctI = make_dct Complex.one 1 trigI

(*
 * DCT-II:  y[k] = sum x[j] cos(pi * (j + 1/2) * k / n)
 *)
let dctII = make_dct Complex.one 0 trigII

(*
 * DCT-III:  y[k] = sum x[j] cos(pi * j * (k + 1/2) / n)
 *)
let dctIII = make_dct Complex.half 0 trigIII

(*
 * DCT-IV  y[k] = sum x[j] cos(pi * (j + 1/2) * (k + 1/2) / n)
 *)
let dctIV = make_dct Complex.half 0 trigIV

let shift s input = fun i -> input (i - s)

(* DST-x input := TRIG-x (input / i) *)
let make_dst scale nshift kshift jshift trig =
  fun n input ->
    Complex.real @@ 
    (shift (- jshift)
       (trig (n + nshift) (Complex.uminus @@
			   (Complex.times Complex.i) @@
			   (Complex.times scale) @@ 
			   Complex.real @@ 
			   (shift kshift (zero_extend n input)))))

(*
 * DST-I:  y[k] = sum x[j] sin(pi * j * k / n)
 *)
let dstI = make_dst Complex.one 1 1 1 trigI

(*
 * DST-II:  y[k] = sum x[j] sin(pi * (j + 1/2) * k / n)
 *)
let dstII = make_dst Complex.one 0 0 1 trigII

(*
 * DST-III:  y[k] = sum x[j] sin(pi * j * (k + 1/2) / n)
 *)
let dstIII = make_dst Complex.half 0 1 0 trigIII

(*
 * DST-IV  y[k] = sum x[j] sin(pi * (j + 1/2) * (k + 1/2) / n)
 *)
let dstIV = make_dst Complex.half 0 0 0 trigIV