Advertisement
Guest User

FizzBuzz Constant-Time Python

a guest
Jan 3rd, 2015
488
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.15 KB | None | 0 0
  1. #!/usr/bin/env python
  2. import math
  3. import argparse
  4. import sys
  5.  
  6. parser = argparse.ArgumentParser(description="Generate a fizzbuzz print function")
  7. parser.add_argument('--file', metavar='filename', nargs='?', type=argparse.FileType(mode="w"),
  8. help='The file to write to', default = "autogen.c")
  9. args = vars(parser.parse_args())
  10.  
  11. number_bits = 27
  12. int_bits = 27
  13.  
  14. # characters in the integer is given by the base 10 log of the maximum number
  15. # but since we're two's complement, we subtract 1 power of two
  16. int_chars = int(math.ceil(math.log(2**(int_bits-1),10)))
  17. frac_chars = 0
  18.  
  19. int_loc = 0
  20. length = int_chars
  21.  
  22. ########
  23.  
  24. bits = [2**i for i in range(0, int_bits)]
  25.  
  26. # Ensure the patterns are up to snuff
  27. fmt = "%%0%d.%df"%(length, frac_chars)
  28. dec_patterns = [fmt%(b) for b in bits]
  29.  
  30. #generate the list of contributory things
  31. fraction_patterns = [s[int_chars:] for s in dec_patterns]
  32. int_patterns = [s[:int_chars] for s in dec_patterns]
  33.  
  34. # make a dictionary of dictionaries for fraction patterns.
  35. # Top level key: character in fraction [0, frac_chars)
  36. # Second level key: contributory bit
  37. # Second level value: resulting decimal digit
  38. ints = {i: {bit: int_patterns[bit][i] for bit in range(len(int_patterns))} for i in range(int_chars)}
  39.  
  40. def int_poly(n):
  41. patterns = [(k,v) for k, v in ints[n].iteritems()]
  42. terms = ["(%c * bit%d)"%(p, bit) for bit, p in patterns if p != "0"]
  43. return " + ".join(terms)
  44.  
  45. with args["file"] as f:
  46. f.write(
  47. """
  48. #include <stdint.h>
  49.  
  50. /*********
  51. * This file is autogenerated by generate_fizzbuzz.py.
  52. * Please don't modify it manually.
  53. *********/
  54.  
  55. void fizzbuzz(char* buffer, int f) {
  56. uint8_t isfizz = (f % 3) == 0;
  57. uint8_t isbuzz = (f % 5) == 0;
  58. uint8_t isfizzonly = isfizz & (!isbuzz);
  59. uint8_t isbuzzonly = isbuzz & (!isfizz);
  60. uint8_t isfizzbuzz = isfizz | isbuzz;
  61.  
  62. uint32_t carry = 0;
  63. uint32_t scratch = 0;
  64.  
  65. """)
  66.  
  67. f.write("\n".join([" uint8_t bit%d = (((f) >> (%d))&1);"%(i,i) for i in range(0,number_bits)]))
  68. f.write("\n")
  69.  
  70. extra_polynomials = {
  71. 0: " + (isfizz * %d) + (isbuzzonly * %d)"%(ord('F'), ord(' ')),
  72. 1: " + (isfizz * %d) + (isbuzzonly * %d)"%(ord('i'), ord(' ')),
  73. 2: " + (isfizz * %d) + (isbuzzonly * %d)"%(ord('z'), ord(' ')),
  74. 3: " + (isfizz * %d) + (isbuzzonly * %d)"%(ord('z'), ord(' ')),
  75. 4: " + (isfizzonly * %d) + (isbuzz * %d)"%(ord(' '), ord('B')),
  76. 5: " + (isfizzonly * %d) + (isbuzz * %d)"%(ord(' '), ord('u')),
  77. 6: " + (isfizzonly * %d) + (isbuzz * %d)"%(ord(' '), ord('z')),
  78. 7: " + (isfizzonly * %d) + (isbuzz * %d)"%(ord(' '), ord('z')),
  79. }
  80. def get_extra_poly(n):
  81. return extra_polynomials.get(n, "+ (isfizzbuzz * %d)"%(ord(' ')))
  82.  
  83. for position in reversed(range(int_chars)):
  84. poly = int_poly(position)
  85. f.write(" scratch = %s + carry;\n"%(poly))
  86. f.write(" buffer[%d] = ((%d + (scratch %% 10)) * (1-(isfizz | isbuzz))) %s;\n"%(int_loc + position, ord('0'),
  87. get_extra_poly(int_loc+position)))
  88. f.write("carry = scratch / 10;\n")
  89.  
  90. f.write(" buffer[%d] = '\\0';"%(length))
  91.  
  92. f.write("""
  93. }""")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement