Skip to content

Commit 2e2f4a1

Browse files
author
Robin Kruppe
committed
---
yaml --- r: 227274 b: refs/heads/auto c: b7e39a1 h: refs/heads/master v: v3
1 parent 696a9ee commit 2e2f4a1

File tree

2 files changed

+135
-1
lines changed

2 files changed

+135
-1
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503
88
refs/tags/release-0.3.1: 495bae036dfe5ec6ceafd3312b4dca48741e845b
99
refs/tags/release-0.4: e828ea2080499553b97dfe33b3f4d472b4562ad7
1010
refs/tags/release-0.5: 7e3bcfbf21278251ee936ad53e92e9b719702d73
11-
refs/heads/auto: 7ebd7f3b9a7ebc020663a13b29b1e50446b3c262
11+
refs/heads/auto: b7e39a1c2dd24fd4110c22c70cad254365b0ffd3
1212
refs/tags/release-0.6: b4ebcfa1812664df5e142f0134a5faea3918544c
1313
refs/tags/0.1: b19db808c2793fe2976759b85a355c3ad8c8b336
1414
refs/tags/0.2: 1754d02027f2924bed83b0160ee340c7f41d5ea1
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#!/usr/bin/env python2.7
2+
#
3+
# Copyright 2015 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.
6+
#
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.
12+
13+
"""
14+
Generate powers of ten using William Clinger's ``AlgorithmM`` for use in
15+
decimal to floating point conversions.
16+
17+
Specifically, computes and outputs (as Rust code) a table of 10^e for some
18+
range of exponents e. The output is one array of 64 bit significands and
19+
another array of corresponding base two exponents. The approximations are
20+
normalized and rounded perfectly, i.e., within 0.5 ULP of the true value.
21+
22+
The representation ([u64], [i16]) instead of the more natural [(u64, i16)]
23+
is used because (u64, i16) has a ton of padding which would make the table
24+
even larger, and it's already uncomfortably large (6 KiB).
25+
"""
26+
from __future__ import print_function
27+
import sys
28+
from fractions import Fraction
29+
from collections import namedtuple
30+
31+
32+
N = 64 # Size of the significand field in bits
33+
MIN_SIG = 2 ** (N - 1)
34+
MAX_SIG = (2 ** N) - 1
35+
36+
37+
# Hand-rolled fp representation without arithmetic or any other operations.
38+
# The significand is normalized and always N bit, but the exponent is
39+
# unrestricted in range.
40+
Fp = namedtuple('Fp', 'sig exp')
41+
42+
43+
def algorithm_m(f, e):
44+
assert f > 0
45+
if e < 0:
46+
u = f
47+
v = 10 ** abs(e)
48+
else:
49+
u = f * 10 ** e
50+
v = 1
51+
k = 0
52+
x = u // v
53+
while True:
54+
if x < MIN_SIG:
55+
u <<= 1
56+
k -= 1
57+
elif x >= MAX_SIG:
58+
v <<= 1
59+
k += 1
60+
else:
61+
break
62+
x = u // v
63+
return ratio_to_float(u, v, k)
64+
65+
66+
def ratio_to_float(u, v, k):
67+
q, r = divmod(u, v)
68+
v_r = v - r
69+
z = Fp(q, k)
70+
if r < v_r:
71+
return z
72+
elif r > v_r:
73+
return next_float(z)
74+
elif q % 2 == 0:
75+
return z
76+
else:
77+
return next_float(z)
78+
79+
80+
def next_float(z):
81+
if z.sig == MAX_SIG:
82+
return Fp(MIN_SIG, z.exp + 1)
83+
else:
84+
return Fp(z.sig + 1, z.exp)
85+
86+
87+
def error(f, e, z):
88+
decimal = f * Fraction(10) ** e
89+
binary = z.sig * Fraction(2) ** z.exp
90+
abs_err = abs(decimal - binary)
91+
# The unit in the last place has value z.exp
92+
ulp_err = abs_err / Fraction(2) ** z.exp
93+
return float(ulp_err)
94+
95+
LICENSE = """
96+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
97+
// file at the top-level directory of this distribution and at
98+
// http://rust-lang.org/COPYRIGHT.
99+
//
100+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
101+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
102+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
103+
// option. This file may not be copied, modified, or distributed
104+
// except according to those terms.
105+
"""
106+
107+
def main():
108+
MIN_E = -305
109+
MAX_E = 305
110+
e_range = range(MIN_E, MAX_E+1)
111+
powers = []
112+
for e in e_range:
113+
z = algorithm_m(1, e)
114+
err = error(1, e, z)
115+
assert err < 0.5
116+
powers.append(z)
117+
typ = "([u64; {0}], [i16; {0}])".format(len(e_range))
118+
print(LICENSE.strip())
119+
print("// Table of approximations of powers of ten.")
120+
print("// DO NOT MODIFY: Generated by a src/etc/dec2flt_table.py")
121+
print("pub const MIN_E: i16 = {};".format(MIN_E))
122+
print("pub const MAX_E: i16 = {};".format(MAX_E))
123+
print()
124+
print("pub const POWERS: ", typ, " = ([", sep='')
125+
for z in powers:
126+
print(" 0x{:x},".format(z.sig))
127+
print("], [")
128+
for z in powers:
129+
print(" {},".format(z.exp))
130+
print("]);")
131+
132+
133+
if __name__ == '__main__':
134+
main()

0 commit comments

Comments
 (0)