Densely Packed Decimal (DPD) を整理する

[10進数3桁の10ビット符号化](https://qiita.com/ikiuo/items/6c02524a35f676ec753b#%E5%B0%8F%E6%95%B0%E9%83%A8%E3%81%AE%E7%AC%A6%E5%8F%B7%E5%8C%96) は見づらかったので、ビット並びを整理した表にする。

| 符号 | 百位 | 十位 | 一位 | 百位 | 十位 | 一位 |
|:--|--:|--:|--:|:-:|:-:|:-:|
| $0$ | $h_2h_1h_0$ | $m_2m_1m_0$ | $l_2l_1l_0$ | $0〜7$ | $0〜7$ | $0〜7$ |
| $100$ | $h_2h_1h_0$ | $m_2m_1m_0$ | $l_0$ | $0〜7$ | $0〜7$ | $8〜9$ |
| $101$ | $h_2h_1h_0$ | $m_0$ | $l_2l_1l_0$ | $0〜7$ | $8〜9$ | $0〜7$ |
| $110$ | $h_0$ | $m_2m_1m_0$ | $l_2l_1l_0$ | $8〜9$ | $0〜7$ | $0〜7$ |
| $111\ 00$ | $h_0$ | $m_0$ | $l_2l_1l_0$ | $8〜9$ | $8〜9$ | $0〜7$ |
| $111\ 01$ | $h_0$ | $m_2m_1m_0$ | $l_0$ | $8〜9$ | $0〜7$ | $8〜9$ |
| $111\ 10$ | $h_2h_1h_0$ | $m_0$ | $l_0$ | $0〜7$ | $8〜9$ | $8〜9$ |
| $111\ 11\ xx$ | $h_0$ | $m_0$ | $l_0$ | $8〜9$ | $8〜9$ | $8〜9$ |

<details><summary>C言語用変換テーブルを生成する Python プログラム</summary><div>

```python:Python
#!/usr/bin/env python3

def decode(e):
    (d1, d2, d3) = ((e >> 7) & 7, (e >> 4) & 7, (e >> 0) & 7)
    (m1, m2, m3) = (d1 & 6, d2 & 6, d3 & 6)
    (l1, l2, l3) = (d1 & 1, d2 & 1, d3 & 1)
    mode = (e >> 1) & 7
    if mode == 4:
        (d1, d2, d3) = (d1,   d2,   l3 | 8)
    elif mode == 5:
        (d1, d2, d3) = (d1,   l2 | 8, l3 | m2)
    elif mode == 6:
        (d1, d2, d3) = (l1 | 8, d2,   l3 | m1)
    elif mode == 7:
        mode = (e >> 5) & 3
        if mode == 0:
            (d1, d2, d3) = (l1 | 8, l2 | 8,  l3 | m1)
        elif mode == 1:
            (d1, d2, d3) = (l1 | 8, l2 | m1, l3 | 8)
        elif mode == 2:
            (d1, d2, d3) = (d1,   l2 | 8,  l3 | 8)
        elif mode == 3:
            (d1, d2, d3) = (l1 | 8, l2 | 8,  l3 | 8)
    return (d1*100 + d2*10 + d3)


def decode_table():
    return [decode(n) for n in range(1024)]


def encode(n):
    if n >= 1000:
        return 0xffff
    (d1, d2, d3) = (int(n/100) % 10, int(n/10) % 10, int(n/1) % 10)
    (h1, m1, l1) = (d1 & 8, d1 & 6, d1 & 1)
    (h2, m2, l2) = (d2 & 8, d2 & 6, d2 & 1)
    (h3, m3, l3) = (d3 & 8, d3 & 6, d3 & 1)
    (d1, d2, d3) = (d1 << 7, d2 << 4, d3)
    (l1, l2, l3) = (l1 << 7, l2 << 4, l3)
    mode = (h1 >> 1) | (h2 >> 2) | (h3 >> 3)
    if mode == 0:
        return (0x00 | d1 | d2 | d3)
    elif mode == 1:
        return (0x08 | d1 | d2 | l3)
    elif mode == 2:
        return (0x0a | d1 | l2 | l3 | (m3 << 4))
    elif mode == 4:
        return (0x0c | l1 | d2 | l3 | (m3 << 7))
    elif mode == 6:
        return (0x0e | l1 | l2 | l3 | (m3 << 7))
    elif mode == 5:
        return (0x2e | l1 | l2 | l3 | (m2 << 7))
    elif mode == 3:
        return (0x4e | d1 | l2 | l3)
    elif mode == 7:
        return (0x6e | l1 | l2 | l3)
    return -1


def encode_table():
    return [encode(n) for n in range(1024)]


def dump(l, m='', t=''):
    for n in range(len(l)):
        m = m + (' %#06x,' % l[n])
        if ((n+1) & 7) == 0:
            m = m + (' /* %#05x */\n' % ((n | 7) & ~7))
    return (m+t)


for n in range(1000):
    e = encode(n)
    d = decode(e)
    if n != d:
        print('%d != %d' % (n, d))
        raise Exception('Bug!')

print(dump(decode_table(), m='unsigned short decode_table[1024] = {\n', t='};'))
print(dump(encode_table(), m='unsigned short encode_table[1024] = {\n', t='};'))
```

</div></details>