Skip to content

Commit 81fc7de

Browse files
authored
Merge pull request #24 from KlausC:krc/flint
use FLINT bigint library to replace `BigInt`.
2 parents 6e2aece + 08ef236 commit 81fc7de

File tree

13 files changed

+379
-61
lines changed

13 files changed

+379
-61
lines changed

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ repo = "https://github.com/KlausC/CommutativeRings.jl"
66
version = "0.6.0"
77

88
[deps]
9+
FLINT_jll = "e134572f-a0d5-539d-bddf-3cad8db41a82"
910
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1011
Primes = "27ebfcd6-29c5-5fa9-bf4b-fb8fc14df3ae"
1112
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
1213

1314
[compat]
1415
Aqua = "0.8"
16+
FLINT_jll = "300.100"
1517
LinearAlgebra = "1"
1618
Polynomials = "1,2,3,4"
1719
Primes = "0.5"

src/CommutativeRings.jl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,17 @@ using LinearAlgebra
44
using Base.Checked
55
using Primes
66
using Random
7+
using FLINT_jll
8+
9+
const libflint = FLINT_jll.libflint
10+
11+
function flint_abort()
12+
error("Problem in the Flint-Subsystem")
13+
end
714

815
export category_trait, isfield
916
export Ring, RingInt, FractionRing, QuotientRing, Polynomial
10-
export ZZ, QQ, ZZmod, Frac, Quotient, UnivariatePolynomial, MultivariatePolynomial
17+
export ZZ, ZZZ, ZI, QQ, ZZmod, Frac, Quotient, UnivariatePolynomial, MultivariatePolynomial
1118
export GaloisField, GF, FSeries, AlgebraicNumber, NumberField, NF
1219

1320
export SpecialPowerSeries, PowerSeries, O, precision, absprecision
@@ -64,6 +71,7 @@ include("typevars.jl")
6471
include("promoteconvert.jl")
6572
include("generic.jl")
6673
include("zz.jl")
74+
include("zzflint.jl")
6775
include("qq.jl")
6876
include("zzmod.jl")
6977
include("quotient.jl")

src/algebraic.jl

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
import Base: *, /, inv, +, -, sqrt, ^, literal_pow, iszero, zero, one, ==, isapprox, hash
3-
import Base: conj, real, imag, abs, copy, isreal
3+
import Base: conj, real, imag, abs, copy, isreal, cispi, cospi, sinpi, tanpi
44

55
# construction
66
basetype(::Type{<:AlgebraicNumber}) = QQ{BigInt}
@@ -160,14 +160,11 @@ function root(a::AlgebraicNumber, n::Integer)
160160
AlgebraicNumber(p, approx(a)^(1 // n))
161161
end
162162

163-
# The imaginary constant a algebraic number
164-
IM() = AlgebraicNumber(monom(QQ{Int}[:x], 2) + 1, im)
165-
166163
sqrt(a::AlgebraicNumber) = ^(a, 1 // 2)
167164
# cbrt(a::AlgebraicNumber) = ^(a, 1 // 3) # intentionally not defined - alike Complex.
168165
isreal(a::AlgebraicNumber) = isreal(approx(a))
169166
real(a::AlgebraicNumber) = isreal(a) ? a : (a + conj(a)) / 2
170-
imag(a::AlgebraicNumber) = isreal(a) ? zero(a) : (conj(a) - a) * IM() / 2
167+
imag(a::AlgebraicNumber) = isreal(a) ? zero(a) : (conj(a) - a) * AlgebraicNumber(im) / 2
171168
abs(a::AlgebraicNumber) = !isreal(a) ? sqrt(a * conj(a)) : real(approx(a)) >= 0 ? a : -a
172169

173170
function *(a::T, b::T) where T<:AlgebraicNumber
@@ -427,8 +424,8 @@ function Base.sinpi(q::QQ)
427424
b = inv(a)
428425
s = (a - b) / 2
429426
fs = sinpi(big(value(q))) * im
430-
as = AlgebraicNumber(s, fs) / IM()
431-
as
427+
as = AlgebraicNumber(s, fs)
428+
AlgebraicNumber(_squaremulim(minimal_polynomial(as)), approx(as) / im)
432429
end
433430
function Base.cospi(q::QQ)
434431
d = cispi(q)
@@ -440,6 +437,29 @@ function Base.cospi(q::QQ)
440437
ac = AlgebraicNumber(c, fc)
441438
ac
442439
end
440+
function Base.tanpi(q::QQ)
441+
d = cispi(q)
442+
N = NF(d)
443+
a = monom(N)
444+
b = inv(a)
445+
c = (a - b) / (a + b)
446+
fc = tanpi(big(value(q))) * im
447+
ac = AlgebraicNumber(c, fc)
448+
AlgebraicNumber(_squaremulim(minimal_polynomial(ac)), approx(ac) / im)
449+
end
450+
451+
# only for internal usage
452+
# assume minimal polynomial has only powers of x^2.
453+
# simulate effect of multiplication with `im` in minimal polynomial
454+
function _squaremulim(p::UnivariatePolynomial)
455+
c = copy(p)
456+
n = length(c.coeff)
457+
for k = n-2:-4:1
458+
c.coeff[k] = -c.coeff[k]
459+
end
460+
c
461+
end
462+
443463

444464
"""
445465
rationalconst(expr)

src/generic.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Base.big(a::T) where T<:Union{QQ,ZZ} = big(T)(a)
4848
basetype(::T) where T<:Ring = basetype(T)
4949
basetype(::Type{T}) where T = Union{}
5050
basetype(::Type{Union{}}) = Union{}
51+
basetype(::Type{Rational{S}}) where S = S
5152

5253
depth(::Type{Union{}}) = -1
5354
depth(::Type) = 0

src/intfactorization.jl

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
"""
44
const MINPRIME = 9999
55

6-
function isirreducible(p::P; p0 = MINPRIME) where P<:UnivariatePolynomial{<:ZZ}
6+
function isirreducible(p::P; p0 = MINPRIME) where {T<:ZI, P<:UnivariatePolynomial{T}}
77
(iszero(p) || isunit(p)) && return false
88
deg(p) <= 1 && return true
99
iszero(p[0]) && return false
1010
X = varname(P)
11-
Z = ZZ{BigInt}[X]
11+
Z = wide_type(T)[X]
1212
q = convert(Z, p)
1313
isone(pgcd(q, derive(q))) || return false
1414
zassenhaus_irr(q, p0)
@@ -20,11 +20,11 @@ function isirreducible(p::P; p0 = MINPRIME) where P<:UnivariatePolynomial{<:QQ}
2020
isirreducible(pp; p0)
2121
end
2222

23-
function factor(p::P, a::Integer = 1; p0 = MINPRIME) where P<:UnivariatePolynomial{<:ZZ}
23+
function factor(p::P, a::Integer=1; p0 = MINPRIME) where {T<:ZI,P<:UnivariatePolynomial{T}}
2424
#println("factor($p)")
2525
X = varname(P)
2626
c = content(p)
27-
Z = ZZ{BigInt}[X]
27+
Z = wide_type(T)[X]
2828
q = Z(isone(c) ? copy(p) : p / c)
2929
x = monom(Z)
3030
q, e, k = stripzeroscompress(q)
@@ -145,8 +145,7 @@ function zassenhaus2(u::UnivariatePolynomial{<:ZZ{<:Integer}}, val::Val{BO}, p0)
145145
end
146146

147147
# D = []
148-
149-
function zassenhaus2(u::P, ::Val{BO}, p0) where {BO,P<:UnivariatePolynomial{ZZ{BigInt}}}
148+
function zassenhaus2(u::P, ::Val{BO}, p0) where {BO,T<:Union{ZZ{BigInt},ZZZ},P<:UnivariatePolynomial{T}}
150149
v, p = best_prime(u, p0)
151150
a = allgcdx(v)
152151
#println(" initial v/$p = "); display([v a])
@@ -266,7 +265,7 @@ function factor_exp(u::P, a::Integer, p0) where P<:UnivariatePolynomial
266265
end
267266

268267
# check if p is coprime with leading coefficient
269-
function compatible_with(p::Integer, u::ZZ)
268+
function compatible_with(p::Integer, u::ZI)
270269
u = abs(value(u))
271270
gcd(p, u) == 1
272271
end
@@ -335,7 +334,7 @@ function combinefactors(
335334
u::Z,
336335
vv::AbstractVector{<:UnivariatePolynomial{Zp}},
337336
aa::AbstractVector,
338-
) where {Z<:UnivariatePolynomial{<:ZZ},Zp}
337+
) where {Z<:UnivariatePolynomial{<:ZI},Zp}
339338
res = Tuple{Z,Any,Any}[]
340339
un = LC(u)
341340
unp = Zp(un)
@@ -394,10 +393,10 @@ end
394393
function stripmod(
395394
::Type{P},
396395
a::UnivariatePolynomial{<:ZZmod},
397-
) where {Z<:ZZ,P<:UnivariatePolynomial{Z}}
396+
) where {Z<:ZI,P<:UnivariatePolynomial{Z}}
398397
P(stripmod.(Z, a.coeff), ord(a))
399398
end
400-
stripmod(::Type{Z}, a::ZZmod) where Z<:ZZ = Z(value(a))
399+
stripmod(::Type{Z}, a::ZZmod) where Z<:ZI = Z(value(a))
401400

402401

403402
function subset_with_a(v, d, a)
@@ -421,8 +420,8 @@ If `u` has an integer factor polynom `v` with `deg(v) == m`,
421420
calculate array of bounds `b` with `abs(v[i]) <= b[i+1] for i = 0:m`.
422421
Algorithm see TAoCP 2.Ed 4.6.2 Exercise 20.
423422
"""
424-
function coeffbounds(u::UnivariatePolynomial{ZZ{T},X}, m::Integer) where {T<:Integer,X}
425-
W = widen(T)
423+
function coeffbounds(u::UnivariatePolynomial{T,X}, m::Integer) where {T<:ZI,X}
424+
W = widen(basetype(T))
426425
n = deg(u)
427426
0 <= m <= n || throw(ArgumentError("required m ∈ [0,deg(u)] but $m ∉ [0,$n]"))
428427
accuracy = 100 # use fixed point decimal arithmetic with accuracy 0.01 for the norm
@@ -475,7 +474,7 @@ function hensel_lift(
475474
v::AbstractVector{Pq},
476475
a::AbstractVector{Pp},
477476
) where {
478-
Z<:ZZ,
477+
Z<:ZI,
479478
Zq<:ZZmod,
480479
Zp<:ZZmod,
481480
Pq<:UnivariatePolynomial{Zq},
@@ -517,10 +516,10 @@ function downmod(::Type{Zp}, f::P, q::Integer) where {Zp,X,T,P<:UnivariatePolyno
517516
end
518517

519518

520-
function _liftmod(::Type{Z}, a::ZZmod) where {T,Z<:ZZ{T}}
521-
Z(signed(T)(value(a)))
519+
function _liftmod(::Type{Z}, a::ZZmod) where {Z<:ZI}
520+
Z(signed(basetype(Z))(value(a)))
522521
end
523-
function _liftmod(::Type{Z}, a::ZZ) where {X,T,Z<:ZZmod{X,T}}
522+
function _liftmod(::Type{Z}, a::ZI) where {X,T,Z<:ZZmod{X,T}}
524523
Z(value(a))
525524
end
526525
function _liftmod(::Type{Z}, a::ZZmod) where {X,T,Z<:ZZmod{X,T}}

src/promoteconvert.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11

22
# promotions
33

4-
_xpromote_rule(::Type{T}, ::Type{S}) where {T<:Ring,S<:RingInt} = begin
4+
function promote_rule(::Type{T}, ::Type{S}) where {T<:Ring,S<:RingInt}
55
depth(T) < depth(S) && return Base.Bottom
66
B = basetype(T)
77
(S <: T || S <: B) ? T : promote_type(B, S) == B ? T : Base.Bottom
88
end
99
_xpromote_rule(a::Type, b::Type) = promote_type(a, b)
10-
10+
#=
1111
@generated function Base.promote_rule(a::Type{<:Ring}, b::Type{<:RingInt})
1212
bt = _xpromote_rule(a.parameters[1], b.parameters[1])
1313
:($bt)
1414
end
15-
15+
=#
1616
function promote_rule(::Type{R}, ::Type{S}) where {R<:Ring,S<:Rational}
1717
promote_rule(R, promote_type(basetype(R), S))
1818
end

src/ringtypes.jl

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,55 @@ struct ZZ{T<:Signed} <: Ring{ZZClass{T}}
9393
ZZ(val::T) where T<:Signed = ZZ{T}(val)
9494
end
9595

96+
mutable struct ZZZ <: Ring{ZZClass{Integer}}
97+
d::Int
98+
99+
function ZZZ(x::ZZZ)
100+
z = new()
101+
ccall((:fmpz_init_set, libflint), Nothing, (Ref{ZZZ}, Ref{ZZZ}), z, x)
102+
finalizer(_fmpz_clear_fn, z)
103+
return z
104+
end
105+
106+
function ZZZ(x::Int)
107+
z = new()
108+
ccall((:fmpz_init_set_si, libflint), Nothing, (Ref{ZZZ}, Int), z, x)
109+
finalizer(_fmpz_clear_fn, z)
110+
return z
111+
end
112+
113+
function ZZZ(x::UInt)
114+
z = new()
115+
ccall((:fmpz_init_set_ui, libflint), Nothing, (Ref{ZZZ}, UInt), z, x)
116+
finalizer(_fmpz_clear_fn, z)
117+
return z
118+
end
119+
120+
function ZZZ(x::BigInt)
121+
z = new()
122+
ccall((:fmpz_init, libflint), Nothing, (Ref{ZZZ},), z)
123+
ccall((:fmpz_set_mpz, libflint), Nothing, (Ref{ZZZ}, Ref{BigInt}), z, x)
124+
finalizer(_fmpz_clear_fn, z)
125+
return z
126+
end
127+
128+
function ZZZ(x::Float64)
129+
!isinteger(x) && throw(InexactError(:convert, ZZZ, x))
130+
z = new()
131+
ccall((:fmpz_init, libflint), Nothing, (Ref{ZZZ},), z)
132+
ccall((:fmpz_set_d, libflint), Nothing, (Ref{ZZZ}, Cdouble), z, x)
133+
finalizer(_fmpz_clear_fn, z)
134+
return z
135+
end
136+
137+
end
138+
139+
const ZI = Union{ZZ,ZZZ}
140+
141+
function _fmpz_clear_fn(a::ZZZ)
142+
ccall((:fmpz_clear, libflint), Nothing, (Ref{ZZZ},), a)
143+
end
144+
96145
"""
97146
ZZmod{m,S<:Integer}
98147
@@ -111,7 +160,7 @@ The ring of fractions of `R`. The elements consist of pairs `num::R,den::R`.
111160
During creation the values may be canceled to achieve `gcd(num, den) == one(R)`.
112161
The special case of `R<:Integer` is handled by `QQ{R}`.
113162
"""
114-
struct Frac{P<:Union{Polynomial,ZZ}} <: FractionRing{P,FractionClass{P}}
163+
struct Frac{P<:Union{Polynomial,ZI}} <: FractionRing{P,FractionClass{P}}
115164
num::P
116165
den::P
117166
Frac{P}(num::P, den::P, ::NCT) where P = new{P}(num, den)

src/univarpolynom.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ function _promote_rule(::Type{UnivariatePolynomial{R,X}}, ::Type{S}) where {X,R,
9999
end
100100
promote_rule(::Type{UnivariatePolynomial{R,X}}, ::Type{S}) where {X,R,S<:Integer} =
101101
UnivariatePolynomial{promote_type(R, S),X}
102+
promote_rule(::Type{UnivariatePolynomial{R,X}}, ::Type{S}) where {X,R,S<:ZI} =
103+
UnivariatePolynomial{promote_type(R, S),X}
102104
promote_rule(::Type{UnivariatePolynomial{R,X}}, ::Type{S}) where {X,R,S<:Rational} =
103105
UnivariatePolynomial{promote_type(R, S),X}
104106

@@ -826,7 +828,7 @@ end
826828

827829
import Base: show
828830

829-
issimple(::Union{ZZ,ZZmod,QQ,Number}) = true
831+
issimple(::Union{ZZ,ZZmod,QQ,Number,ZZZ}) = true
830832
issimple(::Quotient{<:UnivariatePolynomial{S,:γ}}) where S = true
831833
issimple(p::Polynomial) = ismonom(p)
832834
issimple(::Any) = false

src/zz.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ function ZZ{T}(a::Union{QQ{T},Frac{ZZ{T}}}) where T
2323
a.den != 1 && throw(InexactError(:ZZ, ZZ{T}, a))
2424
ZZ(a.num)
2525
end
26-
#ZZ(a::Union{QQ{T},Frac{ZZ{T}}}) where T = ZZ{T}(a)
27-
ZZ{S}(a::Union{QQ{T},Frac{ZZ{T}}}) where {S,T} = ZZ(promote_type(S,T)(a))
26+
27+
ZZ(a::Union{QQ{T},Frac{ZZ{T}}}) where T = ZZ{T}(a)
28+
ZZ{S}(a::Union{QQ{T},Frac{ZZ{T}}}) where {S,T} = ZZ(promote_type(S, T)(a))
2829

2930
# promotion and conversion
3031
promote_rule(::Type{ZZ{T}}, ::Type{ZZ{S}}) where {S,T} = ZZ{promote_type(S, T)}
@@ -78,3 +79,5 @@ Base.show(io::IO, z::ZZ) = print(io, z.val)
7879
function (::Type{T})(a::ZZ) where T<:Integer
7980
T(value(a))
8081
end
82+
83+
wide_type(::Type{<:ZZ}) = ZZ{BigInt}

0 commit comments

Comments
 (0)