File: generate_atof_consts.py

package info (click to toggle)
python-msgspec 0.20.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,416 kB
  • sloc: javascript: 23,944; ansic: 20,940; python: 19,752; makefile: 26; sh: 23
file content (106 lines) | stat: -rw-r--r-- 2,252 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
"""This script generates msgspec/atof_consts.h"""

import math
import os
import textwrap


def gen_hpd_tables():
    log2log10 = math.log(2) / math.log(10)
    shifts = ["0x0000"]
    powers = []
    for i in range(1, 61):
        offset = len(powers)
        assert offset <= 0x07FF
        num_new_digits = int(log2log10 * float(i)) + 1
        assert num_new_digits <= 31
        code = (num_new_digits << 11) | offset
        p = str(5**i)
        powers.extend(p)
        shifts.append("0x%04X" % code)

    for i in range(61, 65):
        shifts.append("0x%04X" % len(powers))

    n_shifts = len(shifts)
    n_powers = len(powers)
    assert n_powers <= 0x07FF

    shifts_str = "\n".join(textwrap.wrap(", ".join(shifts), width=78))
    powers_str = "\n".join(textwrap.wrap(", ".join(powers), width=78))

    return n_shifts, shifts_str, n_powers, powers_str


def gen_row(e):
    z = 1 << 2048
    if e >= 0:
        exp = 10**e
        z = z * exp
    else:
        exp = 10 ** (-e)
        z = z // exp

    n = -2048

    while z >= (1 << 128):
        z = z >> 1
        n += 1

    h = hex(z)[2:]
    assert len(h) == 32

    approx_n = ((217706 * e) >> 16) + 1087
    biased_n = 1214 + n

    assert approx_n == biased_n

    return "{0x%s, 0x%s},  // 1e%-04d" % (h[16:], h[:16], e)


table_rows = [gen_row(e) for e in range(-307, 289)]

f64_powers = [f"1e{i}" for i in range(23)]

n_shifts, shifts, n_powers, powers = gen_hpd_tables()

text = """\
/* DO NOT EDIT - generated by scripts/generate_atof_consts.py */

#ifndef MSGSPEC_ATOF_CONSTS_H
#define MSGSPEC_ATOF_CONSTS_H

static const uint64_t ms_atof_powers_of_10[%d][2] = {
%s
};

static const double ms_atof_f64_powers_of_10[%d] = {
%s
};

static const uint16_t ms_atof_left_shift[%d] = {
%s
};

static const uint8_t ms_atof_powers_of_5[%d] = {
%s
};

#endif
""" % (
    len(table_rows),
    "\n".join(table_rows),
    len(f64_powers),
    "\n".join(textwrap.wrap(", ".join(f64_powers), width=78)),
    n_shifts,
    shifts,
    n_powers,
    powers,
)


if __name__ == "__main__":
    repo = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    path = os.path.join(repo, "msgspec", "atof_consts.h")
    with open(path, "wb") as f:
        f.write(text.encode("utf-8"))