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)
[Python]
>>> 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, ...
[Python]
>>> 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
[Python]
>>> 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)
[Python]
>>> 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
[Python]
>>> 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
[Python]
>>> 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: Element

Class 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, +Infinity otherwise.

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 self and other define 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
is_equal_symbolically(other)[source]

Return whether if the parameters defining the hypergeometric series self and other are 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)
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 1 as a bottom parameter) is increased by s.

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: HypergeometricAlgebraic

Class 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 (see annihilating_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 True since 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 self and other define 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: HypergeometricAlgebraic

Class 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 p is 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 True if this hypergeometric function is algebraic over the rational functions, return False otherwise.

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_infinity is False it 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 number

  • position – a boolean (default: False); if True, 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: HypergeometricAlgebraic

Class 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; if None, 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 number

  • prec – a positive integer (default: None); if None, 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
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, if position is True the index of the first coefficient of the series that attains this valuation.

INPUT:

  • log_radius – a rational number

  • position – a boolean (default: False), if True the 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, UniqueRepresentation

Hypergeometric 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 or Infinity (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_prec is set to Infinity, 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'
zero()[source]

Return the zero function in this parent.

EXAMPLES:

sage: S.<x> = QQ[]
sage: H = hypergeometric([], [], x).parent()
sage: H.zero()
0
>>> from sage.all import *
>>> S = QQ['x']; (x,) = S._first_ngens(1)
>>> H = hypergeometric([], [], x).parent()
>>> H.zero()
0
class sage.functions.hypergeometric_algebraic.HypergeometricToSR[source]

Bases: Map

Map from hypergeometric series to symbolic ring

class sage.functions.hypergeometric_algebraic.ScalarMultiplication[source]

Bases: Action

Action 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]