comparison fft/fftw/fftw-3.3.4/genfft/number.ml @ 19:26056e866c29

Add FFTW to comparison table
author Chris Cannam
date Tue, 06 Oct 2015 13:08:39 +0100
parents
children
comparison
equal deleted inserted replaced
18:8db794ca3e0b 19:26056e866c29
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 (* The generator keeps track of numeric constants in symbolic
23 expressions using the abstract number type, defined in this file.
24
25 Our implementation of the number type uses arbitrary-precision
26 arithmetic from the built-in Num package in order to maintain an
27 accurate representation of constants. This allows us to output
28 constants with many decimal places in the generated C code,
29 ensuring that we will take advantage of the full precision
30 available on current and future machines.
31
32 Note that we have to write our own routine to compute roots of
33 unity, since the Num package only supplies simple arithmetic. The
34 arbitrary-precision operations in Num look like the normal
35 operations except that they have an appended slash (e.g. +/ -/ */
36 // etcetera). *)
37
38 open Num
39
40 type number = N of num
41
42 let makeNum n = N n
43
44 (* decimal digits of precision to maintain internally, and to print out: *)
45 let precision = 50
46 let print_precision = 45
47
48 let inveps = (Int 10) **/ (Int precision)
49 let epsilon = (Int 1) // inveps
50
51 let pinveps = (Int 10) **/ (Int print_precision)
52 let pepsilon = (Int 1) // pinveps
53
54 let round x = epsilon */ (round_num (x */ inveps))
55
56 let of_int n = N (Int n)
57 let zero = of_int 0
58 let one = of_int 1
59 let two = of_int 2
60 let mone = of_int (-1)
61
62 (* comparison predicate for real numbers *)
63 let equal (N x) (N y) = (* use both relative and absolute error *)
64 let absdiff = abs_num (x -/ y) in
65 absdiff <=/ pepsilon or
66 absdiff <=/ pepsilon */ (abs_num x +/ abs_num y)
67
68 let is_zero = equal zero
69 let is_one = equal one
70 let is_mone = equal mone
71 let is_two = equal two
72
73
74 (* Note that, in the following computations, it is important to round
75 to precision epsilon after each operation. Otherwise, since the
76 Num package uses exact rational arithmetic, the number of digits
77 quickly blows up. *)
78 let mul (N a) (N b) = makeNum (round (a */ b))
79 let div (N a) (N b) = makeNum (round (a // b))
80 let add (N a) (N b) = makeNum (round (a +/ b))
81 let sub (N a) (N b) = makeNum (round (a -/ b))
82
83 let negative (N a) = (a </ (Int 0))
84 let negate (N a) = makeNum (minus_num a)
85
86 let greater a b = negative (sub b a)
87
88 let epsilonsq = epsilon */ epsilon
89 let epsilonsq2 = (Int 100) */ epsilonsq
90
91 let sqr a = a */ a
92 let almost_equal (N a) (N b) = (sqr (a -/ b)) <=/ epsilonsq2
93
94 (* find square root by Newton's method *)
95 let sqrt a =
96 let rec sqrt_iter guess =
97 let newguess = div (add guess (div a guess)) two in
98 if (almost_equal newguess guess) then newguess
99 else sqrt_iter newguess
100 in sqrt_iter (div a two)
101
102 let csub (xr, xi) (yr, yi) = (round (xr -/ yr), round (xi -/ yi))
103 let cdiv (xr, xi) r = (round (xr // r), round (xi // r))
104 let cmul (xr, xi) (yr, yi) = (round (xr */ yr -/ xi */ yi),
105 round (xr */ yi +/ xi */ yr))
106 let csqr (xr, xi) = (round (xr */ xr -/ xi */ xi), round ((Int 2) */ xr */ xi))
107 let cabssq (xr, xi) = xr */ xr +/ xi */ xi
108 let cconj (xr, xi) = (xr, minus_num xi)
109 let cinv x = cdiv (cconj x) (cabssq x)
110
111 let almost_equal_cnum (xr, xi) (yr, yi) =
112 (cabssq (xr -/ yr,xi -/ yi)) <=/ epsilonsq2
113
114 (* Put a complex number to an integer power by repeated squaring: *)
115 let rec ipow_cnum x n =
116 if (n == 0) then
117 (Int 1, Int 0)
118 else if (n < 0) then
119 cinv (ipow_cnum x (- n))
120 else if (n mod 2 == 0) then
121 ipow_cnum (csqr x) (n / 2)
122 else
123 cmul x (ipow_cnum x (n - 1))
124
125 let twopi = 6.28318530717958647692528676655900576839433879875021164194989
126
127 (* Find the nth (complex) primitive root of unity by Newton's method: *)
128 let primitive_root_of_unity n =
129 let rec root_iter guess =
130 let newguess = csub guess (cdiv (csub guess
131 (ipow_cnum guess (1 - n)))
132 (Int n)) in
133 if (almost_equal_cnum guess newguess) then newguess
134 else root_iter newguess
135 in let float_to_num f = (Int (truncate (f *. 1.0e9))) // (Int 1000000000)
136 in root_iter (float_to_num (cos (twopi /. (float n))),
137 float_to_num (sin (twopi /. (float n))))
138
139 let cexp n i =
140 if ((i mod n) == 0) then
141 (one,zero)
142 else
143 let (n2,i2) = Util.lowest_terms n i
144 in let (c,s) = ipow_cnum (primitive_root_of_unity n2) i2
145 in (makeNum c, makeNum s)
146
147 let to_konst (N n) =
148 let f = float_of_num n in
149 let f' = if f < 0.0 then f *. (-1.0) else f in
150 let f2 = if (f' >= 1.0) then (f' -. (float (truncate f'))) else f'
151 in let q = string_of_int (truncate(f2 *. 1.0E9))
152 in let r = "0000000000" ^ q
153 in let l = String.length r
154 in let prefix = if (f < 0.0) then "KN" else "KP" in
155 if (f' >= 1.0) then
156 (prefix ^ (string_of_int (truncate f')) ^ "_" ^
157 (String.sub r (l - 9) 9))
158 else
159 (prefix ^ (String.sub r (l - 9) 9))
160
161 let to_string (N n) = approx_num_fix print_precision n
162
163 let to_float (N n) = float_of_num n
164