Beispiel #1
0
    def action(self, i):
        r"""
        The action of the `i`-th automorphism on the affine Dynkin node set.

        EXAMPLES::

            sage: from sage.combinat.root_system.fundamental_group import FundamentalGroupOfExtendedAffineWeylGroup
            sage: F = FundamentalGroupOfExtendedAffineWeylGroup(['A',2,1], general_linear=True)
            sage: F.action(4)(2)
            0
            sage: F.action(-4)(2)
            1
        """
        return lambda j: ZZ(Mod(i + j, self._n))
Beispiel #2
0
    def arf_invariant(self):
        """
        Return the Arf invariant.

        EXAMPLES::

            sage: B = BraidGroup(4)
            sage: K = Knot(B([-1, 2, 1, 2]))
            sage: K.arf_invariant()
            0
            sage: B = BraidGroup(8)
            sage: K = Knot(B([-2, 3, 1, 2, 1, 4]))
            sage: K.arf_invariant()
            0
            sage: K = Knot(B([1, 2, 1, 2]))
            sage: K.arf_invariant()
            1
        """
        a = self.alexander_polynomial()
        if Mod(a(-1), 8) == 1 or Mod(a(-1), 8) == 7:
            return 0

        return 1
Beispiel #3
0
def DuadicCodeEvenPair(F,S1,S2):
    r"""
    Constructs the "even pair" of duadic codes associated to the
    "splitting" (see the docstring for ``_is_a_splitting``
    for the definition) S1, S2 of n.

    .. warning::

       Maybe the splitting should be associated to a sum of
       q-cyclotomic cosets mod n, where q is a *prime*.

    EXAMPLES::

        sage: from sage.coding.code_constructions import _is_a_splitting
        sage: n = 11; q = 3
        sage: C = Zmod(n).cyclotomic_cosets(q); C
        [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
        sage: S1 = C[1]
        sage: S2 = C[2]
        sage: _is_a_splitting(S1,S2,11)
        True
        sage: codes.DuadicCodeEvenPair(GF(q),S1,S2)
        ([11, 5] Cyclic Code over GF(3),
         [11, 5] Cyclic Code over GF(3))
    """
    from sage.misc.stopgap import stopgap
    stopgap("The function DuadicCodeEvenPair has several issues which may cause wrong results", 25896)

    from .cyclic_code import CyclicCode
    n = len(S1) + len(S2) + 1
    if not _is_a_splitting(S1,S2,n):
        raise TypeError("%s, %s must be a splitting of %s."%(S1,S2,n))
    q = F.order()
    k = Mod(q,n).multiplicative_order()
    FF = GF(q**k,"z")
    z = FF.gen()
    zeta = z**((q**k-1)/n)
    P1 = PolynomialRing(FF,"x")
    x = P1.gen()
    g1 = prod([x-zeta**i for i in S1+[0]])
    g2 = prod([x-zeta**i for i in S2+[0]])
    P2 = PolynomialRing(F,"x")
    x = P2.gen()
    gg1 = P2([_lift2smallest_field(c)[0] for c in g1.coefficients(sparse=False)])
    gg2 = P2([_lift2smallest_field(c)[0] for c in g2.coefficients(sparse=False)])
    C1 = CyclicCode(length = n, generator_pol = gg1)
    C2 = CyclicCode(length = n, generator_pol = gg2)
    return C1,C2
Beispiel #4
0
def DuadicCodeOddPair(F,S1,S2):
    """
    Constructs the "odd pair" of duadic codes associated to the
    "splitting" S1, S2 of n.

    .. warning::

       Maybe the splitting should be associated to a sum of
       q-cyclotomic cosets mod n, where q is a *prime*.

    EXAMPLES::

        sage: from sage.coding.code_constructions import is_a_splitting
        sage: n = 11; q = 3
        sage: C = cyclotomic_cosets(q,n); C
        [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
        sage: S1 = C[1]
        sage: S2 = C[2]
        sage: is_a_splitting(S1,S2,11)
        (True, 2)
        sage: codes.DuadicCodeOddPair(GF(q),S1,S2)
        (Linear code of length 11, dimension 6 over Finite Field of size 3,
         Linear code of length 11, dimension 6 over Finite Field of size 3)

    This is consistent with Theorem 6.1.3 in [HP]_.
    """
    n = max(S1+S2)+1
    if not(is_a_splitting(S1,S2,n)):
        raise TypeError, "%s, %s must be a splitting of %s."%(S1,S2,n)
    q = F.order()
    k = Mod(q,n).multiplicative_order()
    FF = GF(q**k,"z")
    z = FF.gen()
    zeta = z**((q**k-1)/n)
    P1 = PolynomialRing(FF,"x")
    x = P1.gen()
    g1 = prod([x-zeta**i for i in S1+[0]])
    g2 = prod([x-zeta**i for i in S2+[0]])
    j = sum([x**i/n for i in range(n)])
    P2 = PolynomialRing(F,"x")
    x = P2.gen()
    coeffs1 = [lift2smallest_field(c)[0] for c in (g1+j).coeffs()]
    coeffs2 = [lift2smallest_field(c)[0] for c in (g2+j).coeffs()]
    gg1 = P2(coeffs1)
    gg2 = P2(coeffs2)
    C1 = CyclicCodeFromGeneratingPolynomial(n,gg1)
    C2 = CyclicCodeFromGeneratingPolynomial(n,gg2)
    return C1,C2
Beispiel #5
0
def intmod_gap_to_sage(x):
    r"""
    INPUT:

    - x -- Gap integer mod ring element

    EXAMPLES::

        sage: a = gap(Mod(3, 18)); a
        ZmodnZObj( 3, 18 )
        sage: b = sage.interfaces.gap.intmod_gap_to_sage(a); b
        3
        sage: b.parent()
        Ring of integers modulo 18

        sage: a = gap(Mod(3, 17)); a
        Z(17)
        sage: b = sage.interfaces.gap.intmod_gap_to_sage(a); b
        3
        sage: b.parent()
        Ring of integers modulo 17

        sage: a = gap(Mod(0, 17)); a
        0*Z(17)
        sage: b = sage.interfaces.gap.intmod_gap_to_sage(a); b
        0
        sage: b.parent()
        Ring of integers modulo 17

        sage: a = gap(Mod(3, 65537)); a
        ZmodpZObj( 3, 65537 )
        sage: b = sage.interfaces.gap.intmod_gap_to_sage(a); b
        3
        sage: b.parent()
        Ring of integers modulo 65537
    """
    from sage.rings.finite_rings.integer_mod import Mod
    from sage.rings.finite_rings.integer_mod_ring import Zmod
    s = str(x)
    m = re.search(r'Z\(([0-9]*)\)', s)
    if m:
        return gfq_gap_to_sage(x, Zmod(m.group(1)))
    m = re.match(r'Zmod[np]ZObj\( ([0-9]*), ([0-9]*) \)', s)
    if m:
        return Mod(m.group(1), m.group(2))
    raise ValueError, "Unable to convert Gap element '%s'" % s
Beispiel #6
0
def DuadicCodeEvenPair(F, S1, S2):
    r"""
    Constructs the "even pair" of duadic codes associated to the
    "splitting" (see the docstring for ``is_a_splitting``
    for the definition) S1, S2 of n.

    .. warning::

       Maybe the splitting should be associated to a sum of
       q-cyclotomic cosets mod n, where q is a *prime*.

    EXAMPLES::

        sage: from sage.coding.code_constructions import is_a_splitting
        sage: n = 11; q = 3
        sage: C = Zmod(n).cyclotomic_cosets(q); C
        [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
        sage: S1 = C[1]
        sage: S2 = C[2]
        sage: is_a_splitting(S1,S2,11)
        True
        sage: codes.DuadicCodeEvenPair(GF(q),S1,S2)
        (Linear code of length 11, dimension 5 over Finite Field of size 3,
         Linear code of length 11, dimension 5 over Finite Field of size 3)
    """
    n = len(S1) + len(S2) + 1
    if not is_a_splitting(S1, S2, n):
        raise TypeError("%s, %s must be a splitting of %s." % (S1, S2, n))
    q = F.order()
    k = Mod(q, n).multiplicative_order()
    FF = GF(q**k, "z")
    z = FF.gen()
    zeta = z**((q**k - 1) / n)
    P1 = PolynomialRing(FF, "x")
    x = P1.gen()
    g1 = prod([x - zeta**i for i in S1 + [0]])
    g2 = prod([x - zeta**i for i in S2 + [0]])
    P2 = PolynomialRing(F, "x")
    x = P2.gen()
    gg1 = P2(
        [lift2smallest_field(c)[0] for c in g1.coefficients(sparse=False)])
    gg2 = P2(
        [lift2smallest_field(c)[0] for c in g2.coefficients(sparse=False)])
    C1 = CyclicCodeFromGeneratingPolynomial(n, gg1)
    C2 = CyclicCodeFromGeneratingPolynomial(n, gg2)
    return C1, C2
Beispiel #7
0
def inverse(a, m, q):
    if q.is_prime_power():
        (p, r) = q.perfect_power()
        res = inverse_p(a, m, p)
        if res[0]:
            b = res[1]
            x = a.parent().gen()

            b = sum([b[i].lift() * (x**i) for i in range(b.degree() + 1)])
            s = p
            while (s < q):
                s = s**2
                b = (b * (2 - a * b)).mod(m)
                b = sum([
                    Mod(b[i], s).lift() * (x**i) for i in range(b.degree() + 1)
                ])
            res = (res[0], b)
        return res
    else:
        raise ValueError
    def additive_order(self):
        """
        Return the additive order of this element.

        EXAMPLES::

            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
            sage: Q = V/W; Q
            Finitely generated module V/W over Integer Ring with invariants (4, 12)
            sage: Q.0.additive_order()
            4
            sage: Q.1.additive_order()
            12
            sage: (Q.0+Q.1).additive_order()
            12
            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1])
            sage: Q = V/W; Q
            Finitely generated module V/W over Integer Ring with invariants (12, 0)
            sage: Q.0.additive_order()
            12
            sage: type(Q.0.additive_order())
            <class 'sage.rings.integer.Integer'>
            sage: Q.1.additive_order()
            +Infinity
        """
        Q = self.parent()
        I = Q.invariants()
        v = self.vector()

        from sage.rings.infinity import infinity
        from sage.rings.finite_rings.integer_mod import Mod
        from sage.rings.integer import Integer
        from sage.arith.all import lcm
        n = Integer(1)
        for i, a in enumerate(I):
            if a == 0:
                if v[i] != 0:
                    return infinity
            else:
                n = lcm(n, Mod(v[i], a).additive_order())
        return n
Beispiel #9
0
    def reduced_word(self, i):
        r"""
        A reduced word for the finite permutation part of the
        special automorphism indexed by `i`.

        More precisely, return a reduced word for the finite Weyl group element `u`
        where `i`-th automorphism (expressed in the extended affine Weyl group)
        has the form `t u` where `t` is a translation element.

        EXAMPLES::

            sage: from sage.combinat.root_system.fundamental_group import FundamentalGroupOfExtendedAffineWeylGroup
            sage: F = FundamentalGroupOfExtendedAffineWeylGroup(['A',2,1], general_linear=True)
            sage: F.reduced_word(10)
            (1, 2)
        """
        i = ZZ(Mod(i, self._n))
        if i == 0:
            return tuple([])
        om = self.cartan_type().classical().root_system().weight_lattice().fundamental_weight(i)
        return tuple((-om).reduced_word())
Beispiel #10
0
import sage.all
from sage.rings.finite_rings.integer_mod import square_root_mod_prime, Mod
from Crypto.Util.number import long_to_bytes, inverse
import gmpy2

n = 27772857409875257529415990911214211975844307184430241451899407838750503024323367895540981606586709985980003435082116995888017731426634845808624796292507989171497629109450825818587383112280639037484593490692935998202437639626747133650990603333094513531505209954273004473567193235535061942991750932725808679249964667090723480397916715320876867803719301313440005075056481203859010490836599717523664197112053206745235908610484907715210436413015546671034478367679465233737115549451849810421017181842615880836253875862101545582922437858358265964489786463923280312860843031914516061327752183283528015684588796400861331354873
e = 16
ct = 11303174761894431146735697569489134747234975144162172162401674567273034831391936916397234068346115459134602443963604063679379285919302225719050193590179240191429612072131629779948379821039610415099784351073443218911356328815458050694493726951231241096695626477586428880220528001269746547018741237131741255022371957489462380305100634600499204435763201371188769446054925748151987175656677342779043435047048130599123081581036362712208692748034620245590448762406543804069935873123161582756799517226666835316588896306926659321054276507714414876684738121421124177324568084533020088172040422767194971217814466953837590498718
d = inverse(e, n-1)
pt = pow(ct, d, n)
print(pt)
ans = []
pt = square_root_mod_prime(Mod(pt, n), n)
ans.append(pt)
ans.append(n-pt)
ans1 = []
for a in ans:
    pt = square_root_mod_prime(Mod(a, n), n)
    ans1.append(pt)
    ans1.append(n-pt)
ans2 = []
for a in ans1:
    pt = square_root_mod_prime(Mod(a, n), n)
    ans2.append(pt)
    ans2.append(n-pt)
for a in ans2:
    print(long_to_bytes(a))
Beispiel #11
0
    def basis(self, reduce=True):
        r"""
        Produce a basis for the free abelian group of eta-products of level
        N (under multiplication), attempting to find basis vectors of the
        smallest possible degree.

        INPUT:


        -  ``reduce`` - a boolean (default True) indicating
           whether or not to apply LLL-reduction to the calculated basis


        EXAMPLES::

            sage: EtaGroup(5).basis()
            [Eta product of level 5 : (eta_1)^6 (eta_5)^-6]
            sage: EtaGroup(12).basis()
            [Eta product of level 12 : (eta_1)^2 (eta_2)^1 (eta_3)^2 (eta_4)^-1 (eta_6)^-7 (eta_12)^3,
            Eta product of level 12 : (eta_1)^-4 (eta_2)^2 (eta_3)^4 (eta_6)^-2,
            Eta product of level 12 : (eta_1)^-1 (eta_2)^3 (eta_3)^3 (eta_4)^-2 (eta_6)^-9 (eta_12)^6,
            Eta product of level 12 : (eta_1)^1 (eta_2)^-1 (eta_3)^-3 (eta_4)^-2 (eta_6)^7 (eta_12)^-2,
            Eta product of level 12 : (eta_1)^-6 (eta_2)^9 (eta_3)^2 (eta_4)^-3 (eta_6)^-3 (eta_12)^1]
            sage: EtaGroup(12).basis(reduce=False) # much bigger coefficients
            [Eta product of level 12 : (eta_2)^24 (eta_12)^-24,
            Eta product of level 12 : (eta_1)^-336 (eta_2)^576 (eta_3)^696 (eta_4)^-216 (eta_6)^-576 (eta_12)^-144,
            Eta product of level 12 : (eta_1)^-8 (eta_2)^-2 (eta_6)^2 (eta_12)^8,
            Eta product of level 12 : (eta_1)^1 (eta_2)^9 (eta_3)^13 (eta_4)^-4 (eta_6)^-15 (eta_12)^-4,
            Eta product of level 12 : (eta_1)^15 (eta_2)^-24 (eta_3)^-29 (eta_4)^9 (eta_6)^24 (eta_12)^5]

        ALGORITHM: An eta product of level `N` is uniquely
        determined by the integers `r_d` for `d | N` with
        `d < N`, since `\sum_{d | N} r_d = 0`. The valid
        `r_d` are those that satisfy two congruences modulo 24,
        and one congruence modulo 2 for every prime divisor of N. We beef
        up the congruences modulo 2 to congruences modulo 24 by multiplying
        by 12. To calculate the kernel of the ensuing map
        `\ZZ^m \to (\ZZ/24\ZZ)^n`
        we lift it arbitrarily to an integer matrix and calculate its Smith
        normal form. This gives a basis for the lattice.

        This lattice typically contains "large" elements, so by default we
        pass it to the reduce_basis() function which performs
        LLL-reduction to give a more manageable basis.
        """
        from six.moves import range
        N = self.level()
        divs = divisors(N)[:-1]
        s = len(divs)
        primedivs = prime_divisors(N)

        rows = []
        for i in range(s):
            # generate a row of relation matrix
            row = [
                Mod(divs[i], 24) - Mod(N, 24),
                Mod(N / divs[i], 24) - Mod(1, 24)
            ]
            for p in primedivs:
                row.append(Mod(12 * (N / divs[i]).valuation(p), 24))
            rows.append(row)
        M = matrix(IntegerModRing(24), rows)
        Mlift = M.change_ring(ZZ)
        # now we compute elementary factors of Mlift
        S, U, V = Mlift.smith_form()
        good_vects = []
        for i in range(U.nrows()):
            vect = U.row(i)
            nf = (i < S.ncols() and S[i, i]) or 0
            good_vects.append((vect * 24 / gcd(nf, 24)).list())
        for v in good_vects:
            v.append(-sum([r for r in v]))
        dicts = []
        for v in good_vects:
            dicts.append({})
            for i in range(s):
                dicts[-1][divs[i]] = v[i]
            dicts[-1][N] = v[-1]
        if reduce:
            return self.reduce_basis([self(d) for d in dicts])
        else:
            return [self(d) for d in dicts]
Beispiel #12
0
    def __call__(self, M):
        r"""
        Return the ciphertext (respectively, plaintext) corresponding to
        ``M``. This is the main place where encryption and decryption takes
        place.

        INPUT:

        - ``M`` -- a message to be encrypted or decrypted. This message must
          be encoded using the plaintext or ciphertext alphabet. The current
          behaviour is that the plaintext and ciphertext alphabets are the
          same alphabet.

        - ``algorithm`` -- (default ``"encrypt"``) whether to use the
          encryption or decryption algorithm on ``M``. The flag ``"encrypt"``
          signifies using the encryption algorithm, while ``"decrypt"``
          signifies using the decryption algorithm. The only acceptable
          values for ``algorithm`` are: ``"encrypt"`` and ``"decrypt"``.

        OUTPUT:

        - The ciphertext or plaintext corresponding to ``M``.

        EXAMPLES::

            sage: A = AffineCryptosystem(AlphabeticStrings()); A
            Affine cryptosystem on Free alphabetic string monoid on A-Z
            sage: P = A.encoding("The affine cryptosystem generalizes the shift cipher.")
            sage: P
            THEAFFINECRYPTOSYSTEMGENERALIZESTHESHIFTCIPHER
            sage: a, b = (9, 13)
            sage: E = A(a, b); E
            Affine cipher on Free alphabetic string monoid on A-Z
            sage: C = E(P); C
            CYXNGGHAXFKVSCJTVTCXRPXAXKNIHEXTCYXTYHGCFHSYXK
            sage: aInv, bInv = A.inverse_key(a, b)
            sage: D = A(aInv, bInv); D
            Affine cipher on Free alphabetic string monoid on A-Z
            sage: D(C)
            THEAFFINECRYPTOSYSTEMGENERALIZESTHESHIFTCIPHER
            sage: D(C) == P
            True
            sage: D(C) == P == D(E(P))
            True
        """
        # sanity check
        D = self.domain()  # = plaintext_space = ciphertext_space
        if M.parent() != D:
            raise TypeError(
                "Argument M must be a string in the plaintext/ciphertext space."
            )

        from sage.rings.finite_rings.integer_mod import Mod
        A = list(D.alphabet())  # plaintext/ciphertext alphabet as a list
        N = self.domain().ngens()  # number of elements in this alphabet
        a, b = self.key()  # encryption/decryption key (a,b)
        # Let I be the index list of M. That is, the i-th element of M has
        # index k in the cipher domain D. We store this cipher domain index
        # as the i-th element of I.
        I = [A.index(str(e)) for e in M]

        # Encrypt the plaintext M. For each element i in I, the ciphertext
        # corresponding to i is ai + b (mod N). This can also be used for
        # decryption, in which case (a, b) is the inverse key corresponding
        # to a secret key.
        return D([A.index(A[Mod(a * i + b, N).lift()]) for i in I])
Beispiel #13
0
    def __call__(self, M):
        r"""
        Return the ciphertext (respectively, plaintext) corresponding to
        ``M``. This is the main place where encryption and decryption takes
        place.

        INPUT:

        - ``M`` -- a message to be encrypted or decrypted. This message must
          be encoded using the plaintext or ciphertext alphabet. The current
          behaviour is that the plaintext and ciphertext alphabets are the
          same alphabet.

        OUTPUT:

        - The ciphertext or plaintext corresponding to ``M``.

        EXAMPLES:

        These are indirect doctests. Functionalities of this class are
        usually invoked from
        :class:`ShiftCryptosystem <sage.crypto.classical.ShiftCryptosystem>`.

        ::

            sage: S = ShiftCryptosystem(AlphabeticStrings())
            sage: S.enciphering(12, S.encoding("Stop shifting me."))
            EFABETURFUZSYQ
            sage: S = ShiftCryptosystem(HexadecimalStrings())
            sage: S.enciphering(7, S.encoding("Shift me now."))
            cadfd0ddeb97d4dc97d5d6ee95
            sage: S = ShiftCryptosystem(BinaryStrings())
            sage: S.enciphering(1, S.encoding("OK, enough shifting."))
            1011000010110100110100111101111110011010100100011001000010001010100110001001011111011111100011001001011110010110100110011000101110010110100100011001100011010001
        """
        dom = self.domain()  # = plaintext_space = ciphertext_space
        if not isinstance(M, StringMonoidElement) and M.parent() == dom:
            raise TypeError(
                "Argument M (= %s) must be a string in the plaintext/ciphertext space."
                % M)
        from sage.rings.finite_rings.integer_mod import Mod
        A = list(dom.alphabet())  # plaintext/ciphertext alphabet as a list
        N = self.domain().ngens()  # number of elements in this alphabet
        K = self.key()  # encryption/decryption key
        # Here, M is a message encoded within the ciphertext/plaintext
        # alphabet of this shift cryptosystem. The list A above is a list of
        # all elements of this alphabet, each element being associated with
        # an index 0 <= i < n, where n is the size of A. Now get the index
        # of each character in the message M, storing all these indices
        # in the index list I.
        # TODO: the following two lines are coded with clarity and
        # readability in mind. It is possible to remove the overhead of
        # doing a list comprehension to get the index associated with each
        # element of M. For example, the next two lines can be crammed into
        # one list comprehension as follows:
        # return dom([ A.index(A[Mod(A.index(str(i)) + K, N).lift()]) for i in M ])
        # But it performs badly compared to the following two lines.
        I = [A.index(str(e)) for e in M]
        # Perform encryption/decryption on the whole message M, returning
        # the result as a string encoded in the alphabet A.
        return dom([A.index(A[Mod(i + K, N).lift()]) for i in I])
Beispiel #14
0
def mod_q(f, q):
    n = f.degree()
    x = f.parent().gen()

    return sum([Mod(f[i], q) * (x**i) for i in range(n + 1)])
Beispiel #15
0
def gaunt(l_1, l_2, l_3, m_1, m_2, m_3, prec=None):
    r"""
    Calculate the Gaunt coefficient.

    The Gaunt coefficient is defined as the integral over three
    spherical harmonics:

    .. math::

        Y(j_1,j_2,j_3,m_1,m_2,m_3)
        =\int Y_{l_1,m_1}(\Omega)
         Y_{l_2,m_2}(\Omega) Y_{l_3,m_3}(\Omega) d\Omega
        =\sqrt{(2l_1+1)(2l_2+1)(2l_3+1)/(4\pi)}
         \; Y(j_1,j_2,j_3,0,0,0) \; Y(j_1,j_2,j_3,m_1,m_2,m_3)

    INPUT:

    -  ``l_1``, ``l_2``, ``l_3``, ``m_1``, ``m_2``, ``m_3`` - integer

    -  ``prec`` - precision, default: ``None``. Providing a precision can
       drastically speed up the calculation.

    OUTPUT:

    Rational number times the square root of a rational number
    (if ``prec=None``), or real number if a precision is given.

    EXAMPLES::

        sage: gaunt(1,0,1,1,0,-1)
        -1/2/sqrt(pi)
        sage: gaunt(1,0,1,1,0,0)
        0
        sage: gaunt(29,29,34,10,-5,-5)
        1821867940156/215552371055153321*sqrt(22134)/sqrt(pi)
        sage: gaunt(20,20,40,1,-1,0)
        28384503878959800/74029560764440771/sqrt(pi)
        sage: gaunt(12,15,5,2,3,-5)
        91/124062*sqrt(36890)/sqrt(pi)
        sage: gaunt(10,10,12,9,3,-12)
        -98/62031*sqrt(6279)/sqrt(pi)
        sage: gaunt(1000,1000,1200,9,3,-12).n(64)
        0.00689500421922113448

    It is an error to use non-integer values for `l` and `m`::

        sage: gaunt(1.2,0,1.2,0,0,0)
        Traceback (most recent call last):
        ...
        ValueError: l values must be integer
        sage: gaunt(1,0,1,1.1,0,-1.1)
        Traceback (most recent call last):
        ...
        ValueError: m values must be integer

    NOTES:

    The Gaunt coefficient obeys the following symmetry rules:

    - invariant under any permutation of the columns

      .. math::
          Y(j_1,j_2,j_3,m_1,m_2,m_3)
          =Y(j_3,j_1,j_2,m_3,m_1,m_2)
          =Y(j_2,j_3,j_1,m_2,m_3,m_1)
          =Y(j_3,j_2,j_1,m_3,m_2,m_1)
          =Y(j_1,j_3,j_2,m_1,m_3,m_2)
          =Y(j_2,j_1,j_3,m_2,m_1,m_3)

    - invariant under space inflection, i.e.

      .. math::
          Y(j_1,j_2,j_3,m_1,m_2,m_3)
          =Y(j_1,j_2,j_3,-m_1,-m_2,-m_3)

    - symmetric with respect to the 72 Regge symmetries as inherited
      for the `3j` symbols [Regge58]_

    - zero for `l_1`, `l_2`, `l_3` not fulfilling triangle relation

    - zero for violating any one of the conditions: `l_1 \ge |m_1|`,
      `l_2 \ge |m_2|`, `l_3 \ge |m_3|`

    - non-zero only for an even sum of the `l_i`, i.e.
      `J=l_1+l_2+l_3=2n` for `n` in `\Bold{N}`

    ALGORITHM:

    This function uses the algorithm of [Liberatodebrito82]_ to
    calculate the value of the Gaunt coefficient exactly. Note that
    the formula contains alternating sums over large factorials and is
    therefore unsuitable for finite precision arithmetic and only
    useful for a computer algebra system [Rasch03]_.

    REFERENCES:

    .. [Liberatodebrito82] 'FORTRAN program for the integral of three
      spherical harmonics', A. Liberato de Brito,
      Comput. Phys. Commun., Volume 25, pp. 81-85 (1982)

    AUTHORS:

    - Jens Rasch (2009-03-24): initial version for Sage
    """
    if int(l_1) != l_1 or int(l_2) != l_2 or int(l_3) != l_3:
        raise ValueError("l values must be integer")
    if int(m_1) != m_1 or int(m_2) != m_2 or int(m_3) != m_3:
        raise ValueError("m values must be integer")

    bigL = (l_1 + l_2 + l_3) / 2
    a1 = l_1 + l_2 - l_3
    if a1 < 0:
        return 0
    a2 = l_1 - l_2 + l_3
    if a2 < 0:
        return 0
    a3 = -l_1 + l_2 + l_3
    if a3 < 0:
        return 0
    if Mod(2 * bigL, 2) != 0:
        return 0
    if (m_1 + m_2 + m_3) != 0:
        return 0
    if (abs(m_1) > l_1) or (abs(m_2) > l_2) or (abs(m_3) > l_3):
        return 0

    imin = max(-l_3 + l_1 + m_2, -l_3 + l_2 - m_1, 0)
    imax = min(l_2 + m_2, l_1 - m_1, l_1 + l_2 - l_3)

    maxfact = max(l_1 + l_2 + l_3 + 1, imax + 1)
    _calc_factlist(maxfact)

    argsqrt = (2 * l_1 + 1) * (2 * l_2 + 1) * (2 * l_3 + 1) * \
        _Factlist[l_1 - m_1] * _Factlist[l_1 + m_1] * _Factlist[l_2 - m_2] * \
        _Factlist[l_2 + m_2] * _Factlist[l_3 - m_3] * _Factlist[l_3 + m_3] / \
        (4*pi)
    ressqrt = argsqrt.sqrt()

    prefac = Integer(_Factlist[bigL] * _Factlist[l_2 - l_1 + l_3] * \
                     _Factlist[l_1 - l_2 + l_3] * _Factlist[l_1 + l_2 - l_3])/ \
                     _Factlist[2 * bigL+1]/ \
                     (_Factlist[bigL - l_1] * _Factlist[bigL - l_2] * _Factlist[bigL - l_3])

    sumres = 0
    for ii in range(imin, imax + 1):
        den = _Factlist[ii] * _Factlist[ii + l_3 - l_1 - m_2] * \
            _Factlist[l_2 + m_2 - ii] * _Factlist[l_1 - ii - m_1] * \
            _Factlist[ii + l_3 - l_2 + m_1] * _Factlist[l_1 + l_2 - l_3 - ii]
        sumres = sumres + Integer((-1)**ii) / den

    res = ressqrt * prefac * sumres * (-1)**(bigL + l_3 + m_1 - m_2)
    if prec is not None:
        res = res.n(prec)
    return res
Beispiel #16
0
def benchmark(pbound=[3, 2**10],
              nbound=[3, 2**8],
              cbound=[1, Infinity],
              obound=[1, Infinity],
              loops=10,
              tloop=Infinity,
              tmax=Infinity,
              prime=False,
              even=False,
              check=False,
              fname=None,
              write=False,
              overwrite=False,
              verbose=True,
              skip_pari=False,
              skip_magma=False,
              skip_rains=False,
              skip_kummer=False):
    if write:
        mode = 'w' if overwrite else 'a'
        f = open(fname, mode, 0)
    else:
        f = sys.stdout
    pmin, pmax = pbound
    nmin, nmax = nbound
    omin, omax = obound
    cmin, cmax = cbound
    M = Magma()
    for p in xrange(pmin, pmax):
        p = ZZ(p)
        if not p.is_prime():
            continue
        for n in xrange(nmin, nmax):
            n = ZZ(n)
            if (prime == 1 and not is_prime(n)) or (prime == 2
                                                    and not is_prime_power(n)):
                continue
            if n < 2:
                continue
            if n % p == 0:
                continue
            if (not even) and (n % 2 == 0):
                continue
            o, G = find_root_order(p, [n, n], n, verbose=False)
            m = G[0][0].parent().order()
            c = Mod(p, n).multiplicative_order()
            if verbose:
                sys.stdout.write("\r" + " " * 79)
                print("\rp = {}, n = {}, (o = {}, c = {})".format(p, n, o, c))
            if verbose:
                t = mytime()
                sys.stdout.write("Constructing fields ({})".format(
                    time.strftime("%c")))
                sys.stdout.flush()
            q = p**n
            k = GF(q, name='z')
            k_rand = GF(q, modulus='random', name='z')
            k_flint = GF_flint(p, k.modulus(), name='z')
            if verbose > 1:
                sys.stdout.write("\ntotal: {}s\n".format(mytime(t)))
                sys.stdout.flush()
            # Magma
            if verbose:
                sys.stdout.write("\r" + " " * 79)
                sys.stdout.write("\rMagma ({})".format(time.strftime("%c")))
                sys.stdout.flush()
            tloops = 0
            for l in xrange(loops):
                if skip_magma:
                    break
                if (o > omax) or (o == p):
                    break
                # let's assume that launching a new Magma instance is cheaper
                # than computing random irreducible polynomials
                try:
                    M._start()
                except OSError as err:
                    # but it can also cause fork issues...
                    # let's accept this
                    # and fail as the situation will only worsen
                    # unless it is "just" a memory issue
                    # which should be mitigated by COW but is not
                    #print(err)
                    if err.errno == errno.ENOMEM:
                        break
                    else:
                        raise
                try:
                    k_magma = M(k)
                    k_rand_magma = M(k_rand)
                    if tloop is not Infinity:
                        alarm(tloop)
                    t = mytime()
                    k_magma.Embed(k_rand_magma, nvals=0)
                    #M._eval_line("Embed(k_magma, k_rand_magma);", wait_for_prompt=False)
                    tloops += mytime(t)
                except TypeError:
                    # sage/magma interface sometimes gets confused
                    pass
                except (KeyboardInterrupt, AlarmInterrupt):
                    # sage interface eats KeyboardInterrupt
                    # and AlarmInterrupt derives from it
                    tloops = 0
                    break
                finally:
                    if tloop is not Infinity:
                        cancel_alarm()
                    M.quit()
                    # sage pexpect interface leaves zombies around
                    try:
                        while os.waitpid(-1, os.WNOHANG)[0]:
                            pass
                    # but sometimes every child is already buried
                    # and we get an ECHILD error...
                    except OSError:
                        pass
                if tloops > tmax:
                    break
            tmagma = tloops / (l + 1)
            if verbose > 1:
                sys.stdout.write("\ntotal: {}s, per loop: {}s\n".format(
                    tloops, tloops / (l + 1)))
                sys.stdout.flush()
            # Rains algorithms
            if verbose:
                sys.stdout.write("\r" + " " * 79)
                sys.stdout.write("\rCyclotomic Rains ({})".format(
                    time.strftime("%c")))
                sys.stdout.flush()
            trains = []
            tloops = 0
            for l in xrange(loops):
                if skip_rains:
                    break
                if (o > omax) or (o == p):
                    break
                try:
                    if tloop is not Infinity:
                        alarm(tloop)
                    t = mytime()
                    a, b = find_gens_cyclorains(k_flint,
                                                k_flint,
                                                use_lucas=False)
                    tloops += mytime(t)
                except (KeyboardInterrupt, AlarmInterrupt):
                    tloops = 0
                    break
                finally:
                    if tloop is not Infinity:
                        cancel_alarm()
                if check and (l == 0 or check > 1):
                    g = a.minpoly()
                    if g.degree() != n:
                        raise RuntimeError("wrong degree")
                    if g != b.minpoly():
                        raise RuntimeError("different minpolys")
                if tloops > tmax:
                    break
            trains.append(tloops / (l + 1))
            if verbose > 1:
                sys.stdout.write("\ntotal: {}s, per loop: {}s\n".format(
                    tloops, tloops / (l + 1)))
                sys.stdout.flush()
            # Conic Rains
            if verbose:
                sys.stdout.write("\r" + " " * 79)
                sys.stdout.write("\rConic Rains ({})".format(
                    time.strftime("%c")))
                sys.stdout.flush()
            tloops = 0
            for l in xrange(loops):
                if skip_rains:
                    break
                if (o != 2) or (o > omax) or (o == p):
                    break
                try:
                    if tloop is not Infinity:
                        alarm(tloop)
                    t = mytime()
                    a, b = find_gens_cyclorains(k_flint,
                                                k_flint,
                                                use_lucas=True)
                    tloops += mytime(t)
                except (KeyboardInterrupt, AlarmInterrupt):
                    tloops = 0
                    break
                finally:
                    if tloop is not Infinity:
                        cancel_alarm()
                if check and (l == 0 or check > 1):
                    g = a.minpoly()
                    if g.degree() != n:
                        raise RuntimeError("wrong degree")
                    if g != b.minpoly():
                        raise RuntimeError("different minpolys")
                if tloops > tmax:
                    break
            trains.append(tloops / (l + 1))
            if verbose > 1:
                sys.stdout.write("\ntotal: {}s, per loop: {}s\n".format(
                    tloops, tloops / (l + 1)))
                sys.stdout.flush()
            # Elliptic Rains
            if verbose:
                sys.stdout.write("\r" + " " * 79)
                sys.stdout.write("\rElliptic Rains ({})".format(
                    time.strftime("%c")))
                sys.stdout.flush()
            tloops = 0
            for l in xrange(loops):
                if skip_rains:
                    break
                try:
                    if tloop is not Infinity:
                        alarm(tloop)
                    t = mytime()
                    a, b = find_gens_ellrains(k_flint, k_flint)
                    tloops += mytime(t)
                except RuntimeError:
                    # sometimes no suitable elliptic curve exists
                    pass
                except (KeyboardInterrupt, AlarmInterrupt):
                    tloops = 0
                    break
                finally:
                    if tloop is not Infinity:
                        cancel_alarm()
                if check and (l == 0 or check > 1):
                    g = a.minpoly()
                    if g.degree() != n:
                        raise RuntimeError("wrong degree")
                    if g != b.minpoly():
                        raise RuntimeError("different minpolys")
                if tloops > tmax:
                    break
            trains.append(tloops / (l + 1))
            if verbose > 1:
                sys.stdout.write("\ntotal: {}s, per loop: {}s\n".format(
                    tloops, tloops / (l + 1)))
                sys.stdout.flush()
            # PARI/GP
            if verbose:
                sys.stdout.write("\r" + " " * 79)
                sys.stdout.write("\rPARI/GP ({})".format(time.strftime("%c")))
                sys.stdout.flush()
            tloops = 0
            for l in xrange(loops):
                if skip_pari:
                    break
                if c < cmin or c > cmax:
                    break
                try:
                    if tloop is not Infinity:
                        alarm(tloop)
                    t = mytime()
                    a, b = find_gens_pari(k, k)
                    tloops += mytime(t)
                except (KeyboardInterrupt, AlarmInterrupt):
                    tloops = 0
                    break
                finally:
                    if tloop is not Infinity:
                        cancel_alarm()
                if check and (l == 0 or check > 1):
                    g = a.minpoly()
                    if g.degree() != n:
                        raise RuntimeError("wrong degree")
                    if g != b.minpoly():
                        raise RuntimeError("different minpolys")
                if tloops > tmax:
                    break
            tpari = tloops / (l + 1)
            # Kummer algorithms
            tkummer = []
            # only linalg and modcomp implemented for c==1
            for i, algo in enumerate(kummer_algolist[2 * (c == 1):-2 *
                                                     (c == 1) - 1]):
                if verbose:
                    sys.stdout.write("\r" + " " * 79)
                    sys.stdout.write("\rKummer {} ({})".format(
                        kummer_namelist[2 * (c == 1) + i],
                        time.strftime("%c")))
                    sys.stdout.flush()
                tloops = 0
                for l in xrange(loops):
                    if skip_kummer:
                        break
                    if c < cmin or c > cmax:
                        break
                    try:
                        if tloop is not Infinity:
                            alarm(tloop)
                        t = mytime()
                        a, b = find_gens_kummer(k_flint, k_flint, n, algo)
                        tloops += mytime(t)
                    except (KeyboardInterrupt, AlarmInterrupt):
                        tloops = 0
                        break
                    finally:
                        if tloop is not Infinity:
                            cancel_alarm()
                    if check and (l == 0 or check > 1):
                        g = a.minpoly()
                        if g.degree() != n:
                            raise RuntimeError("wrong degree")
                        if g != b.minpoly():
                            raise RuntimeError("different minpolys")
                    if tloops > tmax:
                        break
                tkummer.append(tloops / (l + 1))
                if verbose > 1:
                    sys.stdout.write("\ntotal: {}s, per loop: {}s\n".format(
                        tloops, tloops / (l + 1)))
                    sys.stdout.flush()
            tkummer = 2 * (c == 1) * [0] + tkummer + 2 * (c == 1) * [0]
            if verbose:
                sys.stdout.write("\r")
                sys.stdout.flush()
            f.write(("{} {} ({}, {})" + " {}" + " {}" * len(trains) + " {}" +
                     " {}" * len(tkummer) + "\n").format(
                         p, n, o, c, *([tmagma] + trains + [tpari] + tkummer)))
    if write:
        f.close()
Beispiel #17
0
def gaunt(l_1, l_2, l_3, m_1, m_2, m_3, prec=None):
    r"""
    Return the Gaunt coefficient.

    The Gaunt coefficient is defined as the integral over three
    spherical harmonics:

    .. MATH::

        Y(l_1,l_2,l_3,m_1,m_2,m_3) \hspace{12em} \\
        =\int Y_{l_1,m_1}(\Omega) \
         Y_{l_2,m_2}(\Omega) \ Y_{l_3,m_3}(\Omega) \ d\Omega \hspace{5em} \\
        =\sqrt{\frac{(2l_1+1)(2l_2+1)(2l_3+1)}{4\pi}} \hspace{6.5em} \\
         \times \begin{pmatrix} l_1 & l_2 & l_3 \\ 0 & 0 & 0 \end{pmatrix}
         \begin{pmatrix} l_1 & l_2 & l_3 \\ m_1 & m_2 & m_3 \end{pmatrix}

    INPUT:

    -  ``l_1``, ``l_2``, ``l_3``, ``m_1``, ``m_2``, ``m_3`` -- integer

    -  ``prec`` -- precision, default: ``None``. Providing a precision can
       drastically speed up the calculation.

    OUTPUT:

    Rational number times the square root of a rational number
    (if ``prec=None``), or real number if a precision is given.

    EXAMPLES::

        sage: gaunt(1,0,1,1,0,-1)
        -1/2/sqrt(pi)
        sage: gaunt(1,0,1,1,0,0)
        0
        sage: gaunt(29,29,34,10,-5,-5)
        1821867940156/215552371055153321*sqrt(22134)/sqrt(pi)
        sage: gaunt(20,20,40,1,-1,0)
        28384503878959800/74029560764440771/sqrt(pi)
        sage: gaunt(12,15,5,2,3,-5)
        91/124062*sqrt(36890)/sqrt(pi)
        sage: gaunt(10,10,12,9,3,-12)
        -98/62031*sqrt(6279)/sqrt(pi)
        sage: gaunt(1000,1000,1200,9,3,-12).n(64)
        0.00689500421922113448

    If the sum of the `l_i` is odd, the answer is zero, even for Python
    ints (see :trac:`14766`)::

        sage: gaunt(1,2,2,1,0,-1)
        0
        sage: gaunt(int(1),int(2),int(2),1,0,-1)
        0

    It is an error to use non-integer values for `l` or `m`::

        sage: gaunt(1.2,0,1.2,0,0,0)
        Traceback (most recent call last):
        ...
        TypeError: Attempt to coerce non-integral RealNumber to Integer
        sage: gaunt(1,0,1,1.1,0,-1.1)
        Traceback (most recent call last):
        ...
        TypeError: Attempt to coerce non-integral RealNumber to Integer

    TESTS:

    Check for :trac:`14735`::

        sage: gaunt(int(1),int(1),int(1),int(0),int(1),int(-1))
        0

    The Gaunt coefficient obeys the following symmetry rules:

    - invariant under any permutation of the columns

      .. MATH::

          Y(l_1,l_2,l_3,m_1,m_2,m_3)
          =Y(l_3,l_1,l_2,m_3,m_1,m_2) \hspace{3em} \\ \hspace{3em}
          =Y(l_2,l_3,l_1,m_2,m_3,m_1)
          =Y(l_3,l_2,l_1,m_3,m_2,m_1) \\ \hspace{3em}
          =Y(l_1,l_3,l_2,m_1,m_3,m_2)
          =Y(l_2,l_1,l_3,m_2,m_1,m_3)

    - invariant under space inflection, i.e.

      .. MATH::

          Y(l_1,l_2,l_3,m_1,m_2,m_3)
          =Y(l_1,l_2,l_3,-m_1,-m_2,-m_3)

    - symmetric with respect to the 72 Regge symmetries as inherited
      for the 3-`j` symbols [Reg1958]_

    - zero for `l_1`, `l_2`, `l_3` not fulfilling triangle relation

    - zero for violating any one of the conditions: `l_1 \ge |m_1|`,
      `l_2 \ge |m_2|`, `l_3 \ge |m_3|`

    - non-zero only for an even sum of the `l_i`, i.e.
      `J=l_1+l_2+l_3=2n` for `n` in `\Bold{N}`

    ALGORITHM:

    This function uses the algorithm of [LdB1982]_ to
    calculate the value of the Gaunt coefficient exactly. Note that
    the formula contains alternating sums over large factorials and is
    therefore unsuitable for finite precision arithmetic and only
    useful for a computer algebra system [RH2003]_.

    AUTHORS:

    - Jens Rasch (2009-03-24): initial version for Sage
    """
    l_1 = Integer(l_1)
    l_2 = Integer(l_2)
    l_3 = Integer(l_3)
    m_1 = Integer(m_1)
    m_2 = Integer(m_2)
    m_3 = Integer(m_3)

    bigL = (l_1 + l_2 + l_3) / 2
    a1 = l_1 + l_2 - l_3
    if a1 < 0:
        return 0
    a2 = l_1 - l_2 + l_3
    if a2 < 0:
        return 0
    a3 = -l_1 + l_2 + l_3
    if a3 < 0:
        return 0
    if Mod(2 * bigL, 2) != 0:
        return 0
    if (m_1 + m_2 + m_3) != 0:
        return 0
    if (abs(m_1) > l_1) or (abs(m_2) > l_2) or (abs(m_3) > l_3):
        return 0

    imin = int(max(-l_3 + l_1 + m_2, -l_3 + l_2 - m_1, 0))
    imax = int(min(l_2 + m_2, l_1 - m_1, l_1 + l_2 - l_3))

    maxfact = max(l_1 + l_2 + l_3 + 1, imax + 1)
    _calc_factlist(maxfact)

    argsqrt = (2 * l_1 + 1) * (2 * l_2 + 1) * (2 * l_3 + 1) * \
        _Factlist[l_1 - m_1] * _Factlist[l_1 + m_1] * _Factlist[l_2 - m_2] * \
        _Factlist[l_2 + m_2] * _Factlist[l_3 - m_3] * _Factlist[l_3 + m_3] / \
        (4*pi)
    ressqrt = argsqrt.sqrt()

    prefac = Integer(_Factlist[bigL] * _Factlist[l_2 - l_1 + l_3] * \
                     _Factlist[l_1 - l_2 + l_3] * _Factlist[l_1 + l_2 - l_3])/ \
                     _Factlist[2 * bigL + 1] / \
                     (_Factlist[bigL - l_1] * _Factlist[bigL - l_2] * _Factlist[bigL - l_3])

    sumres = 0
    for ii in range(imin, imax + 1):
        den = _Factlist[ii] * _Factlist[ii + l_3 - l_1 - m_2] * \
            _Factlist[l_2 + m_2 - ii] * _Factlist[l_1 - ii - m_1] * \
            _Factlist[ii + l_3 - l_2 + m_1] * _Factlist[l_1 + l_2 - l_3 - ii]
        sumres = sumres + Integer((-1)**ii) / den

    res = ressqrt * prefac * sumres * (-1)**(bigL + l_3 + m_1 - m_2)
    if prec is not None:
        res = res.n(prec)
    return res