code / alex / psage / psage / modform / paramodularforms / siegelmodularformg2_fourierexpansion_cython.pyx
241818 viewsr"""1Functions for reduction of fourier indices and for multiplication of2Siegel modular forms.34AUTHORS:56- Craig Citro, Nathan Ryan Initian version7- Martin Raum (2009 - 04) Refined multiplication by Martin Raum8- Martin Raum (2009 - 07 - 28) Port to new framework9"""1011#===============================================================================12#13# Copyright (C) 2009 Martin Raum14#15# This program is free software; you can redistribute it and/or16# modify it under the terms of the GNU General Public License17# as published by the Free Software Foundation; either version 318# of the License, or (at your option) any later version.19#20# This program is distributed in the hope that it will be useful,21# but WITHOUT ANY WARRANTY; without even the implied warranty of22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU23# General Public License for more details.24#25# You should have received a copy of the GNU General Public License26# along with this program; if not, see <http://www.gnu.org/licenses/>.27#28#===============================================================================2930## TODO : Clean this file up.3132include "interrupt.pxi"33include "stdsage.pxi"34include "cdefs.pxi"3536include 'sage/ext/gmp.pxi'3738from sage.rings.integer cimport Integer39from sage.rings.ring cimport Ring4041cdef struct int_triple:42int a43int b44int c4546cdef struct int_quinruple:47int a48int b49int c50int d # determinant of reducing g \in GL251int s # sign of reducing g \in GL25253cdef struct int_septuple:54int a55int b56int c57int O # upper left entry of reducing g \in GL258int o # upper right entry of reducing g \in GL259int U # lower left entry of reducing g \in GL260int u # lower right entry of reducing g \in GL2616263#####################################################################64#####################################################################65#####################################################################6667#===============================================================================68# reduce_GL69#===============================================================================7071def reduce_GL(tripel) :72r"""73Return the `GL_2(\ZZ)`-reduced form equivalent to (positive semidefinite)74quadratic form `a x^2 + b x y + c y^2`.75"""76cdef int a, b, c77cdef int_triple res7879# We want to check that (a,b,c) is semipositive definite80# since otherwise we might end up in an infinite loop.81# TODO: the discriminant can become to big82if b*b-4*a*c > 0 or a < 0 or c < 0:83raise NotImplementedError, "only implemented for nonpositive discriminant"8485(a, b, c) = tripel86res = _reduce_GL(a, b, c)8788return ((res.a, res.b, res.c), 0)8990#===============================================================================91# _reduce_GL92#===============================================================================9394cdef int_triple _reduce_GL(int a, int b, int c) :95r"""96Return the `GL_2(\ZZ)`-reduced form equivalent to (positive semidefinite)97quadratic form `a x^2 + b x y + c y^2`.98(Following Algorithm 5.4.2 found in Cohen's Computational Algebraic Number Theory.)99"""100cdef int_triple res101cdef int twoa, q, r102cdef int tmp103104if b < 0:105b = -b106107while not (b<=a and a<=c): ## while not GL-reduced108twoa = 2 * a109#if b not in range(-a+1,a+1):110if b > a:111## apply Euclidean step (translation)112q = b / twoa #(2*a)113r = b % twoa #(2*a)114if r > a:115## want (quotient and) remainder such that -a<r<=a116r = r - twoa # 2*a;117q = q + 1118c = c-b*q+a*q*q119b = r120121## apply symmetric step (reflection) if necessary122if a > c:123#(a,c) = (c,a)124tmp = c125c = a126a = tmp127128#b=abs(b)129if b < 0:130b = -b131## iterate132## We're finished! Return the GL2(ZZ)-reduced form (a,b,c):133134res.a = a135res.b = b136res.c = c137138return res139140##TODO: This is a mess. In former implementations the sign was the determinant141## of the reducing matrix. This has to be replaced by d and the sign is the142## GL2(F_2) \cong S_3 character143144#===============================================================================145# #==============================================================================146# # sreduce_GL147# #==============================================================================148#149# def sreduce_GL(a, b, c):150# """151# Return the GL2(ZZ)-reduced form f and a determinant d and a sign s such152# that d is the determinant of the matrices M in GL2(ZZ) such that153# ax^2+bxy+cy^2 = f((x,y)*M).154# """155# cdef int_quadruple res156#157# # We want to check that (a,b,c) is semipositive definite158# # since otherwise we might end up in an infinite loop.159# if b*b-4*a*c > 0 or a < 0 or c < 0:160# raise NotImplementedError, "only implemented for nonpositive discriminant"161#162# res = _sreduce_GL(a, b, c)163# return ((res.a, res.b, res.c), (res.d, res.s))164#165# #===============================================================================166# # int_quintuple _sreduce_GL167# #===============================================================================168#169# cdef int_quintuple _sreduce_GL(int a, int b, int c):170# """171# Return the GL2(ZZ)-reduced form equivalent to (positive semidefinite)172# quadratic form ax^2+bxy+cy^2.173# (Following algorithm 5.4.2 found in Cohen's Computational Algebraic Number Theory.)174#175# TODO176# _xreduce_GL is a factor 20 slower than xreduce_GL.177# How can we improve this factor ?178#179# """180# cdef int_quadruple res181# cdef int twoa, q, r182# cdef int tmp183# cdef int s184#185# # If [A,B,C] is the form to be reduced, then after each reduction186# # step we have s = det(M), where M is the GL2(ZZ)-matrix187# # such that [A,B,C] =[a,b,c]( (x,y)*M)188# s = 1189# if b < 0:190# b = -b191# s = -1192#193# while not (b<=a and a<=c): ## while not GL-reduced194# twoa = 2 * a195# #if b not in range(-a+1,a+1):196# if b > a:197# ## apply Euclidean step (translation)198# q = b / twoa #(2*a)199# r = b % twoa #(2*a)200# if r > a:201# ## want (quotient and) remainder such that -a<r<=a202# r = r - twoa # 2*a;203# q = q + 1204# c = c-b*q+a*q*q205# b = r206#207# ## apply symmetric step (reflection) if necessary208# if a > c:209# #(a,c) = (c,a)210# tmp = c; c = a; a = tmp211# s *= -1212#213# #b=abs(b)214# if b < 0:215# b = -b216# s *= -1217#218# ## iterate219# ## We're finished! Return the GL2(ZZ)-reduced form (a,b,c) and the O,o,U,u-matrix:220#221# res.a = a222# res.b = b223# res.c = c224# res.s = s225#226# return res227#===============================================================================228229#===============================================================================230# xreduce_GL231#===============================================================================232233def xreduce_GL(tripel) :234r"""235Return the `GL_2(\ZZ)`-reduced form equivalent to (positive semidefinite)236quadratic form `a x^2 + b x y + c y^2`.237"""238cdef int a, b, c239cdef int_septuple res240241# We want to check that (a,b,c) is semipositive definite242# since otherwise we might end up in an infinite loop.243# if b*b-4*a*c > 0 or a < 0 or c < 0:244# raise NotImplementedError, "only implemented for nonpositive discriminant"245246(a, b, c) = tripel247res = _xreduce_GL(a, b, c)248return ((res.a, res.b, res.c), (res.O, res.o, res.U, res.u))249250#===============================================================================251# _xreduce_GL252#===============================================================================253254cdef int_septuple _xreduce_GL(int a, int b, int c) :255r"""256Return the `GL_2(\ZZ)`-reduced form `f` and a matrix `M` such that257`a x^2 + b x y + c y^2 = f( (x,y)*M )`.258259TODO:260261``_xreduce_GL`` is a factor 20 slower than ``xreduce_GL``.262How can we improve this factor ?263264"""265cdef int_septuple res266cdef int twoa, q, r267cdef int tmp268cdef int O,o,U,u269270# If [A,B,C] is the form to be reduced, then after each reduction271# step we have [A,B,C] =[a,b,c]( (x,y)*matrix(2,2,[O,o, U,u]) )272O = u = 1273o = U = 0274275if b < 0:276b = -b277O = -1278279while not (b<=a and a<=c): ## while not GL-reduced280twoa = 2 * a281#if b not in range(-a+1,a+1):282if b > a:283## apply Euclidean step (translation)284q = b / twoa #(2*a)285r = b % twoa #(2*a)286if r > a:287## want (quotient and) remainder such that -a<r<=a288r = r - twoa # 2*a;289q = q + 1290c = c-b*q+a*q*q291b = r292O += q*o293U += q*u294295## apply symmetric step (reflection) if necessary296if a > c:297#(a,c) = (c,a)298tmp = c; c = a; a = tmp299tmp = O; O = o; o = tmp300tmp = U; U = u; u = tmp301302#b=abs(b)303if b < 0:304b = -b305O = -O306U = -U307308## iterate309## We're finished! Return the GL2(ZZ)-reduced form (a,b,c) and the O,o,U,u-matrix:310311res.a = a312res.b = b313res.c = c314res.O = O315res.o = o316res.U = U317res.u = u318319return res320321#####################################################################322#####################################################################323#####################################################################324325#===============================================================================326# mult_coeff_int_without_character327#===============================================================================328329cpdef mult_coeff_int_without_character(result_key,330coeffs_dict1, coeffs_dict2, ch1, ch2, result) :331r"""332Returns the value at `(a, b, c)` of the coefficient dictionary of the product333of the two forms with dictionaries ``coeffs_dict1`` and ``coeffs_dict2``.334It is assumed that `(a, b, c)` is a key in ``coeffs_dict1`` and ``coeffs_dict2``.335"""336cdef int a, b, c337cdef int a1, a2338cdef int b1, b2339cdef int c1, c2340cdef int B1, B2341342cdef mpz_t tmp, mpz_zero343cdef mpz_t left, right344cdef mpz_t acc345346mpz_init(tmp)347mpz_init(mpz_zero)348mpz_init(left)349mpz_init(right)350mpz_init(acc)351352(a, b, c) = result_key353354_sig_on355for a1 from 0 <= a1 < a+1 :356a2 = a - a1357for c1 from 0 <= c1 < c+1 :358c2 = c - c1359mpz_set_si(tmp, 4*a1*c1)360mpz_sqrt(tmp, tmp)361B1 = mpz_get_si(tmp)362363mpz_set_si(tmp, 4*a2*c2)364mpz_sqrt(tmp, tmp)365B2 = mpz_get_si(tmp)366367for b1 from max(-B1, b - B2) <= b1 < min(B1 + 1, b + B2 + 1) :368## Guarantes that both (a1,b1,c1) and (a2,b2,c2) are369## positive semidefinite370b2 = b - b1371372get_coeff_int(left, a1, b1, c1, coeffs_dict1)373if mpz_cmp(left, mpz_zero) == 0 : continue374375get_coeff_int(right, a2, b2, c2, coeffs_dict2)376if mpz_cmp(right, mpz_zero) == 0 : continue377378mpz_mul(tmp, left, right)379mpz_add(acc, acc, tmp)380_sig_off381382mpz_set((<Integer>result).value, acc)383384mpz_clear(tmp)385mpz_clear(mpz_zero)386mpz_clear(left)387mpz_clear(right)388mpz_clear(acc)389390return result391392#===============================================================================393# mult_coeff_generic_without_character394#===============================================================================395396cpdef mult_coeff_generic_without_character(result_key,397coeffs_dict1, coeffs_dict2, ch1, ch2, result) :398r"""399Returns the value at `(a, b, c)`of the coefficient dictionary of the product400of the two forms with dictionaries ``coeffs_dict1`` and ``coeffs_dict2``.401It is assumed that `(a, b, c)` is a key in ``coeffs_dict1`` and ``coeffs_dict2``.402"""403cdef int a, b, c404cdef int a1, a2405cdef int b1, b2406cdef int c1, c2407cdef int B1, B2408409cdef mpz_t tmp410411mpz_init(tmp)412413(a, b, c) = result_key414415_sig_on416for a1 from 0 <= a1 < a+1:417a2 = a - a1418for c1 from 0 <= c1 < c+1:419c2 = c - c1420mpz_set_si(tmp, 4*a1*c1)421mpz_sqrt(tmp, tmp)422B1 = mpz_get_si(tmp)423424mpz_set_si(tmp, 4*a2*c2)425mpz_sqrt(tmp, tmp)426B2 = mpz_get_si(tmp)427428for b1 from max(-B1, b - B2) <= b1 < min(B1 + 1, b + B2 + 1) :429## Guarantes that both (a1,b1,c1) and (a2,b2,c2) are430## positive semidefinite431b2 = b - b1432433left = get_coeff_generic(a1, b1, c1, coeffs_dict1)434if left is None : continue435436right = get_coeff_generic(a2, b2, c2, coeffs_dict2)437if right is None : continue438439result += left*right440_sig_off441442mpz_clear(tmp)443444return result445446#####################################################################447448#===============================================================================449# get_coeff_int450#===============================================================================451452cdef inline void get_coeff_int(mpz_t dest, int a, int b, int c, coeffs_dict):453r"""454Return the value of ``coeffs_dict`` at the triple obtained from455reducing `(a, b, c)`.456It is assumed that the latter is a valid key457and that `(a, b, c)` is positive semi-definite.458"""459cdef int_triple tmp_triple460461mpz_set_si(dest, 0)462463tmp_triple = _reduce_GL(a, b, c)464triple = (tmp_triple.a, tmp_triple.b, tmp_triple.c)465try :466mpz_set(dest, (<Integer>(coeffs_dict[triple])).value)467except KeyError :468pass469470#===============================================================================471# get_coeff_generic472#===============================================================================473474cdef get_coeff_generic(int a, int b, int c, coeffs_dict):475r"""476Return the value of ``coeffs_dict`` at the triple obtained from477reducing `(a, b, c)`.478It is assumed that the latter is a valid key479and that `(a, b, c)` is positive semi-definite.480"""481cdef int_triple tmp_triple482483tmp_triple = _reduce_GL(a, b, c)484triple = (tmp_triple.a, tmp_triple.b, tmp_triple.c)485486try :487return coeffs_dict[triple]488except KeyError :489return None490491492