BLOCK_SIZE = 9
CONSTANT = 120
IDX_SIZE = 128
MANT_WIDTH = 112
EXP_WIDTH = 15
MID_INT_SIZE = 256 + 64
MAX_EXP = 2 ** (EXP_WIDTH - 1)
POSITIVE_ARR_SIZE = MAX_EXP // IDX_SIZE
NEGATIVE_ARR_SIZE = (MAX_EXP // IDX_SIZE) + ((MANT_WIDTH + (IDX_SIZE - 1)) // IDX_SIZE)
MOD_SIZE = (10**BLOCK_SIZE) << (CONSTANT + (IDX_SIZE if IDX_SIZE > 1 else 0))
def get_table_positive(exponent, i):
pow_of_two = 1 << (exponent + CONSTANT - (BLOCK_SIZE * i))
pow_of_five = 5 ** (BLOCK_SIZE * i)
result = (pow_of_two // pow_of_five) + 1
return result % MOD_SIZE
def get_table_negative(exponent, i):
result = 1
pow_of_ten = 10 ** (BLOCK_SIZE * i)
shift_amount = CONSTANT - exponent
if shift_amount < 0:
result = pow_of_ten >> (-shift_amount)
else:
result = pow_of_ten << (shift_amount)
return result % MOD_SIZE
def ceil_log10_pow2(e):
return ((e * 0x13441350FBD) >> 42) + 1
def length_for_num(idx, index_size=IDX_SIZE):
return (
ceil_log10_pow2(idx * index_size) + ceil_log10_pow2(MANT_WIDTH) + BLOCK_SIZE - 1
) // BLOCK_SIZE
def get_64bit_window(num, index):
return (num >> (index * 64)) % (2**64)
def mid_int_to_str(num):
outstr = " {"
outstr += str(get_64bit_window(num, 0)) + "u"
for i in range(1, MID_INT_SIZE // 64):
outstr += ", " + str(get_64bit_window(num, i)) + "u"
outstr += "},"
return outstr
def print_positive_table_for_idx(idx):
positive_blocks = length_for_num(idx)
for i in range(positive_blocks):
table_val = get_table_positive(idx * IDX_SIZE, i)
print(mid_int_to_str(table_val))
return positive_blocks
def print_negative_table_for_idx(idx):
i = 0
min_block = -1
table_val = 0
MIN_USEFUL_VAL = 2 ** (CONSTANT - (MANT_WIDTH + 2))
while table_val < MIN_USEFUL_VAL:
i += 1
table_val = get_table_negative((idx) * IDX_SIZE, i)
else:
i -= 1
min_block = i
while table_val >= MIN_USEFUL_VAL:
table_val = get_table_negative((idx) * IDX_SIZE, i + 1)
if table_val >= MIN_USEFUL_VAL:
print(mid_int_to_str(table_val))
i += 1
return i - min_block, min_block
positive_size_arr = [0] * (POSITIVE_ARR_SIZE + 1)
negative_size_arr = [0] * (NEGATIVE_ARR_SIZE + 1)
min_block_arr = [0] * (NEGATIVE_ARR_SIZE + 1)
acc = 0
if MOD_SIZE > (2**MID_INT_SIZE):
print(
"Mod size is too big for current MID_INT_SIZE by a factor of",
MOD_SIZE // (2**MID_INT_SIZE),
)
else:
print("static const uint64_t POW10_SPLIT[][" + str(MID_INT_SIZE // 64) + "] = {")
for idx in range(0, POSITIVE_ARR_SIZE + 1):
num_size = print_positive_table_for_idx(idx)
positive_size_arr[idx] = acc
acc += num_size
print("};")
print(
"static const uint32_t POW10_OFFSET_2[" + str(len(positive_size_arr)) + "] = {",
str(positive_size_arr)[1:-2],
"};",
)
print("static const uint64_t POW10_SPLIT_2[][" + str(MID_INT_SIZE // 64) + "] = {")
for idx in range(0, NEGATIVE_ARR_SIZE):
num_size, min_block = print_negative_table_for_idx(idx)
acc += num_size
negative_size_arr[idx + 1] = acc
min_block_arr[idx] = min_block
print("};")
print(
"static const uint32_t POW10_OFFSET_2[" + str(len(negative_size_arr)) + "] = {",
str(negative_size_arr)[1:-2],
"};",
)
print(
"static const uint16_t MIN_BLOCK_2[" + str(len(min_block_arr)) + "] = {",
str(min_block_arr)[1:-2],
"};",
)