Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/tools/numprint.py
2723 views
1
#!/usr/bin/python3
2
# This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
3
4
# This code can be used to generate power tables for Schubfach algorithm (see lnumprint.cpp)
5
6
import math
7
import sys
8
9
(_, pow10min, pow10max, compact) = sys.argv
10
pow10min = int(pow10min)
11
pow10max = int(pow10max)
12
compact = compact == "True"
13
14
# extract high 128 bits of the value
15
def high128(n, roundup):
16
L = math.ceil(math.log2(n))
17
18
r = 0
19
for i in range(L - 128, L):
20
if i >= 0 and (n & (1 << i)) != 0:
21
r |= (1 << (i - L + 128))
22
23
return r + (1 if roundup else 0)
24
25
def pow10approx(n):
26
if n == 0:
27
return 1 << 127
28
elif n > 0:
29
return high128(10**n, 5**n >= 2**128)
30
else:
31
# 10^-n is a binary fraction that can't be represented in floating point
32
# we need to extract top 128 bits of the fraction starting from the first 1
33
# to get there, we need to divide 2^k by 10^n for a sufficiently large k and repeat the extraction process
34
p = 10**-n
35
k = 2**128 * 16**-n # this guarantees that the fraction has more than 128 extra bits
36
return high128(k // p, True)
37
38
def pow5_64(n):
39
assert(n >= 0)
40
if n == 0:
41
return 1 << 63
42
else:
43
return high128(5**n, False) >> 64
44
45
if not compact:
46
print("// kPow10Table", pow10min, "..", pow10max)
47
print("{")
48
for p in range(pow10min, pow10max + 1):
49
h = hex(pow10approx(p))[2:]
50
assert(len(h) == 32)
51
print(" {0x%s, 0x%s}," % (h[0:16].upper(), h[16:32].upper()))
52
print("}")
53
else:
54
print("// kPow5Table")
55
print("{")
56
for i in range(16):
57
print(" " + hex(pow5_64(i)) + ",")
58
print("}")
59
print("// kPow10Table", pow10min, "..", pow10max)
60
print("{")
61
for p in range(pow10min, pow10max + 1, 16):
62
base = pow10approx(p)
63
errw = 0
64
for i in range(16):
65
real = pow10approx(p + i)
66
appr = (base * pow5_64(i)) >> 64
67
scale = 1 if appr < (1 << 127) else 0 # 1-bit scale
68
69
offset = (appr << scale) - real
70
assert(offset >= -4 and offset <= 3) # 3-bit offset
71
assert((appr << scale) >> 64 == real >> 64) # offset only affects low half
72
assert((appr << scale) - offset == real) # validate full reconstruction
73
74
err = (scale << 3) | (offset + 4)
75
errw |= err << (i * 4)
76
77
hbase = hex(base)[2:]
78
assert(len(hbase) == 32)
79
assert(errw < 1 << 64)
80
81
print(" {0x%s, 0x%s, 0x%16x}," % (hbase[0:16], hbase[16:32], errw))
82
print("}")
83
84