annotate src/fftw-3.3.3/genfft/twiddle.ml @ 23:619f715526df sv_v2.1

Update Vamp plugin SDK to 2.5
author Chris Cannam
date Thu, 09 May 2013 10:52:46 +0100
parents 37bf6b4a2645
children
rev   line source
Chris@10 1 (*
Chris@10 2 * Copyright (c) 1997-1999 Massachusetts Institute of Technology
Chris@10 3 * Copyright (c) 2003, 2007-11 Matteo Frigo
Chris@10 4 * Copyright (c) 2003, 2007-11 Massachusetts Institute of Technology
Chris@10 5 *
Chris@10 6 * This program is free software; you can redistribute it and/or modify
Chris@10 7 * it under the terms of the GNU General Public License as published by
Chris@10 8 * the Free Software Foundation; either version 2 of the License, or
Chris@10 9 * (at your option) any later version.
Chris@10 10 *
Chris@10 11 * This program is distributed in the hope that it will be useful,
Chris@10 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@10 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@10 14 * GNU General Public License for more details.
Chris@10 15 *
Chris@10 16 * You should have received a copy of the GNU General Public License
Chris@10 17 * along with this program; if not, write to the Free Software
Chris@10 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Chris@10 19 *
Chris@10 20 *)
Chris@10 21
Chris@10 22 (* policies for loading/computing twiddle factors *)
Chris@10 23 open Complex
Chris@10 24 open Util
Chris@10 25
Chris@10 26 type twop = TW_FULL | TW_CEXP | TW_NEXT
Chris@10 27
Chris@10 28 let optostring = function
Chris@10 29 | TW_CEXP -> "TW_CEXP"
Chris@10 30 | TW_NEXT -> "TW_NEXT"
Chris@10 31 | TW_FULL -> "TW_FULL"
Chris@10 32
Chris@10 33 type twinstr = (twop * int * int)
Chris@10 34
Chris@10 35 let rec unroll_twfull l = match l with
Chris@10 36 | [] -> []
Chris@10 37 | (TW_FULL, v, n) :: b ->
Chris@10 38 (forall [] cons 1 n (fun i -> (TW_CEXP, v, i)))
Chris@10 39 @ unroll_twfull b
Chris@10 40 | a :: b -> a :: unroll_twfull b
Chris@10 41
Chris@10 42 let twinstr_to_c_string l =
Chris@10 43 let one (op, a, b) = Printf.sprintf "{ %s, %d, %d }" (optostring op) a b
Chris@10 44 in let rec loop first = function
Chris@10 45 | [] -> ""
Chris@10 46 | a :: b -> (if first then "\n" else ",\n") ^ (one a) ^ (loop false b)
Chris@10 47 in "{" ^ (loop true l) ^ "}"
Chris@10 48
Chris@10 49 let twinstr_to_simd_string vl l =
Chris@10 50 let one sep = function
Chris@10 51 | (TW_NEXT, 1, 0) -> sep ^ "{TW_NEXT, " ^ vl ^ ", 0}"
Chris@10 52 | (TW_NEXT, _, _) -> failwith "twinstr_to_simd_string"
Chris@10 53 | (TW_CEXP, v, b) -> sep ^ (Printf.sprintf "VTW(%d,%d)" v b)
Chris@10 54 | _ -> failwith "twinstr_to_simd_string"
Chris@10 55 in let rec loop first = function
Chris@10 56 | [] -> ""
Chris@10 57 | a :: b -> (one (if first then "\n" else ",\n") a) ^ (loop false b)
Chris@10 58 in "{" ^ (loop true (unroll_twfull l)) ^ "}"
Chris@10 59
Chris@10 60 let rec pow m n =
Chris@10 61 if (n = 0) then 1
Chris@10 62 else m * pow m (n - 1)
Chris@10 63
Chris@10 64 let rec is_pow m n =
Chris@10 65 n = 1 || ((n mod m) = 0 && is_pow m (n / m))
Chris@10 66
Chris@10 67 let rec log m n = if n = 1 then 0 else 1 + log m (n / m)
Chris@10 68
Chris@10 69 let rec largest_power_smaller_than m i =
Chris@10 70 if (is_pow m i) then i
Chris@10 71 else largest_power_smaller_than m (i - 1)
Chris@10 72
Chris@10 73 let rec smallest_power_larger_than m i =
Chris@10 74 if (is_pow m i) then i
Chris@10 75 else smallest_power_larger_than m (i + 1)
Chris@10 76
Chris@10 77 let rec_array n f =
Chris@10 78 let g = ref (fun i -> Complex.zero) in
Chris@10 79 let a = Array.init n (fun i -> lazy (!g i)) in
Chris@10 80 let h i = f (fun i -> Lazy.force a.(i)) i in
Chris@10 81 begin
Chris@10 82 g := h;
Chris@10 83 h
Chris@10 84 end
Chris@10 85
Chris@10 86
Chris@10 87 let ctimes use_complex_arith a b =
Chris@10 88 if use_complex_arith then
Chris@10 89 Complex.ctimes a b
Chris@10 90 else
Chris@10 91 Complex.times a b
Chris@10 92
Chris@10 93 let ctimesj use_complex_arith a b =
Chris@10 94 if use_complex_arith then
Chris@10 95 Complex.ctimesj a b
Chris@10 96 else
Chris@10 97 Complex.times (Complex.conj a) b
Chris@10 98
Chris@10 99 let make_bytwiddle sign use_complex_arith g f i =
Chris@10 100 if i = 0 then
Chris@10 101 f i
Chris@10 102 else if sign = 1 then
Chris@10 103 ctimes use_complex_arith (g i) (f i)
Chris@10 104 else
Chris@10 105 ctimesj use_complex_arith (g i) (f i)
Chris@10 106
Chris@10 107 (* various policies for computing/loading twiddle factors *)
Chris@10 108
Chris@10 109 let twiddle_policy_load_all v use_complex_arith =
Chris@10 110 let bytwiddle n sign w f =
Chris@10 111 make_bytwiddle sign use_complex_arith (fun i -> w (i - 1)) f
Chris@10 112 and twidlen n = 2 * (n - 1)
Chris@10 113 and twdesc r = [(TW_FULL, v, r);(TW_NEXT, 1, 0)]
Chris@10 114 in bytwiddle, twidlen, twdesc
Chris@10 115
Chris@10 116 (*
Chris@10 117 * if i is a power of two, then load w (log i)
Chris@10 118 * else let x = largest power of 2 less than i in
Chris@10 119 * let y = i - x in
Chris@10 120 * compute w^{x+y} = w^x * w^y
Chris@10 121 *)
Chris@10 122 let twiddle_policy_log2 v use_complex_arith =
Chris@10 123 let bytwiddle n sign w f =
Chris@10 124 let g = rec_array n (fun self i ->
Chris@10 125 if i = 0 then Complex.one
Chris@10 126 else if is_pow 2 i then w (log 2 i)
Chris@10 127 else let x = largest_power_smaller_than 2 i in
Chris@10 128 let y = i - x in
Chris@10 129 ctimes use_complex_arith (self x) (self y))
Chris@10 130 in make_bytwiddle sign use_complex_arith g f
Chris@10 131 and twidlen n = 2 * (log 2 (largest_power_smaller_than 2 (2 * n - 1)))
Chris@10 132 and twdesc n =
Chris@10 133 (List.flatten
Chris@10 134 (List.map
Chris@10 135 (fun i ->
Chris@10 136 if i > 0 && is_pow 2 i then
Chris@10 137 [TW_CEXP, v, i]
Chris@10 138 else
Chris@10 139 [])
Chris@10 140 (iota n)))
Chris@10 141 @ [(TW_NEXT, 1, 0)]
Chris@10 142 in bytwiddle, twidlen, twdesc
Chris@10 143
Chris@10 144 let twiddle_policy_log3 v use_complex_arith =
Chris@10 145 let rec terms_needed i pi s n =
Chris@10 146 if (s >= n - 1) then i
Chris@10 147 else terms_needed (i + 1) (3 * pi) (s + pi) n
Chris@10 148 in
Chris@10 149 let rec bytwiddle n sign w f =
Chris@10 150 let nterms = terms_needed 0 1 0 n in
Chris@10 151 let maxterm = pow 3 (nterms - 1) in
Chris@10 152 let g = rec_array (3 * n) (fun self i ->
Chris@10 153 if i = 0 then Complex.one
Chris@10 154 else if is_pow 3 i then w (log 3 i)
Chris@10 155 else if i = (n - 1) && maxterm >= n then
Chris@10 156 w (nterms - 1)
Chris@10 157 else let x = smallest_power_larger_than 3 i in
Chris@10 158 if (i + i >= x) then
Chris@10 159 let x = min x (n - 1) in
Chris@10 160 ctimesj use_complex_arith (self (x - i)) (self x)
Chris@10 161 else let x = largest_power_smaller_than 3 i in
Chris@10 162 ctimes use_complex_arith (self (i - x)) (self x))
Chris@10 163 in make_bytwiddle sign use_complex_arith g f
Chris@10 164 and twidlen n = 2 * (terms_needed 0 1 0 n)
Chris@10 165 and twdesc n =
Chris@10 166 (List.map
Chris@10 167 (fun i ->
Chris@10 168 let x = min (pow 3 i) (n - 1) in
Chris@10 169 TW_CEXP, v, x)
Chris@10 170 (iota ((twidlen n) / 2)))
Chris@10 171 @ [(TW_NEXT, 1, 0)]
Chris@10 172 in bytwiddle, twidlen, twdesc
Chris@10 173
Chris@10 174 let current_twiddle_policy = ref twiddle_policy_load_all
Chris@10 175
Chris@10 176 let twiddle_policy use_complex_arith =
Chris@10 177 !current_twiddle_policy use_complex_arith
Chris@10 178
Chris@10 179 let set_policy x = Arg.Unit (fun () -> current_twiddle_policy := x)
Chris@10 180 let set_policy_int x = Arg.Int (fun i -> current_twiddle_policy := x i)
Chris@10 181
Chris@10 182 let undocumented = " Undocumented twiddle policy"
Chris@10 183
Chris@10 184 let speclist = [
Chris@10 185 "-twiddle-load-all", set_policy twiddle_policy_load_all, undocumented;
Chris@10 186 "-twiddle-log2", set_policy twiddle_policy_log2, undocumented;
Chris@10 187 "-twiddle-log3", set_policy twiddle_policy_log3, undocumented;
Chris@10 188 ]