File: half_float_tables.py

package info (click to toggle)
cbor2 5.7.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 648 kB
  • sloc: ansic: 5,522; python: 3,884; makefile: 19; sh: 8
file content (142 lines) | stat: -rw-r--r-- 3,802 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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/python3

"""
A simple script to generate the tables used in halffloat.c. The algorithms in
this script are based upon the paper `Fast Half Float Conversions`_, referenced
by the Wikipedia article on `half-precision floating point`_.

.. _half-precision floating point:
   https://en.wikipedia.org/wiki/Half-precision_floating-point_format
.. _Fast Half Float Conversions:
   ftp://ftp.fox-toolkit.org/pub/fasthalffloatconversion.pdf
"""

from itertools import zip_longest


def grouper(iterable, n, fillvalue=None):
    args = [iter(iterable)] * n
    return zip_longest(*args, fillvalue=fillvalue)


def sigtable():
    print("static const uint32_t sigtable[] = {")
    values = (
        0 if i == 0 else convertsig(i) if 1 <= i < 1024 else 0x38000000 + ((i - 1024) << 13)
        for i in range(2048)
    )
    values = (f"{i:#010x}" for i in values)
    for row in grouper(values, 8):
        print("    " + (", ".join(row)) + ",")
    print("};")


def exptable():
    values = (
        0
        if i == 0
        else 0x47800000
        if i == 31
        else 0x80000000
        if i == 32
        else i << 23
        if 1 <= i < 31
        else 0x80000000 + ((i - 32) << 23)
        if 33 <= i < 63
        else 0xC7800000  # i == 63
        for i in range(64)
    )

    print("static const uint32_t exptable[] = {")
    values = (f"{i:#010x}" for i in values)
    for row in grouper(values, 8):
        print("    " + (", ".join(row)) + ",")
    print("};")


def offsettable():
    values = (0 if i in (0, 32) else 1024 for i in range(64))

    print("static const uint16_t offsettable[] = {")
    values = (f"{i:#06x}" for i in values)
    for row in grouper(values, 8):
        print("    " + (", ".join(row)) + ",")
    print("};")


def convertsig(i):
    if not i:
        return 0
    m = i << 13
    e = 0
    while not m & 0x00800000:
        e -= 0x00800000
        m <<= 1
    m &= ~0x00800000
    e += 0x38800000
    return m | e


def basetable():
    values = [0] * 512
    for i in range(256):
        e = i - 127
        if e < -24:  # underflow to 0
            values[i | 0x000] = 0
            values[i | 0x100] = 0x8000
        elif e < -14:  # smalls to denorms
            values[i | 0x000] = 0x400 >> (-e - 14)
            values[i | 0x100] = (0x400 >> (-e - 14)) | 0x8000
        elif e < 15:  # normal case
            values[i | 0x000] = (e + 15) << 10
            values[i | 0x100] = ((e + 15) << 10) | 0x8000
        elif e < 128:  # overflow to inf
            values[i | 0x000] = 0x7C00
            values[i | 0x100] = 0xFC00
        else:  # inf and nan
            values[i | 0x000] = 0x7C00
            values[i | 0x100] = 0xFC00

    print("static const uint16_t basetable[] = {")
    values = (f"{i:#06x}" for i in values)
    for row in grouper(values, 8):
        print("    " + (", ".join(row)) + ",")
    print("};")


def shifttable():
    values = [0] * 512
    for i in range(256):
        e = i - 127
        if e < -24:  # underflow to 0
            values[i | 0x000] = 24
            values[i | 0x100] = 24
        elif e < -14:  # smalls to denorms
            values[i | 0x000] = -e - 1
            values[i | 0x100] = -e - 1
        elif e < 15:  # normal case
            values[i | 0x000] = 13
            values[i | 0x100] = 13
        elif e < 128:  # overflow to inf
            values[i | 0x000] = 24
            values[i | 0x100] = 24
        else:  # inf and nan
            values[i | 0x000] = 13
            values[i | 0x100] = 13

    print("static const uint16_t shifttable[] = {")
    values = (f"{i:#06x}" for i in values)
    for row in grouper(values, 8):
        print("    " + (", ".join(row)) + ",")
    print("};")


sigtable()
print()
exptable()
print()
offsettable()
print()
basetable()
print()
shifttable()