# Path: crysp/utils/operators.py
# def ror(x,n):
#     return (x>>n | x<<(x.size-n))
# 
# def rol(x,n):
#     return (x<<n | x>>(x.size-n))
# 
# 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.utils.operators import ror,rol,concat
    table = [
        0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60,
        64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124,
        1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61,
        65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125,
        2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62,
        66, 70, 74, 78, 82, 86, 90, 94, 98, 102, 106, 110, 114, 118, 122, 126,
        3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63,
        67, 71, 75, 79, 83, 87, 91, 95, 99, 103, 107, 111, 115, 119, 123, 127,
    ]
    return X[table]

def _keysched(prekey):
    keys = []
    k = 8
    for r in range(35,2,-1):
        Kr = concat(prekey[k:k+4])
        k+=4
        keys.append(_S(r%8,Kr))
    assert len(keys)==33
    return keys

def _L(X):
    assert X.size==128
    X = X.split(32)
    X[0] = rol(X[0],13)
    X[2] = rol(X[2],3)
    X[1] = X[1]^X[0]^X[2]
    X[3] = X[3]^X[2]^(X[0]<<3)
    X[1] = rol(X[1],1)

# Path: crysp/utils/operators.py
# def ror(x,n):
#     return (x>>n | x<<(x.size-n))
# 
# def rol(x,n):
#     return (x<<n | x>>(x.size-n))
# 
# 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/serpent.py
from crysp.bits import *
from crysp.utils.operators import ror,rol,concat

    table = [
        0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60,
        64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124,
        1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61,
        65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125,
        2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62,
        66, 70, 74, 78, 82, 86, 90, 94, 98, 102, 106, 110, 114, 118, 122, 126,
        3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63,
        67, 71, 75, 79, 83, 87, 91, 95, 99, 103, 107, 111, 115, 119, 123, 127,
    ]
    return X[table]

def _keysched(prekey):
    keys = []
    k = 8
    for r in range(35,2,-1):
        Kr = concat(prekey[k:k+4])
        k+=4
        keys.append(_S(r%8,Kr))
    assert len(keys)==33
    return keys

def _L(X):
    assert X.size==128
    X = X.split(32)
    X[0] = rol(X[0],13)
    X[2] = rol(X[2],3)
    X[1] = X[1]^X[0]^X[2]
    X[3] = X[3]^X[2]^(X[0]<<3)
    X[1] = rol(X[1],1)

    X[3] = rol(X[3],7)