#!/usr/bin/env python3
# 20221231 djb

print('// auto-generated by keccak.py')
print('')

R = 1

print('static const uint64_t roundconstant[24] = {')
for n in range(24):
  roundconstant = 0
  for y in range(7):
    R = (R<<1)^(113*(R>>7))
    R &= 255
    if R&2:
      roundconstant ^= 1<<((1<<y)-1)
  print('  0x%016x,'%roundconstant)
print('} ;')
print('')

print('static void keccak(uint64_t *s)')
print('{')
for j in range(25):
  print('  uint64_t s%d%d = s[%d];' % (j//5,j%5,j))
print('  uint64_t B0,B1,B2,B3,B4;')
print('  uint64_t D0,D1,D2,D3,D4;')
print('  uint64_t %s;' % ','.join('t%d%d' % (y,x) for y in range(5) for x in range(5)))
print('')
print('  for (int n = 0;n < 24;++n) {')

for x in range(5):
  print('    B%d = s0%d^s1%d^s2%d^s3%d^s4%d;' % (x,x,x,x,x,x))
print('')

for x in range(5):
  print('    D%d = B%d^ROL(B%d,1);' % (x,(x+4)%5,(x+1)%5))
  for y in range(5):
    print('    s%d%d ^= D%d;' % (y,x,x))

x,y = 1,0
r = 0
for j in range(24):
  newx,newy = y,(2*x+3*y)%5
  r += j+1
  r %= 64
  print('    t%d%d = ROL(s%d%d,%d);' % (newy,newx,y,x,r))
  x,y = newx,newy

print('    t00 = s00;')
print('')

for y in range(5):
  for x in range(5):
    print('    s%d%d = t%d%d^(t%d%d&~t%d%d);' % (y,x,y,x,y,(x+2)%5,y,(x+1)%5))

print('    s00 ^= roundconstant[n];')
print('  }')
print('')
for j in range(25):
  print('  s[%d] = s%d%d;' % (j,j//5,j%5))
print('}')
