Fraction fields
Nemo allows the creation of fraction fields over any ring . We don't require to be an integral domain, however no attempt is made to deal with the general case. Two fractions and are equal in Nemo iff . Thus, in practice, a greatest common divisor function is currently required for the ring .
In order to make the representation unique for printing, we have a notion of canonical unit for elements of a ring . When canonicalising , each of the elements and is first divided by the canonical unit of .
The canonical_unit
function is defined for elements of every Nemo ring. It must have the properties
canonical_unit(u) == u
canonical_unit(a*b) == canonical_unit(a)*canonical_unit(b)
for any unit of the ring in question, and and arbitrary elements of the ring.
For example, the canonical unit of an integer is its sign. Thus a fraction of integers always has positive denominator after canonicalisation.
The canonical unit of a polynomial is the canonical unit of its leading coefficient, etc.
There are two different kinds of implementation of fraction fields in Nemo: a generic one for the case where no specific implementation exists (provided by AbstractAlgebra.jl), and efficient implementations of fractions over specific rings, usually provided by C/C++ libraries.
The following table shows each of the fraction types available in Nemo, the base ring , and the Julia/Nemo types for that kind of fraction (the type information is mainly of concern to developers).
Base ring | Library | Element type | Parent type |
---|---|---|---|
Generic ring | AbstractAlgebra.jl | Generic.FracFieldElem{T} | Generic.FracField{T} |
FLINT | QQFieldElem | QQField |
All fraction element types belong to the abstract type FracElem
and all of the fraction field types belong to the abstract type FracField
. This enables one to write generic functions that can accept any Nemo fraction type.
Fraction functionality
All fraction types in Nemo provide functionality for fields described in AbstractAlgebra.jl:
https://nemocas.github.io/AbstractAlgebra.jl/stable/field
In addition all the fraction field functionality of AbstractAlgebra.jl is provided, along with generic fractions fields as described here:
https://nemocas.github.io/AbstractAlgebra.jl/stable/fraction
Basic manipulation
sign
— Methodsign(a::QQFieldElem)
Return the sign of (, or ) as a fraction.
height
— Methodheight(a::QQFieldElem)
Return the height of the fraction , namely the largest of the absolute values of the numerator and denominator.
height_bits
— Methodheight_bits(a::QQFieldElem)
Return the number of bits of the height of the fraction .
<<
— Method<<(a::QQFieldElem, b::Int)
Return .
>>
— Method>>(a::QQFieldElem, b::Int)
Return .
floor
— Methodfloor(a::QQFieldElem)
Return the greatest integer that is less than or equal to . The result is returned as a rational with denominator .
ceil
— Methodceil(a::QQFieldElem)
Return the least integer that is greater than or equal to . The result is returned as a rational with denominator .
Examples
julia> d = abs(ZZ(11)//3)
11//3
julia> 4 <= ZZ(7)//ZZ(3)
false
Modular arithmetic
The following functions are available for rationals.
mod
— Methodmod(a::QQFieldElem, b::ZZRingElem)
mod(a::QQFieldElem, b::Integer)
Return where is an integer coprime to the denominator of .
Examples
julia> mod(-ZZ(2)//3, 7)
4
julia> mod(ZZ(1)//2, ZZ(5))
3
Rational Reconstruction
Rational reconstruction is available for rational numbers.
reconstruct
— Methodreconstruct(a::ZZRingElem, m::ZZRingElem)
reconstruct(a::ZZRingElem, m::Integer)
reconstruct(a::Integer, m::ZZRingElem)
reconstruct(a::Integer, m::Integer)
Attempt to return a rational number such that and such that gcd and . If no solution exists, an exception is thrown.
Examples
julia> a = reconstruct(7, 13)
1//2
julia> b = reconstruct(ZZ(15), 31)
-1//2
julia> c = reconstruct(ZZ(123), ZZ(237))
9//2
reconstruct
— Methodreconstruct(a::ZZRingElem, m::ZZRingElem, N::ZZRingElem, D::ZZRingElem)
Attempt to return a rational number such that and such that , gcd, and .
Returns a tuple (success
, n/d
), where success
signals the success of reconstruction.
The behaviour is undefined if is negative or larger than .
Rational enumeration
Various methods exist to enumerate rationals.
next_minimal
— Methodnext_minimal(a::QQFieldElem)
Given , return the next rational number in the sequence obtained by enumerating all positive denominators , and for each enumerating the numerators in order and generating both and , but skipping all gcd. Starting with zero, this generates every non-negative rational number once and only once, with the first few entries being . This enumeration produces the rational numbers in order of minimal height. It has the disadvantage of being somewhat slower to compute than the Calkin-Wilf enumeration. If we throw a DomainError()
.
Examples
julia> next_minimal(ZZ(2)//3)
3//2
next_signed_minimal
— Methodnext_signed_minimal(a::QQFieldElem)
Given a signed rational number assumed to be in canonical form, return the next element in the minimal-height sequence generated by next_minimal
but with negative numbers interleaved. The sequence begins . Starting with zero, this generates every rational number once and only once, in order of minimal height.
Examples
julia> next_signed_minimal(-ZZ(21)//31)
31//21
next_calkin_wilf
— Methodnext_calkin_wilf(a::QQFieldElem)
Return the next number after in the breadth-first traversal of the Calkin-Wilf tree. Starting with zero, this generates every non-negative rational number once and only once, with the first few entries being . Despite the appearance of the initial entries, the Calkin-Wilf enumeration does not produce the rational numbers in order of height: some small fractions will appear late in the sequence. This order has the advantage of being faster to produce than the minimal-height order.
Examples
julia> next_calkin_wilf(ZZ(321)//113)
113//244
next_signed_calkin_wilf
— Methodnext_signed_calkin_wilf(a::QQFieldElem)
Given a signed rational number returns the next element in the Calkin-Wilf sequence with negative numbers interleaved. The sequence begins . Starting with zero, this generates every rational number once and only once, but not in order of minimal height.
Examples
julia> next_signed_calkin_wilf(-ZZ(51)//(17))
1//4
Random generation
rand_bits
— Methodrand_bits(::QQField, b::Int)
Return a random signed rational whose numerator and denominator both have bits before canonicalisation. Note that the resulting numerator and denominator can be smaller than bits.
Special functions
The following special functions are available for specific rings in Nemo.
harmonic
— Methodharmonic(n::Int)
Return the harmonic number . Table lookup is used for whose numerator and denominator fit in a single limb. For larger , a divide and conquer strategy is used.
Examples
julia> a = harmonic(12)
86021//27720
bernoulli
— Methodbernoulli(n::Int)
Return the Bernoulli number for non-negative .
See also bernoulli_cache
.
Examples
julia> d = bernoulli(12)
-691//2730
bernoulli_cache
— Methodbernoulli_cache(n::Int)
Precomputes and caches all the Bernoulli numbers up to . This is much faster than repeatedly calling bernoulli(k)
. Once cached, subsequent calls to bernoulli(k)
for any will read from the cache, making them virtually free.
See also bernoulli
.
Examples
julia> bernoulli_cache(100)
julia> e = bernoulli(100)
-94598037819122125295227433069493721872702841533066936133385696204311395415197247711//33330
dedekind_sum
— Methoddedekind_sum(h::ZZRingElem, k::ZZRingElem)
Return the Dedekind sum for arbitrary and .
Examples
julia> b = dedekind_sum(12, 13)
-11//13
julia> c = dedekind_sum(-120, ZZ(1305))
-575//522
simplest_between
— Method simplest_between(l::QQFieldElem, r::QQFieldElem)
Return the simplest fraction in the closed interval . A canonical fraction is defined to be simpler than if and only if or and .
Examples
julia> simplest_between(QQ(1//10), QQ(3//10))
1//4