Пример #1
0
def isfinished_bsgscv(n, sossp, sogsp, nt, lpt, qpt, disc, classnum, indofg):
    """
    Determine whether the bsgs algorithm is finished or not yet.
    This is a submodule called by the bsgs module.
    """
    lpt.append(n)
    sumn = 1
    for nid in lpt:
        sumn = sumn * nid
    if sumn == qpt:
        return True, sossp, sogsp
    elif sumn > qpt:
        raise ValueError

    if n == 1:
        return False, sossp, sogsp
    else:
        tpsq = misc.primePowerTest(n)
        if (tpsq[1] != 0) and ((tpsq[1] % 2) == 0):
            q = arith1.floorsqrt(n)
        else:
            q = arith1.floorsqrt(n) + 1

    ss = sossp.retel()
    new_sossp = ClassGroup(disc, classnum, [])
    tnt = copy.deepcopy(nt)
    for i in range(q):
        base = tnt ** i
        for ssi in ss:
            newel = base * ssi
            if new_sossp.search(newel) is False:
                newel.alpha = ssi.alpha[:]
                lenal = len(newel.alpha)
                sfind = indofg - lenal
                for sit in range(sfind):
                    newel.alpha.append([lenal + sit, 0, 0])
                newel.alpha.append([indofg, tnt, i])
                new_sossp.insttree(newel) # multiple of two elements of G

    y = nt ** q
    ltl = sogsp.retel()
    new_sogsp = ClassGroup(disc, classnum, [])
    for i in range(q + 1):
        base = y ** (-i)
        for eol in ltl:
            newel2 = base * eol
            if new_sogsp.search(newel2) is False:
                newel2.beta = eol.beta[:]
                lenbt = len(newel2.beta)
                gfind = indofg - lenbt
                for git in range(gfind):
                    newel2.beta.append([lenbt + git, 0, 0])
                newel2.beta.append([indofg, tnt, q * (-i)])
                new_sogsp.insttree(newel2) # multiple of two elements of G

    return False, new_sossp, new_sogsp
Пример #2
0
def isfinished_bsgscv(n, sossp, sogsp, nt, lpt, qpt, disc, classnum, indofg):
    """
    Determine whether the bsgs algorithm is finished or not yet.
    This is a submodule called by the bsgs module.
    """
    lpt.append(n)
    sumn = 1
    for nid in lpt:
        sumn = sumn * nid
    if sumn == qpt:
        return True, sossp, sogsp
    elif sumn > qpt:
        raise ValueError

    if n == 1:
        return False, sossp, sogsp
    else:
        tpsq = misc.primePowerTest(n)
        if (tpsq[1] != 0) and ((tpsq[1] & 1) == 0):
            q = arith1.floorsqrt(n)
        else:
            q = arith1.floorsqrt(n) + 1

    ss = sossp.retel()
    new_sossp = ClassGroup(disc, classnum, [])
    tnt = copy.deepcopy(nt)
    for i in range(q):
        base = tnt**i
        for ssi in ss:
            newel = base * ssi
            if new_sossp.search(newel) is False:
                newel.alpha = ssi.alpha[:]
                lenal = len(newel.alpha)
                sfind = indofg - lenal
                for sit in range(sfind):
                    newel.alpha.append([lenal + sit, 0, 0])
                newel.alpha.append([indofg, tnt, i])
                new_sossp.insttree(newel)  # multiple of two elements of G

    y = nt**q
    ltl = sogsp.retel()
    new_sogsp = ClassGroup(disc, classnum, [])
    for i in range(q + 1):
        base = y**(-i)
        for eol in ltl:
            newel2 = base * eol
            if new_sogsp.search(newel2) is False:
                newel2.beta = eol.beta[:]
                lenbt = len(newel2.beta)
                gfind = indofg - lenbt
                for git in range(gfind):
                    newel2.beta.append([lenbt + git, 0, 0])
                newel2.beta.append([indofg, tnt, q * (-i)])
                new_sogsp.insttree(newel2)  # multiple of two elements of G

    return False, new_sossp, new_sogsp
Пример #3
0
def class_number_bsgs(disc):
    """
    Return the class number with the given 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")

    lx = max(arith1.floorpowerroot(abs(disc), 5),
             500 * (math.log(abs(disc)))**2)
    uprbd = int(class_formula(disc, int(lx)) * 3 / 2)
    lwrbd = (uprbd >> 1) + 1
    bounds = [lwrbd, uprbd]

    # get the unit
    element = RetNext(disc)
    ut = element.unit()

    # append the unit to subset of G
    sossp = ClassGroup(disc, 0, [])
    sogsp = ClassGroup(disc, 0, [])
    sossp.insttree(ut)
    sogsp.insttree(ut)

    h = 1  # order
    finished = False
    while not finished:
        mstp1 = bounds[1] - bounds[0]
        if mstp1 <= 1:
            q = 1
        else:
            q = arith1.floorsqrt(mstp1)
            if misc.primePowerTest(mstp1)[1] != 2:
                q += 1
        # get next element
        nt = element.retnext()
        # x is the set of elements of G
        x = [ut, nt**h]
        if q > 2:
            x.extend([0] * (q - 2))
        # compute small steps
        if x[1] == ut:
            # compute the order of nt
            n = trorder(h, sossp, sogsp, nt, disc)
        else:
            n = trbabysp(q, x, bounds, sossp, sogsp, ut, h, nt, disc)

        # finished?
        finished, h, sossp, sogsp = isfinished_trbsgs(lwrbd, bounds, h, n,
                                                      sossp, sogsp, nt, disc)

    return h
Пример #4
0
def class_number_bsgs(disc):
    """
    Return the class number with the given 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")

    lx = max(arith1.floorpowerroot(abs(disc), 5), 500 * (math.log(abs(disc)))**2)
    uprbd = int(class_formula(disc, int(lx)) * 3 / 2)
    lwrbd = uprbd // 2 + 1
    bounds = [lwrbd, uprbd]

    # get the unit
    element = RetNext(disc)
    ut = element.unit()

    # append the unit to subset of G
    sossp = ClassGroup(disc, 0, [])
    sogsp = ClassGroup(disc, 0, [])
    sossp.insttree(ut)
    sogsp.insttree(ut)

    h = 1 # order
    finished = False
    while not finished:
        mstp1 = bounds[1] - bounds[0]
        if mstp1 <= 1:
            q = 1
        else:
            q = arith1.floorsqrt(mstp1)
            if misc.primePowerTest(mstp1)[1] != 2:
                q += 1
        # get next element
        nt = element.retnext()
        # x is the set of elements of G
        x = [ut, nt ** h]
        if q > 2:
            x.extend([0] * (q - 2))
        # compute small steps
        if x[1] == ut:
            # compute the order of nt
            n = trorder(h, sossp, sogsp, nt, disc)
        else:
            n = trbabysp(q, x, bounds, sossp, sogsp, ut, h, nt, disc)

        # finished?
        finished, h, sossp, sogsp = isfinished_trbsgs(lwrbd, bounds, h, n, sossp, sogsp, nt, disc)

    return h
Пример #5
0
 def testPrimePowerTest(self):
     # not a power
     self.assertEqual((12, 0), misc.primePowerTest(12))
     self.assertEqual((53, 1), misc.primePowerTest(53))
     # not a prime power
     self.assertEqual((36, 0), misc.primePowerTest(36))
     # powers
     self.assertEqual((7, 2), misc.primePowerTest(49))
     self.assertEqual((3, 4), misc.primePowerTest(81))
     self.assertEqual((5, 3), misc.primePowerTest(125))
     self.assertEqual((2, 7), misc.primePowerTest(128))
Пример #6
0
def babyspcv(bounds, sossp, sogsp, utwi, nt, disc, classnum):
    """
    Compute small steps
    """
    mstp1 = bounds[1] - bounds[0]
    if (mstp1 == 0) or (mstp1 == 1):
        q = 1
    else:
        tppm = misc.primePowerTest(mstp1)
        q = arith1.floorsqrt(mstp1)
        if (tppm[1] == 0) or (tppm[1] % 2):
            q += 1

    n_should_be_set = True
    # initialize
    c_s1 = ClassGroup(disc, classnum, []) # a subset of G

    # extracting i = 0 case of main loop
    for ttr in sossp.retel():
        tmpx = ttr
        tmpx.s_parent = ttr # tmpx belongs ttr in the set of smallstep
        # index of the element
        tmpx.ind = 0
        c_s1.insttree(tmpx)

    # main loop
    x_i = nt
    for i in range(1, q):
        for ttr in sossp.retel():
            tmpx = x_i * ttr
            tmpx.s_parent = ttr # tmpx belongs ttr in the set of smallstep
            if n_should_be_set and tmpx == utwi:
                n = i
                tmp_ss = tmpx.s_parent
                tmp_gs = utwi
                n_should_be_set = False
            # index of the element
            tmpx.ind = i
            c_s1.insttree(tmpx)
        x_i = nt * x_i
    assert x_i == nt ** q

    if n_should_be_set:
        sz = nt ** bounds[0]
        n, tmp_ss, tmp_gs = giantspcv(q, sz, x_i, c_s1, bounds, sogsp)
    return ordercv(n, sossp, sogsp, nt, disc, classnum, tmp_ss, tmp_gs)
Пример #7
0
    def generate(self, target, **options):
        """
        Generate squarefree factors of the target number with their
        valuations.  The method may terminate with yielding (1, 1)
        to indicate the factorization is incomplete.

        If a keyword option 'strict' is False (default to True),
        factorization will stop after the first square factor no
        matter whether it is squarefree or not.
        """
        strict = options.get('strict', True)
        options['n'] = target
        primeseq = self._parse_seq(options)
        for p in primeseq:
            if not (target % p):
                e, target = arith1.vp(target, p)
                yield p, e
                if target == 1:
                    break
                elif e > 1 and not strict:
                    yield 1, 1
                    break
                elif trivial_test_ternary(target):
                    # the factor remained is squarefree.
                    yield target, 1
                    break
                q, e = factor_misc.primePowerTest(target)
                if e:
                    yield q, e
                    break
                sqrt = arith1.issquare(target)
                if sqrt:
                    if strict:
                        for q, e in self.factor(sqrt, iterator=primeseq):
                            yield q, 2 * e
                    else:
                        yield sqrt, 2
                    break
            if p ** 3 > target:
                # there are no more square factors of target,
                # thus target is squarefree
                yield target, 1
                break
        else:
            # primeseq is exhausted but target has not been proven prime
            yield 1, 1
Пример #8
0
def babyspcv(bounds, sossp, sogsp, utwi, nt, disc, classnum):
    """
    Compute small steps
    """
    mstp1 = bounds[1] - bounds[0]
    if (mstp1 == 0) or (mstp1 == 1):
        q = 1
    else:
        tppm = misc.primePowerTest(mstp1)
        q = arith1.floorsqrt(mstp1)
        if (tppm[1] == 0) or (tppm[1] & 1):
            q += 1

    n_should_be_set = True
    # initialize
    c_s1 = ClassGroup(disc, classnum, [])  # a subset of G

    # extracting i = 0 case of main loop
    for ttr in sossp.retel():
        tmpx = ttr
        tmpx.s_parent = ttr  # tmpx belongs ttr in the set of smallstep
        # index of the element
        tmpx.ind = 0
        c_s1.insttree(tmpx)

    # main loop
    x_i = nt
    for i in range(1, q):
        for ttr in sossp.retel():
            tmpx = x_i * ttr
            tmpx.s_parent = ttr  # tmpx belongs ttr in the set of smallstep
            if n_should_be_set and tmpx == utwi:
                n = i
                tmp_ss = tmpx.s_parent
                tmp_gs = utwi
                n_should_be_set = False
            # index of the element
            tmpx.ind = i
            c_s1.insttree(tmpx)
        x_i = nt * x_i
    assert x_i == nt**q

    if n_should_be_set:
        sz = nt**bounds[0]
        n, tmp_ss, tmp_gs = giantspcv(q, sz, x_i, c_s1, bounds, sogsp)
    return ordercv(n, sossp, sogsp, nt, disc, classnum, tmp_ss, tmp_gs)
Пример #9
0
    def generate(self, target, **options):
        """
        Generate squarefree factors of the target number with their
        valuations.  The method may terminate with yielding (1, 1)
        to indicate the factorization is incomplete.

        If a keyword option 'strict' is False (default to True),
        factorization will stop after the first square factor no
        matter whether it is squarefree or not.
        """
        strict = options.get('strict', True)
        options['n'] = target
        primeseq = self._parse_seq(options)
        for p in primeseq:
            if not (target % p):
                e, target = arith1.vp(target, p)
                yield p, e
                if target == 1:
                    break
                elif e > 1 and not strict:
                    yield 1, 1
                    break
                elif trivial_test_ternary(target):
                    # the factor remained is squarefree.
                    yield target, 1
                    break
                q, e = factor_misc.primePowerTest(target)
                if e:
                    yield q, e
                    break
                sqrt = arith1.issquare(target)
                if sqrt:
                    if strict:
                        for q, e in self.factor(sqrt, iterator=primeseq):
                            yield q, 2 * e
                    else:
                        yield sqrt, 2
                    break
            if p ** 3 > target:
                # there are no more square factors of target,
                # thus target is squarefree
                yield target, 1
                break
        else:
            # primeseq is exhausted but target has not been proven prime
            yield 1, 1
Пример #10
0
def isfinished_trbsgs(lwrbd, bounds, h, n, sossp, sogsp, nt, disc):
    """
    Determine whether bsgs is finished or not yet.
    This is a submodule called by the bsgs module.

    lwrbd, h, n: int
    nt: element
    """
    h *= n
    if h >= lwrbd:
        result = True
    elif n == 1:
        result = False
    else:
        bounds[0] = (bounds[0] + n - 1) // n # ceil of lower bound // n
        bounds[1] = bounds[1] // n # floor of upper bound // n
        q = arith1.floorsqrt(n)
        if misc.primePowerTest(n)[1] != 2:
            q = arith1.floorsqrt(n) + 1 # ceil of sqrt
        sossp, sogsp = _update_subgrps(q, nt, sossp, sogsp, disc)
        result = False

    return result, h, sossp, sogsp
Пример #11
0
def isfinished_trbsgs(lwrbd, bounds, h, n, sossp, sogsp, nt, disc):
    """
    Determine whether bsgs is finished or not yet.
    This is a submodule called by the bsgs module.

    lwrbd, h, n: int
    nt: element
    """
    h *= n
    if h >= lwrbd:
        result = True
    elif n == 1:
        result = False
    else:
        bounds[0] = (bounds[0] + n - 1) // n  # ceil of lower bound // n
        bounds[1] = bounds[1] // n  # floor of upper bound // n
        q = arith1.floorsqrt(n)
        if misc.primePowerTest(n)[1] != 2:
            q = arith1.floorsqrt(n) + 1  # ceil of sqrt
        sossp, sogsp = _update_subgrps(q, nt, sossp, sogsp, disc)
        result = False

    return result, h, sossp, sogsp