/ externals / fmt / support / compute-powers.py
compute-powers.py
 1  #!/usr/bin/env python
 2  # Compute 10 ** exp with exp in the range [min_exponent, max_exponent] and print
 3  # normalized (with most-significant bit equal to 1) significands in hexadecimal.
 4  
 5  from __future__ import print_function
 6  
 7  min_exponent = -348
 8  max_exponent = 340
 9  step = 8
10  significand_size = 64
11  exp_offset = 2000
12  
13  class fp:
14      pass
15  
16  powers = []
17  for i, exp in enumerate(range(min_exponent, max_exponent + 1, step)):
18      result = fp()
19      n = 10 ** exp if exp >= 0 else 2 ** exp_offset / 10 ** -exp
20      k = significand_size + 1
21      # Convert to binary and round.
22      binary = '{:b}'.format(n)
23      result.f = (int('{:0<{}}'.format(binary[:k], k), 2) + 1) / 2
24      result.e = len(binary) - (exp_offset if exp < 0 else 0) - significand_size
25      powers.append(result)
26      # Sanity check.
27      exp_offset10 = 400
28      actual = result.f * 10 ** exp_offset10
29      if result.e > 0:
30          actual *= 2 ** result.e
31      else:
32          for j in range(-result.e):
33              actual /= 2
34      expected = 10 ** (exp_offset10 + exp)
35      precision = len('{}'.format(expected)) - len('{}'.format(actual - expected))
36      if precision < 19:
37          print('low precision:', precision)
38          exit(1)
39  
40  print('Significands:', end='')
41  for i, fp in enumerate(powers):
42      if i % 3 == 0:
43          print(end='\n ')
44      print(' {:0<#16x}'.format(fp.f, ), end=',')
45  
46  print('\n\nExponents:', end='')
47  for i, fp in enumerate(powers):
48      if i % 11 == 0:
49          print(end='\n ')
50      print(' {:5}'.format(fp.e), end=',')
51  
52  print('\n\nMax exponent difference:',
53        max([x.e - powers[i - 1].e for i, x in enumerate(powers)][1:]))