def quadratic_L_function__exact(n, d): r""" Returns the exact value of a quadratic twist of the Riemann Zeta function by `\chi_d(x) = \left(\frac{d}{x}\right)`. The input `n` must be a critical value. EXAMPLES:: sage: quadratic_L_function__exact(1, -4) 1/4*pi sage: quadratic_L_function__exact(-4, -4) 5/2 TESTS:: sage: quadratic_L_function__exact(2, -4) Traceback (most recent call last): ... TypeError: n must be a critical value (i.e. odd > 0 or even <= 0) REFERENCES: - [Iwasawa]_, pp 16-17, Special values of `L(1-n, \chi)` and `L(n, \chi)` - [IreRos]_ - [WashCyc]_ """ from sage.all import SR, sqrt if n <= 0: return QuadraticBernoulliNumber(1 - n, d) / (n - 1) elif n >= 1: # Compute the kind of critical values (p10) if kronecker_symbol(fundamental_discriminant(d), -1) == 1: delta = 0 else: delta = 1 # Compute the positive special values (p17) if ((n - delta) % 2 == 0): f = abs(fundamental_discriminant(d)) if delta == 0: GS = sqrt(f) else: GS = I * sqrt(f) ans = SR(ZZ(-1)**(1 + (n - delta) / 2)) ans *= (2 * pi / f)**n ans *= GS # Evaluate the Gauss sum here! =0 ans *= 1 / (2 * I**delta) ans *= QuadraticBernoulliNumber(n, d) / factorial(n) return ans else: if delta == 0: raise TypeError( "n must be a critical value (i.e. even > 0 or odd < 0)") if delta == 1: raise TypeError( "n must be a critical value (i.e. odd > 0 or even <= 0)")
def quadratic_L_function__exact(n, d): r""" Returns the exact value of a quadratic twist of the Riemann Zeta function by `\chi_d(x) = \left(\frac{d}{x}\right)`. The input `n` must be a critical value. EXAMPLES:: sage: quadratic_L_function__exact(1, -4) 1/4*pi sage: quadratic_L_function__exact(-4, -4) 5/2 TESTS:: sage: quadratic_L_function__exact(2, -4) Traceback (most recent call last): ... TypeError: n must be a critical value (i.e. odd > 0 or even <= 0) REFERENCES: - [Iwasawa]_, pp 16-17, Special values of `L(1-n, \chi)` and `L(n, \chi)` - [IreRos]_ - [WashCyc]_ """ from sage.all import SR, sqrt if n <= 0: return QuadraticBernoulliNumber(1 - n, d) / (n - 1) elif n >= 1: # Compute the kind of critical values (p10) if kronecker_symbol(fundamental_discriminant(d), -1) == 1: delta = 0 else: delta = 1 # Compute the positive special values (p17) if (n - delta) % 2 == 0: f = abs(fundamental_discriminant(d)) if delta == 0: GS = sqrt(f) else: GS = I * sqrt(f) ans = SR(ZZ(-1) ** (1 + (n - delta) / 2)) ans *= (2 * pi / f) ** n ans *= GS # Evaluate the Gauss sum here! =0 ans *= 1 / (2 * I ** delta) ans *= QuadraticBernoulliNumber(n, d) / factorial(n) return ans else: if delta == 0: raise TypeError("n must be a critical value (i.e. even > 0 or odd < 0)") if delta == 1: raise TypeError("n must be a critical value (i.e. odd > 0 or even <= 0)")
def duke_imamoglu_lift(self, f, f_k, precision, half_integral_weight=False): """ INPUT: - ``half_integral_weight`` -- If ``False`` we assume that `f` is the Fourier expansion of a Jacobi form. Otherwise we assume it is the Fourier expansion of a half integral weight elliptic modular form. """ if half_integral_weight: coeff_index = lambda d: d else: coeff_index = lambda d: ((d + (-d % 4)) // 4, (-d) % 4) coeffs = dict() for t in precision.iter_positive_forms(): dt = (-1)**(precision.genus() // 2) * t.det() d = fundamental_discriminant(dt) eps = Integer(isqrt(dt / d)) coeffs[t] = 0 for a in eps.divisors(): d_a = abs(d * (eps // a)**2) coeffs[t] = coeffs[t] + a**(f_k - 1) * self._kohnen_phi(a, t) \ * f[coeff_index(d_a)] return coeffs
def QuadraticBernoulliNumber(k, d): r""" Compute `k`-th Bernoulli number for the primitive quadratic character associated to `\chi(x) = \left(\frac{d}{x}\right)`. EXAMPLES: Let us create a list of some odd negative fundamental discriminants:: sage: test_set = [d for d in range(-163, -3, 4) if is_fundamental_discriminant(d)] In general, we have `B_{1, \chi_d} = -2 h/w` for odd negative fundamental discriminants:: sage: all(QuadraticBernoulliNumber(1, d) == -len(BinaryQF_reduced_representatives(d)) for d in test_set) True REFERENCES: - [Iwasawa]_, pp 7-16. """ # Ensure the character is primitive d1 = fundamental_discriminant(d) f = abs(d1) # Make the (usual) k-th Bernoulli polynomial x = PolynomialRing(QQ, 'x').gen() bp = bernoulli_polynomial(x, k) # Make the k-th quadratic Bernoulli number total = sum([kronecker_symbol(d1, i) * bp(i/f) for i in range(f)]) total *= (f ** (k-1)) return total
def QuadraticBernoulliNumber(k, d): r""" Compute k-th Bernoulli number for the primitive quadratic character associated to `\chi(x) = \left(\frac{d}{x}\right)`. Reference: Iwasawa's "Lectures on p-adic L-functions", pp7-16. EXAMPLES:: sage: ## Makes a set of odd fund discriminants < -3 sage: Fund_odd_test_set = [D for D in range(-163, -3, 4) if is_fundamental_discriminant(D)] sage: ## In general, we have B_{1, \chi_d} = -2h/w for odd fund disc < 0 sage: for D in Fund_odd_test_set: ... if len(BinaryQF_reduced_representatives(D)) != -QuadraticBernoulliNumber(1, D): ... print "Oops! There is an error at D = ", D """ ## Ensure the character is primitive d1 = fundamental_discriminant(d) f = abs(d1) ## Make the (usual) k-th Bernoulli polynomial x = PolynomialRing(QQ, 'x').gen() bp = bernoulli_polynomial(x, k) ## Make the k-th quadratic Bernoulli number total = sum([kronecker_symbol(d1, i) * bp(i/f) for i in range(f)]) total *= (f ** (k-1)) return total
def QuadraticBernoulliNumber(k, d): r""" Compute k-th Bernoulli number for the primitive quadratic character associated to `\chi(x) = \left(\frac{d}{x}\right)`. Reference: Iwasawa's "Lectures on p-adic L-functions", pp7-16. EXAMPLES:: sage: ## Makes a set of odd fund discriminants < -3 sage: Fund_odd_test_set = [D for D in range(-163, -3, 4) if is_fundamental_discriminant(D)] sage: ## In general, we have B_{1, \chi_d} = -2h/w for odd fund disc < 0 sage: for D in Fund_odd_test_set: ... if len(BinaryQF_reduced_representatives(D)) != -QuadraticBernoulliNumber(1, D): ... print "Oops! There is an error at D = ", D """ ## Ensure the character is primitive d1 = fundamental_discriminant(d) f = abs(d1) ## Make the (usual) k-th Bernoulli polynomial x = PolynomialRing(QQ, 'x').gen() bp = bernoulli_polynomial(x, k) ## Make the k-th quadratic Bernoulli number total = sum([kronecker_symbol(d1, i) * bp(i / f) for i in range(f)]) total *= (f**(k - 1)) return total
def QuadraticBernoulliNumber(k, d): r""" Compute `k`-th Bernoulli number for the primitive quadratic character associated to `\chi(x) = \left(\frac{d}{x}\right)`. EXAMPLES: Let us create a list of some odd negative fundamental discriminants:: sage: test_set = [d for d in range(-163, -3, 4) if is_fundamental_discriminant(d)] In general, we have `B_{1, \chi_d} = -2 h/w` for odd negative fundamental discriminants:: sage: all(QuadraticBernoulliNumber(1, d) == -len(BinaryQF_reduced_representatives(d)) for d in test_set) True REFERENCES: - [Iwasawa]_, pp 7-16. """ # Ensure the character is primitive d1 = fundamental_discriminant(d) f = abs(d1) # Make the (usual) k-th Bernoulli polynomial x = PolynomialRing(QQ, 'x').gen() bp = bernoulli_polynomial(x, k) # Make the k-th quadratic Bernoulli number total = sum([kronecker_symbol(d1, i) * bp(i / f) for i in range(f)]) total *= (f**(k - 1)) return total
def duke_imamoglu_lift(self, f, f_k, precision, half_integral_weight = False) : """ INPUT: - ``half_integral_weight`` -- If ``False`` we assume that `f` is the Fourier expansion of a Jacobi form. Otherwise we assume it is the Fourier expansion of a half integral weight elliptic modular form. """ if half_integral_weight : coeff_index = lambda d : d else : coeff_index = lambda d : ((d + (-d % 4)) // 4, (-d) % 4) coeffs = dict() for t in precision.iter_positive_forms() : dt = (-1)**(precision.genus() // 2) * t.det() d = fundamental_discriminant(dt) eps = Integer(isqrt(dt / d)) coeffs[t] = 0 for a in eps.divisors() : d_a = abs(d * (eps // a)**2) coeffs[t] = coeffs[t] + a**(f_k - 1) * self._kohnen_phi(a, t) \ * f[coeff_index(d_a)] return coeffs
def quadratic_L_function__exact(n, d): r""" Returns the exact value of a quadratic twist of the Riemann Zeta function by `\chi_d(x) = \left(\frac{d}{x}\right)`. References: - Iwasawa's "Lectures on p-adic L-functions", p16-17, "Special values of `L(1-n, \chi)` and `L(n, \chi)` - Ireland and Rosen's "A Classical Introduction to Modern Number Theory" - Washington's "Cyclotomic Fields" EXAMPLES:: sage: bool(quadratic_L_function__exact(1, -4) == pi/4) True """ from sage.all import SR, sqrt if n <= 0: k = 1 - n return -QuadraticBernoulliNumber(k, d) / k elif n >= 1: ## Compute the kind of critical values (p10) if kronecker_symbol(fundamental_discriminant(d), -1) == 1: delta = 0 else: delta = 1 ## Compute the positive special values (p17) if ((n - delta) % 2 == 0): f = abs(fundamental_discriminant(d)) if delta == 0: GS = sqrt(f) else: GS = I * sqrt(f) ans = SR(ZZ(-1)**(1 + (n - delta) / 2)) ans *= (2 * pi / f)**n ans *= GS ## Evaluate the Gauss sum here! =0 ans *= 1 / (2 * I**delta) ans *= QuadraticBernoulliNumber(n, d) / factorial(n) return ans else: if delta == 0: raise TypeError, "n must be a critical value!\n" + "(I.e. even > 0 or odd < 0.)" if delta == 1: raise TypeError, "n must be a critical value!\n" + "(I.e. odd > 0 or even <= 0.)"
def quadratic_L_function__exact(n, d): r""" Returns the exact value of a quadratic twist of the Riemann Zeta function by `\chi_d(x) = \left(\frac{d}{x}\right)`. References: - Iwasawa's "Lectures on p-adic L-functions", p16-17, "Special values of `L(1-n, \chi)` and `L(n, \chi)` - Ireland and Rosen's "A Classical Introduction to Modern Number Theory" - Washington's "Cyclotomic Fields" EXAMPLES:: sage: bool(quadratic_L_function__exact(1, -4) == pi/4) True """ from sage.all import SR, sqrt if n<=0: k = 1-n return -QuadraticBernoulliNumber(k,d)/k elif n>=1: ## Compute the kind of critical values (p10) if kronecker_symbol(fundamental_discriminant(d), -1) == 1: delta = 0 else: delta = 1 ## Compute the positive special values (p17) if ((n - delta) % 2 == 0): f = abs(fundamental_discriminant(d)) if delta == 0: GS = sqrt(f) else: GS = I * sqrt(f) ans = SR(ZZ(-1)**(1+(n-delta)/2)) ans *= (2*pi/f)**n ans *= GS ## Evaluate the Gauss sum here! =0 ans *= 1/(2 * I**delta) ans *= QuadraticBernoulliNumber(n,d)/factorial(n) return ans else: if delta == 0: raise TypeError, "n must be a critical value!\n" + "(I.e. even > 0 or odd < 0.)" if delta == 1: raise TypeError, "n must be a critical value!\n" + "(I.e. odd > 0 or even <= 0.)"
def _kohnen_rho(self, t, a) : dt = (-1)**(t.nrows() // 2) * t.det() d = fundamental_discriminant(dt) eps = isqrt(dt // d) res = 1 for (p,e) in gcd(a, eps).factor() : pol = self._kohnen_rho_polynomial(t, p).coefficients() if e < len(pol) : res = res * pol[e] return res
def _kohnen_rho(self, t, a): dt = (-1)**(t.nrows() // 2) * t.det() d = fundamental_discriminant(dt) eps = isqrt(dt // d) res = 1 for (p, e) in gcd(a, eps).factor(): pol = self._kohnen_rho_polynomial(t, p).coefficients() if e < len(pol): res = res * pol[e] return res
def quadratic_L_function__numerical(n, d, num_terms=1000): """ Evaluate the Dirichlet L-function (for quadratic character) numerically (in a very naive way). EXAMPLES: First, let us test several values for a given character:: sage: RR = RealField(100) sage: for i in range(5): ... print "L(" + str(1+2*i) + ", (-4/.)): ", RR(quadratic_L_function__exact(1+2*i, -4)) - quadratic_L_function__numerical(RR(1+2*i),-4, 10000) L(1, (-4/.)): 0.000049999999500000024999996962707 L(3, (-4/.)): 4.99999970000003...e-13 L(5, (-4/.)): 4.99999922759382...e-21 L(7, (-4/.)): ...e-29 L(9, (-4/.)): ...e-29 This procedure fails for negative special values, as the Dirichlet series does not converge here:: sage: quadratic_L_function__numerical(-3,-4, 10000) Traceback (most recent call last): ... ValueError: the Dirichlet series does not converge here Test for several characters that the result agrees with the exact value, to a given accuracy :: sage: for d in range(-20,0): # long time (2s on sage.math 2014) ....: if abs(RR(quadratic_L_function__numerical(1, d, 10000) - quadratic_L_function__exact(1, d))) > 0.001: ....: print "Oops! We have a problem at d = ", d, " exact = ", RR(quadratic_L_function__exact(1, d)), " numerical = ", RR(quadratic_L_function__numerical(1, d)) """ # Set the correct precision if it is given (for n). if is_RealField(n.parent()): R = n.parent() else: R = RealField() if n < 0: raise ValueError('the Dirichlet series does not converge here') d1 = fundamental_discriminant(d) ans = R(0) for i in range(1, num_terms): ans += R(kronecker_symbol(d1, i) / R(i)**n) return ans
def quadratic_L_function__numerical(n, d, num_terms=1000): """ Evaluate the Dirichlet L-function (for quadratic character) numerically (in a very naive way). EXAMPLES: First, let us test several values for a given character:: sage: RR = RealField(100) sage: for i in range(5): ... print "L(" + str(1+2*i) + ", (-4/.)): ", RR(quadratic_L_function__exact(1+2*i, -4)) - quadratic_L_function__numerical(RR(1+2*i),-4, 10000) L(1, (-4/.)): 0.000049999999500000024999996962707 L(3, (-4/.)): 4.99999970000003...e-13 L(5, (-4/.)): 4.99999922759382...e-21 L(7, (-4/.)): ...e-29 L(9, (-4/.)): ...e-29 This procedure fails for negative special values, as the Dirichlet series does not converge here:: sage: quadratic_L_function__numerical(-3,-4, 10000) Traceback (most recent call last): ... ValueError: the Dirichlet series does not converge here Test for several characters that the result agrees with the exact value, to a given accuracy :: sage: for d in range(-20,0): # long time (2s on sage.math 2014) ....: if abs(RR(quadratic_L_function__numerical(1, d, 10000) - quadratic_L_function__exact(1, d))) > 0.001: ....: print "Oops! We have a problem at d = ", d, " exact = ", RR(quadratic_L_function__exact(1, d)), " numerical = ", RR(quadratic_L_function__numerical(1, d)) """ # Set the correct precision if it is given (for n). if is_RealField(n.parent()): R = n.parent() else: R = RealField() if n < 0: raise ValueError('the Dirichlet series does not converge here') d1 = fundamental_discriminant(d) ans = R(0) for i in range(1,num_terms): ans += R(kronecker_symbol(d1,i) / R(i)**n) return ans
def quadratic_L_function__numerical(n, d, num_terms=1000): """ Evaluate the Dirichlet L-function (for quadratic character) numerically (in a very naive way). EXAMPLES:: sage: ## Test several values for a given character sage: RR = RealField(100) sage: for i in range(5): ... print "L(" + str(1+2*i) + ", (-4/.)): ", RR(quadratic_L_function__exact(1+2*i, -4)) - quadratic_L_function__numerical(RR(1+2*i),-4, 10000) L(1, (-4/.)): 0.000049999999500000024999996962707 L(3, (-4/.)): 4.99999970000003...e-13 L(5, (-4/.)): 4.99999922759382...e-21 L(7, (-4/.)): ...e-29 L(9, (-4/.)): ...e-29 sage: ## Testing the accuracy of the negative special values sage: ## ---- THIS FAILS SINCE THE DIRICHLET SERIES DOESN'T CONVERGE HERE! ---- sage: ## Test several characters agree with the exact value, to a given accuracy. sage: for d in range(-20,0): ... if abs(RR(quadratic_L_function__numerical(1, d, 10000) - quadratic_L_function__exact(1, d))) > 0.001: ... print "Oops! We have a problem at d = ", d, " exact = ", RR(quadratic_L_function__exact(1, d)), " numerical = ", RR(quadratic_L_function__numerical(1, d)) ... """ ## Set the correct precision if it's given (for n). if is_RealField(n.parent()): R = n.parent() else: R = RealField() d1 = fundamental_discriminant(d) ans = R(0) for i in range(1,num_terms): ans += R(kronecker_symbol(d1,i) / R(i)**n) return ans
def quadratic_L_function__numerical(n, d, num_terms=1000): """ Evaluate the Dirichlet L-function (for quadratic character) numerically (in a very naive way). EXAMPLES:: sage: ## Test several values for a given character sage: RR = RealField(100) sage: for i in range(5): ... print "L(" + str(1+2*i) + ", (-4/.)): ", RR(quadratic_L_function__exact(1+2*i, -4)) - quadratic_L_function__numerical(RR(1+2*i),-4, 10000) L(1, (-4/.)): 0.000049999999500000024999996962707 L(3, (-4/.)): 4.99999970000003...e-13 L(5, (-4/.)): 4.99999922759382...e-21 L(7, (-4/.)): ...e-29 L(9, (-4/.)): ...e-29 sage: ## Testing the accuracy of the negative special values sage: ## ---- THIS FAILS SINCE THE DIRICHLET SERIES DOESN'T CONVERGE HERE! ---- sage: ## Test several characters agree with the exact value, to a given accuracy. sage: for d in range(-20,0): ... if abs(RR(quadratic_L_function__numerical(1, d, 10000) - quadratic_L_function__exact(1, d))) > 0.001: ... print "Oops! We have a problem at d = ", d, " exact = ", RR(quadratic_L_function__exact(1, d)), " numerical = ", RR(quadratic_L_function__numerical(1, d)) ... """ ## Set the correct precision if it's given (for n). if is_RealField(n.parent()): R = n.parent() else: R = RealField() d1 = fundamental_discriminant(d) ans = R(0) for i in range(1, num_terms): ans += R(kronecker_symbol(d1, i) / R(i)**n) return ans
def siegel_product(self, u): """ Computes the infinite product of local densities of the quadratic form for the number `u`. EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: Q.theta_series(11) 1 + 8*q + 24*q^2 + 32*q^3 + 24*q^4 + 48*q^5 + 96*q^6 + 64*q^7 + 24*q^8 + 104*q^9 + 144*q^10 + O(q^11) sage: Q.siegel_product(1) 8 sage: Q.siegel_product(2) ## This one is wrong -- expect 24, and the higher powers of 2 don't work... =( 24 sage: Q.siegel_product(3) 32 sage: Q.siegel_product(5) 48 sage: Q.siegel_product(6) 96 sage: Q.siegel_product(7) 64 sage: Q.siegel_product(9) 104 sage: Q.local_density(2,1) 1 sage: M = 4; len([v for v in mrange([M,M,M,M]) if Q(v) % M == 1]) / M^3 1 sage: M = 16; len([v for v in mrange([M,M,M,M]) if Q(v) % M == 1]) / M^3 # long time (41s on sage.math, 2011) 1 sage: Q.local_density(2,2) 3/2 sage: M = 4; len([v for v in mrange([M,M,M,M]) if Q(v) % M == 2]) / M^3 3/2 sage: M = 16; len([v for v in mrange([M,M,M,M]) if Q(v) % M == 2]) / M^3 # long time (41s on sage.math, 2011) 3/2 TESTS:: sage: [1] + [Q.siegel_product(ZZ(a)) for a in range(1,11)] == Q.theta_series(11).list() True """ ## Protect u (since it fails often if it's an just an int!) u = ZZ(u) n = self.dim() d = self.det() ## ??? Warning: This is a factor of 2^n larger than it should be! ## DIAGNOSTIC verbose("n = " + str(n)) verbose("d = " + str(d)) verbose("In siegel_product: d = ", d, "\n"); ## Product of "bad" places to omit S = 2 * d * u ## DIAGNOSTIC verbose("siegel_product Break 1. \n") verbose(" u = ", u, "\n") ## Make the odd generic factors if ((n % 2) == 1): m = (n-1) / 2 d1 = fundamental_discriminant(((-1)**m) * 2*d * u) ## Replaced d by 2d here to compensate for the determinant f = abs(d1) ## gaining an odd power of 2 by using the matrix of 2Q instead ## of the matrix of Q. ## --> Old d1 = CoreDiscriminant((mpz_class(-1)^m) * d * u); ## Make the ratio of factorials factor: [(2m)! / m!] * prod_{i=1}^m (2*i-1) factor1 = 1 for i in range(1, m+1): factor1 *= 2*i - 1 for i in range(m+1, 2*m + 1): factor1 *= i genericfactor = factor1 * ((u / f) ** m) \ * QQ(sqrt((2 ** n) * f) / (u * d)) \ * abs(QuadraticBernoulliNumber(m, d1) / bernoulli(2*m)) ## DIAGNOSTIC verbose("siegel_product Break 2. \n") ## Make the even generic factor if ((n % 2) == 0): m = n / 2 d1 = fundamental_discriminant(((-1)**m) * d) f = abs(d1) ## DIAGNOSTIC #cout << " mpz_class(-1)^m = " << (mpz_class(-1)^m) << " and d = " << d << endl; #cout << " f = " << f << " and d1 = " << d1 << endl; genericfactor = m / QQ(sqrt(f*d)) \ * ((u/2) ** (m-1)) * (f ** m) \ / abs(QuadraticBernoulliNumber(m, d1)) \ * (2 ** m) ## This last factor compensates for using the matrix of 2*Q ##return genericfactor ## Omit the generic factors in S and compute them separately omit = 1 include = 1 S_divisors = prime_divisors(S) ## DIAGNOSTIC #cout << "\n S is " << S << endl; #cout << " The Prime divisors of S are :"; #PrintV(S_divisors); for p in S_divisors: Q_normal = self.local_normal_form(p) ## DIAGNOSTIC verbose(" p = " + str(p) + " and its Kronecker symbol (d1/p) = (" + str(d1) + "/" + str(p) + ") is " + str(kronecker_symbol(d1, p)) + "\n") omit *= 1 / (1 - (kronecker_symbol(d1, p) / (p**m))) ## DIAGNOSTIC verbose(" omit = " + str(omit) + "\n") verbose(" Q_normal is \n" + str(Q_normal) + "\n") verbose(" Q_normal = \n" + str(Q_normal)) verbose(" p = " + str(p) + "\n") verbose(" u = " +str(u) + "\n") verbose(" include = " + str(include) + "\n") include *= Q_normal.local_density(p, u) ## DIAGNOSTIC #cout << " Including the p = " << p << " factor: " << local_density(Q_normal, p, u) << endl; ## DIAGNSOTIC verbose(" --- Exiting loop \n") #// **************** Important ******************* #// Additional fix (only included for n=4) to deal #// with the power of 2 introduced at the real place #// by working with Q instead of 2*Q. This needs to #// be done for all other n as well... #/* #if (n==4) # genericfactor = 4 * genericfactor; #*/ ## DIAGNSOTIC #cout << endl; #cout << " generic factor = " << genericfactor << endl; #cout << " omit = " << omit << endl; #cout << " include = " << include << endl; #cout << endl; ## DIAGNSOTIC #// cout << "siegel_product Break 3. " << endl; ## Return the final factor (and divide by 2 if n=2) if (n == 2): return (genericfactor * omit * include / 2) else: return (genericfactor * omit * include)
def siegel_product(self, u): """ Computes the infinite product of local densities of the quadratic form for the number `u`. EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: Q.theta_series(11) 1 + 8*q + 24*q^2 + 32*q^3 + 24*q^4 + 48*q^5 + 96*q^6 + 64*q^7 + 24*q^8 + 104*q^9 + 144*q^10 + O(q^11) sage: Q.siegel_product(1) 8 sage: Q.siegel_product(2) ## This one is wrong -- expect 24, and the higher powers of 2 don't work... =( 24 sage: Q.siegel_product(3) 32 sage: Q.siegel_product(5) 48 sage: Q.siegel_product(6) 96 sage: Q.siegel_product(7) 64 sage: Q.siegel_product(9) 104 sage: Q.local_density(2,1) 1 sage: M = 4; len([v for v in mrange([M,M,M,M]) if Q(v) % M == 1]) / M^3 1 sage: M = 16; len([v for v in mrange([M,M,M,M]) if Q(v) % M == 1]) / M^3 # long time (41s on sage.math, 2011) 1 sage: Q.local_density(2,2) 3/2 sage: M = 4; len([v for v in mrange([M,M,M,M]) if Q(v) % M == 2]) / M^3 3/2 sage: M = 16; len([v for v in mrange([M,M,M,M]) if Q(v) % M == 2]) / M^3 # long time (41s on sage.math, 2011) 3/2 TESTS:: sage: [1] + [Q.siegel_product(ZZ(a)) for a in range(1,11)] == Q.theta_series(11).list() True """ ## Protect u (since it fails often if it's an just an int!) u = ZZ(u) n = self.dim() d = self.det( ) ## ??? Warning: This is a factor of 2^n larger than it should be! ## DIAGNOSTIC verbose("n = " + str(n)) verbose("d = " + str(d)) verbose("In siegel_product: d = ", d, "\n") ## Product of "bad" places to omit S = 2 * d * u ## DIAGNOSTIC verbose("siegel_product Break 1. \n") verbose(" u = ", u, "\n") ## Make the odd generic factors if ((n % 2) == 1): m = (n - 1) / 2 d1 = fundamental_discriminant( ((-1)**m) * 2 * d * u) ## Replaced d by 2d here to compensate for the determinant f = abs( d1) ## gaining an odd power of 2 by using the matrix of 2Q instead ## of the matrix of Q. ## --> Old d1 = CoreDiscriminant((mpz_class(-1)^m) * d * u); ## Make the ratio of factorials factor: [(2m)! / m!] * prod_{i=1}^m (2*i-1) factor1 = 1 for i in range(1, m + 1): factor1 *= 2 * i - 1 for i in range(m + 1, 2 * m + 1): factor1 *= i genericfactor = factor1 * ((u / f) ** m) \ * QQ(sqrt((2 ** n) * f) / (u * d)) \ * abs(QuadraticBernoulliNumber(m, d1) / bernoulli(2*m)) ## DIAGNOSTIC verbose("siegel_product Break 2. \n") ## Make the even generic factor if ((n % 2) == 0): m = n / 2 d1 = fundamental_discriminant(((-1)**m) * d) f = abs(d1) ## DIAGNOSTIC #cout << " mpz_class(-1)^m = " << (mpz_class(-1)^m) << " and d = " << d << endl; #cout << " f = " << f << " and d1 = " << d1 << endl; genericfactor = m / QQ(sqrt(f*d)) \ * ((u/2) ** (m-1)) * (f ** m) \ / abs(QuadraticBernoulliNumber(m, d1)) \ * (2 ** m) ## This last factor compensates for using the matrix of 2*Q ##return genericfactor ## Omit the generic factors in S and compute them separately omit = 1 include = 1 S_divisors = prime_divisors(S) ## DIAGNOSTIC #cout << "\n S is " << S << endl; #cout << " The Prime divisors of S are :"; #PrintV(S_divisors); for p in S_divisors: Q_normal = self.local_normal_form(p) ## DIAGNOSTIC verbose(" p = " + str(p) + " and its Kronecker symbol (d1/p) = (" + str(d1) + "/" + str(p) + ") is " + str(kronecker_symbol(d1, p)) + "\n") omit *= 1 / (1 - (kronecker_symbol(d1, p) / (p**m))) ## DIAGNOSTIC verbose(" omit = " + str(omit) + "\n") verbose(" Q_normal is \n" + str(Q_normal) + "\n") verbose(" Q_normal = \n" + str(Q_normal)) verbose(" p = " + str(p) + "\n") verbose(" u = " + str(u) + "\n") verbose(" include = " + str(include) + "\n") include *= Q_normal.local_density(p, u) ## DIAGNOSTIC #cout << " Including the p = " << p << " factor: " << local_density(Q_normal, p, u) << endl; ## DIAGNSOTIC verbose(" --- Exiting loop \n") #// **************** Important ******************* #// Additional fix (only included for n=4) to deal #// with the power of 2 introduced at the real place #// by working with Q instead of 2*Q. This needs to #// be done for all other n as well... #/* #if (n==4) # genericfactor = 4 * genericfactor; #*/ ## DIAGNSOTIC #cout << endl; #cout << " generic factor = " << genericfactor << endl; #cout << " omit = " << omit << endl; #cout << " include = " << include << endl; #cout << endl; ## DIAGNSOTIC #// cout << "siegel_product Break 3. " << endl; ## Return the final factor (and divide by 2 if n=2) if (n == 2): return (genericfactor * omit * include / 2) else: return (genericfactor * omit * include)
def HermitianModularFormD2Factory( precision, discriminant = None ) : """ Create an instance of a factory for Fourier expansions of Hermitian modular forms. INPUT: - ``precision`` -- An integer or an instance of a precision class. - ``discriminant`` -- A negative integer or ``None`` (default: ``None``); The fundamental discriminant of an imaginary quadratic field. Can be omited if the precision is not an integer. OUTPUT: An instance of :class:~`.HermitianModularFormD2Factory_class`. SEE: :class:~`.HermitianModularFormD2Factory_class`. TESTS:: sage: from hermitianmodularforms.hermitianmodularformd2_fegenerators import HermitianModularFormD2Factory sage: from hermitianmodularforms.hermitianmodularformd2_fourierexpansion import HermitianModularFormD2Filter_diagonal sage: h = HermitianModularFormD2Factory(3, -3) sage: h.precision() Reduced diagonal filter for discriminant -3 with bound 3 sage: HermitianModularFormD2Factory(HermitianModularFormD2Filter_diagonal(2, -3)) Factory for Fourier expansions of hermitian modular forms with precision Reduced diagonal filter for discriminant -3 with bound 2 sage: HermitianModularFormD2Factory(HermitianModularFormD2Filter_diagonal(2, -3), -4) Traceback (most recent call last): ... ValueError: Discriminant must coinside with the precision's discriminant. sage: HermitianModularFormD2Factory(2, -1) Traceback (most recent call last): ... ValueError: Discriminant must be a fundamental discriminant. sage: HermitianModularFormD2Factory(2, -4) Traceback (most recent call last): ... NotImplementedError: Only discriminant -3 is implemented. """ if not isinstance(precision, HermitianModularFormD2Filter_diagonal) : if discriminant is None : raise ValueError( "If precision is not a precision class, discriminant must be set." ) precision = HermitianModularFormD2Filter_diagonal(precision, discriminant) else : if not discriminant is None and precision.discriminant() != discriminant : raise ValueError( "Discriminant must coinside with the precision's discriminant." ) else : discriminant = precision.discriminant() if discriminant >= 0 : raise ValueError( "Discriminant must be negative." ) if fundamental_discriminant(discriminant) != discriminant : raise ValueError( "Discriminant must be a fundamental discriminant." ) if discriminant != -3 : raise NotImplementedError( "Only discriminant -3 is implemented." ) key = (precision) global _hermitianmodularformd2factory_cache try : return _hermitianmodularformd2factory_cache[key] except : factory = HermitianModularFormD2Factory_class(precision) _hermitianmodularformd2factory_cache[key] = factory return factory
def HermitianModularFormD2Factory(precision, discriminant=None): """ Create an instance of a factory for Fourier expansions of Hermitian modular forms. INPUT: - ``precision`` -- An integer or an instance of a precision class. - ``discriminant`` -- A negative integer or ``None`` (default: ``None``); The fundamental discriminant of an imaginary quadratic field. Can be omited if the precision is not an integer. OUTPUT: An instance of :class:~`.HermitianModularFormD2Factory_class`. SEE: :class:~`.HermitianModularFormD2Factory_class`. TESTS:: sage: from hermitianmodularforms.hermitianmodularformd2_fegenerators import HermitianModularFormD2Factory sage: from hermitianmodularforms.hermitianmodularformd2_fourierexpansion import HermitianModularFormD2Filter_diagonal sage: h = HermitianModularFormD2Factory(3, -3) sage: h.precision() Reduced diagonal filter for discriminant -3 with bound 3 sage: HermitianModularFormD2Factory(HermitianModularFormD2Filter_diagonal(2, -3)) Factory for Fourier expansions of hermitian modular forms with precision Reduced diagonal filter for discriminant -3 with bound 2 sage: HermitianModularFormD2Factory(HermitianModularFormD2Filter_diagonal(2, -3), -4) Traceback (most recent call last): ... ValueError: Discriminant must coinside with the precision's discriminant. sage: HermitianModularFormD2Factory(2, -1) Traceback (most recent call last): ... ValueError: Discriminant must be a fundamental discriminant. sage: HermitianModularFormD2Factory(2, -4) Traceback (most recent call last): ... NotImplementedError: Only discriminant -3 is implemented. """ if not isinstance(precision, HermitianModularFormD2Filter_diagonal): if discriminant is None: raise ValueError( "If precision is not a precision class, discriminant must be set." ) precision = HermitianModularFormD2Filter_diagonal( precision, discriminant) else: if not discriminant is None and precision.discriminant( ) != discriminant: raise ValueError( "Discriminant must coinside with the precision's discriminant." ) else: discriminant = precision.discriminant() if discriminant >= 0: raise ValueError("Discriminant must be negative.") if fundamental_discriminant(discriminant) != discriminant: raise ValueError("Discriminant must be a fundamental discriminant.") if discriminant != -3: raise NotImplementedError("Only discriminant -3 is implemented.") key = (precision) global _hermitianmodularformd2factory_cache try: return _hermitianmodularformd2factory_cache[key] except: factory = HermitianModularFormD2Factory_class(precision) _hermitianmodularformd2factory_cache[key] = factory return factory