Hypergeometric functions over arbitrary rings¶
When the given variable \(x\) is not symbolic but lies in a polynomial
ring or a power series ring, the hypergeometric function, implemented by
Hypergeometric,
returns an instance of the class HypergeometricAlgebraic:
sage: S.<x> = QQ[]
sage: f = hypergeometric([1/9, 4/9, 5/9], [1/3, 1], x)
sage: f.parent()
Hypergeometric functions in x over Rational Field
>>> from sage.all import *
>>> S = QQ['x']; (x,) = S._first_ngens(1)
>>> f = hypergeometric([Integer(1)/Integer(9), Integer(4)/Integer(9), Integer(5)/Integer(9)], [Integer(1)/Integer(3), Integer(1)], x)
>>> f.parent()
Hypergeometric functions in x over Rational Field
Below, we illustrate the main features provided by this class. We introduce two additional hypergeometric series which will serve as running examples:
sage: g = hypergeometric([1/2, 5/6, 1], [5/3, 2], x)
sage: h = hypergeometric([1/5, 1/5, 1/5, 1/5], [1/3, 27/5 - 1], x)
>>> from sage.all import *
>>> g = hypergeometric([Integer(1)/Integer(2), Integer(5)/Integer(6), Integer(1)], [Integer(5)/Integer(3), Integer(2)], x)
>>> h = hypergeometric([Integer(1)/Integer(5), Integer(1)/Integer(5), Integer(1)/Integer(5), Integer(1)/Integer(5)], [Integer(1)/Integer(3), Integer(27)/Integer(5) - Integer(1)], x)
Hypergeometric functions over \(\QQ\)
A series \(s(x)\) is said globally bounded when it has positive radius
of convergence and there exist integers \(a\) and \(b\) such that \(a \cdot
s(bx)\) has integral coefficients.
The method is_globally_bounded() checks
when this property is satisfied:
sage: f.is_globally_bounded()
True
sage: g.is_globally_bounded()
True
sage: h.is_globally_bounded()
False
>>> from sage.all import *
>>> f.is_globally_bounded()
True
>>> g.is_globally_bounded()
True
>>> h.is_globally_bounded()
False
More generally, the method
HypergeometricAlgebraic_QQ.good_reduction_primes() returns the
set of primes modulo which the hypergeometric function can be reduced:
sage: f.good_reduction_primes()
Set of all prime numbers with 3 excluded: 2, 5, 7, 11, ...
sage: g.good_reduction_primes()
Set of all prime numbers with 2 excluded: 3, 5, 7, 11, ...
sage: h.good_reduction_primes()
Set of prime numbers congruent to 1, 8, 11 modulo 15 with 3, 17 included and 11 excluded: 3, 17, 23, 31, ...
>>> from sage.all import *
>>> f.good_reduction_primes()
Set of all prime numbers with 3 excluded: 2, 5, 7, 11, ...
>>> g.good_reduction_primes()
Set of all prime numbers with 2 excluded: 3, 5, 7, 11, ...
>>> h.good_reduction_primes()
Set of prime numbers congruent to 1, 8, 11 modulo 15 with 3, 17 included and 11 excluded: 3, 17, 23, 31, ...
On a different note, the method is_algebraic()
checks whether an hypergeometric series defines an algebraic function
over \(\QQ(x)\):
sage: f.is_algebraic()
False
sage: g.is_algebraic()
True
sage: h.is_algebraic()
False
>>> from sage.all import *
>>> f.is_algebraic()
False
>>> g.is_algebraic()
True
>>> h.is_algebraic()
False
Hypergeometric functions over finite fields
When \(p\) is a prime of good reduction of an hypergeometric function, we
can reduce the latter modulo \(p\) using the mod operator (%):
sage: f19 = f % 19
sage: f19
hypergeometric((1/9, 4/9, 5/9), (1/3, 1), x)
sage: f19.base_ring()
Finite Field of size 19
>>> from sage.all import *
>>> f19 = f % Integer(19)
>>> f19
hypergeometric((1/9, 4/9, 5/9), (1/3, 1), x)
>>> f19.base_ring()
Finite Field of size 19
A remarkable feature of hypergeometric functions over finite fields is
that they are always algebraic!
The method annihilating_ore_polynomial()
returns an annihilating polynomial (in the Frobenius):
sage: f19.annihilating_ore_polynomial()
(18*x^76 + 13*x^57 + 6*x^38 + 17*x^19 + 12)*Frob^2 +
(12*x^38 + 11*x^32 + 10*x^31 + ... + 18*x^12 + 7)*Frob +
x^30 + 16*x^29 + 9*x^28 + ... + 6*x^13 + x^12
>>> from sage.all import *
>>> f19.annihilating_ore_polynomial()
(18*x^76 + 13*x^57 + 6*x^38 + 17*x^19 + 12)*Frob^2 +
(12*x^38 + 11*x^32 + 10*x^31 + ... + 18*x^12 + 7)*Frob +
x^30 + 16*x^29 + 9*x^28 + ... + 6*x^13 + x^12
One subtlety is positive characteristic is that different set of parameters may lead to the same series:
sage: T.<y> = GF(13)[]
sage: h1 = hypergeometric([1/12, 1/4], [1/2], y)
sage: h2 = hypergeometric([1/12, 1/6], [1/3], y)
sage: h1.power_series(500)
1 + 6*y + 6*y^13 + 10*y^14 + 6*y^169 + 10*y^170 + 10*y^182 + 8*y^183 + O(y^500)
sage: h2.power_series(500)
1 + 6*y + 6*y^13 + 10*y^14 + 6*y^169 + 10*y^170 + 10*y^182 + 8*y^183 + O(y^500)
>>> from sage.all import *
>>> T = GF(Integer(13))['y']; (y,) = T._first_ngens(1)
>>> h1 = hypergeometric([Integer(1)/Integer(12), Integer(1)/Integer(4)], [Integer(1)/Integer(2)], y)
>>> h2 = hypergeometric([Integer(1)/Integer(12), Integer(1)/Integer(6)], [Integer(1)/Integer(3)], y)
>>> h1.power_series(Integer(500))
1 + 6*y + 6*y^13 + 10*y^14 + 6*y^169 + 10*y^170 + 10*y^182 + 8*y^183 + O(y^500)
>>> h2.power_series(Integer(500))
1 + 6*y + 6*y^13 + 10*y^14 + 6*y^169 + 10*y^170 + 10*y^182 + 8*y^183 + O(y^500)
The method is_equal_as_series() checks
when this happens:
sage: h1.is_equal_as_series(h2)
True
>>> from sage.all import *
>>> h1.is_equal_as_series(h2)
True
Hypergeometric functions over \(p\)-adic fields
Some methods related to \(p\)-adic properties of hypergeometric series are also available,. This includes the computation of the \(p\)-adic valuation:
sage: hp3 = h.change_ring(Qp(3))
sage: hp3.valuation()
0
>>> from sage.all import *
>>> hp3 = h.change_ring(Qp(Integer(3)))
>>> hp3.valuation()
0
We can also compute the \(p\)-adic radius of convergence:
sage: hp3.log_radius_of_convergence()
2
>>> from sage.all import *
>>> hp3.log_radius_of_convergence()
2
Here, the log radius of convergence refers to the exponent on \(p\) of the actual radius of convergence; in our example, the \(p\)-adic radius of convergence of \(h\) is then \(p^2\).
Evaluation of hypergeometric series at \(p\)-adic arguments also works:
sage: hp3(1/3)
3 + 3^4 + 2*3^5 + 2*3^7 + 3^8 + 2*3^9 + 2*3^10 + 3^11 + 3^12 + 3^13 + 2*3^14 + 2*3^15 + 3^16 + 3^17 + 3^19 + O(3^20)
sage: hp3(1/9)
Traceback (most recent call last):
...
ValueError: outside the domain of convergence
>>> from sage.all import *
>>> hp3(Integer(1)/Integer(3))
3 + 3^4 + 2*3^5 + 2*3^7 + 3^8 + 2*3^9 + 2*3^10 + 3^11 + 3^12 + 3^13 + 2*3^14 + 2*3^15 + 3^16 + 3^17 + 3^19 + O(3^20)
>>> hp3(Integer(1)/Integer(9))
Traceback (most recent call last):
...
ValueError: outside the domain of convergence
AUTHORS:
Xavier Caruso, Florian Fürnsinn (2026-02): initial version
- class sage.functions.hypergeometric_algebraic.HypergeometricAlgebraic(parent, arg1, arg2=None, scalar=None, check=True)[source]¶
Bases:
ElementClass for (scalar multiples of) hypergeometric functions over arbitrary base rings.
- base_ring()[source]¶
Return the ring over which this hypergeometric function is defined.
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.base_ring() Rational Field
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.base_ring() Rational Field
sage: T.<y> = Qp(5)[] sage: g = hypergeometric([1/3, 2/3], [1/2], y) sage: g.base_ring() 5-adic Field with capped relative precision 20
[Python]>>> from sage.all import * >>> T = Qp(Integer(5))['y']; (y,) = T._first_ngens(1) >>> g = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], y) >>> g.base_ring() 5-adic Field with capped relative precision 20
sage: U.<z> = GF(5)[] sage: h = hypergeometric([1/3, 2/3], [1/2], z) sage: h.base_ring() Finite Field of size 5
>>> from sage.all import * >>> U = GF(Integer(5))['z']; (z,) = U._first_ngens(1) >>> h = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], z) >>> h.base_ring() Finite Field of size 5
sage: V.<w> = CC[] sage: k = hypergeometric([1/3, 2/3], [1/2], w) sage: k.base_ring() Complex Field with 53 bits of precision
[Python]>>> from sage.all import * >>> V = CC['w']; (w,) = V._first_ngens(1) >>> k = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], w) >>> k.base_ring() Complex Field with 53 bits of precision
- bottom()[source]¶
Return the bottom parameters of this hypergeometric function (excluding the extra
1).EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.bottom() (1/2,)
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.bottom() (1/2,)
- change_ring(R)[source]¶
Return this hypergeometric function with changed base ring.
INPUT:
R– a commutative ring
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.base_ring() Rational Field sage: g = f.change_ring(Qp(5)) sage: g.base_ring() 5-adic Field with capped relative precision 20
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.base_ring() Rational Field >>> g = f.change_ring(Qp(Integer(5))) >>> g.base_ring() 5-adic Field with capped relative precision 20
- change_variable_name(name)[source]¶
Return this hypergeometric function with changed variable name
INPUT:
name– a string, the new variable name
EXAMPLES:
sage: S.<x> = Qp(5)[] sage: T.<y> = Qp(5)[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f hypergeometric((1/3, 2/3), (1/2,), x) sage: g = f.change_variable_name('y') sage: g hypergeometric((1/3, 2/3), (1/2,), y)
>>> from sage.all import * >>> S = Qp(Integer(5))['x']; (x,) = S._first_ngens(1) >>> T = Qp(Integer(5))['y']; (y,) = T._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f hypergeometric((1/3, 2/3), (1/2,), x) >>> g = f.change_variable_name('y') >>> g hypergeometric((1/3, 2/3), (1/2,), y)
- coefficient(n)[source]¶
Return the
n-th coefficient of the series representation of this hypergeometric function.INPUT:
n– a non-negative integer
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.coefficient(9) 409541017600/2541865828329 sage: g = f % 5 sage: g.coefficient(9) 0
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.coefficient(Integer(9)) 409541017600/2541865828329 >>> g = f % Integer(5) >>> g.coefficient(Integer(9)) 0
- degree()[source]¶
Return the degree of this hypergeometric function if it is a polynomial,
+Infinityotherwise.EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, -3], [1/2], x) sage: f.degree() 3
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), -Integer(3)], [Integer(1)/Integer(2)], x) >>> f.degree() 3
sage: g = hypergeometric([1/3, 2/3], [1/2], x) sage: g.degree() +Infinity
[Python]>>> from sage.all import * >>> g = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> g.degree() +Infinity
Currently, this method is only implemented in characteristic zero:
sage: T.<y> = GF(5)[] sage: h = hypergeometric([1/3, 2/3], [1/2], y) sage: h.degree() Traceback (most recent call last): ... NotImplementedError: degree is not implemented in positive characteristic
>>> from sage.all import * >>> T = GF(Integer(5))['y']; (y,) = T._first_ngens(1) >>> h = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], y) >>> h.degree() Traceback (most recent call last): ... NotImplementedError: degree is not implemented in positive characteristic
- derivative()[source]¶
Return the derivative of this hypergeometric function.
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.derivative() 4/9*hypergeometric((4/3, 5/3), (3/2,), x)
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.derivative() 4/9*hypergeometric((4/3, 5/3), (3/2,), x)
- differential_operator(var='d')[source]¶
Return the hypergeometric differential operator that annihilates this hypergeometric function as an Ore polynomial in the variable
var.INPUT:
var– a string (default:d), the variable name of the derivation
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.differential_operator(var='D') (-x^2 + x)*D^2 + (-2*x + 1/2)*D - 2/9
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.differential_operator(var='D') (-x^2 + x)*D^2 + (-2*x + 1/2)*D - 2/9
Note that this does not necessarily give the minimal differential operator annihilating this hypergeometric function: in the example below, this method returns an operator of order \(3\) where \(g\) is solution of a differential equation of order \(2\):
sage: g = hypergeometric([1/3, 2/3, 6/5], [1/5, 1/2], x) sage: L = g.differential_operator() sage: L.degree() 3 sage: gs = g.power_series(100) sage: (72*x^3 - 234*x^2 + 162*x)*gs.derivative(2) + (144*x^2 - 450*x + 81)*gs.derivative() + (16*x - 216)*gs O(x^99)
[Python]>>> from sage.all import * >>> g = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3), Integer(6)/Integer(5)], [Integer(1)/Integer(5), Integer(1)/Integer(2)], x) >>> L = g.differential_operator() >>> L.degree() 3 >>> gs = g.power_series(Integer(100)) >>> (Integer(72)*x**Integer(3) - Integer(234)*x**Integer(2) + Integer(162)*x)*gs.derivative(Integer(2)) + (Integer(144)*x**Integer(2) - Integer(450)*x + Integer(81))*gs.derivative() + (Integer(16)*x - Integer(216))*gs O(x^99)
- hadamard_product(other)[source]¶
Return the Hadamard product of this hypergeometric function and
other.INPUT:
other– a hypergeometric function
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: h = 1/2*hypergeometric([1/5, 2/5], [3/5], x) sage: f.hadamard_product(h) 1/2*hypergeometric((1/5, 1/3, 2/5, 2/3), (1/2, 3/5, 1), x)
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> h = Integer(1)/Integer(2)*hypergeometric([Integer(1)/Integer(5), Integer(2)/Integer(5)], [Integer(3)/Integer(5)], x) >>> f.hadamard_product(h) 1/2*hypergeometric((1/5, 1/3, 2/5, 2/3), (1/2, 3/5, 1), x)
- is_equal_as_series(other)[source]¶
Return whether
selfandotherdefine the same series.INPUT:
other– an hypergeometric function over the same base
EXAMPLES:
sage: S.<x> = GF(13)[] sage: f = hypergeometric([1/12, 1/6], [1/3], x) sage: g = hypergeometric([1/12, 1/4], [1/2], x) sage: f.is_equal_as_series(g) True
>>> from sage.all import * >>> S = GF(Integer(13))['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(12), Integer(1)/Integer(6)], [Integer(1)/Integer(3)], x) >>> g = hypergeometric([Integer(1)/Integer(12), Integer(1)/Integer(4)], [Integer(1)/Integer(2)], x) >>> f.is_equal_as_series(g) True
Note that this method is not implemented over all bases:
sage: S.<x> = Integers(169)[] sage: f = hypergeometric([1/12, 1/6], [1/3], x) sage: g = hypergeometric([1/12, 1/4], [1/2], x) sage: f.is_equal_as_series(g) Traceback (most recent call last): ... NotImplementedError: equality as series is not implemented over Ring of integers modulo 169
[Python]>>> from sage.all import * >>> S = Integers(Integer(169))['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(12), Integer(1)/Integer(6)], [Integer(1)/Integer(3)], x) >>> g = hypergeometric([Integer(1)/Integer(12), Integer(1)/Integer(4)], [Integer(1)/Integer(2)], x) >>> f.is_equal_as_series(g) Traceback (most recent call last): ... NotImplementedError: equality as series is not implemented over Ring of integers modulo 169
See also
- is_equal_symbolically(other)[source]¶
Return whether if the parameters defining the hypergeometric series
selfandotherare the same.INPUT:
other– an hypergeometric function
EXAMPLES:
The order of the parameters is not relevant:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/12, 1/6], [1/3], x) sage: g = hypergeometric([1/6, 1/12], [1/3], x) sage: f.is_equal_symbolically(g) True
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(12), Integer(1)/Integer(6)], [Integer(1)/Integer(3)], x) >>> g = hypergeometric([Integer(1)/Integer(6), Integer(1)/Integer(12)], [Integer(1)/Integer(3)], x) >>> f.is_equal_symbolically(g) True
sage: h = hypergeometric([1/12, 1/4], [1/2], x) sage: g.is_equal_symbolically(h) False
[Python]>>> from sage.all import * >>> h = hypergeometric([Integer(1)/Integer(12), Integer(1)/Integer(4)], [Integer(1)/Integer(2)], x) >>> g.is_equal_symbolically(h) False
We emphasize that two hypergeometric functions are considered as different as soon as they have different parameters even if they define the same series:
sage: Fq = GF(13) sage: g13 = g % 13 sage: h13 = h % 13 sage: g13 == h13 False sage: g13.power_series(500) 1 + 6*x + 6*x^13 + 10*x^14 + 6*x^169 + 10*x^170 + 10*x^182 + 8*x^183 + O(x^500) sage: h13.power_series(500) 1 + 6*x + 6*x^13 + 10*x^14 + 6*x^169 + 10*x^170 + 10*x^182 + 8*x^183 + O(x^500)
>>> from sage.all import * >>> Fq = GF(Integer(13)) >>> g13 = g % Integer(13) >>> h13 = h % Integer(13) >>> g13 == h13 False >>> g13.power_series(Integer(500)) 1 + 6*x + 6*x^13 + 10*x^14 + 6*x^169 + 10*x^170 + 10*x^182 + 8*x^183 + O(x^500) >>> h13.power_series(Integer(500)) 1 + 6*x + 6*x^13 + 10*x^14 + 6*x^169 + 10*x^170 + 10*x^182 + 8*x^183 + O(x^500)
See also
- is_polynomial()[source]¶
Return whether this hypergeometric series is a polynomial.
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, -3], [1/2], x) sage: f.is_polynomial() True
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), -Integer(3)], [Integer(1)/Integer(2)], x) >>> f.is_polynomial() True
sage: g = hypergeometric([1/3, 2/3], [1/2], x) sage: g.is_polynomial() False
[Python]>>> from sage.all import * >>> g = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> g.is_polynomial() False
- polynomial()[source]¶
Return a polynomial representing a hypergeometric function, or raise an error if this hypergeometric function is not polynomial.
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, -3], [1/2], x) sage: f.polynomial() -224/405*x^3 + 16/9*x^2 - 2*x + 1
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), -Integer(3)], [Integer(1)/Integer(2)], x) >>> f.polynomial() -224/405*x^3 + 16/9*x^2 - 2*x + 1
sage: g = hypergeometric([1/3, 2/3], [1/2], x) sage: g.polynomial() Traceback (most recent call last): ... ValueError: this hypergeometric series is not a polynomial
[Python]>>> from sage.all import * >>> g = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> g.polynomial() Traceback (most recent call last): ... ValueError: this hypergeometric series is not a polynomial
- power_series(prec=20)[source]¶
Return the power series representation of this hypergeometric function up to a given precision.
INPUT:
prec– a positive integer (default:20)
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.power_series(3) 1 + 4/9*x + 80/243*x^2 + O(x^3)
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.power_series(Integer(3)) 1 + 4/9*x + 80/243*x^2 + O(x^3)
- scalar()[source]¶
Return the scalar of this hypergeometric function.
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.scalar() 1 sage: g = 4*f sage: g.scalar() 4
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.scalar() 1 >>> g = Integer(4)*f >>> g.scalar() 4
- series(prec=20)[source]¶
alias of
power_series().
- shift(s)[source]¶
Return this hypergeometric function, where each parameter (including the additional
1as a bottom parameter) is increased bys.INPUT:
s– a rational number
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: g = f.shift(3/2) sage: g hypergeometric((1, 11/6, 13/6), (2, 5/2), x)
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> g = f.shift(Integer(3)/Integer(2)) >>> g hypergeometric((1, 11/6, 13/6), (2, 5/2), x)
- top()[source]¶
Return the top parameters of this hypergeometric function.
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.top() (1/3, 2/3)
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.top() (1/3, 2/3)
- class sage.functions.hypergeometric_algebraic.HypergeometricAlgebraic_GFp(parent, arg1, arg2=None, scalar=None, check=True)[source]¶
Bases:
HypergeometricAlgebraicClass for hypergeometric functions over prime finite fields.
- annihilating_ore_polynomial(var='Frob')[source]¶
Return an Ore polynomaial in the Frobenius morphism, that annihilates this hypergeometric function.
ALGORITHM:
See [CF2026], Subsection 3.3
INPUT:
var– a string (default:Frob), name of the variable representing the Frobenius morphism.
EXAMPLES:
sage: S.<x> = GF(5)[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.annihilating_ore_polynomial() (4*x^10 + 2*x^5 + 4)*Frob^2 + (4*x^3 + 4*x^2 + 1)*Frob + x^2 sage: s = f.power_series(1000) sage: (4*x^10 + 2*x^5 + 4)*s^(5^2) + (4*x^3 + 4*x^2 + 1)*s^5 + x^2*s O(x^1000)
>>> from sage.all import * >>> S = GF(Integer(5))['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.annihilating_ore_polynomial() (4*x^10 + 2*x^5 + 4)*Frob^2 + (4*x^3 + 4*x^2 + 1)*Frob + x^2 >>> s = f.power_series(Integer(1000)) >>> (Integer(4)*x**Integer(10) + Integer(2)*x**Integer(5) + Integer(4))*s**(Integer(5)**Integer(2)) + (Integer(4)*x**Integer(3) + Integer(4)*x**Integer(2) + Integer(1))*s**Integer(5) + x**Integer(2)*s O(x^1000)
There is no guarantee that the returned Ore polynomial is minimal. As an illustration, in the next example, the method outputs a Ore polynomial of degree \(2\) while \(f\) is already solution of a Frobenius equation of degree \(1\):
sage: S.<x> = GF(11)[] sage: f = hypergeometric([1/10, 5/24], [5/12], x) sage: f.annihilating_ore_polynomial() (8*x^12 + 6*x^11 + 6*x + 10)*Frob^2 + 1 sage: s = f.power_series(1000) sage: s == (1 + 5*x)*s^11 True
[Python]>>> from sage.all import * >>> S = GF(Integer(11))['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(10), Integer(5)/Integer(24)], [Integer(5)/Integer(12)], x) >>> f.annihilating_ore_polynomial() (8*x^12 + 6*x^11 + 6*x + 10)*Frob^2 + 1 >>> s = f.power_series(Integer(1000)) >>> s == (Integer(1) + Integer(5)*x)*s**Integer(11) True
- dwork_relation()[source]¶
Return a list \((P_1, h_1), ..., (P_s, h_s)\) where the \(P_i\) are polynomials and the \(h_i\) are hypergeometric functions such that \(P_1 h_1^p + \cdots + P_s h_s^p\) is equal to
self.Note
This method is used as a main ingrediant in the computation of an annihilating polynomial of
self(seeannihilating_ore_polynomial()).ALGORITHM:
See [CF2026], Subsection 3.2
EXAMPLES:
sage: S.<x> = GF(3)[] sage: f = hypergeometric([7/8, 9/8, 11/8], [3/2, 7/4], x) sage: f.dwork_relation() {hypergeometric((1, 21/8, 25/8, 27/8), (3, 13/4, 7/2), x): 2*x^7, hypergeometric((3/8, 5/8, 9/8), (1/2, 5/4), x): 1}
>>> from sage.all import * >>> S = GF(Integer(3))['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(7)/Integer(8), Integer(9)/Integer(8), Integer(11)/Integer(8)], [Integer(3)/Integer(2), Integer(7)/Integer(4)], x) >>> f.dwork_relation() {hypergeometric((1, 21/8, 25/8, 27/8), (3, 13/4, 7/2), x): 2*x^7, hypergeometric((3/8, 5/8, 9/8), (1/2, 5/4), x): 1}
- is_algebraic()[source]¶
Return whether this hypergeometric function is algebraic.
This method always returns
Truesince every hypergeometric function in characteristic \(p\) is algebraic.EXAMPLES:
sage: S.<x> = GF(13)[] sage: f = hypergeometric([1/5, 2/5, 3/5, 1/11], [1/2, 1/7], x) sage: f.is_algebraic() True
>>> from sage.all import * >>> S = GF(Integer(13))['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(5), Integer(2)/Integer(5), Integer(3)/Integer(5), Integer(1)/Integer(11)], [Integer(1)/Integer(2), Integer(1)/Integer(7)], x) >>> f.is_algebraic() True
- is_equal_as_series(other)[source]¶
Return whether
selfandotherdefine the same series.INPUT:
other– an hypergeometric function over the same base
EXAMPLES:
sage: S.<x> = GF(13)[] sage: f = hypergeometric([1/12, 1/6], [1/3], x) sage: g = hypergeometric([1/12, 1/4], [1/2], x) sage: f.is_equal_as_series(g) True
>>> from sage.all import * >>> S = GF(Integer(13))['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(12), Integer(1)/Integer(6)], [Integer(1)/Integer(3)], x) >>> g = hypergeometric([Integer(1)/Integer(12), Integer(1)/Integer(4)], [Integer(1)/Integer(2)], x) >>> f.is_equal_as_series(g) True
sage: f.power_series(1000) 1 + 6*x + 6*x^13 + 10*x^14 + 6*x^169 + 10*x^170 + 10*x^182 + 8*x^183 + O(x^1000) sage: g.power_series(1000) 1 + 6*x + 6*x^13 + 10*x^14 + 6*x^169 + 10*x^170 + 10*x^182 + 8*x^183 + O(x^1000)
[Python]>>> from sage.all import * >>> f.power_series(Integer(1000)) 1 + 6*x + 6*x^13 + 10*x^14 + 6*x^169 + 10*x^170 + 10*x^182 + 8*x^183 + O(x^1000) >>> g.power_series(Integer(1000)) 1 + 6*x + 6*x^13 + 10*x^14 + 6*x^169 + 10*x^170 + 10*x^182 + 8*x^183 + O(x^1000)
We emphasize that, although they define the same series, \(f\) and \(g\) are not considered as equal:
sage: f == g False
>>> from sage.all import * >>> f == g False
- is_lucas()[source]¶
Return whether this hypergeometric function has the
p-Lucas property.EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/5, 4/5], [1], x) sage: g = f % 19 sage: g.is_lucas() True sage: h = f % 17 sage: h.is_lucas() False
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(5), Integer(4)/Integer(5)], [Integer(1)], x) >>> g = f % Integer(19) >>> g.is_lucas() True >>> h = f % Integer(17) >>> h.is_lucas() False
sage: S.<x> = GF(11)[] sage: h = hypergeometric([1/10, 5/24], [5/12], x) sage: h.is_lucas() True
[Python]>>> from sage.all import * >>> S = GF(Integer(11))['x']; (x,) = S._first_ngens(1) >>> h = hypergeometric([Integer(1)/Integer(10), Integer(5)/Integer(24)], [Integer(5)/Integer(12)], x) >>> h.is_lucas() True
- p_curvature()[source]¶
Return the matrix of the \(p\)-curvature of the associated differential operator, in the standard basis.
EXAMPLES:
sage: S.<x> = GF(5)[] sage: f = hypergeometric ([1/9, 4/9, 5/9], [1/3, 1], x) sage: f.p_curvature() [ 0 2/(x^5 + 4*x^4) 1/(x^4 + 4*x^3)] [ 0 0 0] [ 0 0 0]
>>> from sage.all import * >>> S = GF(Integer(5))['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric ([Integer(1)/Integer(9), Integer(4)/Integer(9), Integer(5)/Integer(9)], [Integer(1)/Integer(3), Integer(1)], x) >>> f.p_curvature() [ 0 2/(x^5 + 4*x^4) 1/(x^4 + 4*x^3)] [ 0 0 0] [ 0 0 0]
The following example defines an algebraic function over
QQ, thus its p-curvature vanishes for almost all of its reductions.:sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.is_algebraic() True sage: g = f % 5 sage: g.p_curvature() [0 0] [0 0]
[Python]>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.is_algebraic() True >>> g = f % Integer(5) >>> g.p_curvature() [0 0] [0 0]
- p_curvature_corank()[source]¶
Return the corank of the
p-curvature matrix.ALGORITHM:
We use [CFV2025], Thm. 3.1.17 and the fact that the corank of the p-curvature agrees with the number of solutions of the hypergeometric differential equation.
EXAMPLES:
sage: S.<x> = GF(5)[] sage: f = hypergeometric([1/9, 4/9, 5/9], [1/3, 1], x) sage: f.p_curvature_corank() 2
>>> from sage.all import * >>> S = GF(Integer(5))['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(9), Integer(4)/Integer(9), Integer(5)/Integer(9)], [Integer(1)/Integer(3), Integer(1)], x) >>> f.p_curvature_corank() 2
- section(r)[source]¶
Return the \(r\)-th section of this hypergeometric series: if this series reads \(\sum_n a_n x^n\), it is by definition
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([7/8, 9/8, 11/8], [3/2, 7/4], x) sage: g = f % 5 sage: g.section(0) hypergeometric((3/8, 5/8, 7/8), (1/2, 3/4), x) sage: g.section(1) 2*hypergeometric((3/8, 5/8, 7/8), (1/2, 3/4), x) sage: g.section(2) hypergeometric((5/8, 7/8, 11/8), (3/4, 3/2), x)
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(7)/Integer(8), Integer(9)/Integer(8), Integer(11)/Integer(8)], [Integer(3)/Integer(2), Integer(7)/Integer(4)], x) >>> g = f % Integer(5) >>> g.section(Integer(0)) hypergeometric((3/8, 5/8, 7/8), (1/2, 3/4), x) >>> g.section(Integer(1)) 2*hypergeometric((3/8, 5/8, 7/8), (1/2, 3/4), x) >>> g.section(Integer(2)) hypergeometric((5/8, 7/8, 11/8), (3/4, 3/2), x)
In certain rare cases, the section is not a scalar multiple of an hypergeometric function, by a monomial times a hypergeometric function. Since there is no support for such functions in SageMath at the time being, an error is raised in this case:
sage: g = f % 3 sage: g.section(1) Traceback (most recent call last): ... NotImplementedError: the reduction is not a hypergeometric function
[Python]>>> from sage.all import * >>> g = f % Integer(3) >>> g.section(Integer(1)) Traceback (most recent call last): ... NotImplementedError: the reduction is not a hypergeometric function
- class sage.functions.hypergeometric_algebraic.HypergeometricAlgebraic_QQ(parent, arg1, arg2=None, scalar=None, check=True)[source]¶
Bases:
HypergeometricAlgebraicClass for hypergeometric functions over \(\QQ\).
- good_reduction_primes()[source]¶
Return the set of prime numbers modulo which this hypergeometric function can be reduced, i.e., the p-adic valuation is nonnegative.
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.good_reduction_primes() Set of all prime numbers with 3 excluded: 2, 5, 7, 11, ...
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.good_reduction_primes() Set of all prime numbers with 3 excluded: 2, 5, 7, 11, ...
ALGORITHM:
We implement the algorithm of [CF2026], Subsection 3.1
EXAMPLES:
sage: f = hypergeometric([1/5, 2/5, 3/5], [1/2, 1/7, 1/11], x) sage: f.good_reduction_primes() Finite set of prime numbers: 2, 7, 11
[Python]>>> from sage.all import * >>> f = hypergeometric([Integer(1)/Integer(5), Integer(2)/Integer(5), Integer(3)/Integer(5)], [Integer(1)/Integer(2), Integer(1)/Integer(7), Integer(1)/Integer(11)], x) >>> f.good_reduction_primes() Finite set of prime numbers: 2, 7, 11
sage: g = hypergeometric([1/4, 1/2, 3/4], [1/8], x) sage: g.good_reduction_primes() Set of prime numbers congruent to 3, 5, 7 modulo 8: 3, 5, 7, 11, ... sage: (73*g).good_reduction_primes() Set of prime numbers congruent to 3, 5, 7 modulo 8 with 73 included: 3, 5, 7, 11, ...
>>> from sage.all import * >>> g = hypergeometric([Integer(1)/Integer(4), Integer(1)/Integer(2), Integer(3)/Integer(4)], [Integer(1)/Integer(8)], x) >>> g.good_reduction_primes() Set of prime numbers congruent to 3, 5, 7 modulo 8: 3, 5, 7, 11, ... >>> (Integer(73)*g).good_reduction_primes() Set of prime numbers congruent to 3, 5, 7 modulo 8 with 73 included: 3, 5, 7, 11, ...
- has_good_reduction(p)[source]¶
Return whether the \(p\)-adic valuation of this hypergeometric function is nonnegative, i.e., if its reduction modulo
pis well-defined.INPUT:
p– a prime number
EXAMPLES:
sage: S.<x> = QQ[x] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.valuation(5) 0 sage: f.has_good_reduction(5) True sage: g = 1/5*f sage: g.has_good_reduction(5) False
>>> from sage.all import * >>> S = QQ[x]; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.valuation(Integer(5)) 0 >>> f.has_good_reduction(Integer(5)) True >>> g = Integer(1)/Integer(5)*f >>> g.has_good_reduction(Integer(5)) False
- is_algebraic()[source]¶
Return
Trueif this hypergeometric function is algebraic over the rational functions, returnFalseotherwise.ALGORITHM:
We rely on the (Christol-)Beukers-Heckmann interlacing criterion (see [Chr1986], p.15, Cor.; [BeukersHeckman], Thm. 4.5). For integer differences between parameters we follow the flowchart in [FY2024], Fig. 1.
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.is_algebraic() True sage: g = hypergeometric([1/3, 2/3, 1/4], [5/4, 1/2], x) sage: g.is_algebraic() False
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.is_algebraic() True >>> g = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3), Integer(1)/Integer(4)], [Integer(5)/Integer(4), Integer(1)/Integer(2)], x) >>> g.is_algebraic() False
Using \(fricas\), we can further compute minimal polynomials:
sage: fricas.guessAlg(f.power_series(20).list()) # optional - fricas [ n 3 [[x ]f(x): (4 x - 4)f(x) + 3 f(x) + 1 = 0, 2 3 4 x 80 x 1792 x 4 f(x) = 1 + --- + ----- + ------- + O(x )] 9 243 6561 ]
[Python]>>> from sage.all import * >>> fricas.guessAlg(f.power_series(Integer(20)).list()) # optional - fricas [ n 3 [[x ]f(x): (4 x - 4)f(x) + 3 f(x) + 1 = 0, 2 3 4 x 80 x 1792 x 4 f(x) = 1 + --- + ----- + ------- + O(x )] 9 243 6561 ]
- is_globally_bounded(include_infinity=True)[source]¶
Return whether this hypergeometric function is globally bounded (if
include_infinityisFalseit is not checked whether the radius of convergence is finite).INPUT:
include_infinity– a boolean (default:True)
ALGORITHM:
We rely on Christol’s classification of globally bounded hypergeometric functions (see [Chr1986], Prop. 1).
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/9, 4/9, 5/9], [1/3, 1], x) sage: f.is_globally_bounded() True sage: g = hypergeometric([1/9, 4/9, 5/9], [1/3], x) sage: g.is_globally_bounded() False sage: g.is_globally_bounded(include_infinity=False) True
- is_maximum_unipotent_monodromy()[source]¶
Return whether the hypergeometric differential operator associated to this hypergeometric function has maximal unipotent monodromy (MUM).
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.is_maximum_unipotent_monodromy() False sage: g = hypergeometric([1/9, 4/9, 5/9], [1, 2], x) sage: g.is_maximum_unipotent_monodromy() True
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.is_maximum_unipotent_monodromy() False >>> g = hypergeometric([Integer(1)/Integer(9), Integer(4)/Integer(9), Integer(5)/Integer(9)], [Integer(1), Integer(2)], x) >>> g.is_maximum_unipotent_monodromy() True
- is_mum()[source]¶
alias of
is_maximum_unipotent_monodromy().
- monodromy(x=0, var='z')[source]¶
Return a local monodromy matrix of the hypergeometric differential equation associated to this hypergeometric function at the point
x.INPUT:
x– a complex number (default:0)var– a string (default:z), the name of the variable representing a \(d\)-th root of unity for \(d\) being the least common multiple of the parameters.
EXAMPLES:
sage: S.<x> = QQ[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.monodromy() [0 1] [1 0]
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.monodromy() [0 1] [1 0]
The bases of the solution space are chosen in a compatible way across the three singularities of the differential equation:
sage: g = hypergeometric([1/9, 4/9, 5/9], [1/3, 1], x) sage: g.monodromy(var='a') [ -a^3 + 1 1 0] [2*a^3 + 1 0 1] [ -a^3 - 1 0 0] sage: g.monodromy(x=Infinity) * g.monodromy(x=1) * g.monodromy() [1 0 0] [0 1 0] [0 0 1]
[Python]>>> from sage.all import * >>> g = hypergeometric([Integer(1)/Integer(9), Integer(4)/Integer(9), Integer(5)/Integer(9)], [Integer(1)/Integer(3), Integer(1)], x) >>> g.monodromy(var='a') [ -a^3 + 1 1 0] [2*a^3 + 1 0 1] [ -a^3 - 1 0 0] >>> g.monodromy(x=Infinity) * g.monodromy(x=Integer(1)) * g.monodromy() [1 0 0] [0 1 0] [0 0 1]
ALGORITHM:
We use the explicit formulas for the monodromy matrices presented in [BeukersHeckman], Thm. 3.5, attributed to Levelt.
- p_curvature_coranks()[source]¶
Return a dictionary, where the integers from \(1\) to the number of parameters of this hypergeometric function are assigned the set of prime numbers for which the \(p\)-curvature has this given corank.
EXAMPLES:
sage: S.<x> = QQ[] sage: g = hypergeometric([1/8, 3/8, 1/2], [1/4, 5/8], x) sage: g.p_curvature_coranks() {1: Set of prime numbers congruent to 3, 5 modulo 8: 3, 5, 11, 13, ..., 2: Set of prime numbers congruent to 1, 7 modulo 8: 7, 17, 23, 31, ..., 3: Empty set of prime numbers}
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> g = hypergeometric([Integer(1)/Integer(8), Integer(3)/Integer(8), Integer(1)/Integer(2)], [Integer(1)/Integer(4), Integer(5)/Integer(8)], x) >>> g.p_curvature_coranks() {1: Set of prime numbers congruent to 3, 5 modulo 8: 3, 5, 11, 13, ..., 2: Set of prime numbers congruent to 1, 7 modulo 8: 7, 17, 23, 31, ..., 3: Empty set of prime numbers}
- valuation(p, position=False)[source]¶
Return the \(p\)-adic valuation of this hypergeometric function, i.e., the maximal \(s\), such that \(p^{-s}\) times this hypergeometric function has p-integral coefficients.
INPUT:
p– a prime numberposition– a boolean (default:False); ifTrue, return also the first index in the series expansion at which the valuation is attained.
ALGORITHM:
See [CF2026], Section 2.2
EXAMPLES:
sage: S.<x> = QQ[x] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.valuation(5) 0 sage: g = 5*f sage: g.valuation(5) 1
>>> from sage.all import * >>> S = QQ[x]; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.valuation(Integer(5)) 0 >>> g = Integer(5)*f >>> g.valuation(Integer(5)) 1
An example where we ask for the position:
sage: h = hypergeometric([1/5, 1/5, 1/5], [1/3, 9/5], x) sage: h.valuation(3, position=True) (-1, 1)
[Python]>>> from sage.all import * >>> h = hypergeometric([Integer(1)/Integer(5), Integer(1)/Integer(5), Integer(1)/Integer(5)], [Integer(1)/Integer(3), Integer(9)/Integer(5)], x) >>> h.valuation(Integer(3), position=True) (-1, 1)
We can check that the coefficient in \(x\) in the series expansion has indeed valuation \(-1\):
sage: s = h.power_series() sage: s 1 + 1/75*x + 27/8750*x^2 + ... + O(x^20) sage: s[1].valuation(3) -1
>>> from sage.all import * >>> s = h.power_series() >>> s 1 + 1/75*x + 27/8750*x^2 + ... + O(x^20) >>> s[Integer(1)].valuation(Integer(3)) -1
- class sage.functions.hypergeometric_algebraic.HypergeometricAlgebraic_padic(parent, arg1, arg2=None, scalar=None, check=True)[source]¶
Bases:
HypergeometricAlgebraicClass for hypergeometric functions over \(p\)-adic fields.
- dwork_image()[source]¶
Return the hypergeometric function obtained from this one by applying the Dwork map to each of its parameters.
EXAMPLES:
sage: S.<x> = Qp(7)[] sage: f = hypergeometric([1/4, 1/3, 1/2], [2/5, 3/5, 1], x) sage: f.dwork_image() hypergeometric((1/3, 1/2, 3/4), (1/5, 4/5, 1), x)
>>> from sage.all import * >>> S = Qp(Integer(7))['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(4), Integer(1)/Integer(3), Integer(1)/Integer(2)], [Integer(2)/Integer(5), Integer(3)/Integer(5), Integer(1)], x) >>> f.dwork_image() hypergeometric((1/3, 1/2, 3/4), (1/5, 4/5, 1), x)
- log_radius_of_convergence()[source]¶
Return the logarithmic \(p\)-adic radius of convergence of this hypergeometric function, that is the exponent on \(p\) on the \(p\)-adic radius of convergence.
EXAMPLES:
sage: S.<x> = Qp(5)[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.log_radius_of_convergence() 0
>>> from sage.all import * >>> S = Qp(Integer(5))['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.log_radius_of_convergence() 0
Here the \(p\)-adic radius of convergence is \(p^0 = 1\), whereas, in the example below, it is \(p^{5/4}\):
sage: g = hypergeometric([1/3, 2/3], [1/5], x) sage: g.log_radius_of_convergence() 5/4
[Python]>>> from sage.all import * >>> g = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(5)], x) >>> g.log_radius_of_convergence() 5/4
- newton_polygon(log_radius=None)[source]¶
Return the Newton polygon of this hypergeometric series.
INPUT:
log_radius– a rational number (default:None); the last slope of the Newton polygon; ifNone, the logarithmic \(p\)-adic radius of convergence of this hypergeometric function is used.
ALGORITHM:
See [CF2026], Section 2.3
EXAMPLES:
sage: S.<x> = Qp(19)[] sage: h = hypergeometric([1/5, 2/5, 3/5, 1/11], [1/2, 1/7], x) sage: h.newton_polygon() Traceback (most recent call last): ... ValueError: infinite Newton polygon; try to truncate it by giving a log radius less than 1/18
>>> from sage.all import * >>> S = Qp(Integer(19))['x']; (x,) = S._first_ngens(1) >>> h = hypergeometric([Integer(1)/Integer(5), Integer(2)/Integer(5), Integer(3)/Integer(5), Integer(1)/Integer(11)], [Integer(1)/Integer(2), Integer(1)/Integer(7)], x) >>> h.newton_polygon() Traceback (most recent call last): ... ValueError: infinite Newton polygon; try to truncate it by giving a log radius less than 1/18
Here the Newton polygon has an infinite number of vertices, so it cannot be computed entirely. As suggested by the error message, we can obtain a result by passing in a log radius or last slope: all the segments with slope less than this number will be discarded, resulting then in a finite number of vertices. When the given log radius gets closer to the actual log radius of convergence, the result gets more and more accurate:
sage: h.newton_polygon(1/18 - 1/10) Infinite Newton polygon with 2 vertices: (0, 0), (10, -1) ending by an infinite line of slope -2/45 sage: h.newton_polygon(1/18 - 1/1000) Infinite Newton polygon with 4 vertices: (0, 0), (10, -1), (11, -1), (144, 6) ending by an infinite line of slope 491/9000
[Python]>>> from sage.all import * >>> h.newton_polygon(Integer(1)/Integer(18) - Integer(1)/Integer(10)) Infinite Newton polygon with 2 vertices: (0, 0), (10, -1) ending by an infinite line of slope -2/45 >>> h.newton_polygon(Integer(1)/Integer(18) - Integer(1)/Integer(1000)) Infinite Newton polygon with 4 vertices: (0, 0), (10, -1), (11, -1), (144, 6) ending by an infinite line of slope 491/9000
- residue()[source]¶
Return the reduction of this hypergeometric function in the residue field of the p-adics over which this hypergeometric function is defined.
EXAMPLES:
sage: S.<x> = Qp(5)[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.parent() Hypergeometric functions in x over 5-adic Field with capped relative precision 20 sage: g = f.residue() sage: g.parent() Hypergeometric functions in x over Finite Field of size 5
>>> from sage.all import * >>> S = Qp(Integer(5))['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.parent() Hypergeometric functions in x over 5-adic Field with capped relative precision 20 >>> g = f.residue() >>> g.parent() Hypergeometric functions in x over Finite Field of size 5
- tate_series(log_radius, prec=None)[source]¶
Return this hypergeometric series viewed in the Tate algebra with the given log radius.
INPUT:
log_radius– a rational numberprec– a positive integer (default:None); ifNone, use the default precision of the base ring
EXAMPLES:
sage: K = Qp(7, prec=5, print_mode='digits') sage: S.<x> = K[] sage: h = hypergeometric([1/5, 2/5, 3/5, 1/11], [1/2, 1/7], x) sage: h.tate_series(0) ...00001 + ...40040*x + ...44000*x^2 + ...20000*x^4 + ...30000*x^3 + O(7^5 * <x>) sage: h.tate_series(1) ...562320000*x^4 + ...140040*x + ...00001 + ...5131000000*x^5 + ... + O(7^5 * <7*x>)
>>> from sage.all import * >>> K = Qp(Integer(7), prec=Integer(5), print_mode='digits') >>> S = K['x']; (x,) = S._first_ngens(1) >>> h = hypergeometric([Integer(1)/Integer(5), Integer(2)/Integer(5), Integer(3)/Integer(5), Integer(1)/Integer(11)], [Integer(1)/Integer(2), Integer(1)/Integer(7)], x) >>> h.tate_series(Integer(0)) ...00001 + ...40040*x + ...44000*x^2 + ...20000*x^4 + ...30000*x^3 + O(7^5 * <x>) >>> h.tate_series(Integer(1)) ...562320000*x^4 + ...140040*x + ...00001 + ...5131000000*x^5 + ... + O(7^5 * <7*x>)
The given log radius needs to be less than the \(p\)-adic logarithmic radius of convergence of the hypergeometric series. Otherwise, the hypergeometric series does not define an element in the corresponding Tate algebra and an error is raised:
sage: h.log_radius_of_convergence() 4/3 sage: h.tate_series(2) Traceback (most recent call last): ... ValueError: outside the domain of convergence
[Python]>>> from sage.all import * >>> h.log_radius_of_convergence() 4/3 >>> h.tate_series(Integer(2)) Traceback (most recent call last): ... ValueError: outside the domain of convergence
See also
- valuation(log_radius=0, position=False)[source]¶
Return the p-adic valuation of this hypergeometric function on the disk of logarithmic radius
log_radius, and, ifpositionisTruethe index of the first coefficient of the series that attains this valuation.INPUT:
log_radius– a rational numberposition– a boolean (default:False), ifTruethe index of the first coefficient attaining the valuation is also returned
ALGORITHM:
See [CF2026], Section 2.2
EXAMPLES:
sage: S.<x> = Qp(5)[] sage: f = hypergeometric([1/3, 2/3], [1/2], x) sage: f.valuation() 0
>>> from sage.all import * >>> S = Qp(Integer(5))['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(1)/Integer(2)], x) >>> f.valuation() 0
sage: S.<x> = Qp(5)[] sage: g = 1/5 * hypergeometric([1/3, 2/3], [5^3/3], x) sage: g.valuation(-1, position=True) (-3, 1)
[Python]>>> from sage.all import * >>> S = Qp(Integer(5))['x']; (x,) = S._first_ngens(1) >>> g = Integer(1)/Integer(5) * hypergeometric([Integer(1)/Integer(3), Integer(2)/Integer(3)], [Integer(5)**Integer(3)/Integer(3)], x) >>> g.valuation(-Integer(1), position=True) (-3, 1)
- class sage.functions.hypergeometric_algebraic.HypergeometricFunctions(base, name, symbolic_equality, category=None)[source]¶
Bases:
Parent,UniqueRepresentationHypergeometric functions over a base ring.
- base_ring()[source]¶
Return the base ring over which the hypergeometric functions in this parent are defined.
EXAMPLES:
sage: S.<x> = QQ[] sage: H = hypergeometric([], [], x).parent() sage: H.base_ring() Rational Field
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> H = hypergeometric([], [], x).parent() >>> H.base_ring() Rational Field
- change_ring(R)[source]¶
Return the parent for hypergeometric functions in the same variable over the ring
R.INPUT:
R– a commutative ring
EXAMPLES:
sage: S.<x> = QQ[] sage: H = hypergeometric([], [], x).parent() sage: H Hypergeometric functions in x over Rational Field sage: H.change_ring(GF(5)) Hypergeometric functions in x over Finite Field of size 5
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> H = hypergeometric([], [], x).parent() >>> H Hypergeometric functions in x over Rational Field >>> H.change_ring(GF(Integer(5))) Hypergeometric functions in x over Finite Field of size 5
- change_variable_name(name)[source]¶
Return the parent for hypergeometric functions over the same ring with variable name
name.INPUT:
name– a string
EXAMPLES:
sage: S.<x> = QQ[] sage: H = hypergeometric([], [], x).parent() sage: H Hypergeometric functions in x over Rational Field sage: H.change_variable_name('y') Hypergeometric functions in y over Rational Field
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> H = hypergeometric([], [], x).parent() >>> H Hypergeometric functions in x over Rational Field >>> H.change_variable_name('y') Hypergeometric functions in y over Rational Field
- latex_variable_name()[source]¶
Return the LaTeX variable name of the hypergeometric functions in this parent.
EXAMPLES:
sage: S.<xi> = QQ[] sage: H = hypergeometric([], [], xi).parent() sage: H.latex_variable_name() '\\xi'
>>> from sage.all import * >>> S = QQ['xi']; (xi,) = S._first_ngens(1) >>> H = hypergeometric([], [], xi).parent() >>> H.latex_variable_name() '\\xi'
- polynomial_ring()[source]¶
Return the polynomial ring with same variable name and same base field as
self.EXAMPLES:
sage: S.<x> = QQ[] sage: H = hypergeometric([], [], x).parent() sage: H.polynomial_ring() is S True
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> H = hypergeometric([], [], x).parent() >>> H.polynomial_ring() is S True
- power_series_ring(default_prec=None)[source]¶
Return the power series ring with same variable name and same base field as
self.INPUT:
default_prec– a positive integer orInfinity(default:20)
EXAMPLES:
sage: S.<x> = QQ[] sage: H = hypergeometric([], [], x).parent() sage: H.power_series_ring() Power Series Ring in x over Rational Field
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> H = hypergeometric([], [], x).parent() >>> H.power_series_ring() Power Series Ring in x over Rational Field
When
default_precis set toInfinity, a lazy power series ring is returned:sage: H.power_series_ring(infinity) Lazy Taylor Series Ring in x over Rational Field
[Python]>>> from sage.all import * >>> H.power_series_ring(infinity) Lazy Taylor Series Ring in x over Rational Field
- symbolic_equality()[source]¶
Return whether or not the equality in the parent is checked symbolically.
EXAMPLES:
sage: S.<x> = GF(5)[] sage: f = hypergeometric([1/2, 1/3], [1], x) sage: f.parent().symbolic_equality() True
>>> from sage.all import * >>> S = GF(Integer(5))['x']; (x,) = S._first_ngens(1) >>> f = hypergeometric([Integer(1)/Integer(2), Integer(1)/Integer(3)], [Integer(1)], x) >>> f.parent().symbolic_equality() True
sage: g = hypergeometric([1/2, 1/3], [1], x, symbolic_equality=False) sage: g.parent().symbolic_equality() False
[Python]>>> from sage.all import * >>> g = hypergeometric([Integer(1)/Integer(2), Integer(1)/Integer(3)], [Integer(1)], x, symbolic_equality=False) >>> g.parent().symbolic_equality() False
- variable_name()[source]¶
Return the variable name of the hypergeometric functions in this parent.
EXAMPLES:
sage: S.<x> = QQ[] sage: H = hypergeometric([], [], x).parent() sage: H.variable_name() 'x'
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> H = hypergeometric([], [], x).parent() >>> H.variable_name() 'x'
- class sage.functions.hypergeometric_algebraic.HypergeometricToSR[source]¶
Bases:
MapMap from hypergeometric series to symbolic ring
- class sage.functions.hypergeometric_algebraic.ScalarMultiplication[source]¶
Bases:
ActionAction on hypergeometric series by left multiplication by scalars.
- sage.functions.hypergeometric_algebraic.insert_zeroes(P, n)[source]¶
Return \(P(x^n)\).
INPUT:
P– a polynomial in \(x\)n– a positive integer
EXAMPLES:
sage: from sage.functions.hypergeometric_algebraic import insert_zeroes sage: S.<x> = QQ[] sage: insert_zeroes(x + 1, 5) x^5 + 1
>>> from sage.all import * >>> from sage.functions.hypergeometric_algebraic import insert_zeroes >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> insert_zeroes(x + Integer(1), Integer(5)) x^5 + 1
- sage.functions.hypergeometric_algebraic.kernel(M, repeat=2)[source]¶
Return a generator of the left kernel of the polynomial matrix \(M\), assuming that the latter has rank at most \(1\).
INPUT:
repeat– a positive integer (default:2); the number of evaluation points we pick to check that the kernel is nonzero
Note
The implementation is based on Cramer determinants. It is however currently faster than
sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense.minimal_kernel_basis()for matrices of small sizes with entries of large degrees.EXAMPLES:
sage: from sage.functions.hypergeometric_algebraic import kernel sage: S.<x> = GF(5)[]
>>> from sage.all import * >>> from sage.functions.hypergeometric_algebraic import kernel >>> S = GF(Integer(5))['x']; (x,) = S._first_ngens(1)
When the kernel is zero, the function returns nothing:
sage: M = matrix(2, 2, [x, x+1, x+2, x+3]) sage: kernel(M)
[Python]>>> from sage.all import * >>> M = matrix(Integer(2), Integer(2), [x, x+Integer(1), x+Integer(2), x+Integer(3)]) >>> kernel(M)
Otherwise, it returns the smallest generator as a list of polynomials:
sage: M = matrix(3, 2, [x, x+1, x+2, x^2, x^2+2, x^2+4]) sage: kernel(M) [x^4 + 4*x^3 + x + 2, 4*x^2 + 2*x + 3, 4*x^3 + x^2 + 3*x + 2]
>>> from sage.all import * >>> M = matrix(Integer(3), Integer(2), [x, x+Integer(1), x+Integer(2), x**Integer(2), x**Integer(2)+Integer(2), x**Integer(2)+Integer(4)]) >>> kernel(M) [x^4 + 4*x^3 + x + 2, 4*x^2 + 2*x + 3, 4*x^3 + x^2 + 3*x + 2]