Mercurial > hg > sv-dependency-builds
comparison src/fftw-3.3.8/genfft/twiddle.ml @ 167:bd3cc4d1df30
Add FFTW 3.3.8 source, and a Linux build
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Tue, 19 Nov 2019 14:52:55 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
166:cbd6d7e562c7 | 167:bd3cc4d1df30 |
---|---|
1 (* | |
2 * Copyright (c) 1997-1999 Massachusetts Institute of Technology | |
3 * Copyright (c) 2003, 2007-14 Matteo Frigo | |
4 * Copyright (c) 2003, 2007-14 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 (* policies for loading/computing twiddle factors *) | |
23 open Complex | |
24 open Util | |
25 | |
26 type twop = TW_FULL | TW_CEXP | TW_NEXT | |
27 | |
28 let optostring = function | |
29 | TW_CEXP -> "TW_CEXP" | |
30 | TW_NEXT -> "TW_NEXT" | |
31 | TW_FULL -> "TW_FULL" | |
32 | |
33 type twinstr = (twop * int * int) | |
34 | |
35 let rec unroll_twfull l = match l with | |
36 | [] -> [] | |
37 | (TW_FULL, v, n) :: b -> | |
38 (forall [] cons 1 n (fun i -> (TW_CEXP, v, i))) | |
39 @ unroll_twfull b | |
40 | a :: b -> a :: unroll_twfull b | |
41 | |
42 let twinstr_to_c_string l = | |
43 let one (op, a, b) = Printf.sprintf "{ %s, %d, %d }" (optostring op) a b | |
44 in let rec loop first = function | |
45 | [] -> "" | |
46 | a :: b -> (if first then "\n" else ",\n") ^ (one a) ^ (loop false b) | |
47 in "{" ^ (loop true l) ^ "}" | |
48 | |
49 let twinstr_to_simd_string vl l = | |
50 let one sep = function | |
51 | (TW_NEXT, 1, 0) -> sep ^ "{TW_NEXT, " ^ vl ^ ", 0}" | |
52 | (TW_NEXT, _, _) -> failwith "twinstr_to_simd_string" | |
53 | (TW_CEXP, v, b) -> sep ^ (Printf.sprintf "VTW(%d,%d)" v b) | |
54 | _ -> failwith "twinstr_to_simd_string" | |
55 in let rec loop first = function | |
56 | [] -> "" | |
57 | a :: b -> (one (if first then "\n" else ",\n") a) ^ (loop false b) | |
58 in "{" ^ (loop true (unroll_twfull l)) ^ "}" | |
59 | |
60 let rec pow m n = | |
61 if (n = 0) then 1 | |
62 else m * pow m (n - 1) | |
63 | |
64 let rec is_pow m n = | |
65 n = 1 || ((n mod m) = 0 && is_pow m (n / m)) | |
66 | |
67 let rec log m n = if n = 1 then 0 else 1 + log m (n / m) | |
68 | |
69 let rec largest_power_smaller_than m i = | |
70 if (is_pow m i) then i | |
71 else largest_power_smaller_than m (i - 1) | |
72 | |
73 let rec smallest_power_larger_than m i = | |
74 if (is_pow m i) then i | |
75 else smallest_power_larger_than m (i + 1) | |
76 | |
77 let rec_array n f = | |
78 let g = ref (fun i -> Complex.zero) in | |
79 let a = Array.init n (fun i -> lazy (!g i)) in | |
80 let h i = f (fun i -> Lazy.force a.(i)) i in | |
81 begin | |
82 g := h; | |
83 h | |
84 end | |
85 | |
86 | |
87 let ctimes use_complex_arith a b = | |
88 if use_complex_arith then | |
89 Complex.ctimes a b | |
90 else | |
91 Complex.times a b | |
92 | |
93 let ctimesj use_complex_arith a b = | |
94 if use_complex_arith then | |
95 Complex.ctimesj a b | |
96 else | |
97 Complex.times (Complex.conj a) b | |
98 | |
99 let make_bytwiddle sign use_complex_arith g f i = | |
100 if i = 0 then | |
101 f i | |
102 else if sign = 1 then | |
103 ctimes use_complex_arith (g i) (f i) | |
104 else | |
105 ctimesj use_complex_arith (g i) (f i) | |
106 | |
107 (* various policies for computing/loading twiddle factors *) | |
108 | |
109 let twiddle_policy_load_all v use_complex_arith = | |
110 let bytwiddle n sign w f = | |
111 make_bytwiddle sign use_complex_arith (fun i -> w (i - 1)) f | |
112 and twidlen n = 2 * (n - 1) | |
113 and twdesc r = [(TW_FULL, v, r);(TW_NEXT, 1, 0)] | |
114 in bytwiddle, twidlen, twdesc | |
115 | |
116 (* | |
117 * if i is a power of two, then load w (log i) | |
118 * else let x = largest power of 2 less than i in | |
119 * let y = i - x in | |
120 * compute w^{x+y} = w^x * w^y | |
121 *) | |
122 let twiddle_policy_log2 v use_complex_arith = | |
123 let bytwiddle n sign w f = | |
124 let g = rec_array n (fun self i -> | |
125 if i = 0 then Complex.one | |
126 else if is_pow 2 i then w (log 2 i) | |
127 else let x = largest_power_smaller_than 2 i in | |
128 let y = i - x in | |
129 ctimes use_complex_arith (self x) (self y)) | |
130 in make_bytwiddle sign use_complex_arith g f | |
131 and twidlen n = 2 * (log 2 (largest_power_smaller_than 2 (2 * n - 1))) | |
132 and twdesc n = | |
133 (List.flatten | |
134 (List.map | |
135 (fun i -> | |
136 if i > 0 && is_pow 2 i then | |
137 [TW_CEXP, v, i] | |
138 else | |
139 []) | |
140 (iota n))) | |
141 @ [(TW_NEXT, 1, 0)] | |
142 in bytwiddle, twidlen, twdesc | |
143 | |
144 let twiddle_policy_log3 v use_complex_arith = | |
145 let rec terms_needed i pi s n = | |
146 if (s >= n - 1) then i | |
147 else terms_needed (i + 1) (3 * pi) (s + pi) n | |
148 in | |
149 let rec bytwiddle n sign w f = | |
150 let nterms = terms_needed 0 1 0 n in | |
151 let maxterm = pow 3 (nterms - 1) in | |
152 let g = rec_array (3 * n) (fun self i -> | |
153 if i = 0 then Complex.one | |
154 else if is_pow 3 i then w (log 3 i) | |
155 else if i = (n - 1) && maxterm >= n then | |
156 w (nterms - 1) | |
157 else let x = smallest_power_larger_than 3 i in | |
158 if (i + i >= x) then | |
159 let x = min x (n - 1) in | |
160 ctimesj use_complex_arith (self (x - i)) (self x) | |
161 else let x = largest_power_smaller_than 3 i in | |
162 ctimes use_complex_arith (self (i - x)) (self x)) | |
163 in make_bytwiddle sign use_complex_arith g f | |
164 and twidlen n = 2 * (terms_needed 0 1 0 n) | |
165 and twdesc n = | |
166 (List.map | |
167 (fun i -> | |
168 let x = min (pow 3 i) (n - 1) in | |
169 TW_CEXP, v, x) | |
170 (iota ((twidlen n) / 2))) | |
171 @ [(TW_NEXT, 1, 0)] | |
172 in bytwiddle, twidlen, twdesc | |
173 | |
174 let current_twiddle_policy = ref twiddle_policy_load_all | |
175 | |
176 let twiddle_policy use_complex_arith = | |
177 !current_twiddle_policy use_complex_arith | |
178 | |
179 let set_policy x = Arg.Unit (fun () -> current_twiddle_policy := x) | |
180 let set_policy_int x = Arg.Int (fun i -> current_twiddle_policy := x i) | |
181 | |
182 let undocumented = " Undocumented twiddle policy" | |
183 | |
184 let speclist = [ | |
185 "-twiddle-load-all", set_policy twiddle_policy_load_all, undocumented; | |
186 "-twiddle-log2", set_policy twiddle_policy_log2, undocumented; | |
187 "-twiddle-log3", set_policy twiddle_policy_log3, undocumented; | |
188 ] |