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

	Args:
		G: a Gram matrix

	Format: FFT

	Corresponds to algorithm 14 (LDL) of Falcon's documentation.
	"""
    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 for j in range(deg)]
        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_fft(
                    L[i][j],
                    mul_fft(mul_fft(L[i][k], adj_fft(L[j][k])), D[k][k]))
            L[i][j] = div_fft(L[i][j], D[j][j])
            D[i][i] = sub_fft(
                D[i][i], mul_fft(mul_fft(L[i][j], adj_fft(L[i][j])), D[j][j]))
    return [L, D]
Beispiel #2
0
def ldl_fft(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:     FFT
    """
    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 for j in range(deg)]
        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_fft(
                    L[i][j],
                    mul_fft(mul_fft(L[i][k], adj_fft(L[j][k])), D[k][k]))
            L[i][j] = div_fft(L[i][j], D[j][j])
            D[i][i] = sub_fft(
                D[i][i], mul_fft(mul_fft(L[i][j], adj_fft(L[i][j])), D[j][j]))
    return [L, D]
def ldl_fft(G):
    """
    Compute the LDL decomposition of G. Only works with 2 * 2 matrices.

    Args:
        G: a Gram matrix

    Format: FFT

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

    zero = [0] * deg
    one = [1] * deg
    D00 = G[0][0][:]
    L10 = div_fft(G[1][0], G[0][0])
    D11 = sub_fft(G[1][1], mul_fft(mul_fft(L10, adj_fft(L10)), G[0][0]))
    L = [[one, zero], [L10, one]]
    D = [[D00, zero], [zero, D11]]

    return [L, D]
def ffsampling_fft(t, T, sigmin, randombytes):
    """Compute the ffsampling of t, using T as auxilary information.

    Args:
        t: a vector
        T: a ldl decomposition tree

    Format: FFT

    Corresponds to algorithm 11 (ffSampling) of Falcon's documentation.
    """
    n = len(t[0]) * fft_ratio
    z = [0, 0]
    if (n > 1):
        l10, T0, T1 = T
        z[1] = merge_fft(
            ffsampling_fft(split_fft(t[1]), T1, sigmin, randombytes))
        t0b = add_fft(t[0], mul_fft(sub_fft(t[1], z[1]), l10))
        z[0] = merge_fft(
            ffsampling_fft(split_fft(t0b), T0, sigmin, randombytes))
        return z
    elif (n == 1):
        z[0] = [samplerz(t[0][0].real, T[0], sigmin, randombytes)]
        z[1] = [samplerz(t[1][0].real, T[0], sigmin, randombytes)]
        return z
Beispiel #5
0
def ffnp_fft(t, T):
    """
    Compute the FFNP reduction of t, using T as auxilary information.

    Input:
    t           A vector
    T           The LDL decomposition tree of an (implicit) matrix G

    Output:
    z           An integer vector such that (t - z) * B is short

    Format:     FFT
    """
    m = len(t)
    n = len(t[0]) * fft_ratio
    z = [None] * m
    # General case
    if (n > 1):
        L = T[0]
        for i in range(m - 1, -1, -1):
            # t[i] is "corrected", taking into accounts the t[j], z[j] (j > i)
            tib = t[i][:]
            for j in range(m - 1, i, -1):
                tib = add_fft(tib, mul_fft(sub_fft(t[j], z[j]), L[j][i]))
            # Recursive call
            z[i] = merge_fft(ffnp_fft(split_fft(tib), T[i + 1]))
        return z
    # Bottom case: round each coefficient in parallel
    elif (n == 1):
        z[0] = [round(t[0][0].real)]
        z[1] = [round(t[1][0].real)]
        return z
def ffnp_fft(t, T):
    """Compute the ffnp reduction of t, using T as auxilary information.

    Args:
        t: a vector
        T: a ldl decomposition tree

    Format: FFT
    """
    n = len(t[0]) * fft_ratio
    z = [0, 0]
    if (n > 1):
        l10, T0, T1 = T
        z[1] = merge_fft(ffnp_fft(split_fft(t[1]), T1))
        t0b = add_fft(t[0], mul_fft(sub_fft(t[1], z[1]), l10))
        z[0] = merge_fft(ffnp_fft(split_fft(t0b), T0))
        return z
    elif (n == 1):
        z[0] = [round(t[0][0].real)]
        z[1] = [round(t[1][0].real)]
        return z
Beispiel #7
0
def ffsampling_fft(t, T):
    """
    Compute the fast Fourier sampling of t, using T as auxilary information.

    Input:
    t           A vector
    T           The LDL decomposition tree of an (implicit) matrix G

    Output:
    z           An integer vector such that (t - z) * B is short

    Format:     FFT

    This algorithim is a randomized version of ffnp_fft,
    such that z * B is distributed as a spherical Gaussian
    centered around t * B.
    """
    m = len(t)
    n = len(t[0]) * fft_ratio
    z = [None] * m
    # General case
    if (n > 1):
        L = T[0]
        for i in range(m - 1, -1, -1):
            # t[i] is "corrected", taking into accounts the t[j], z[j] (j > i)
            tib = t[i][:]
            for j in range(m - 1, i, -1):
                tib = add_fft(tib, mul_fft(sub_fft(t[j], z[j]), L[j][i]))
            # Recursive call
            z[i] = merge_fft(ffsampling_fft(split_fft(tib), T[i + 1]))
        return z
    # Bottom case: round each coefficient in parallel
    elif (n == 1):
        z[0] = [sampler_z(T[0], t[0][0].real)]
        z[1] = [sampler_z(T[0], t[1][0].real)]
        return z