# Path: crysp/poly.py
# class Poly(SubPoly):
# 
#   def __getitem__(self,i):
#       if isinstance(i,int):
#           return Poly(self.ival[i],self.size)
#       elif isinstance(i,slice):
#           return Poly(self.span(i),self.size)
#       else:
#           return Poly([self.ival[j] for j in i],self.size)
# 
# Path: crysp/utils/operators.py
# def concat(L,bigend=False):
#     if len(L)==1: return L[0]
#     if bigend: L = reversed(L)
#     return reduce(lambda x,y: x//y, L)


from crysp.bits import *
from crysp.poly import Poly
from crysp.utils.operators import concat

    def InvShiftRows(self,state):
        state[:] = state[0,13,10,7,
                         4,1,14,11,
                         8,5,2,15,
                         12,9,6,3]

    def MixColumns(self,state):
        W = state[0:4],state[4:8],state[8:12],state[12:16]
        i = 0
        for w in W:
            a,b,c,d = w.ival
            state.ival[i+0] = gmul(a,2)^gmul(b,3)^c^d
            state.ival[i+1] = a^gmul(b,2)^gmul(c,3)^d
            state.ival[i+2] = a^b^gmul(c,2)^gmul(d,3)
            state.ival[i+3] = gmul(a,3)^b^c^gmul(d,2)
            i += 4

    def InvMixColumns(self,state):
        W = state[0:4],state[4:8],state[8:12],state[12:16]
        i = 0
        for w in W:
            a,b,c,d = w.ival
            state.ival[i+0] = gmul(a,0xe)^gmul(b,0xb)^gmul(c,0xd)^gmul(d,0x9)
            state.ival[i+1] = gmul(a,0x9)^gmul(b,0xe)^gmul(c,0xb)^gmul(d,0xd)
            state.ival[i+2] = gmul(a,0xd)^gmul(b,0x9)^gmul(c,0xe)^gmul(d,0xb)
            state.ival[i+3] = gmul(a,0xb)^gmul(b,0xd)^gmul(c,0x9)^gmul(d,0xe)
            i += 4

    def AddRoundKey(self,state,w):

# Path: crysp/poly.py
# class Poly(SubPoly):
# 
#   def __getitem__(self,i):
#       if isinstance(i,int):
#           return Poly(self.ival[i],self.size)
#       elif isinstance(i,slice):
#           return Poly(self.span(i),self.size)
#       else:
#           return Poly([self.ival[j] for j in i],self.size)
# 
# Path: crysp/utils/operators.py
# def concat(L,bigend=False):
#     if len(L)==1: return L[0]
#     if bigend: L = reversed(L)
#     return reduce(lambda x,y: x//y, L)


# Path: crysp/aes.py
from crysp.bits import *
from crysp.poly import Poly
from crysp.utils.operators import concat


    def InvShiftRows(self,state):
        state[:] = state[0,13,10,7,
                         4,1,14,11,
                         8,5,2,15,
                         12,9,6,3]

    def MixColumns(self,state):
        W = state[0:4],state[4:8],state[8:12],state[12:16]
        i = 0
        for w in W:
            a,b,c,d = w.ival
            state.ival[i+0] = gmul(a,2)^gmul(b,3)^c^d
            state.ival[i+1] = a^gmul(b,2)^gmul(c,3)^d
            state.ival[i+2] = a^b^gmul(c,2)^gmul(d,3)
            state.ival[i+3] = gmul(a,3)^b^c^gmul(d,2)
            i += 4

    def InvMixColumns(self,state):
        W = state[0:4],state[4:8],state[8:12],state[12:16]
        i = 0
        for w in W:
            a,b,c,d = w.ival
            state.ival[i+0] = gmul(a,0xe)^gmul(b,0xb)^gmul(c,0xd)^gmul(d,0x9)
            state.ival[i+1] = gmul(a,0x9)^gmul(b,0xe)^gmul(c,0xb)^gmul(d,0xd)
            state.ival[i+2] = gmul(a,0xd)^gmul(b,0x9)^gmul(c,0xe)^gmul(d,0xb)
            state.ival[i+3] = gmul(a,0xb)^gmul(b,0xd)^gmul(c,0x9)^gmul(d,0xe)
            i += 4

    def AddRoundKey(self,state,w):

        state[:] = state^concat(w)