Beispiel #1
0
def ldl(G):
    """
    Compute the LDL decomposition of G.

    Input:
    G           A self-adjoint matrix (i.e. G is equal to its conjugate transpose)

    Output:
    L, D        The LDL decomposition of G, that is G = L * D * (L*), where:
                - L is lower triangular with a diagonal of 1's
                - D is diagonal

    Format:     Coefficient
    """
    deg = len(G[0][0])
    dim = len(G)
    L = [[[0 for k in range(deg)] for j in range(dim)] for i in range(dim)]
    D = [[[0 for k in range(deg)] for j in range(dim)] for i in range(dim)]
    for i in range(dim):
        L[i][i] = [1] + [0 for j in range(deg - 1)]
        D[i][i] = G[i][i]
        for j in range(i):
            L[i][j] = G[i][j]
            for k in range(j):
                L[i][j] = sub(L[i][j], mul(mul(L[i][k], adj(L[j][k])),
                                           D[k][k]))
            L[i][j] = div(L[i][j], D[j][j])
            D[i][i] = sub(D[i][i], mul(mul(L[i][j], adj(L[i][j])), D[j][j]))
    return [L, D]
def ffldl(G):
    """Compute the ffLDL decomposition tree of G.

    Args:
        G: a Gram matrix

    Format: coefficient

    Corresponds to algorithm 9 (ffLDL) of Falcon's documentation,
    except it's in polynomial representation.
    """
    n = len(G[0][0])
    L, D = ldl(G)
    # Coefficients of L, D are elements of R[x]/(x^n - x^(n/2) + 1), in coefficient representation
    if (n > 2):
        # A bisection is done on elements of a 2*2 diagonal matrix.
        d00, d01 = split(D[0][0])
        d10, d11 = split(D[1][1])
        G0 = [[d00, d01], [adj(d01), d00]]
        G1 = [[d10, d11], [adj(d11), d10]]
        return [L[1][0], ffldl(G0), ffldl(G1)]
    elif (n == 2):
        # Bottom of the recursion.
        D[0][0][1] = 0
        D[1][1][1] = 0
        return [L[1][0], D[0][0], D[1][1]]
Beispiel #3
0
def ldl(G):
    """Compute the LDL decomposition of G.

	Args:
		G: a Gram matrix

	Format: coefficient

	Corresponds to algorithm 14 (LDL) of Falcon's documentation,
	except it's in polynomial representation.
	"""
    deg = len(G[0][0])
    dim = len(G)
    L = [[[0 for k in range(deg)] for j in range(dim)] for i in range(dim)]
    D = [[[0 for k in range(deg)] for j in range(dim)] for i in range(dim)]
    for i in range(dim):
        L[i][i] = [1] + [0 for j in range(deg - 1)]
        D[i][i] = G[i][i]
        for j in range(i):
            L[i][j] = G[i][j]
            for k in range(j):
                L[i][j] = sub(L[i][j], mul(mul(L[i][k], adj(L[j][k])),
                                           D[k][k]))
            L[i][j] = div(L[i][j], D[j][j])
            D[i][i] = sub(D[i][i], mul(mul(L[i][j], adj(L[i][j])), D[j][j]))
    return [L, D]
Beispiel #4
0
def gs_norm(f, g, q):
    """Compute the squared Gram-Schmidt norm of the NTRU matrix generated by f, g.

    This matrix is [[g, - f], [G, - F]].
    This algorithm is equivalent to line 9 of algorithm 5 (NTRUGen).
    """
    sqnorm_fg = sqnorm([f, g])
    ffgg = add(mul(f, adj(f)), mul(g, adj(g)))
    Ft = div(adj(g), ffgg)
    Gt = div(adj(f), ffgg)
    sqnorm_FG = (q**2) * sqnorm([Ft, Gt])
    return max(sqnorm_fg, sqnorm_FG)
def ldl(G):
    """
    Compute the LDL decomposition of G. Only works with 2 * 2 matrices.

    Args:
        G: a Gram matrix

    Format: coefficient

    Corresponds to algorithm 8 (LDL*) of Falcon's documentation,
    except it's in polynomial representation.
    """
    deg = len(G[0][0])
    dim = len(G)
    assert (dim == 2)
    assert (dim == len(G[0]))

    zero = [0] * deg
    one = [1] + [0] * (deg - 1)
    D00 = G[0][0][:]
    L10 = div(G[1][0], G[0][0])
    D11 = sub(G[1][1], mul(mul(L10, adj(L10)), G[0][0]))
    L = [[one, zero], [L10, one]]
    D = [[D00, zero], [zero, D11]]

    return [L, D]
Beispiel #6
0
def ffldl(G):
    """
    Compute the ffLDL decomposition tree of G.

    Input:
    G           A Gram matrix

    Output:
    T           The ffLDL decomposition tree of G

    Format:     Coefficient

    Similar to algorithm ffLDL of Falcon's documentation,
    except it's in polynomial representation.
    """
    m = len(G) - 1
    d = len(G[0][0])
    # LDL decomposition
    L, D = ldl(G)
    # General case
    if (d > 2):
        rep = [L]
        for i in range(m + 1):
            # Split the output
            d0, d1 = split(D[i][i])
            Gi = [[d0, d1], [adj(d1), d0]]
            # Recursive call on the split parts
            rep += [ffldl(Gi)]
        return rep
    # Bottom case
    elif (d == 2):
        D[0][0][1] = 0
        D[1][1][1] = 0
        return [L, D[0][0], D[1][1]]
def gram(B):
    """Compute the Gram matrix of B.

    Args:
        B: a matrix

    Format: coefficient
    """
    rows = range(len(B))
    ncols = len(B[0])
    deg = len(B[0][0])
    G = [[[0 for coef in range(deg)] for j in rows] for i in rows]
    for i in rows:
        for j in rows:
            for k in range(ncols):
                G[i][j] = add(G[i][j], mul(B[i][k], adj(B[j][k])))
    return G
Beispiel #8
0
def gram(B):
    """
    Compute the Gram matrix of B.

    Input:
    B           A matrix

    Output:
    G           The Gram matrix of B: G = B * (B*)

    Format:     Coefficient
    """
    rows = range(len(B))
    ncols = len(B[0])
    deg = len(B[0][0])
    G = [[[0 for coef in range(deg)] for j in rows] for i in rows]
    for i in rows:
        for j in rows:
            for k in range(ncols):
                G[i][j] = add(G[i][j], mul(B[i][k], adj(B[j][k])))
    return G