Example #1
0
def square_free_decomposition(poly):
    assert type(poly) == ZPoly
    print("!")
    
    if len(poly) == 1:
        print(poly)
        return poly
    
    d = poly.derivative()
    
    if d != ZPoly([0],poly.M):
        g = zpoly_gcd(poly,d)
        print(g)
        if g == ZPoly([1],poly.M):
            print("!!!")
            print(poly)
            return poly
        else:
            print(poly//g)
            return square_free_decomposition(g)
        
    else:
        pwr = 1
        while True:
            for g in all_monic_zpolys(poly.M):
                p = g**(poly.M**pwr)
                if p == poly and g.derivative() != ZPoly([0],poly.M):
                    return square_free_decomposition(g)
                if len(p) > len(poly):
                    pwr += 1
                    break
Example #2
0
def all_irreducible_mod2():
    """Sieve of Eratosthenes for polynomials in Z/2Z"""
    out = [ZPoly([1,1,1],2)]
    
    yield ZPoly([0,1],2)
    
    yield ZPoly([1,1],2)
    
    all_p = all_zpolys(2)
    for i in range(7):
        next(all_p)
    
    while True:
        poly = next(all_p)
        
        if poly(0) == poly(1) == 1:

            for i in out:
                
                if len(i) > len(poly) // 2:
                    out.append(poly)
                    yield poly
                    break
                
                r = poly%i
                if r == ZPoly([0],2):
                    out.append(poly)
                    yield poly
                    break
Example #3
0
def zpoly_egcd(a, b):
    """Extended Euclidean Algorithm for ZPolys"""
    M = a.M
    if a == ZPoly([0],M):
        return (b, ZPoly([0],M), ZPoly([1],M))
    else:
        g, y, x = zpoly_egcd(b % a, a)
        return (g, x - (b // a) * y, y)
Example #4
0
def zpoly_lagrange_interpolation(X,Y,M):
    """Use lagrange polynomial to interpolate points of a zpoly"""
    final = ZPoly([0],M)
    for x,y in zip(X,Y):
        out = ZPoly([y],M)
        for m in X:
            if m != x:
                d = mod_inv(x-m,M)
                P = ZPoly([-m,1],M)
                out *= P*d
        final += out
    return final
Example #5
0
def all_monic_zpolys(M):
    """Generator for all monic polynomials over M"""
    
    yield ZPoly([1],M)
    co = [i for i in range(M)]
    
    l = 1
    while True:
        P = product(co,repeat=l)
        for p in P:
            coefs = [i for i in reversed((1,)+p)]
            yield ZPoly(coefs,M)
        l += 1
Example #6
0
def all_zpolys(M):
    """Generator for all polynomials over M"""
    
    co = [i for i in range(M)]
    for c in co:
        yield ZPoly([c],M)
    
    l = 1
    while True:
        P = product(co,repeat=l)
        for p in P:
            for c in co[1:]:
                coefs = [i for i in reversed((c,)+p)]
                yield ZPoly(coefs,M)
        l += 1
Example #7
0
def finite_field_example(P):

    S = FF2(ZPoly([0, 1], P.M), P)
    out = FF2(ZPoly([1], P.M), P)

    L = [FF2(P, P)]

    elems = (P.M)**(len(P) - 1)

    for i in range(1, elems):
        if out in L:
            raise Exception("Not a finite field")
        L.append(out)
        out = (out * S)


#    for i in L:
#        print(i)

    return L
Example #8
0
def ff_inv(a, R):
    """Modular Multiplicative Inverse"""

    a = a % R

    g, x, _ = zpoly_egcd(a, R)
    if g != ZPoly([1], a.M):
        raise ValueError(
            f"Multiplicative inverse of {a.full_name} mod {R.full_name} does not exist"
        )
    else:
        return x % R
    def __pow__(self, other):
        if type(other) != int:
            raise TypeError("Power of ZPolyProd must be an integer")
        if other < 0:
            raise TypeError("Power of ZPolyProd must be non-negative")

        if other == 0:
            return ZPolyProd(ZPoly([1], self.M), self.M)
        if other == 1:
            return self
        else:
            out = self
            for i in range(other - 1):
                out *= self
            return out
Example #10
0
def make_shamir_secret(secret,k,n,M):
    """Take a number and produce k ordered pairs such that n can be used to reconstruct the number"""
    if secret > M:
        raise ValueError("secret cannot be less than M or information will be lost")
    if k > n:
        raise ValueError("parts needed to reconstruct cannot be greater than total points created")
    if len(prime_factorization(M)) != 1:
        raise ValueError("Order for finite field must be a prime")
        
    co = [secret] + [randint(0,M-1) for i in range(k-1)]

    P = ZPoly( co, M )
    
    pts = []
    for i in range(n):
        r = randint(0,M-1)
        pts.append( (r,P(r)) )
    
    return pts
    def __add__(self, other):

        A = self.terms.copy()

        if type(other) == int:
            return self + ZPoly([other], self.M)

        if type(other) == ZPoly:
            if other.M == self.M:
                A.update([other])
            else:
                raise ValueError("Values of M do not match")

        elif type(other) == ZPolySum:
            A.update(other.terms)

        else:
            return NotImplemented

        return ZPolySum(A, self.M)
Example #12
0
U = RFunc(["1/8"], ["1/3", "5/4"])

rf_minitests = [
    (R, "(x + 1) / (3x + 2)"),
    (S, "(12x + 28) / (x^2 - 3x + 2)"),  #simplify
    (T, "x^2 + 5x + 3"),  # denominator one
    (U, "1/8 / (5/4x + 1/3)"),
    (U.primitive_part, "12 / (120x + 32)")
]

###########
## ZPoly ##
###########

M = 29
P = ZPoly([50, 0, -8, 121, 9], M)
Q = ZPoly([25, 29, 8], M)
PP = ZPoly([50, 0, -8, 121, 9])
QQ = ZPoly([25, 29, 1])

z_minitests = [
    (P, "9x^4 + 5x^3 + 21x^2 + 21"),
    (Q, "8x^2 + 25"),
    (P + Q, "9x^4 + 5x^3 + 17"),
    (P * Q, "14x^6 + 11x^5 + 16x^4 + 9x^3 + 26x^2 + 3"),
    (Q**0, "1"),
    (Q**1, "8x^2 + 25"),
    (Q**2, "6x^4 + 23x^2 + 16"),
    (P // Q, "12x^2 + 26x + 5"),
    (P % Q, "17x + 12"),
    (P // Q * Q + P % Q, str(P)),
 def cast_to_poly(self):
     """Add everything together as a ZPoly"""
     out = ZPoly([0], self.M)
     for val, mul in self.terms.items():
         out += mul * val
     return out
Example #14
0
    pts = make_shamir_secret(secret,min_parts,total_parts,F)
    
    print(f"We will use Shamir's method to break up the secret number {secret} into {total_parts} pieces such any {min_parts} pieces can be used to get the secret.")
    print(f"\nTo do this we create a random polynomial of degree {min_parts} that has constant term {secret} over a finite field and choose {total_parts} points on it.")
    
    print(f"\nUsing a finite field of order {F} we get the points:")
    for i in pts:
        print(i)
    
    print(f"\nPicking three of those we can reconstruct the answer:")
    rpts = sample(pts,min_parts)
    print(get_shamir_secret(rpts,F))


    print("\n\nGCD of ZPolys")
    P = ZPoly( [1,2,3], 5) * ZPoly( [2,4], 5)
    Q = ZPoly( [1,2,3], 5)
    print(P)
    print(Q)
    print(zpoly_gcd(P,Q))


    print("\n\nSquare-Free Decomposition")
    P = ZPoly([1,0,2,2,0,1,1,0,2,2,0,1],3)
    print(P)
    print(square_free_decomposition(P))


    print("\nAll monic polynomials over Z/3Z with degree less than 3")
    for poly in all_monic_zpolys(3):
        if len(poly) > 3:
 def cast_to_poly(self):
     """Multiply everything together as a ZPoly"""
     out = ZPoly([1], self.M)
     for val, pwr in self.terms.items():
         out *= val**pwr
     return out
        # Remove the modulo terms
        out = re.sub(" \(mod \d*\)", "", out)
        # Remove $ signs
        out = out.replace("$", "")
        if self.M:
            return f"${out}$ [mod {self.M}]"
        else:
            return f"${out}$"

    # Things that are like attributes can be access as properties
    pretty_name = property(_pretty_name)
    full_name = property(_full_name)


if __name__ == '__main__':
    P = ZPoly([1, 2, 3], 19)
    Q = ZPoly([2, 4], 19)
    C = ZPolyProd([P, Q], 19)
    print(P)
    print(Q)
    print(C)
    print(C * Q)
    print(C * C)
    print(C**3)
    print(C * 2)

    D = 2 * C * Q
    print(D)
    print(D**0)
    print(D.pretty_name)
    print(D.full_name)
Example #17
0
            f"Multiplicative inverse of {a.full_name} mod {R.full_name} does not exist"
        )
    else:
        return x % R


def ff_div(a, b, R):
    if b == R or str(b) == "0":
        raise ZeroDivisionError
    return (a * ff_inv(b, R)) % R


if __name__ == '__main__':
    import random

    P = ZPoly([1, 1, 1, 0, 0, 0, 0, 1, 1], 2)
    L = finite_field_example(P)

    print(
        f"\n\nFinite Field of Characteristic 2 with {len(L)} elements\nReducing Polynomial: {P}"
    )

    print("\n\nAddition and Subtraction and identical")
    for i in range(3):
        a, b = random.sample(L, 2)
        print(f"{a.bitstring()} + {b.bitstring()} = {(a+b).bitstring()}")
        print(f"{a.bitstring()} - {b.bitstring()} = {(a-b).bitstring()}")
        print()

    print("\n\nExamples of Multiplication over the Finite Field")
    for i in range(3):