Beispiel #1
0
def crt(inlist):
    """
    Chinese Remainder Theorem, Algo. 1.3.11 of Cohen's Book.
    """
    k = len(inlist)
    if k < 2:
        raise ValueError("nothing to be done for one element")
    ccj = [None] # gabage to simplify loop index
    ellist = list(inlist)
    ellist.sort()
    modulus = 1
    for j in range(1, k):
        modulus *= ellist[j - 1][1]
        d, tpl = gcd.gcd_of_list([modulus % ellist[j][1], ellist[j][1]])
        if d > 1:
            raise ValueError("moduli are not pairwise coprime")
        ccj.append(tpl[0])

    yj = [ellist[0][0] % ellist[0][1]]
    for j in range(1, k):
        ctp = yj[-1]
        for i in range(j - 2, -1, -1):
            ctp = yj[i] + ellist[i][1] * ctp
        yj.append(((ellist[j][0] - ctp) * ccj[j]) % ellist[j][1])
    outp = yj.pop()
    for j in range(k - 2, -1, -1):
        outp = yj.pop() + (ellist[j][1]) * outp
    return outp
Beispiel #2
0
def class_number(disc, limit_of_disc=100000000):
    """
    Return class number with the given discriminant by counting reduced forms.
    Not only fundamental discriminant.
    """
    if disc & 3 not in (0, 1):
        raise ValueError("a discriminant must be 0 or 1 mod 4")
    if disc >= 0:
        raise ValueError("a discriminant must be negative")
    if -disc >= limit_of_disc:
        warnings.warn("the discriminant seems to have too big absolute value")

    h = 1
    b = disc & 1
    c_b = int(math.sqrt(-disc / 3))

    while b <= c_b:
        q = (b**2 - disc) >> 2
        a = b
        if a <= 1:
            a = 2
        while a**2 <= q:
            if q % a == 0 and gcd.gcd_of_list([a, b, q // a])[0] == 1:
                if a == b or a**2 == q or b == 0:
                    h += 1
                else:
                    h += 2
            a += 1
        b += 2
    return h
Beispiel #3
0
def class_number(disc, limit_of_disc=100000000):
    """
    Return class number with the given discriminant by counting reduced forms.
    Not only fundamental discriminant.
    """
    if disc % 4 not in (0, 1):
        raise ValueError("a discriminant must be 0 or 1 mod 4")
    if disc >= 0:
        raise ValueError("a discriminant must be negative")
    if -disc >= limit_of_disc:
        warnings.warn("the discriminant seems to have too big absolute value")

    h = 1
    b = disc % 2
    c_b = int(math.sqrt(-disc / 3))

    while b <= c_b:
        q = (b**2 - disc) // 4
        a = b
        if a <= 1:
            a = 2
        while a**2 <= q:
            if q % a == 0 and gcd.gcd_of_list([a, b, q//a])[0] == 1:
                if a == b or a**2 == q or b == 0:
                    h += 1
                else:
                    h += 2
            a += 1
        b += 2
    return h
Beispiel #4
0
def crt(inlist):
    """
    Chinese Remainder Theorem, Algo. 1.3.11 of Cohen's Book.
    """
    k = len(inlist)
    if k < 2:
        raise ValueError("nothing to be done for one element")
    ccj = [None]  # gabage to simplify loop index
    ellist = list(inlist)
    ellist.sort()
    modulus = 1
    for j in range(1, k):
        modulus *= ellist[j - 1][1]
        d, tpl = gcd.gcd_of_list([modulus % ellist[j][1], ellist[j][1]])
        if d > 1:
            raise ValueError("moduli are not pairwise coprime")
        ccj.append(tpl[0])

    yj = [ellist[0][0] % ellist[0][1]]
    for j in range(1, k):
        ctp = yj[-1]
        for i in range(j - 2, -1, -1):
            ctp = yj[i] + ellist[i][1] * ctp
        yj.append(((ellist[j][0] - ctp) * ccj[j]) % ellist[j][1])
    outp = yj.pop()
    for j in range(k - 2, -1, -1):
        outp = yj.pop() + (ellist[j][1]) * outp
    return outp
Beispiel #5
0
def compositePDF(f_1, f_2):
    """
    Return the reduced form of composition of the given forms 'f_1' and 'f_2'.
    'f_1' and 'f_2' are quadratic forms with same disc.
    """
    if gcd.gcd_of_list(f_1)[0] != 1:
        raise ValueError(
            "coefficients of a quadratic form must be relatively prime")
    if gcd.gcd_of_list(f_2)[0] != 1:
        raise ValueError(
            "coefficients of a quadratic form must be relatively prime")
    if disc(f_1) != disc(f_2):
        raise ValueError("two quadratic forms must have same discriminant")

    if f_1[0] > f_2[0]:
        f_1, f_2 = f_2, f_1

    s = (f_1[1] + f_2[1]) >> 1
    n = f_2[1] - s

    if f_2[0] % f_1[0] == 0:
        y_1 = 0
        d = f_1[0]
    else:
        u, v, d = euclid_exd(f_2[0], f_1[0])
        y_1 = u

    if s % d == 0:
        y_2 = -1
        x_2 = 0
        d_1 = d
    else:
        u, v, d_1 = euclid_exd(s, d)
        x_2 = u
        y_2 = -v

    v_1 = f_1[0] // d_1
    v_2 = f_2[0] // d_1
    r = (y_1 * y_2 * n - x_2 * f_2[2]) % v_1

    b_3 = f_2[1] + 2 * v_2 * r
    a_3 = v_1 * v_2
    c_3 = (f_2[2] * d_1 + r * (f_2[1] + v_2 * r)) // v_1

    return reducePDF((a_3, b_3, c_3))
Beispiel #6
0
def compositePDF(f_1, f_2):
    """
    Return the reduced form of composition of the given forms 'f_1' and 'f_2'.
    'f_1' and 'f_2' are quadratic forms with same disc.
    """
    if gcd.gcd_of_list(f_1)[0] != 1:
        raise ValueError("coefficients of a quadratic form must be relatively prime")
    if gcd.gcd_of_list(f_2)[0] != 1:
        raise ValueError("coefficients of a quadratic form must be relatively prime")
    if disc(f_1) != disc(f_2):
        raise ValueError("two quadratic forms must have same discriminant")

    if f_1[0] > f_2[0]:
        f_1, f_2 = f_2, f_1

    s = (f_1[1] + f_2[1]) // 2
    n = f_2[1] - s

    if f_2[0] % f_1[0] == 0:
        y_1 = 0
        d = f_1[0]
    else:
        u, v, d = euclid_exd(f_2[0], f_1[0])
        y_1 = u

    if s % d == 0:
        y_2 = -1
        x_2 = 0
        d_1 = d
    else:
        u, v, d_1 = euclid_exd(s, d)
        x_2 = u
        y_2 = -v

    v_1 = f_1[0] // d_1
    v_2 = f_2[0] // d_1
    r = (y_1*y_2*n - x_2*f_2[2]) % v_1

    b_3 = f_2[1] + 2*v_2*r
    a_3 = v_1*v_2
    c_3 = (f_2[2]*d_1 + r*(f_2[1] + v_2*r)) // v_1

    return reducePDF((a_3, b_3, c_3))
Beispiel #7
0
def class_group(disc, limit_of_disc=100000000):
    """
    Return the class number and the class group with the given discriminant
    by counting reduced forms. Not only fundamental discriminant.
    """
    if disc % 4 not in (0, 1):
        raise ValueError("a discriminant must be 0 or 1 mod 4")
    if disc >= 0:
        raise ValueError("a discriminant must be negative")
    if -disc >= limit_of_disc:
        warnings.warn("the discriminant seems to have too big absolute value")

    h = 1
    b = disc % 2
    c_b = int(math.sqrt(-disc / 3))

    ret_list = []
    f_a = 1
    if disc % 4 == 0:
        f_b = 0
        f_c = -(disc // 4)
    else:
        f_b = 1
        f_c = -((disc - 1) // 4)
    unit = (f_a, f_b, f_c)
    ret_list.append(ReducedQuadraticForm(unit, unit))

    while b <= c_b:
        q = (b**2 - disc) // 4
        a = b
        if a <= 1:
            a = 2
        while a**2 <= q:
            if q % a == 0 and gcd.gcd_of_list([a, b, q//a])[0] == 1:
                f_c = (b**2 - disc) // (4 * a)
                if a == b or a**2 == q or b == 0:
                    h += 1
                    ret_list.append(ReducedQuadraticForm((a, b, f_c), unit))
                else:
                    h += 2
                    ret_list.append(ReducedQuadraticForm((a, b, f_c), unit))
                    ret_list.append(ReducedQuadraticForm((a, -b, f_c), unit))
            a += 1
        b += 2

    return h, ret_list
Beispiel #8
0
def class_group(disc, limit_of_disc=100000000):
    """
    Return the class number and the class group with the given discriminant
    by counting reduced forms. Not only fundamental discriminant.
    """
    if disc & 3 not in (0, 1):
        raise ValueError("a discriminant must be 0 or 1 mod 4")
    if disc >= 0:
        raise ValueError("a discriminant must be negative")
    if -disc >= limit_of_disc:
        warnings.warn("the discriminant seems to have too big absolute value")

    h = 1
    b = disc & 1
    c_b = int(math.sqrt(-disc / 3))

    ret_list = []
    f_a = 1
    if disc & 3 == 0:
        f_b = 0
        f_c = -(disc >> 2)
    else:
        f_b = 1
        f_c = -((disc - 1) >> 2)
    unit = (f_a, f_b, f_c)
    ret_list.append(ReducedQuadraticForm(unit, unit))

    while b <= c_b:
        q = (b**2 - disc) >> 2
        a = b
        if a <= 1:
            a = 2
        while a**2 <= q:
            if q % a == 0 and gcd.gcd_of_list([a, b, q // a])[0] == 1:
                f_c = (b**2 - disc) // (4 * a)
                if a == b or a**2 == q or b == 0:
                    h += 1
                    ret_list.append(ReducedQuadraticForm((a, b, f_c), unit))
                else:
                    h += 2
                    ret_list.append(ReducedQuadraticForm((a, b, f_c), unit))
                    ret_list.append(ReducedQuadraticForm((a, -b, f_c), unit))
            a += 1
        b += 2

    return h, ret_list
Beispiel #9
0
 def __init__(self, valuelist, polynomial, precompute=False):
     if len(polynomial) != len(valuelist[0])+1:
         raise ValueError
     self.value = valuelist
     self.coeff = valuelist[0]
     self.denom = valuelist[1]
     self.degree = len(polynomial) - 1
     self.polynomial = polynomial
     self.field = NumberField(self.polynomial)
     Gcd = gcd.gcd_of_list(self.coeff)
     GCD = gcd.gcd(Gcd[0], self.denom) 
     if GCD != 1:
         self.coeff = [i//GCD for i in self.coeff]
         self.denom = self.denom//GCD
     if precompute:
         self.getConj()
         self.getApprox()
         self.getCharPoly()
Beispiel #10
0
 def __init__(self, valuelist, polynomial, precompute=False):
     if len(polynomial) != len(valuelist[0]) + 1:
         raise ValueError
     self.value = valuelist
     self.coeff = valuelist[0]
     self.denom = valuelist[1]
     self.degree = len(polynomial) - 1
     self.polynomial = polynomial
     self.field = NumberField(self.polynomial)
     Gcd = gcd.gcd_of_list(self.coeff)
     GCD = gcd.gcd(Gcd[0], self.denom)
     if GCD != 1:
         self.coeff = [i // GCD for i in self.coeff]
         self.denom = self.denom // GCD
     if precompute:
         self.getConj()
         self.getApprox()
         self.getCharPoly()
Beispiel #11
0
def randomele(disc, unit):
    """
    Return a reduced random form with the given discriminant and the given unit.
    Also random element is not unit.
    """
    limit = int(math.sqrt(-disc / 3))
    while True:
        a = bigrandom.randrange(1, limit + 1)
        ind = 0
        while ind < 2*a:
            b = bigrandom.randrange(a)
            if bigrandom.randrange(2):
                b = -b
            tp = disc - b**2
            if tp % (-4 * a) == 0:
                c = tp // (-4 * a)
                if gcd.gcd_of_list([a, b, c])[0] != 1:
                    continue
                red = reducePDF((a, b, c))
                if red != unit:
                    return ReducedQuadraticForm(red, unit)
            ind += 1
Beispiel #12
0
def randomele(disc, unit):
    """
    Return a reduced random form with the given discriminant and the given unit.
    Also random element is not unit.
    """
    limit = int(math.sqrt(-disc / 3))
    while True:
        a = bigrandom.randrange(1, limit + 1)
        ind = 0
        while ind < 2 * a:
            b = bigrandom.randrange(a)
            if bigrandom.randrange(2):
                b = -b
            tp = disc - b**2
            if tp % (-4 * a) == 0:
                c = tp // (-4 * a)
                if gcd.gcd_of_list([a, b, c])[0] != 1:
                    continue
                red = reducePDF((a, b, c))
                if red != unit:
                    return ReducedQuadraticForm(red, unit)
            ind += 1
Beispiel #13
0
 def testGcdOfList(self):
     self.assertEqual([8, [1]], gcd.gcd_of_list([8]))
     self.assertEqual([1, [-4, 3]], gcd.gcd_of_list([8, 11]))
     self.assertEqual([1, [-4, 3, 0, 0, 0, 0, 0]],
                      gcd.gcd_of_list([8, 11, 10, 9, 6, 5, 4]))