3 # Copyright 2013 The Rust Project Developers. See the COPYRIGHT
4 # file at the top-level directory of this distribution and at
5 # http://rust-lang.org/COPYRIGHT.
7 # Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
8 # http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
9 # <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
10 # option. This file may not be copied, modified, or distributed
11 # except according to those terms.
13 # This creates the tables used for distributions implemented using the
14 # ziggurat algorithm in `rand::distributions;`. They are
15 # (basically) the tables as used in the ZIGNOR variant (Doornik 2005).
16 # They are changed rarely, so the generated file should be checked in
19 # It creates 3 tables: X as in the paper, F which is f(x_i), and
20 # F_DIFF which is f(x_i) - f(x_{i-1}). The latter two are just cached
21 # values which is not done in that paper (but is done in other
22 # variants). Note that the adZigR table is unnecessary because of
25 # It is designed to be compatible with Python 2 and 3.
27 from math import exp, sqrt, log, floor
30 # The order should match the return value of `tables`
31 TABLE_NAMES = ['X', 'F']
33 # The actual length of the table is 1 more, to stop
34 # index-out-of-bounds errors. This should match the bitwise operation
35 # to find `i` in `zigurrat` in `libstd/rand/mod.rs`. Also the *_R and
36 # *_V constants below depend on this value.
39 # equivalent to `zigNorInit` in Doornik2005, but generalised to any
40 # distribution. r = dR, v = dV, f = probability density function,
41 # f_inv = inverse of f
42 def tables(r, v, f, f_inv):
44 xvec = [0]*(TABLE_LEN+1)
49 for i in range(2, TABLE_LEN):
51 xvec[i] = f_inv(v / last + f(last))
54 fvec = [0]*(TABLE_LEN+1)
55 for i in range(TABLE_LEN+1):
65 return sqrt(-2.0*log(y))
67 NORM_R = 3.6541528853610088
68 NORM_V = 0.00492867323399
70 NORM = tables(NORM_R, NORM_V,
79 EXP_R = 7.69711747013104972
80 EXP_V = 0.0039496598225815571993
82 EXP = tables(EXP_R, EXP_V,
86 # Output the tables/constants/types
88 def render_static(name, type, value):
90 return 'pub static %s: %s =%s;\n' % (name, type, value)
92 # static `name`: [`type`, .. `len(values)`] =
93 # [values[0], ..., values[3],
94 # values[4], ..., values[7],
96 def render_table(name, values):
98 # 4 values on each row
99 for i in range(0, len(values), 4):
101 rows.append(', '.join('%.18f' % f for f in row))
103 rendered = '\n [%s]' % ',\n '.join(rows)
104 return render_static(name, '[f64, .. %d]' % len(values), rendered)
107 with open('ziggurat_tables.rs', 'w') as f:
108 f.write('''// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
109 // file at the top-level directory of this distribution and at
110 // http://rust-lang.org/COPYRIGHT.
112 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
113 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
114 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
115 // option. This file may not be copied, modified, or distributed
116 // except according to those terms.
118 // Tables for distributions which are sampled using the ziggurat
119 // algorithm. Autogenerated by `ziggurat_tables.py`.
121 pub type ZigTable = &\'static [f64, .. %d];
122 ''' % (TABLE_LEN + 1))
123 for name, tables, r in [('NORM', NORM, NORM_R),
124 ('EXP', EXP, EXP_R)]:
125 f.write(render_static('ZIG_%s_R' % name, 'f64', ' %.18f' % r))
126 for (tabname, table) in zip(TABLE_NAMES, tables):
127 f.write(render_table('ZIG_%s_%s' % (name, tabname), table))