comparison src/fftw-3.3.3/genfft/conv.ml @ 95:89f5e221ed7b

Add FFTW3
author Chris Cannam <cannam@all-day-breakfast.com>
date Wed, 20 Mar 2013 15:35:50 +0000
parents
children
comparison
equal deleted inserted replaced
94:d278df1123f9 95:89f5e221ed7b
1 (*
2 * Copyright (c) 1997-1999 Massachusetts Institute of Technology
3 * Copyright (c) 2003, 2007-11 Matteo Frigo
4 * Copyright (c) 2003, 2007-11 Massachusetts Institute of Technology
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 *)
21
22 open Complex
23 open Util
24
25 let polyphase m a ph i = a (m * i + ph)
26
27 let rec divmod n i =
28 if (i < 0) then
29 let (a, b) = divmod n (i + n)
30 in (a - 1, b)
31 else (i / n, i mod n)
32
33 let unpolyphase m a i = let (x, y) = divmod m i in a y x
34
35 let lift2 f a b i = f (a i) (b i)
36
37 (* convolution of signals A and B *)
38 let rec conv na a nb b =
39 let rec naive na a nb b i =
40 sigma 0 na (fun j -> (a j) @* (b (i - j)))
41
42 and recur na a nb b =
43 if (na <= 1 || nb <= 1) then
44 naive na a nb b
45 else
46 let p = polyphase 2 in
47 let ee = conv (na - na / 2) (p a 0) (nb - nb / 2) (p b 0)
48 and eo = conv (na - na / 2) (p a 0) (nb / 2) (p b 1)
49 and oe = conv (na / 2) (p a 1) (nb - nb / 2) (p b 0)
50 and oo = conv (na / 2) (p a 1) (nb / 2) (p b 1) in
51 unpolyphase 2 (function
52 0 -> fun i -> (ee i) @+ (oo (i - 1))
53 | 1 -> fun i -> (eo i) @+ (oe i)
54 | _ -> failwith "recur")
55
56
57 (* Karatsuba variant 1: (a+bx)(c+dx) = (ac+bdxx)+((a+b)(c+d)-ac-bd)x *)
58 and karatsuba1 na a nb b =
59 let p = polyphase 2 in
60 let ae = p a 0 and nae = na - na / 2
61 and ao = p a 1 and nao = na / 2
62 and be = p b 0 and nbe = nb - nb / 2
63 and bo = p b 1 and nbo = nb / 2 in
64 let ae = infinite nae ae and ao = infinite nao ao
65 and be = infinite nbe be and bo = infinite nbo bo in
66 let aeo = lift2 (@+) ae ao and naeo = nae
67 and beo = lift2 (@+) be bo and nbeo = nbe in
68 let ee = conv nae ae nbe be
69 and oo = conv nao ao nbo bo
70 and eoeo = conv naeo aeo nbeo beo in
71
72 let q = function
73 0 -> fun i -> (ee i) @+ (oo (i - 1))
74 | 1 -> fun i -> (eoeo i) @- ((ee i) @+ (oo i))
75 | _ -> failwith "karatsuba1" in
76 unpolyphase 2 q
77
78 (* Karatsuba variant 2:
79 (a+bx)(c+dx) = ((a+b)c-b(c-dxx))+x((a+b)c-a(c-d)) *)
80 and karatsuba2 na a nb b =
81 let p = polyphase 2 in
82 let ae = p a 0 and nae = na - na / 2
83 and ao = p a 1 and nao = na / 2
84 and be = p b 0 and nbe = nb - nb / 2
85 and bo = p b 1 and nbo = nb / 2 in
86 let ae = infinite nae ae and ao = infinite nao ao
87 and be = infinite nbe be and bo = infinite nbo bo in
88
89 let c1 = conv nae (lift2 (@+) ae ao) nbe be
90 and c2 = conv nao ao (nbo + 1) (fun i -> be i @- bo (i - 1))
91 and c3 = conv nae ae nbe (lift2 (@-) be bo) in
92
93 let q = function
94 0 -> lift2 (@-) c1 c2
95 | 1 -> lift2 (@-) c1 c3
96 | _ -> failwith "karatsuba2" in
97 unpolyphase 2 q
98
99 and karatsuba na a nb b =
100 let m = na + nb - 1 in
101 if (m < !Magic.karatsuba_min) then
102 recur na a nb b
103 else
104 match !Magic.karatsuba_variant with
105 1 -> karatsuba1 na a nb b
106 | 2 -> karatsuba2 na a nb b
107 | _ -> failwith "unknown karatsuba variant"
108
109 and via_circular na a nb b =
110 let m = na + nb - 1 in
111 if (m < !Magic.circular_min) then
112 karatsuba na a nb b
113 else
114 let rec find_min n = if n >= m then n else find_min (2 * n) in
115 circular (find_min 1) a b
116
117 in
118 let a = infinite na a and b = infinite nb b in
119 let res = array (na + nb - 1) (via_circular na a nb b) in
120 infinite (na + nb - 1) res
121
122 and circular n a b =
123 let via_dft n a b =
124 let fa = Fft.dft (-1) n a
125 and fb = Fft.dft (-1) n b
126 and scale = inverse_int n in
127 let fab i = ((fa i) @* (fb i)) @* scale in
128 Fft.dft 1 n fab
129
130 in via_dft n a b