Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241852 views
�
eYc@s�dZddlmZmZmZmZmZmZmZeed�Z	ee	de	dd�a
t
j�Zet
ddd�a
d�Zd	�Zd
�Zd�Zed��Zd
�Zd�Zdd�Zd�Zdefd��YZd�Zd�Zd�Zd�Zd�Zd�Zddlm Z d�Z!d�Z"d�Z#dd9d��YZ$dd l%Z%d!e%j&d"Z'e%j'j(e'�s�e%j)e'�nee'd#e*�d$��Z+d%�Z,d&d:d'��YZ-d(�Z.d)d;d*��YZ/d+e/fd,��YZ0d-e/fd.��YZ1d/e/fd0��YZ2d1e/fd2��YZ3d3d<d4��YZ4d5d=d6��YZ5d7d>d8��YZ6d S(?s�

Toy Implementation of Hilbert Modular Forms

This file contains an incredibly slow naive toy implementation of
Dembele's quaternion algebra algorithm for computing Hilbert modular
forms of weight (2,2) and ramified or split prime level.  This is for
testing and educational purposes only.  The file sqrt5_fast.pyx
contains a dramatically faster version.  That said, figuring out the
content of this file based on the contents of Dembele's paper
"Explicit Computations of Hilbert Modular Forms on Q(sqrt(5))"
was a timing consuming and very painful task.

EXAMPLES:

LEVEL 31::

    sage: from psage.modform.hilbert.sqrt5.sqrt5 import THETA, hecke_ops, F
    sage: B.<i,j,k> = QuaternionAlgebra(F,-1,-1)
    sage: c = F.factor(31)[1][0]
    sage: P = F.primes_above(5)[0]
    sage: TH = THETA(20)        # about 1 minute
    pi = [...]
    Sorting through 22440 elements
    sage: T = hecke_ops(c, TH); T   # random output do to choice of basis
    [(5, a + 2, [1 5]
    [3 3]), (9, 3, [5 5]
    [3 7]), (11, a + 3, [ 2 10]
    [ 6  6]), (11, 2*a + 3, [7 5]
    [3 9]), (19, a + 4, [10 10]
    [ 6 14]), (19, 3*a + 4, [ 5 15]
    [ 9 11])]
    sage: for nm,p,t in T:
    ...       print nm, p, t.charpoly().factor()
    5 a + 2 (x - 6) * (x + 2)
    9 3 (x - 10) * (x - 2)
    11 a + 3 (x - 12) * (x + 4)
    11 2*a + 3 (x - 12) * (x - 4)
    19 a + 4 (x - 20) * (x - 4)
    19 3*a + 4 (x - 20) * (x + 4)

LEVEL 41::

    sage: from psage.modform.hilbert.sqrt5.sqrt5 import THETA, hecke_ops, F
    sage: B.<i,j,k> = QuaternionAlgebra(F,-1,-1)
    sage: F.primes_above(41)
    [Fractional ideal (a - 7), Fractional ideal (a + 6)]
    sage: c = F.primes_above(41)[0]
    sage: TH = THETA(11)    # about 30 seconds
    pi = [...]
    Sorting through 6660 elements
    sage: T = hecke_ops(c, TH); T   # random output do to choice of basis
    [(5, a + 2, [4 2]
    [5 1]), (9, 3, [ 6  4]
    [10  0]), (11, a + 3, [10  2]
    [ 5  7]), (11, 2*a + 3, [ 8  4]
    [10  2])]
    sage: for nm,p,t in T:
    ...         print nm, p, t.charpoly().factor()
    5 a + 2 (x - 6) * (x + 1)
    9 3 (x - 10) * (x + 4)
    11 a + 3 (x - 12) * (x - 5)
    11 2*a + 3 (x - 12) * (x + 2)
    

LEVEL 389!:

This relies on having TH from above (say from the level 31 block above)::
    
    sage: F.primes_above(389)
    [Fractional ideal (18*a - 5), Fractional ideal (-18*a + 13)]
    sage: c = F.primes_above(389)[0]
    sage: T = hecke_ops(c, TH)
    sage: for nm,p,t in T:
    ...       print nm, p, t.charpoly().factor()
    5 a + 2 (x - 6) * (x^2 + 4*x - 1) * (x^2 - x - 4)^2
    9 3 (x - 10) * (x^2 + 3*x - 9) * (x^4 - 5*x^3 + 3*x^2 + 6*x - 4)
    11 a + 3 (x - 12) * (x + 3)^2 * (x^4 - 17*x^2 + 68)
    11 2*a + 3 (x - 12) * (x^2 + 5*x + 5) * (x^4 - x^3 - 23*x^2 + 18*x + 52)
i����(tNumberFieldtpolygentQQtZZtQuaternionAlgebratcached_functiontdisk_cached_functiontxiitasi,j,kc
Cs<|j�tj�kr$td�n|j�s<td�nt|j�k	r^tdt�n|j�}ddlm}||d�}tj	�\}}||�}||�}|j
�dkr|dks�|dkr�t�n|ddddg�|ddddg�fS|d|ddg�}d|}d
}xOt
|�D]A}	|	s[qIn|||	|	}
|
j�rI|
j�}PqIqIW|d
kr�xI|D]>}||}|||kr�|||kr�|||fSq�Wn|||	||||	|g�}||}|||ks2td	��||fS(s�
    INPUT:
        
        - p -- ideal of the number field K = B.base() with ring O of integers.
        
    OUTPUT:
        
        - matrices I, J in M_2(O/p) such that i |--> I and j |--> J defines 
          an algebra morphism, i.e., I^2=a, J^2=b, I*J=-J*I.

    EXAMPLES::    

        sage: from psage.modform.hilbert.sqrt5.sqrt5 import F, B, modp_splitting
        sage: c = F.factor(31)[0][0]
        sage: modp_splitting(c)
        (
        [ 0 30]  [18  4]
        [ 1  0], [ 4 13]
        )
        sage: c = F.factor(37)[0][0]; c
        Fractional ideal (37)
        sage: I, J = modp_splitting(c); I, J
        (
        [ 0 36]  [23*abar + 21  36*abar + 8]
        [ 1  0], [ 36*abar + 8 14*abar + 16]
        )
        sage: I^2
        [36  0]
        [ 0 36]
        sage: J^2
        [36  0]
        [ 0 36]
        sage: I*J == -J*I
        True

    AUTHOR: William Stein
    sCp must be a prime ideal in the base field of the quaternion algebrasp must be primesp must be a prime of %si����(tMatrixSpaceiiis"bug in that I,J don't skew commuteN(tnumber_fieldtBtbaset
ValueErrortis_primetFt
residue_fieldtsage.allR	t
invariantstcharacteristictNotImplementedErrortNonetlistt	is_squaretsqrttAssertionError(
tptkR	tMti2tj2tIti2invRtbtctJtK((s$psage/modform/hilbert/sqrt5/sqrt5.pytmodp_splittingosF*	.



!%
cs7t|�\��|j�����fd�}|S(s
    Return a map from subset of B to 2x2 matrix space isomorphic
    to R tensor OF/p.

    INPUT:
        - `B` -- quaternion algebra over F=Q(sqrt(5))
          with invariants -1, -1.
        - `p` -- prime ideal of F=Q(sqrt(5))

    EXAMPLES::

        sage: from psage.modform.hilbert.sqrt5.sqrt5 import F, B, modp_splitting_map
        sage: i,j,k = B.gens()
        sage: theta = modp_splitting_map(F.primes_above(5)[0])
        sage: theta(i + j - k)
        [2 1]
        [3 3]
        sage: s = 2 + 3*i - 2*j - 2*k
        sage: theta(s)
        [1 3]
        [4 3]
        sage: s.reduced_characteristic_polynomial()
        x^2 - 4*x + 21
        sage: theta(s).charpoly()
        x^2 + x + 1
        sage: s.reduced_characteristic_polynomial().change_ring(GF(5))
        x^2 + x + 1
        sage: theta = modp_splitting_map(F.primes_above(3)[0])
        sage: smod = theta(s); smod
        [2*abar + 1   abar + 1]
        [  abar + 1       abar]
        sage: smod^2 - 4*smod + 21
        [0 0]
        [0 0]    
    csH�|d���|d���|d����|d�S(Niiii((R(RRR#(s$psage/modform/hilbert/sqrt5/sqrt5.pytf�s(R%R(RR&((RRR#s$psage/modform/hilbert/sqrt5/sqrt5.pytmodp_splitting_map�s$c	CsXtj�}dtj�}gdddddd||fgD]}t|�d^q>S(	s�
    Return generators of the icosian group, as elements of the 
    Hamilton quaternion algebra B over Q(sqrt(5)).
    
    AUTHOR: William Stein

    EXAMPLES::
    
        sage: from psage.modform.hilbert.sqrt5.sqrt5 import icosian_gens
        sage: icosian_gens()
        [i, j, k, -1/2 + 1/2*i + 1/2*j + 1/2*k, 1/2*i + 1/2*a*j + (-1/2*a + 1/2)*k]
        sage: [a.reduced_norm() for a in icosian_gens()]
        [1, 1, 1, 1, 1]
    iiii����(iiii(iiii(iiii(i����iii(RtgenR(tomegat	omega_bartv((s$psage/modform/hilbert/sqrt5/sqrt5.pyticosian_gens�s	cCsJddlm}m}g}t�}|td��}|gdddddgD]}td|�^qP�}x�|D]�}x�|D]�}||d|d}	||d|d}
||d|d}||d|d}||d|d}
|	|
|||
}||kr�|j|�q�q�Wt|�d	kru|SquWd
S(s
    Return a list of the elements of the Icosian group of order 120,
    which we compute by generating enough products of icosian
    generators.
    
    EXAMPLES::

        sage: from psage.modform.hilbert.sqrt5.sqrt5 import compute_all_icosians, all_icosians
        sage: v = compute_all_icosians()
        sage: len(v)
        120
        sage: v
        [1/2 + 1/2*a*i + (-1/2*a + 1/2)*k, 1/2 + (-1/2*a + 1/2)*i + 1/2*a*j,..., -k, i, j, -i]
        sage: assert set(v) == set(all_icosians())  # double check
    i����(tpermutationstcartesian_product_iteratoriiiiiiixN(RR-R.R,trangetappendtlen(R-R.tIcostigtpertitexpR&Rte0te1te2te3te4telt((s$psage/modform/hilbert/sqrt5/sqrt5.pytcompute_all_icosianss"	7

cCs�d}t|itj�d6tjd�d6tjd�d6tjd�tjd�d6�}g|D]}t|�td�^qfS(	s�
    Return a list of all 120 icosians, from a precomputed table.

    EXAMPLES::

    sage: from psage.modform.hilbert.sqrt5.sqrt5 import all_icosians
    sage: v = all_icosians()
    sage: len(v)
    120
    s[1+a*i+(-a+1)*k,1+(-a+1)*i+a*j,-a+i+(a-1)*j,1+(-a)*i+(-a+1)*k,-a-j+(-a+1)*k,1+(a-1)*i+(-a)*j,-1+(-a)*i+(a-1)*k,-1+(a-1)*i+(-a)*j,-a+1+(-a)*j-k,-1+a*i+(-a+1)*k,-a+1+i+(-a)*k,-1+(-a+1)*i+(-a)*j,(-a+1)*i+j+(-a)*k,a-1+(-a)*j+k,(a-1)*i-j+a*k,a+i+(-a+1)*j,1+a*i+(a-1)*k,-1+(-a)*i+(-a+1)*k,a*i+(-a+1)*j-k,a-1+i+a*k,(-a)*i+(a-1)*j+k,a+j+(-a+1)*k,1+(-a+1)*i+(-a)*j,-1+(a-1)*i+a*j,a-i+(-a+1)*j,-1+a*i+(a-1)*k,a+j+(a-1)*k,-1+(-a+1)*i+a*j,(-a+1)*i+j+a*k,a-1+a*j+k,-a+i+(-a+1)*j,1+(-a)*i+(a-1)*k,a*i+(-a+1)*j+k,a-1-i+a*k,-a+j+(a-1)*k,1+(a-1)*i+a*j,(a-1)*i+j+a*k,-a+1+a*j+k,(-a)*i+(-a+1)*j+k,-a+1+i+a*k,-a-i+(-a+1)*j,-a+1+(-a)*j+k,(-a+1)*i-j+a*k,(a-1)*i+j+(-a)*k,a+i+(a-1)*j,a-1+a*j-k,-a+j+(-a+1)*k,-a+1-i+a*k,a*i+(a-1)*j+k,(-a)*i+(-a+1)*j-k,a-j+(a-1)*k,a-1+i+(-a)*k,-1+i+j+k,-1-i-j+k,1-i-j-k,1+i-j+k,a-j+(-a+1)*k,-1+i-j-k,1-i+j+k,(a-1)*i-j+(-a)*k,-a-j+(a-1)*k,1+i+j-k,a*i+(a-1)*j-k,-1-i+j-k,a-1+(-a)*j-k,-a+1+a*j-k,(-a)*i+(a-1)*j-k,-a+1-i+(-a)*k,-a-i+(a-1)*j,a-1-i+(-a)*k,(-a+1)*i-j+(-a)*k,a-i+(a-1)*j,-i+(-a)*j+(a-1)*k,i+a*j+(a-1)*k,i+a*j+(-a+1)*k,-i+a*j+(a-1)*k,-i+a*j+(-a+1)*k,i+(-a)*j+(a-1)*k,-i+(-a)*j+(-a+1)*k,i+(-a)*j+(-a+1)*k,-1-i-j-k,1+i+j+k,2,-a+1+a*i-j,-2,-a+(-a+1)*i-k,a-1+a*i+j,a+(-a+1)*i+k,a-1+(-a)*i+j,1+(-a+1)*j+(-a)*k,-a+1+a*i+j,-1+(-a+1)*j+a*k,a+(a-1)*i+k,-1+(a-1)*j+a*k,-a+(-a+1)*i+k,1+(-a+1)*j+a*k,-a+1+(-a)*i+j,-a+(a-1)*i+k,a-1+a*i-j,1+(a-1)*j+a*k,a+(-a+1)*i-k,-1+(-a+1)*j+(-a)*k,-a+1+(-a)*i-j,-a+(a-1)*i-k,a-1+(-a)*i-j,1+(a-1)*j+(-a)*k,a+(a-1)*i-k,-1+(a-1)*j+(-a)*k,-1+i+j-k,1-i+j-k,1-i-j+k,-1-i+j+k,-1+i-j+k,1+i-j-k,2*k,(-2)*j,(-2)*k,2*i,2*j,(-2)*i]RiR5itjRi(tevalRR(R(tsR+R((s$psage/modform/hilbert/sqrt5/sqrt5.pytall_icosians'sYcCs}tj�}dtj�}gd||dfd|d|fd||dfdd||fgD]}t|�d^qcS(s�
    Return ring generators for the icosian ring (a maximal order) in the
    quaternion algebra ramified only at infinity over F=Q(sqrt(5)).
    These are generators over the ring of integers of F.

    OUTPUT:

       - list

    EXAMPLES::

        sage: from psage.modform.hilbert.sqrt5.sqrt5 import icosian_ring_gens
        sage: icosian_ring_gens()
        [1/2 + (1/2*a - 1/2)*i + 1/2*a*j, (1/2*a - 1/2)*i + 1/2*j + 1/2*a*k, 1/2*a*i + (1/2*a - 1/2)*j + 1/2*k, 1/2*i + 1/2*a*j + (1/2*a - 1/2)*k]
    iii(RR(R(R)R*R+((s$psage/modform/hilbert/sqrt5/sqrt5.pyticosian_ring_gens8scCs4t�}tj�}|g|D]}||^qS(s!
    Return basis over ZZ for the icosian ring, which has ZZ-rank 8.

    EXAMPLES::
    
        sage: from psage.modform.hilbert.sqrt5.sqrt5 import icosian_ring_gens_over_ZZ
        sage: v = icosian_ring_gens_over_ZZ(); v
        [1/2 + (1/2*a - 1/2)*i + 1/2*a*j, (1/2*a - 1/2)*i + 1/2*j + 1/2*a*k, 1/2*a*i + (1/2*a - 1/2)*j + 1/2*k, 1/2*i + 1/2*a*j + (1/2*a - 1/2)*k, 1/2*a + 1/2*i + (1/2*a + 1/2)*j, 1/2*i + 1/2*a*j + (1/2*a + 1/2)*k, (1/2*a + 1/2)*i + 1/2*j + 1/2*a*k, 1/2*a*i + (1/2*a + 1/2)*j + 1/2*k]
        sage: len(v)
        8
    (RBRR((RR)R((s$psage/modform/hilbert/sqrt5/sqrt5.pyticosian_ring_gens_over_ZZSs
	i5csNddlm}|d|�}|d�tj|����fd�}|S(s�
    Return map from the quaternion algebra B to the tensor product of
    B over QQ with RealField(prec), viewed as an 8-dimensional real
    vector space.

    INPUT:
        - prec -- (integer: default 53); bits of real precision 

    OUTPUT:
        - a Python function

    EXAMPLES::

        sage: from psage.modform.hilbert.sqrt5.sqrt5 import tensor_over_QQ_with_RR, B
        sage: f = tensor_over_QQ_with_RR()
        sage: B.gens()
        [i, j, k]
        sage: f(B.0)
        (0.000000000000000, 1.00000000000000, 0.000000000000000, 0.000000000000000, 0.000000000000000, 1.00000000000000, 0.000000000000000, 0.000000000000000)
        sage: f(B.1)
        (0.000000000000000, 0.000000000000000, 1.00000000000000, 0.000000000000000, 0.000000000000000, 0.000000000000000, 1.00000000000000, 0.000000000000000)
        sage: f = tensor_over_QQ_with_RR(20)
        sage: f(B.0 - (1/9)*B.1)
        (0.00000, 1.0000, -0.11111, 0.00000, 0.00000, 1.0000, -0.11111, 0.00000)
    i����(t	RealFieldtprecics?�tg�D]%}g|D]}||�^q^q
g��S(N(tsum(RtsigmaR(tStV(s$psage/modform/hilbert/sqrt5/sqrt5.pyR&�s(RRDRt
embeddings(RERDtRRR&((RHRIs$psage/modform/hilbert/sqrt5/sqrt5.pyttensor_over_QQ_with_RRds
cCs�t|�\}}||}|j�}gt�D]L}||d�||d�|||d�|||d�|^q2}ddlm}g||�D]}|j�^q�S(s/
    Return matrices of images of all 120 icosians modulo p.

    INPUT:
        - p -- *split* or ramified prime ideal of real quadratic field F=Q(sqrt(5))

    OUTPUT:
        - list of matrices modulo p.

    EXAMPLES::

        sage: from psage.modform.hilbert.sqrt5.sqrt5 import F, modp_icosians
        sage: len(modp_icosians(F.primes_above(5)[0]))
        120
        sage: v = modp_icosians(F.primes_above(11)[0])
        sage: len(v)
        120
        sage: v[0]
        [10  8]
        [ 8  1]
        sage: v[-1]
        [0 3]
        [7 0]
    iiiii����(tMatrixGroup(R%RR,RRMtmatrix(RRR#R$RtgtGRM((s$psage/modform/hilbert/sqrt5/sqrt5.pyt
modp_icosians�s
\t	P1ModListcBsMeZdZd�Zd�Zd�Zd�Zd�Zd�Zd�Z	RS(s3
    Object the represents the elements of the projective line modulo
    a nonzero *prime* ideal of the ring of integers of Q(sqrt(5)).

    Elements of the projective line are represented by elements of a 2-dimension
    vector space over the residue field.

    EXAMPLES::

    We construct the projective line modulo the ideal (2), and illustrate
    all the standard operations with it::
    
        sage: from psage.modform.hilbert.sqrt5.sqrt5 import F, P1ModList
        sage: P1 = P1ModList(F.primes_above(2)[0]); P1
        Projective line over Residue field in abar of Fractional ideal (2)
        sage: len(P1)
        5
        sage: list(P1)
        [(0, 1), (1, 0), (1, abar), (1, abar + 1), (1, 1)]
        sage: P1.random_element()   # random output
        (1, abar + 1)
        sage: z = P1.random_element(); z   # random output
        (1, 0)
        sage: z[0].parent()
        Residue field in abar of Fractional ideal (2)
        sage: g = z[0].parent().gen()
        sage: P1.normalize((g,g))
        (1, 1)
        sage: P1((g,g))
        (1, 1)
    cCs�||_|j�}|d}||_||_|ddg�gg|D]}|d|g�^qJ|_x|jD]}|j�qvWdS(s8
        INPUT:
           - c -- a nonzero prime of the ring of integers of Q(sqrt(5))

        EXAMPLES::

            sage: from psage.modform.hilbert.sqrt5.sqrt5 import F, P1ModList
            sage: P1ModList(F.primes_above(3)[0])
            Projective line over Residue field in abar of Fractional ideal (3)
            sage: P1ModList(F.primes_above(11)[1])
            Projective line over Residue field of Fractional ideal (3*a - 1)
            sage: list(P1ModList(F.primes_above(5)[0]))
            [(0, 1), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4)]
        iiiN(t_cRt_Vt_Ft_listt
set_immutable(tselfR"RRIR((s$psage/modform/hilbert/sqrt5/sqrt5.pyt__init__�s	
		;cCsddl}|j|j�S(sq
        Return a random element of this projective line.

            sage: from psage.modform.hilbert.sqrt5.sqrt5 import F, P1ModList
            sage: P1 = P1ModList(F.primes_above(13)[0]); P1
            Projective line over Residue field in abar of Fractional ideal (13)
            sage: P1.random_element()   # random output
            (1, 10*abar + 5)
        i����N(trandomtchoiceRV(RXRZ((s$psage/modform/hilbert/sqrt5/sqrt5.pytrandom_element�s
cCsE|j|�}|dr6|d|}|j�|S|jdSdS(sI
        Normalize a representative element so it is either of the form
        (1,*) if the first entry is nonzero, or of the form (0,1)
        otherwise.

        EXAMPLES::

            sage: from psage.modform.hilbert.sqrt5.sqrt5 import F, P1ModList
            sage: p = F.primes_above(13)[0]
            sage: P1 = P1ModList(p)
            sage: k = p.residue_field()
            sage: g = k.gen()
            sage: P1.normalize([3,4])
            (1, 10)
            sage: P1.normalize([g,g])
            (1, 1)
            sage: P1.normalize([0,g])
            (0, 1)
        iN(RTRWRV(RXtuvtw((s$psage/modform/hilbert/sqrt5/sqrt5.pyt	normalize�s

cCs
t|j�S(s�
        Return number of elements of this P1.

        EXAMPLES::

            sage: from psage.modform.hilbert.sqrt5.sqrt5 import F, P1ModList
            sage: len(P1ModList(F.primes_above(3)[0]))
            10
            sage: len(P1ModList(F.primes_above(5)[0]))
            6
            sage: len(P1ModList(F.primes_above(19)[0]))
            20
            sage: len(P1ModList(F.primes_above(19)[1]))
            20
        (R1RV(RX((s$psage/modform/hilbert/sqrt5/sqrt5.pyt__len__scCs|j|S(s{
        Return i-th element.

        EXAMPLES::

            sage: from psage.modform.hilbert.sqrt5.sqrt5 import F, P1ModList
            sage: P = P1ModList(F.primes_above(3)[0]); list(P)
            [(0, 1), (1, 0), (1, 2*abar), (1, abar + 1), (1, abar + 2), (1, 2), (1, abar), (1, 2*abar + 2), (1, 2*abar + 1), (1, 1)]
            sage: P[2]
            (1, 2*abar)
        (RV(RXR5((s$psage/modform/hilbert/sqrt5/sqrt5.pyt__getitem__scCs
|j|�S(sw
        Coerce x into this P1 list. Here x is anything that coerces to
        the 2-dimensional vector space over the residue field.  The
        result is normalized (in fact this function is just an alias
        for the normalize function).

        EXAMPLES::

            sage: from psage.modform.hilbert.sqrt5.sqrt5 import F, P1ModList
            sage: p = F.primes_above(13)[0]
            sage: k = p.residue_field(); g = k.gen()
            sage: P1 = P1ModList(p)
            sage: P1([3,4])
            (1, 10)
            sage: P1([g,g])
            (1, 1)
            sage: P1(P1([g,g]))
            (1, 1)
        (R_(RXR((s$psage/modform/hilbert/sqrt5/sqrt5.pyt__call__(scCsd|jS(s
        EXAMPLES::
        
            sage: from psage.modform.hilbert.sqrt5.sqrt5 import F, P1ModList
            sage: P1ModList(F.primes_above(19)[1]).__repr__()
            'Projective line over Residue field of Fractional ideal (-4*a + 3)'
        sProjective line over %s(RU(RX((s$psage/modform/hilbert/sqrt5/sqrt5.pyt__repr__>s(
t__name__t
__module__t__doc__RYR\R_R`RaRbRc(((s$psage/modform/hilbert/sqrt5/sqrt5.pyRR�s		
				c	st|��t|�}�fd�}�j�}|g}i||6}x�t|�t��krx9|D]1}|||�}|j|�sk|||<qkqkWt|�t��krLxFtr��j�}||kr�|}|j|�|||<Pq�q�WqLqLW||�fS(s�
    INPUT:
       - p -- a split or ramified prime of the integers of Q(sqrt(5)).

    OUTPUT:
        - ``orbits`` -- dictionary mapping elements of P1 to a choice of orbit rep
        - ``reps`` -- list of representatives for the orbits
        - ``P1`` -- the P1ModList object

    AUTHOR: William Stein

    EXAMPLES::

        sage: from psage.modform.hilbert.sqrt5.sqrt5 import P1_orbits, F
        sage: orbits, reps, P1 = P1_orbits(F.primes_above(5)[0])
        sage: orbits   # random output
        {(1, 2): (1, 0), (0, 1): (1, 0), (1, 3): (1, 0), (1, 4): (1, 0), (1, 0): (1, 0), (1, 1): (1, 0)}
        sage: reps   # random output
        [(1, 1)]
        sage: len(reps)
        1
        sage: P1
        Projective line over Residue field of Fractional ideal (2*a - 1)
        sage: orbits, reps, P1 = P1_orbits(F.primes_above(41)[0])
        sage: reps   # random output
        [(1, 40), (1, 5)]
        sage: len(reps)
        2
    cs�||�S(N((tutt(tP1(s$psage/modform/hilbert/sqrt5/sqrt5.pytactls(RRRQR\R1thas_keytTrueR0(	RtICORjtcurtrepstorbitsRgR@R"((Ris$psage/modform/hilbert/sqrt5/sqrt5.pyt	P1_orbitsIs( 	

	

cCs�t|�}t|�}g}x�td�|D��t|�kr�|j�}t}x$|D]}||kr\t}Pq\q\W|r�q!ntg|D]}|||�^q��}|j|�q!W|S(s�
    INPUT:
        - p -- a split or ramified prime of the integers of Q(sqrt(5)).

    OUTPUT:
        - list of disjoint sets of elements of P1 that are orbits

    AUTHOR: William Stein

    EXAMPLES::

        sage: from psage.modform.hilbert.sqrt5.sqrt5 import P1_orbits2, F
        sage: P1_orbits2(F.primes_above(5)[0])  # random output
        [set([(1, 2), (0, 1), (1, 3), (1, 4), (1, 0), (1, 1)])]
        sage: P1_orbits2(F.primes_above(11)[0])  # random output
        [set([(0, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 8), (1, 6), (1, 9), (1, 7), (1, 10), (1, 0), (1, 1)])]
        sage: len(P1_orbits2(F.primes_above(41)[0]))
        2
    css|]}t|�VqdS(N(R1(t.0R((s$psage/modform/hilbert/sqrt5/sqrt5.pys	<genexpr>�s(	RRRQRFR1R\tFalseRltsetR0(RRiRmRpR+tskiptORO((s$psage/modform/hilbert/sqrt5/sqrt5.pyt
P1_orbits2�s%
)c
Cs|j�}|j�dkr0|j�dks6t�|j�}t|�dkr`td�n|d}ddlm}|j	|�}g|D]}||�^q�}|j
�jd�}g|D]}||�^q�}	|	ddkr	|	ddkr	|d9}n|ddkr.|ddkr.|S|ddkr�|ddkr�|	ddkrv|	ddkrv||Std�ny|ddkr�|ddkr�|S|ddkr�|ddkr�|	ddkr�|	ddkr�||Std�nts
td��d	S(
s
    Given a prime ideal p of a narrow class number 1 real quadratic
    field, return a totally positive generator for p.

    INPUT:
        - p -- prime ideal of narrow class number 1 real
          quadratic field

    OUTPUT:
        - generator of p that is totally positive

    AUTHOR: William Stein

    EXAMPLES::
    
        sage: from psage.modform.hilbert.sqrt5.sqrt5 import F, totally_pos_gen
        sage: g = totally_pos_gen(F.factor(19)[0][0]); g
        3*a + 4
        sage: g.norm()
        19
        sage: g.complex_embeddings()
        [2.14589803375032, 8.85410196624968]

        sage: for p in primes(14):
        ...       for P, e in F.factor(p):
        ...           g = totally_pos_gen(P)
        ...           print P, g, g.complex_embeddings()
        Fractional ideal (2) 2 [2.00000000000000, 2.00000000000000]
        Fractional ideal (3) 3 [3.00000000000000, 3.00000000000000]
        Fractional ideal (2*a - 1) a + 2 [1.38196601125011, 3.61803398874989]
        Fractional ideal (7) 7 [7.00000000000000, 7.00000000000000]
        Fractional ideal (3*a - 2) a + 3 [2.38196601125011, 4.61803398874989]
        Fractional ideal (3*a - 1) 2*a + 3 [1.76393202250021, 6.23606797749979]
        Fractional ideal (13) 13 [13.0000000000000, 13.0000000000000]
    iiisideal not principali����(RKsno totally positive generatortbugN(
R
tdegreetdiscriminantRtgens_reducedR1R
RRKRJt
unit_groupR(Rs(
RRRPRORKRGR@teRgtue((s$psage/modform/hilbert/sqrt5/sqrt5.pyttotally_pos_gen�s4$*
 
      	cCssgtd�D]C}gtd�D]*}||||j�j�j�^q ^q
}ddlm}|t|�S(s.
    Return 8x8 Gram matrix of maximal order defined by R, which is assumed to be
    a basis for maximal order over ZZ.

    EXAMPLES::

        sage: from psage.modform.hilbert.sqrt5.sqrt5 import icosian_ring_gens_over_ZZ, gram_matrix_of_maximal_order
        sage: R = icosian_ring_gens_over_ZZ()
        sage: gram_matrix_of_maximal_order(R)
        [4 2 2 1 2 1 1 3]
        [2 4 1 1 1 2 3 3]
        [2 1 4 1 1 3 2 3]
        [1 1 1 4 3 3 3 2]
        [2 1 1 3 6 3 3 4]
        [1 2 3 3 3 6 4 4]
        [1 3 2 3 3 4 6 4]
        [3 3 3 2 4 4 4 6]
    ii����(RN(R/t	conjugatet
reduced_tracettraceRRNR(tRR>R5RPRN((s$psage/modform/hilbert/sqrt5/sqrt5.pytgram_matrix_of_maximal_order�sScCsWd}xJ|dkrRy|jd|d|�SWq	tk
rN|d8}q	Xq	WdS(s�
    Call the PARI qfminim method on qf and 2*N, with smaller and
    and smaller search range, until a MemoryError is *not* raised.
    On a large-memory machine this will succeed the first time.

    EXAMPLES::

        sage: from psage.modform.hilbert.sqrt5.sqrt5 import icosian_ring_gens_over_ZZ, gram_matrix_of_maximal_order
        sage: R = icosian_ring_gens_over_ZZ()
        sage: G = gram_matrix_of_maximal_order(R)
        sage: qf = pari(G)
        sage: from psage.modform.hilbert.sqrt5.sqrt5 import icosian_ring_gens_over_ZZ, gram_matrix_of_maximal_order, qfminim
        sage: n, m, v = qfminim(qf, 2)
        sage: n
        120
        sage: m
        4
        sage: v[0]
        [0, 0, 0, -1, 1, 0, 0, 0]~
    i i
iiN(tqfminimtMemoryError(tqftNR5((s$psage/modform/hilbert/sqrt5/sqrt5.pyR�s
cs�t��t��}ddlm}||�}t||�}|dj�j�}g}xPt|j��D]<}||�|j	t
��fd�td�D���qoW|S(s�
    Return elements in maximal order of B that have reduced norm
    whose trace is at most N.

    EXAMPLES::

        sage: from psage.modform.hilbert.sqrt5.sqrt5 import bounded_elements
        sage: X = bounded_elements(3)
        sage: len(X)
        180
        sage: rnX = [a.reduced_norm() for a in X]
        sage: set([a.trace() for a in rnX])
        set([2, 3])
        sage: set([a.norm() for a in rnX])
        set([1])
        sage: X = bounded_elements(5)
        sage: len(X)
        1200
        sage: rnX = [a.reduced_norm() for a in X]
        sage: set([a.trace() for a in rnX])
        set([2, 3, 4, 5])
        sage: set([a.norm() for a in rnX])
        set([1, 4, 5])    
    i����(tpariic3s!|]}�|�|VqdS(N((RrR>(R�R^(s$psage/modform/hilbert/sqrt5/sqrt5.pys	<genexpr>Qsi(RCR�RR�R�tsaget	transposeR/tnrowsR0RF(R�RPR�R�tZtZ2RIR5((R�R^s$psage/modform/hilbert/sqrt5/sqrt5.pytbounded_elements"s	
0(tprimes_of_bounded_normcCsgt|�}g|D]}t|�^q}dG|GHg|D]}t|j��^q;}t|�}t|�}i}x.t|�D] \}}t|�|||<q�Wt|�}	|	j	d�i}
x|	D]}i|
|<q�Wdt
|�GHxo|D]g}|j�}
|
|	kr�||
|�j�j
�d}|
|
}|j|�rRq_|||<q�q�W|
S(se
    Return representative elements of the maximal order of `R` of
    reduced norm `\pi_p` up to `N` modulo the left action of the units
    of `R` (the icosians).  Here `\pi_p` runs through totally positive
    generators of the odd prime ideals with norm up to `N`.

    INPUT:
        - `N` -- a positive integer >= 4.

    OUTPUT:
        - dictionary with keys the totally positive generators of the
          odd prime ideals with norm up to and including `N`, and values
          a dictionary with values the actual elements of reduced norm
          `\pi_p`.

    AUTHOR: William Stein

    EXAMPLES::

        sage: from psage.modform.hilbert.sqrt5.sqrt5 import THETA
        sage: d = THETA(9)
        pi = [2, a + 2, 3]
        Sorting through 2400 elements
        sage: d.keys()
        [a + 2, 3]
        sage: d[3]
        {(0, 1): a + 1/2*i + (-1/2*a + 1)*j + (-1/2*a + 1/2)*k, (1, 2): a - 1 + a*j, (1, abar): a - 1/2 + (1/2*a + 1/2)*i + (-1/2*a + 1)*j, (1, abar + 1): a - 1/2 + 1/2*i + 1/2*j + (-a + 1/2)*k, (1, abar + 2): a - 1 + (1/2*a + 1/2)*i + 1/2*j + (-1/2*a)*k, (1, 2*abar + 2): a - 1 + 1/2*a*i + (1/2*a + 1/2)*j + 1/2*k, (1, 2*abar): a - 1/2 + i + (-1/2*a + 1/2)*j + (-1/2*a)*k, (1, 2*abar + 1): a - 1/2 + (-1/2*a)*i + j + (-1/2*a + 1/2)*k, (1, 0): a + (-a + 1)*k, (1, 1): a - 1/2 + 1/2*a*i + j + (-1/2*a + 1/2)*k}
        sage: k = d[3].keys(); k
        [(0, 1), (1, 2), (1, abar), (1, abar + 1), (1, abar + 2), (1, 2*abar + 2), (1, 2*abar), (1, 2*abar + 1), (1, 0), (1, 1)]
        sage: d[3][k[0]]
        a + 1/2*i + (-1/2*a + 1)*j + (-1/2*a + 1/2)*k
        sage: d[3][k[0]].reduced_norm()
        3
    spi =isSorting through %s elementsi(R�RtabsR�tmaxR�t	enumerateR'RttremoveR1treduced_normR�techelon_formRk(R�RHRtpiRttrtXt	theta_mapR5tpi_settThetatpi_pRtnrmR+tz((s$psage/modform/hilbert/sqrt5/sqrt5.pytTHETAVs06	%


 
cs~t|�\���t|�������fd�}g�j�D]!}|j�|||�f^qI}|j�|S(Ncs��|}g}x��D]�}dgt��}x`|j�D]R\}}�|�}|d|}��j|�}	|�j|	�cd7<q=W|j|�qWddlm}
|
t|�S(Nii����i(RN(R1t	iteritemsR_tindexR0RRNR(R�R�tmatRtrowt_R^tw_ctyty_redRN(RiR�RpRottheta_c(s$psage/modform/hilbert/sqrt5/sqrt5.pytTp�s

(RqR'tkeystnormtsort(R"R�R�R�tans((RiR�RpRoR�s$psage/modform/hilbert/sqrt5/sqrt5.pyt	hecke_ops�s
4
cs~t|�\���t|�������fd�}g�j�D]!}|j�|||�f^qI}|j�|S(Ncs�|}g}x��D]�}d|tg�j�D]}�||kr3|^q3�fGHdgt��}xo|j�D]a\}}�|�}|d|}	dG|	GH��|	�}
|�j|
�cd7<dG|
GHq{W|j|�qWddlm}|t|�S(Nsx = %s,  card = %sii����sy =isy_red =(RN(R1R�R�R�R0RRNR(R�R�R�RRR�R�R^R�R�R�RN(RiR�treduceRoR�(s$psage/modform/hilbert/sqrt5/sqrt5.pyR��s

>	
(RqR'R�R�R�(R"R�R�R�R�((RiR�R�RoR�s$psage/modform/hilbert/sqrt5/sqrt5.pyt
hecke_ops2�s4
tAlphaZcBsPeZd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Z	RS(cCszt�|_||_|j�|_t|�|_|j�|_t	|j�}g|jD]}||�^q[|_
dS(s 
        Computing elements with norm pi, where P=(pi).

        INPUT:
            - P - a prime of O_F

        OUTPUT:
            - element alpha in B with norm pi
              whose image via the mod-p splitting map
              has column echelon form with first column z
        N(RCtR_ZtPtsmallest_integerRRR�tresidue_class_degreetdegR'tn(RXR�R&RO((s$psage/modform/hilbert/sqrt5/sqrt5.pyRY�s	cCs�|j}|jdkrn|dj�j�}|d}|d}|jg|D]}||j��^qO�Sddlm}||j�}|d}|d}|jg|D]@}|t	g|j�D]}|j
�j�^q�g��^q��SdS(Niiiii����(tGF(R�R�tparentt	base_ringthomRRR�RRFt_vector_(RXR�RtWRIRR�R�((s$psage/modform/hilbert/sqrt5/sqrt5.pyt	local_maps	

,

cCs|j�}|j�}|j�}|jdkr�||dd|ddg�}|d|dd|dg�}|j||g�}n�|j}|dj�}	|	j�j�}
|	|dd|ddg�}|
|}|	d|dd|dg�}|
|}||||g}|jg|D]@}
|tg|
j	�D]}|j
�j	�^qBg��^q)�}|j|�S(sD
        INPUT:
            - z - an element of P^1(O_F/p).
        ii(R�tcodomainR�tspanR�R�R�R(RFRR�t
inverse_image(RXR�tAtphiRItg0tg1R�R�tM2Rtg2tg3RR�((s$psage/modform/hilbert/sqrt5/sqrt5.pytideal_mod_ps"  	 
 
VcCsf|j|�}|j�j�}ddlm}|j}|j||td��}|j�}|S(Ni����(tidentity_matrixi(	R�tbasis_matrixtliftRR�RtstackRt
row_module(RXR�tImodR�R�RRRI((s$psage/modform/hilbert/sqrt5/sqrt5.pytideal+s	csT|j|�}|j�g|j�D]+�t��fd�td�D��^q%S(Nc3s!|]}�|�|VqdS(N((RrR5(R�RO(s$psage/modform/hilbert/sqrt5/sqrt5.pys	<genexpr>7si(R�R�tgensRFR/(RXR�R#((R�ROs$psage/modform/hilbert/sqrt5/sqrt5.pytideal_basis4s	cCssgtd�D]C}gtd�D]*}||||j�j�j�^q ^q
}ddlm}|t|�S(Nii����(RN(R/R�R�R�RRNR(RXR�R>R5RPRN((s$psage/modform/hilbert/sqrt5/sqrt5.pyt
ideal_gram9sScCs�|j|�}|j|�}ddlm}||�}|jj�}t||�}xh|dj�j�D]P}t	gt
d�D]}	||	||	^q��}
|
j�|jkro|
SqoWtd�dS(sD
        INPUT:
            - z - an element of P^1(O_F/P).
        i����(R�iiRxN(
R�R�RR�R�R�R�R�R�RFR/R�R
(RXR�R�RPR�R�RhR"trR5R((s$psage/modform/hilbert/sqrt5/sqrt5.pytalpha?s1cCs)gt|j�D]}|j|�^qS(N(RRR�R�(RXR�((s$psage/modform/hilbert/sqrt5/sqrt5.pyt	all_alphaQs(
RdReRYR�R�R�R�R�R�R�(((s$psage/modform/hilbert/sqrt5/sqrt5.pyR��s								Ns/tmp/hmf-%stUSERtmemory_cachecCsU|j�dkr-gt�D]
}|^qSgt|�j�D]
}|^q@SdS(Ni(R�thecke_elements_2R�R�(R�R((s$psage/modform/hilbert/sqrt5/sqrt5.pythecke_elementsZscs�tjd�d}ddlm}ddlm�||��t��|j���j������fd�}i}tj�}d}gt	||d�D]/}t	||d�D]}|||^q�q�}ddl
m}	x�|	|gd	�D]��t��fd
�t	d	�D��}
|
j
�dkr�||
�}|j|�sc|
||<nt|�dkr�g|j�D]\}}
|
^q�Sq�q�Wt�dS(Niii����(tModN_Reduction(RNcsX��dt�|�jdd�i�d6��j�}|j�d}|j�|S(Nit;t,ROi(R?treplaceR�R�RW(R�RR+(R&RORRN(s$psage/modform/hilbert/sqrt5/sqrt5.pyR�os:
i(R.ic3s!|]}�|�|VqdS(N((RrR5(RPR+(s$psage/modform/hilbert/sqrt5/sqrt5.pys	<genexpr>~si(Rtprimes_abovet
sqrt5_fastR�tsage.matrix.allRNRBRR(R/t
sage.misc.allR.RFR�RkR1R�tRuntimeError(R�R�R�R�RRR5R>R�R.R�RhR�R((RPR&RORRNR+s$psage/modform/hilbert/sqrt5/sqrt5.pyR�fs,		J%
*tHMFcBs2eZd�Zd�Zd�Zd�ZeZRS(cCsbddlm}m}||_t|�\}}}||_||_||_t|�|_	dS(Ni����(tQuadraticFieldR(
RR�Rt_NRqt_reducet_repst_P1R't_theta_N(RXR�R�RtredRoRi((s$psage/modform/hilbert/sqrt5/sqrt5.pyRY�s				cCs#d|j|jj�|j�fS(NsUSpace of Hilbert modular forms over Q(sqrt(5)) of level %s (norm=%s) and dimension %s(R�R�t	dimension(RX((s$psage/modform/hilbert/sqrt5/sqrt5.pyRc�scCs
t|j�S(N(R1R�(RX((s$psage/modform/hilbert/sqrt5/sqrt5.pyR��sc
Cs�g}t|�}|j}g|j�D]}||�d^q(}|j}|j}xu|jD]j}dgt|j�}	x>|D]6}
|||
|�}|	|jj|�cd7<q�W|j|	�q`Wddl	m
}|t|�S(Ni����ii(RN(R�R�R�R�R�R�R1R�R0RRNR(
RXR�R�R�tthetaRR�RiR�R�R^R�RN((s$psage/modform/hilbert/sqrt5/sqrt5.pythecke_matrix�s	)		
 (RdReRYRcR�R�R�(((s$psage/modform/hilbert/sqrt5/sqrt5.pyR��s
					cCs�|j�}t|�dkr*td�nddlm}|d\}}|j�}||d�}|dkr{|j�S|dkr�t||||�S|dkr�t||||�S|ddkr�t	||||�St
||||�SdS(NisP must be a prime poweri����(tkronecker_symboliii(tfactorR1Rtsage.rings.allR�R�RtResidueRing_splittResidueRing_inerttResidueRing_ramified_eventResidueRing_ramified_odd(R�tfacR�R�R}RR@((s$psage/modform/hilbert/sqrt5/sqrt5.pytresidue_ring�s 
tResidueRing_basecBs5eZd�Zd�Zd�Zd�Zd�ZRS(cCs4|j�|jk	r'|j|�}n|j|�S(N(R�RUt_to_ring(RXR((s$psage/modform/hilbert/sqrt5/sqrt5.pyRb�scCs
|jj�S(N(t_ringR(RX((s$psage/modform/hilbert/sqrt5/sqrt5.pyR�scCs)|j|d�|j|j|d�S(Nii(R�t_im_gen(RXR((s$psage/modform/hilbert/sqrt5/sqrt5.pyR��scCs|jS(N(R�(RX((s$psage/modform/hilbert/sqrt5/sqrt5.pytring�scCsd|j|jfS(NsFResidue class ring of ZZ[(1+sqrt(5))/2] modulo %s of characteristic %s(R�t_p(RX((s$psage/modform/hilbert/sqrt5/sqrt5.pyRc�s(RdReRbRR�R�Rc(((s$psage/modform/hilbert/sqrt5/sqrt5.pyR��s
				R�cBs eZdZd�Zd�ZRS(s?
    Quotient of ring of integers of F by a prime power N.
    c
Cs	||_|j�|_||_|jj�j|d|d�}t|�dks[t�g|D]}|ddj�^qb}|jj	�}||d|kr�|d}	n*||d|kr�|d}	n	t
d�tj||�|_
|j
|	�|_dS(NREiiiRx(R�R
RUR�tdefining_polynomialtfactor_padicR1RR�R(tRuntimErrorRtquotientR�R�(
RXR�R�RR}R�RtrootsR(tim_gen((s$psage/modform/hilbert/sqrt5/sqrt5.pyRY�s		"(

	cCs|j|j��S(N(RUR�(RXR((s$psage/modform/hilbert/sqrt5/sqrt5.pyR��s(RdReRfRYR�(((s$psage/modform/hilbert/sqrt5/sqrt5.pyR��s	R�cBs#eZd�Zd�Zd�ZRS(c	Cs�||_|j�|_||_ddlm}|||�}|jj�j|�}|d}||_|j	|�|_
|j
j�|_dS(Ni����(tIntegersR(
R�R
RUR�R�RR�tchange_ringt_basetquotient_by_principal_idealR�R(R�(	RXR�R�RR}RR�tmodulusRH((s$psage/modform/hilbert/sqrt5/sqrt5.pyRY�s		
	cCs"|j�jt�}|j|�S(N(R�RRRU(RXRR&((s$psage/modform/hilbert/sqrt5/sqrt5.pyR�scCsM|j}|j�}g|jD]*}|jD]}||||�^q,qS(N(R�R(R(RXR�RRR!((s$psage/modform/hilbert/sqrt5/sqrt5.pyRs	(RdReRYR�R(((s$psage/modform/hilbert/sqrt5/sqrt5.pyR��s		R�cBseZd�Zd�ZRS(c	Cs�||_|j�|_||_ddlm}|ddksGt�|||d�}|jj�j|�}|d}|j	|�|_
|j
j�|_dS(Ni����(RiiR(
R�R
RUR�R�RRR�RRR�R(R�(	RXR�R�RR}RR�R	RH((s$psage/modform/hilbert/sqrt5/sqrt5.pyRYs		
cCs"|j�jt�}|j|�S(N(R�RRRU(RXRR&((s$psage/modform/hilbert/sqrt5/sqrt5.pyR�s(RdReRYR�(((s$psage/modform/hilbert/sqrt5/sqrt5.pyR�
s	R�cBs eZdZd�Zd�ZRS(sZ
    Residue class ring R = O_F / P^(2f-1), where e=2f-1
    is odd, and P=sqrt(5)O_F is the ramified prime. 

    Computing with this ring is trickier than all the rest,
    since it's not a quotient of Z[x] of the form Z[x]/(m,g),
    where m is an integer and g is a polynomial.
    The ring R is the quotient of
        O_F/P^(2f) = O_F/5^f = (Z/5^fZ)[x]/(x^2-x-1),
    by the ideal x^e.  We have
        O_F/P^(2f-2) subset R subset O_F/P^(2f)
    and each successive quotient has order 5 = #(O_F/P).
    Thus R has cardinality 5^(2f-1) and characteristic 5^f.
    The ring R can't be a quotient of Z[x] of the
    form Z[x]/(m,g), since such a quotient has
    cardinality m^deg(g) and characteristic m, and
    5^(2f-1) is not a power of 5^f.

    We thus view R as

        R = (Z/5^fZ)[x] / (x^2 - 5,  5^(f-1)*x).

    The elements of R are pairs (a,b) in (Z/5^fZ) x (Z/5^(f-1)Z),
    which correspond to the class of a + b*x.  The arithmetic laws
    are thus:

       (a,b) + (c,d) = (a+c mod 5^f, b+d mod 5^(f-1))

    and

       (a,b) * (c,d) = (a*c+b*d*5 mod 5^f, a*d+b*c mod 5^(f-1))

    The element omega = F.gen(), which is (1+sqrt(5))/2 maps to
    (1+x)/2 = (1/2, 1/2), which is the generator of this ring.

    EXAMPLES::

        sage: from psage.modform.hilbert.sqrt5.sqrt5 import F, residue_ring
        sage: P = F.primes_above(5)[0]; P
        Fractional ideal (2*a - 1)
        sage: R = residue_ring(P^5)
        sage: a = R(F.gen()); a
        [0 + 1*sqrt(5)]
        sage: a*a
        [5 + 0*sqrt(5)]
        sage: a*a*a
        [0 + 5*sqrt(5)]
        sage: a*a*a*a
        [0 + 0*sqrt(5)]
    c	Cs�||_|j�|_||_ddlm}|dd}|dd|ksYt�|||�}|||d�}t||�|_|jj	�|_
|jj	�ddd|_dS(Ni����(Rii(R�R
RUR�R�RRtRamifiedProductRingR�R(R�t_sqrt5(	RXR�R�RR}RR&tR0tR1((s$psage/modform/hilbert/sqrt5/sqrt5.pyRYQs		cCs#|dj�|j|dj�S(Nii(R�R(RXR((s$psage/modform/hilbert/sqrt5/sqrt5.pyR�^s(RdReRfRYR�(((s$psage/modform/hilbert/sqrt5/sqrt5.pyR�s2	
tRamifiedProductRingElementcBsAeZed�Zd�Zd�Zd�Zd�Zd�ZRS(cCs�||_t|t�r3|j|kr3||_n�|r�t|tttf�r}|j|d�|j|d�f|_q�|j|�|jd�f|_n|d|df|_dS(Nii(t_parentt
isinstanceRt_xRttuplet_R0t_R1(RXR�Rtcheck((s$psage/modform/hilbert/sqrt5/sqrt5.pyRYbs	,$cCs|j|S(N(R(RXR5((s$psage/modform/hilbert/sqrt5/sqrt5.pyRaoscCsd|jS(Ns[%s + %s*sqrt(5)](R(RX((s$psage/modform/hilbert/sqrt5/sqrt5.pyRcrscCsB|j\}}|j\}}t|j||||gdt�S(NR(RRRRs(tlefttrightRR!R"td((s$psage/modform/hilbert/sqrt5/sqrt5.pyt__add__uscCsB|j\}}|j\}}t|j||||gdt�S(NR(RRRRs(RRRR!R"R((s$psage/modform/hilbert/sqrt5/sqrt5.pyt__sub__zscCsV|j\}}|j\}}t|j||||d||||gdt�S(NiR(RRRRs(RRRR!R"R((s$psage/modform/hilbert/sqrt5/sqrt5.pyt__mul__s(	RdReRlRYRaRcRRR(((s$psage/modform/hilbert/sqrt5/sqrt5.pyRas
				R
cBs#eZd�Zd�Zd�ZRS(cCs?||_||_|td�dtd�dg�|_dS(Nii(RRRt_gen(RXRR
((s$psage/modform/hilbert/sqrt5/sqrt5.pyRY�s		cCs
t||�S(N(R(RXR((s$psage/modform/hilbert/sqrt5/sqrt5.pyRb�scCs|jS(N(R(RX((s$psage/modform/hilbert/sqrt5/sqrt5.pyR(�s(RdReRYRbR((((s$psage/modform/hilbert/sqrt5/sqrt5.pyR
�s		tMod_P_reduction_mapcBs>eZd�Zd�Zd�Zd�Zd�Zd�ZRS(cCs{|j�}t|�dks$t�|d\|_|_|j|j|j�\|_|_|_|j|j|_	dS(Nii(
R�R1RR�t_et_compute_IJt_It_Jt
_residue_ringt_IJ(RXR�tFAC((s$psage/modform/hilbert/sqrt5/sqrt5.pyRY�s
*cCsdt|jj�|jfS(Ns=(Partial) homomorphism from %s onto 2x2 matrices modulo %s^%s(RR�t_repr_shortR(RX((s$psage/modform/hilbert/sqrt5/sqrt5.pyRc�scCstS(N(R(RX((s$psage/modform/hilbert/sqrt5/sqrt5.pytdomain�scCs
|jj�S(N(R R�(RX((s$psage/modform/hilbert/sqrt5/sqrt5.pyR��scCsw|j}|j�tk	r*t|�}n||d�|j||d�|j||d�|j||d�S(Niiii(R"R�RR R!R#(RXRR�((s$psage/modform/hilbert/sqrt5/sqrt5.pyRb�s	cCsc|j�tj�kr$td�n|j�s<td�n|j�tj�kr`td�n|j�sxtd�nt|j�k	r�tdt�nt||�}t|t�r�|j	�}n|}ddl
m}||d�}tj�\}}||�}||�}|j
�dkr2t�n|d|ddg�}	|d�|}
d}xO|j�D]A}|sqmn||
||}
|
j�rm|
j�}PqmqmW|dkr
xI|D]>}|	|}|||kr�|||	kr�|	||fSq�Wn||||||||g�}|	|}|||	ksVtd	��|	||fS(
NsCp must be a prime ideal in the base field of the quaternion algebrasp must be primesp must be a prime of %si����(R	iiis"bug in that I,J don't skew commute(R
RRR
RRR�RR�R�RR	RRRRRRRR(RXRR}R�RR	RRRRR RR!R"R#R$((s$psage/modform/hilbert/sqrt5/sqrt5.pyR�sP	


!%
(RdReRYRcR&R�RbR(((s$psage/modform/hilbert/sqrt5/sqrt5.pyR�s					(((((((7RfRRRRRRRRRRtring_of_integerstO_FRR%R'R,R=RARBRCRLRQtobjectRRRqRwRR�R�R�ttablesR�R�R�R�R�tostenvirontpathtexiststmakedirsRlR�R�R�R�R�R�R�R�R�RR
R(((s$psage/modform/hilbert/sqrt5/sqrt5.pyt<module>esT4	T	*		"		#	�	:	'	C			2	m		g	!*	C#