diff --git a/Project.toml b/Project.toml index 03b0d31e71..ed61a1ef56 100644 --- a/Project.toml +++ b/Project.toml @@ -1,14 +1,16 @@ name = "AbstractAlgebra" uuid = "c3fe647b-3220-5bb0-a1ea-a7954cac585d" -version = "0.10.0" +version = "0.11.0" [deps] InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +RandomExtensions = "fb686558-2515-59ef-acaa-46db3789a887" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [compat] +RandomExtensions = "0.4.2" julia = "1" diff --git a/src/AbstractAlgebra.jl b/src/AbstractAlgebra.jl index 5e2cdba59d..403c772cac 100644 --- a/src/AbstractAlgebra.jl +++ b/src/AbstractAlgebra.jl @@ -99,7 +99,8 @@ import Base: Array, abs, acos, acosh, adjoint, asin, asinh, atan, atanh, bin, typed_hcat, typed_vcat, vcat, xor, zero, zeros, +, -, *, ==, ^, &, |, <<, >>, ~, <=, >=, <, >, //, /, != -using Random: Random, AbstractRNG +using Random: Random, AbstractRNG, SamplerTrivial +using RandomExtensions: RandomExtensions, make, Make2 export elem_type, parent_type diff --git a/src/Generic.jl b/src/Generic.jl index 0eca87f378..258c8218a8 100644 --- a/src/Generic.jl +++ b/src/Generic.jl @@ -7,6 +7,9 @@ import LinearAlgebra: lu, lu!, tr using Markdown, Random, InteractiveUtils +using Random: SamplerTrivial, GLOBAL_RNG +using RandomExtensions: RandomExtensions, make, Make, Make2, Make3, Make4 + import Base: Array, abs, asin, asinh, atan, atanh, axes, bin, checkbounds, cmp, conj, convert, copy, cos, cosh, dec, deepcopy, deepcopy_internal, exponent, gcd, gcdx, getindex, hash, hcat, hex, intersect, diff --git a/src/generic/Fraction.jl b/src/generic/Fraction.jl index 83241e383d..327804dde2 100644 --- a/src/generic/Fraction.jl +++ b/src/generic/Fraction.jl @@ -968,17 +968,33 @@ end # ############################################################################### -function rand(rng::AbstractRNG, S::AbstractAlgebra.FracField, v...) +RandomExtensions.maketype(R::AbstractAlgebra.FracField, _) = elem_type(R) + +function RandomExtensions.make(S::AbstractAlgebra.FracField, vs...) R = base_ring(S) - n = rand(rng, R, v...) + if length(vs) == 1 && elem_type(R) == Random.gentype(vs[1]) + RandomExtensions.Make(S, vs[1]) # forward to default Make constructor + else + make(S, make(R, vs...)) + end +end + +function rand(rng::AbstractRNG, + sp::SamplerTrivial{<:Make2{<:RingElement, <:AbstractAlgebra.FracField}}) + S, v = sp[][1:end] + R = base_ring(S) + n = rand(rng, v) d = R() while iszero(d) - d = rand(rng, R, v...) + d = rand(rng, v) end return S(n, d) end -rand(S::AbstractAlgebra.FracField, v...) = rand(Random.GLOBAL_RNG, S, v...) +rand(rng::AbstractRNG, S::AbstractAlgebra.FracField, v...) = + rand(rng, make(S, v...)) + +rand(S::AbstractAlgebra.FracField, v...) = rand(GLOBAL_RNG, S, v...) ############################################################################### # diff --git a/src/generic/LaurentPoly.jl b/src/generic/LaurentPoly.jl index 9a113029fa..6ebc9b6fe5 100644 --- a/src/generic/LaurentPoly.jl +++ b/src/generic/LaurentPoly.jl @@ -241,14 +241,31 @@ end # ############################################################################### -function rand(rng::AbstractRNG, S::LaurentPolyWrapRing, degrees_range, v...) - m = minimum(degrees_range) - degrees_range = degrees_range .- m - LaurentPolyWrap(rand(rng, S.polyring, degrees_range, v...), m) +RandomExtensions.maketype(S::LaurentPolyWrapRing, _, _) = elem_type(S) + +function RandomExtensions.make(S::LaurentPolyWrapRing, v1, vs...) + R = S.polyring + if length(vs) == 1 && vs[1] isa Integer && elem_type(R) == Random.gentype(v1) + Make(S, v1, vs[1]) # forward to default Make constructor + else + degrees_range = v1 + m = minimum(degrees_range) + degrees_range = degrees_range .- m + make(S, make(R, degrees_range, vs...), m) + end end +function rand(rng::AbstractRNG, + sp::SamplerTrivial{<:Make3{<:LaurentPolyWrap, <:LaurentPolyWrapRing}}) + v, m = sp[][2:end] + LaurentPolyWrap(rand(rng, v), m) +end + +rand(rng::AbstractRNG, S::LaurentPolyWrapRing, degrees_range, v...) = + rand(rng, make(S, degrees_range, v...)) + rand(S::LaurentPolyWrapRing, degrees_range, v...) = - rand(Random.GLOBAL_RNG, S, degrees_range, v...) + rand(GLOBAL_RNG, S, degrees_range, v...) ############################################################################### diff --git a/src/generic/LaurentSeries.jl b/src/generic/LaurentSeries.jl index 02801fd0e9..3016d907d0 100644 --- a/src/generic/LaurentSeries.jl +++ b/src/generic/LaurentSeries.jl @@ -1484,29 +1484,39 @@ end # ############################################################################### -function rand(rng::AbstractRNG, S::LaurentSeriesRing, val_range::UnitRange{Int}, v...) +const LaurentSeriesRingOrField = Union{LaurentSeriesRing,LaurentSeriesField} + +RandomExtensions.maketype(S::LaurentSeriesRingOrField, ::UnitRange{Int}, _) = elem_type(S) + +function RandomExtensions.make(S::LaurentSeriesRingOrField, val_range::UnitRange{Int}, vs...) R = base_ring(S) - f = S() - x = gen(S) - for i = 0:S.prec_max - 1 - f += rand(rng, R, v...)*x^i + if length(vs) == 1 && elem_type(R) == Random.gentype(vs[1]) + Make(S, val_range, vs[1]) # forward to default Make constructor + else + make(S, val_range, make(R, vs...)) end - return shift_left(f, rand(rng, val_range)) end -function rand(rng::AbstractRNG, S::LaurentSeriesField, val_range::UnitRange{Int}, v...) +function rand(rng::AbstractRNG, + sp::SamplerTrivial{<:Make3{<:RingElement, + <:LaurentSeriesRingOrField, + UnitRange{Int}}}) + S, val_range, v = sp[][1:end] R = base_ring(S) f = S() x = gen(S) for i = 0:S.prec_max - 1 - f += rand(rng, R, v...)*x^i + f += rand(rng, v)*x^i end return shift_left(f, rand(rng, val_range)) end -function rand(S::Union{LaurentSeriesRing,LaurentSeriesField}, val_range, v...) - rand(Random.GLOBAL_RNG, S, val_range, v...) -end +rand(rng::AbstractRNG, S::LaurentSeriesRingOrField, val_range::UnitRange{Int}, v...) = + rand(rng, make(S, val_range, v...)) + +rand(S::LaurentSeriesRingOrField, val_range, v...) = + rand(GLOBAL_RNG, S, val_range, v...) + ############################################################################### # diff --git a/src/generic/MPoly.jl b/src/generic/MPoly.jl index 3488e1b917..eabb27f27a 100644 --- a/src/generic/MPoly.jl +++ b/src/generic/MPoly.jl @@ -4682,8 +4682,21 @@ function rand_ordering(rng::AbstractRNG=Random.GLOBAL_RNG) end end -function rand(rng::AbstractRNG, S::AbstractAlgebra.MPolyRing, - term_range::UnitRange{Int}, exp_bound::UnitRange{Int}, v...) +RandomExtensions.maketype(S::AbstractAlgebra.MPolyRing, _, _, _) = elem_type(S) + +function RandomExtensions.make(S::AbstractAlgebra.MPolyRing, term_range::UnitRange{Int}, + exp_bound::UnitRange{Int}, vs...) + R = base_ring(S) + if length(vs) == 1 && elem_type(R) == Random.gentype(vs[1]) + Make(S, term_range, exp_bound, vs[1]) + else + make(S, term_range, exp_bound, make(R, vs...)) + end +end + +function rand(rng::AbstractRNG, sp::SamplerTrivial{<:Make4{ + <:RingElement,<:AbstractAlgebra.MPolyRing,UnitRange{Int},UnitRange{Int}}}) + S, term_range, exp_bound, v = sp[][1:end] f = S() g = gens(S) R = base_ring(S) @@ -4692,14 +4705,19 @@ function rand(rng::AbstractRNG, S::AbstractAlgebra.MPolyRing, for j = 1:length(g) term *= g[j]^rand(rng, exp_bound) end - term *= rand(rng, R, v...) + term *= rand(rng, v) f += term end return f end +function rand(rng::AbstractRNG, S::AbstractAlgebra.MPolyRing, + term_range::UnitRange{Int}, exp_bound::UnitRange{Int}, v...) + rand(rng, make(S, term_range, exp_bound, v...)) +end + function rand(S::AbstractAlgebra.MPolyRing, term_range, exp_bound, v...) - rand(Random.GLOBAL_RNG, S, term_range, exp_bound, v...) + rand(GLOBAL_RNG, S, term_range, exp_bound, v...) end ############################################################################### diff --git a/src/generic/Matrix.jl b/src/generic/Matrix.jl index 61e906f168..4e25f3817f 100644 --- a/src/generic/Matrix.jl +++ b/src/generic/Matrix.jl @@ -5070,17 +5070,34 @@ Base.map(f, a::MatrixElem) = map_entries(f, a) # ############################################################################### -function rand(rng::AbstractRNG, S::AbstractAlgebra.MatSpace, v...) +RandomExtensions.maketype(S::AbstractAlgebra.MatSpace, _) = elem_type(S) + +function RandomExtensions.make(S::AbstractAlgebra.MatSpace, vs...) + R = base_ring(S) + if length(vs) == 1 && elem_type(R) == Random.gentype(vs[1]) + Make(S, vs[1]) # forward to default Make constructor + else + make(S, make(R, vs...)) + end +end + + +function rand(rng::AbstractRNG, + sp::SamplerTrivial{<:Make2{<:MatSpaceElem, + <:AbstractAlgebra.MatSpace}}) + S, v = sp[][1:end] M = S() R = base_ring(S) for i = 1:nrows(M) for j = 1:ncols(M) - M[i, j] = rand(rng, R, v...) + M[i, j] = rand(rng, v) end end return M end +rand(rng::AbstractRNG, S::AbstractAlgebra.MatSpace, v...) = rand(rng, make(S, v...)) + rand(S::AbstractAlgebra.MatSpace, v...) = rand(Random.GLOBAL_RNG, S, v...) function randmat_triu(rng::AbstractRNG, S::AbstractAlgebra.MatSpace, v...) diff --git a/src/generic/MatrixAlgebra.jl b/src/generic/MatrixAlgebra.jl index 0667fbdeb4..48bd15a4fa 100644 --- a/src/generic/MatrixAlgebra.jl +++ b/src/generic/MatrixAlgebra.jl @@ -344,18 +344,35 @@ end # ############################################################################### -function rand(rng::AbstractRNG, S::AbstractAlgebra.MatAlgebra, v...) + +RandomExtensions.maketype(S::AbstractAlgebra.MatAlgebra, _) = elem_type(S) + +function RandomExtensions.make(S::AbstractAlgebra.MatAlgebra, vs...) + R = base_ring(S) + if length(vs) == 1 && elem_type(R) == Random.gentype(vs[1]) + Make(S, vs[1]) # forward to default Make constructor + else + make(S, make(R, vs...)) + end +end + +function rand(rng::AbstractRNG, + sp::SamplerTrivial{<:Make2{<:AbstractAlgebra.MatAlgElem, + <:AbstractAlgebra.MatAlgebra}}) + S, v = sp[][1:end] M = S() n = degree(M) R = base_ring(S) for i = 1:n for j = 1:n - M[i, j] = rand(rng, R, v...) + M[i, j] = rand(rng, v) end end return M end +rand(rng::AbstractRNG, S::AbstractAlgebra.MatAlgebra, v...) = rand(rng, make(S, v...)) + rand(S::AbstractAlgebra.MatAlgebra, v...) = rand(Random.GLOBAL_RNG, S, v...) function randmat_triu(rng::AbstractRNG, S::AbstractAlgebra.MatAlgebra, v...) diff --git a/src/generic/Module.jl b/src/generic/Module.jl index f28dd531a0..57e0171131 100644 --- a/src/generic/Module.jl +++ b/src/generic/Module.jl @@ -337,10 +337,26 @@ end # ############################################################################### -function rand(rng::AbstractRNG, M::AbstractAlgebra.FPModule{T}, vals...) where T <: RingElement +RandomExtensions.maketype(M::AbstractAlgebra.FPModule, _) = elem_type(M) + +function RandomExtensions.make(M::AbstractAlgebra.FPModule, vs...) R = base_ring(M) - v = [rand(rng, R, vals...) for i in 1:ngens(M)] - return M(v) + if length(vs) == 1 && elem_type(R) == Random.gentype(vs[1]) + Make(M, vs[1]) # forward to default Make constructor + else + make(M, make(R, vs...)) + end +end + +function rand(rng::AbstractRNG, + sp::SamplerTrivial{<:Make2{ + <:AbstractAlgebra.FPModuleElem, <:AbstractAlgebra.FPModule}}) + M, vals = sp[][1:end] + M(rand(rng, vals, ngens(M))) +end + +function rand(rng::AbstractRNG, M::AbstractAlgebra.FPModule{T}, vals...) where T <: RingElement + rand(rng, make(M, vals...)) end rand(M::AbstractAlgebra.FPModule, vals...) = rand(Random.GLOBAL_RNG, M, vals...) diff --git a/src/generic/NCPoly.jl b/src/generic/NCPoly.jl index 475d1c6d51..f9d4e172d2 100644 --- a/src/generic/NCPoly.jl +++ b/src/generic/NCPoly.jl @@ -694,19 +694,35 @@ end # ############################################################################### -function rand(rng::AbstractRNG, S::AbstractAlgebra.NCPolyRing, deg_range::UnitRange{Int}, v...) +RandomExtensions.maketype(S::AbstractAlgebra.NCPolyRing, dr::UnitRange{Int}, _) = elem_type(S) + +function RandomExtensions.make(S::AbstractAlgebra.NCPolyRing, deg_range::UnitRange{Int}, vs...) + R = base_ring(S) + if length(vs) == 1 && elem_type(R) == Random.gentype(vs[1]) + Make(S, deg_range, vs[1]) # forward to default Make constructor + else + make(S, deg_range, make(R, vs...)) + end +end + +function rand(rng::AbstractRNG, + sp::SamplerTrivial{<:Make3{<:AbstractAlgebra.NCPolyElem, + <:AbstractAlgebra.NCPolyRing, + UnitRange{Int}}}) + S, deg_range, v = sp[][1:end] R = base_ring(S) f = S() x = gen(S) for i = 0:rand(rng, deg_range) - f += rand(rng, R, v...)*x^i + f += rand(rng, v)*x^i end return f end -function rand(S::AbstractAlgebra.NCPolyRing, deg_range, v...) - rand(Random.GLOBAL_RNG, S, deg_range, v...) -end +rand(rng::AbstractRNG, S::AbstractAlgebra.NCPolyRing, deg_range::UnitRange{Int}, v...) = + rand(rng, make(S, deg_range, v...)) + +rand(S::AbstractAlgebra.NCPolyRing, deg_range, v...) = rand(Random.GLOBAL_RNG, S, deg_range, v...) ############################################################################### # diff --git a/src/generic/Poly.jl b/src/generic/Poly.jl index d799ac469b..65ed0b88eb 100644 --- a/src/generic/Poly.jl +++ b/src/generic/Poly.jl @@ -1281,7 +1281,7 @@ function pseudodivrem(f::AbstractAlgebra.PolyElem{T}, g::AbstractAlgebra.PolyEle s = b^k return q*s, f*s end - + ################################################################################ # # Remove and valuation @@ -2743,16 +2743,32 @@ end # ############################################################################### -function rand(rng::AbstractRNG, S::AbstractAlgebra.PolyRing, deg_range::UnitRange{Int}, v...) +RandomExtensions.maketype(S::AbstractAlgebra.PolyRing, dr::UnitRange{Int}, _) = elem_type(S) + +function RandomExtensions.make(S::AbstractAlgebra.PolyRing, deg_range::UnitRange{Int}, vs...) + R = base_ring(S) + if length(vs) == 1 && elem_type(R) == Random.gentype(vs[1]) + Make(S, deg_range, vs[1]) # forward to default Make constructor + else + make(S, deg_range, make(R, vs...)) + end +end + +# define rand for make(S, deg_range, v) +function rand(rng::AbstractRNG, sp::SamplerTrivial{<:Make3{<:RingElement,<:AbstractAlgebra.PolyRing,UnitRange{Int}}}) + S, deg_range, v = sp[][1:end] R = base_ring(S) f = S() x = gen(S) for i = 0:rand(rng, deg_range) - f += rand(rng, R, v...)*x^i + f += rand(rng, v)*x^i end return f end +rand(rng::AbstractRNG, S::AbstractAlgebra.PolyRing, deg_range::UnitRange{Int}, v...) = + rand(rng, make(S, deg_range, v...)) + rand(S::AbstractAlgebra.PolyRing, deg_range, v...) = rand(Random.GLOBAL_RNG, S, deg_range, v...) ############################################################################### diff --git a/src/generic/PuiseuxSeries.jl b/src/generic/PuiseuxSeries.jl index a174fa6cca..be00582b53 100644 --- a/src/generic/PuiseuxSeries.jl +++ b/src/generic/PuiseuxSeries.jl @@ -600,19 +600,30 @@ end # ############################################################################### -function rand(rng::AbstractRNG, S::PuiseuxSeriesRing, val_range::UnitRange{Int}, scale_range::UnitRange{Int}, v...) - (first(scale_range) <= 0 || last(scale_range) <= 0) && error("Scale must be positive") - return S(rand(rng, laurent_ring(S), val_range, v...), rand(rng, scale_range)) -end +const PuiseuxSeriesRingOrField = Union{PuiseuxSeriesRing,PuiseuxSeriesField} + +RandomExtensions.maketype(S::PuiseuxSeriesRingOrField, ::UnitRange{Int}, _) = elem_type(S) + +RandomExtensions.make(S::PuiseuxSeriesRingOrField, val_range::UnitRange{Int}, + scale_range::UnitRange{Int}, vs...) = + make(S, scale_range, make(laurent_ring(S), val_range, vs...)) -function rand(rng::AbstractRNG, S::PuiseuxSeriesField, val_range::UnitRange{Int}, scale_range::UnitRange{Int}, v...) +function rand(rng::AbstractRNG, + sp::SamplerTrivial{<:Make3{<:RingElement, + <:PuiseuxSeriesRingOrField, + UnitRange{Int}}}) + S, scale_range, v = sp[][1:end] (first(scale_range) <= 0 || last(scale_range) <= 0) && error("Scale must be positive") - return S(rand(rng, laurent_ring(S), val_range, v...), rand(rng, scale_range)) + return S(rand(rng, v), rand(rng, scale_range)) end -function rand(S::Union{PuiseuxSeriesRing,PuiseuxSeriesField}, val_range, scale_range, v...) +rand(rng::AbstractRNG, S::PuiseuxSeriesRingOrField, val_range::UnitRange{Int}, + scale_range::UnitRange{Int}, v...) = + rand(rng, make(S, val_range, scale_range, v...)) + +rand(S::PuiseuxSeriesRingOrField, val_range, scale_range, v...) = rand(Random.GLOBAL_RNG, S, val_range, scale_range, v...) -end + ############################################################################### # diff --git a/src/generic/RelSeries.jl b/src/generic/RelSeries.jl index 091558226c..8f0f8771f4 100644 --- a/src/generic/RelSeries.jl +++ b/src/generic/RelSeries.jl @@ -1231,16 +1231,32 @@ end # ############################################################################### -function rand(rng::AbstractRNG, S::SeriesRing, val_range::UnitRange{Int}, v...) +RandomExtensions.maketype(S::SeriesRing, ::UnitRange{Int}, _) = elem_type(S) + +function RandomExtensions.make(S::SeriesRing, val_range::UnitRange{Int}, vs...) + R = base_ring(S) + if length(vs) == 1 && elem_type(R) == Random.gentype(vs[1]) + Make(S, val_range, vs[1]) # forward to default Make constructor + else + make(S, val_range, make(R, vs...)) + end +end + +function rand(rng::AbstractRNG, + sp::SamplerTrivial{<:Make3{<:RingElement, <:SeriesRing, UnitRange{Int}}}) + S, val_range, v = sp[][1:end] R = base_ring(S) f = S() x = gen(S) for i = 0:S.prec_max - 1 - f += rand(rng, R, v...)*x^i + f += rand(rng, v)*x^i end return shift_left(f, rand(rng, val_range)) end +rand(rng::AbstractRNG, S::SeriesRing, val_range::UnitRange{Int}, v...) = + rand(rng, make(S, val_range, v...)) + rand(S::SeriesRing, val_range, v...) = rand(Random.GLOBAL_RNG, S, val_range, v...) ############################################################################### diff --git a/src/generic/Residue.jl b/src/generic/Residue.jl index bb3fef2e2e..d4208be07c 100644 --- a/src/generic/Residue.jl +++ b/src/generic/Residue.jl @@ -504,11 +504,28 @@ end # ############################################################################### -function rand(rng::AbstractRNG, S::AbstractAlgebra.ResRing{T}, v...) where {T <: RingElement} +RandomExtensions.maketype(R::AbstractAlgebra.ResRing, _) = elem_type(R) + +# define rand(make(S, v)) +function rand(rng::AbstractRNG, + sp::SamplerTrivial{<:Make2{<:AbstractAlgebra.ResElem{T}, + <:AbstractAlgebra.ResRing{T}}} + ) where {T} + S, v = sp[][1:end] + S(rand(rng, v)) +end + +function RandomExtensions.make(S::AbstractAlgebra.ResRing, vs...) R = base_ring(S) - return S(rand(rng, R, v...)) + if length(vs) == 1 && elem_type(R) == Random.gentype(vs[1]) + Make(S, vs[1]) + else + make(S, make(base_ring(S), vs...)) + end end +rand(rng::AbstractRNG, S::AbstractAlgebra.ResRing, v...) = rand(rng, make(S, v...)) + rand(S::AbstractAlgebra.ResRing, v...) = rand(Random.GLOBAL_RNG, S, v...) ############################################################################### diff --git a/src/generic/ResidueField.jl b/src/generic/ResidueField.jl index d07982f4a6..2c41d32b69 100644 --- a/src/generic/ResidueField.jl +++ b/src/generic/ResidueField.jl @@ -563,11 +563,27 @@ end # ############################################################################### -function rand(rng::AbstractRNG, S::AbstractAlgebra.ResField{T}, v...) where {T <: RingElement} +RandomExtensions.maketype(R::AbstractAlgebra.ResField, _) = elem_type(R) + +function rand(rng::AbstractRNG, + sp::SamplerTrivial{<:Make2{<:AbstractAlgebra.ResFieldElem{T}, + <:AbstractAlgebra.ResField{T}}} + ) where {T} + S, v = sp[][1:end] + S(rand(rng, v)) +end + +function RandomExtensions.make(S::AbstractAlgebra.ResField, vs...) R = base_ring(S) - return S(rand(rng, R, v...)) + if length(vs) == 1 && elem_type(R) == Random.gentype(vs[1]) + Make(S, vs[1]) + else + make(S, make(base_ring(S), vs...)) + end end +rand(rng::AbstractRNG, S::AbstractAlgebra.ResField, v...) = rand(rng, make(S, v...)) + rand(S::AbstractAlgebra.ResField, v...) = rand(Random.GLOBAL_RNG, S, v...) ############################################################################### diff --git a/src/julia/Float.jl b/src/julia/Float.jl index 02191d6ed0..b70ea7b430 100644 --- a/src/julia/Float.jl +++ b/src/julia/Float.jl @@ -185,14 +185,19 @@ end # ############################################################################### -function rand(rng::AbstractRNG, R::Floats, n::UnitRange{<:AbstractFloat}) - return R(n.start + rand(rng, Float64)*(n.stop - n.start)) -end +RandomExtensions.maketype(R::Floats{T}, _) where {T} = T -function rand(rng::AbstractRNG, R::Floats, n::UnitRange{Int}) - return R(n.start + rand(rng, Float64)*(n.stop - n.start)) +function rand(rng::AbstractRNG, + sp::SamplerTrivial{<:Make2{T, Floats{T}, + <:UnitRange{<:Union{AbstractFloat, Int}}}} + ) where {T} + R, n = sp[][1:end] + R(n.start + rand(rng, Float64)*(n.stop - n.start)) end + +rand(rng::AbstractRNG, R::Floats, n::UnitRange) = rand(rng, make(R, n)) + rand(R::Floats, n) = rand(Random.GLOBAL_RNG, R, n) ############################################################################### diff --git a/src/julia/Integer.jl b/src/julia/Integer.jl index d5770bfd39..9c122c2b07 100644 --- a/src/julia/Integer.jl +++ b/src/julia/Integer.jl @@ -351,9 +351,16 @@ end # ############################################################################### -function rand(rng::AbstractRNG, R::Integers, n::UnitRange{Int}) - return R(rand(rng, n)) -end +RandomExtensions.maketype(R::AbstractAlgebra.Integers{T}, _) where {T} = T + +# define rand(make(ZZ, n:m)) +rand(rng::AbstractRNG, + sp::SamplerTrivial{<:Make2{T, Integers{T}, UnitRange{Int}}} + ) where {T} = + sp[][1](rand(rng, sp[][2])) + + +rand(rng::AbstractRNG, R::Integers, n) = R(rand(rng, n)) rand(R::Integers, n) = rand(Random.GLOBAL_RNG, R, n) diff --git a/src/julia/Rational.jl b/src/julia/Rational.jl index 35358054df..3e59da3245 100644 --- a/src/julia/Rational.jl +++ b/src/julia/Rational.jl @@ -299,7 +299,12 @@ end # ############################################################################### -function rand(rng::AbstractRNG, R::Rationals{T}, n::UnitRange{Int}) where T <: Integer +RandomExtensions.maketype(R::Rationals{T}, _) where {T} = Rational{T} + +function rand(rng::AbstractRNG, + sp::SamplerTrivial{<:Make2{Rational{T}, Rationals{T}, UnitRange{Int}}} + ) where {T} + R, n = sp[][1:end] d = T(0) while d == 0 d = T(rand(rng, n)) @@ -308,6 +313,9 @@ function rand(rng::AbstractRNG, R::Rationals{T}, n::UnitRange{Int}) where T <: I return R(n, d) end + +rand(rng::AbstractRNG, R::Rationals, n) = rand(rng, make(R, n)) + rand(R::Rationals, n) = rand(Random.GLOBAL_RNG, R, n) ############################################################################### diff --git a/test/generic/Fraction-test.jl b/test/generic/Fraction-test.jl index 5220502125..3567422fbc 100644 --- a/test/generic/Fraction-test.jl +++ b/test/generic/Fraction-test.jl @@ -52,10 +52,12 @@ end @testset "Generic.Frac.rand..." begin S, x = PolynomialRing(ZZ, "x") K = FractionField(S) - f = rand(K, 0:3, -3:3) - @test f isa Generic.Frac - f = rand(rng, K, 0:3, -3:3) - @test f isa Generic.Frac + m = make(K, 0:3, -3:3) + for f in Any[rand(m), rand(rng, m), rand(m, 3)..., + rand(K, 0:3, -3:3), + rand(rng, K, 0:3, -3:3)] + @test f isa Generic.Frac + end end @testset "Generic.Frac.manipulation..." begin diff --git a/test/generic/LaurentPoly-test.jl b/test/generic/LaurentPoly-test.jl index c241e205b9..e44ba3d9b8 100644 --- a/test/generic/LaurentPoly-test.jl +++ b/test/generic/LaurentPoly-test.jl @@ -375,18 +375,16 @@ using AbstractAlgebra.Generic: Integers, LaurentPolyWrapRing, LaurentPolyWrap, @testset "rand" begin L, y = LaurentPolynomialRing(ZZ, "y") - f = rand(L, -5:5, -10:10) - @test f isa LaurentPolyElem{BigInt} - @test AbstractAlgebra.degrees_range(f) ⊆ -5:5 - for i = -5:5 - @test coeff(f, i) ∈ -10:10 - end - - f = rand(rng, L, -5:5, -10:10) - @test f isa LaurentPolyElem{BigInt} - @test AbstractAlgebra.degrees_range(f) ⊆ -5:5 - for i = -5:5 - @test coeff(f, i) ∈ -10:10 + m = make(L, -5:5, -10:10) + for f in (rand(m), rand(rng, m), + rand(L, -5:5, -10:10), + rand(rng, L, -5:5, -10:10)) + + @test f isa LaurentPolyElem{BigInt} + @test AbstractAlgebra.degrees_range(f) ⊆ -5:5 + for i = -5:5 + @test coeff(f, i) ∈ -10:10 + end end end diff --git a/test/generic/LaurentSeries-test.jl b/test/generic/LaurentSeries-test.jl index b1da87183d..2e19ae8f13 100644 --- a/test/generic/LaurentSeries-test.jl +++ b/test/generic/LaurentSeries-test.jl @@ -106,11 +106,25 @@ end f = rand(rng, R, -12:12, -10:10) @test f isa Generic.LaurentSeriesRingElem + for m in (make(R, -12:12, -10:10), + make(R, -12:12, make(ZZ, -10:10))) + for f in (rand(m), rand(rng, m)) + @test f isa Generic.LaurentSeriesRingElem{BigInt} + end + end + R, x = LaurentSeriesField(RealField, 10, "x") f = rand(R, -12:12, -1:1) @test f isa Generic.LaurentSeriesFieldElem f = rand(rng, R, -12:12, -1:1) @test f isa Generic.LaurentSeriesFieldElem + + for m in (make(R, -12:12, -1:1), + make(R, -12:12, make(RealField, -1:1))) + for f in (rand(m), rand(rng, m)) + @test f isa Generic.LaurentSeriesFieldElem{BigFloat} + end + end end @testset "Generic.LaurentSeries.manipulation..." begin diff --git a/test/generic/MPoly-test.jl b/test/generic/MPoly-test.jl index 8697584cbe..0e458b5308 100644 --- a/test/generic/MPoly-test.jl +++ b/test/generic/MPoly-test.jl @@ -108,10 +108,12 @@ end @test ord in [:lex, :deglex, :degrevlex] S, varlist = PolynomialRing(R, var_names, ordering = ord) - f = rand(S, 0:5, 0:100, 0:0, -100:100) - @test f isa Generic.MPoly - f = rand(rng, S, 0:5, 0:100, 0:0, -100:100) - @test f isa Generic.MPoly + m = make(S, 0:5, 0:100, 0:0, -100:100) + for f in (rand(m), rand(rng, m), + rand(S, 0:5, 0:100, 0:0, -100:100), + rand(rng, S, 0:5, 0:100, 0:0, -100:100)) + @test f isa Generic.MPoly + end end @testset "Generic.MPoly.manipulation..." begin diff --git a/test/generic/Matrix-test.jl b/test/generic/Matrix-test.jl index acc27270c7..0837e9f234 100644 --- a/test/generic/Matrix-test.jl +++ b/test/generic/Matrix-test.jl @@ -519,7 +519,7 @@ end end M0 = MatrixAlgebra(R, 0) - m0 = rand(M0, 0:9, -9, 9) + m0 = rand(M0, 0:9, -9:9) @test length(m0) == 0 @test isempty(m0) @@ -2902,3 +2902,19 @@ end @test Matrix(F) == B @test eltype(B) == F2Elem end + +@testset "Generic.Mat.rand" begin + M = MatrixSpace(ZZ, 2, 3) + m = make(M, 1:9) + for A in Any[rand(m), rand(rng, m), rand(m, 3)..., + rand(M, 1:9), rand(rng, M, 1:9)] + @test A isa elem_type(M) + end + + M = MatrixSpace(GF(7), 3, 2) + m = make(M) + for A in Any[rand(m), rand(rng, m), rand(m, 3)..., + rand(M), rand(rng, M)] + @test A isa elem_type(M) + end +end diff --git a/test/generic/MatrixAlgebra-test.jl b/test/generic/MatrixAlgebra-test.jl index 3982647986..03e9a508b7 100644 --- a/test/generic/MatrixAlgebra-test.jl +++ b/test/generic/MatrixAlgebra-test.jl @@ -1250,3 +1250,19 @@ end end end end + +@testset "Generic.MatAlg.rand" begin + M = MatrixAlgebra(ZZ, 3) + m = make(M, 1:9) + for A in Any[rand(m), rand(rng, m), rand(m, 3)..., + rand(M, 1:9), rand(rng, M, 1:9)] + @test A isa elem_type(M) + end + + M = MatrixAlgebra(GF(7), 2) + m = make(M) + for A in Any[rand(m), rand(rng, m), rand(m, 3)..., + rand(M), rand(rng, M)] + @test A isa elem_type(M) + end +end diff --git a/test/generic/Module-test.jl b/test/generic/Module-test.jl index dff5f8cf61..b64825ddea 100644 --- a/test/generic/Module-test.jl +++ b/test/generic/Module-test.jl @@ -15,10 +15,11 @@ end @testset "Generic.Module.rand..." begin F = FreeModule(ZZ, 3) - f = rand(F, 1:9) - @test f isa Generic.FreeModuleElem - f = rand(rng, F, 1:9) - @test f isa Generic.FreeModuleElem + m = make(F, 1:9) + for f in Any[rand(m), rand(rng, m), rand(m, 3)..., + rand(F, 1:9), rand(rng, F, 1:9)] + @test f isa Generic.FreeModuleElem + end end @testset "Generic.Module.manipulation..." begin diff --git a/test/generic/NCPoly-test.jl b/test/generic/NCPoly-test.jl index 1976e9379d..3b9b57aeb5 100644 --- a/test/generic/NCPoly-test.jl +++ b/test/generic/NCPoly-test.jl @@ -103,10 +103,12 @@ end R = MatrixAlgebra(ZZ, 2) S, y = PolynomialRing(R, "y") - f = rand(S, 0:10, -10:10) - @test f isa Generic.NCPoly - f = rand(rng, S, 0:10, -10:10) - @test f isa Generic.NCPoly + m = make(S, 0:10, -10:10) + for f in (rand(m), rand(rng, m), + rand(S, 0:10, -10:10), + rand(rng, S, 0:10, -10:10)) + @test f isa Generic.NCPoly + end end @testset "Generic.NCPoly.binary_ops..." begin diff --git a/test/generic/Poly-test.jl b/test/generic/Poly-test.jl index 0dc631183d..3de6f3820f 100644 --- a/test/generic/Poly-test.jl +++ b/test/generic/Poly-test.jl @@ -86,11 +86,41 @@ end @testset "Generic.Poly.rand..." begin + # TODO: test more than just the result type R, x = PolynomialRing(ZZ, "x") f = rand(R, 0:10, -10:10) @test f isa Generic.Poly f = rand(rng, R, 0:10, -10:10) @test f isa Generic.Poly + + # make API + for m in (make(R, 0:10, make(ZZ, -10:10)), + make(R, 0:10, -10:10)) # convenience only + for f in (rand(m), rand(rng, m)) + @test f isa Generic.Poly + end + @test rand(m, 3) isa Vector{Generic.Poly{BigInt}} + @test size(rand(rng, m, 2, 3)) == (2, 3) + end + + S, y = PolynomialRing(R, "y") + for m in (make(S, 0:5, make(R, 0:10, make(ZZ, -10:10))), + make(S, 0:5, make(R, 0:10, -10:10)), + make(S, 0:5, 0:10, -10:10)) + + for f in (rand(m), rand(rng, m)) + @test f isa Generic.Poly{Generic.Poly{BigInt}} + end + a = rand(m, 3) + @test length(a) == 3 + @test a isa Vector{Generic.Poly{Generic.Poly{BigInt}}} + end + + T, z = PolynomialRing(GF(7), "z") + m = make(T, 0:4) + for f in (rand(m), rand(rng, m)) + @test f isa Generic.Poly{AbstractAlgebra.GFElem{Int64}} + end end @testset "Generic.Poly.manipulation..." begin diff --git a/test/generic/PuiseuxSeries-test.jl b/test/generic/PuiseuxSeries-test.jl index 50b358aa6a..7717dad2f0 100644 --- a/test/generic/PuiseuxSeries-test.jl +++ b/test/generic/PuiseuxSeries-test.jl @@ -98,11 +98,25 @@ end f = rand(rng, R, -12:12, 1:6, -10:10) @test f isa Generic.PuiseuxSeriesRingElem + for m in (make(R, -12:12, 1:6, -10:10), + make(R, -12:12, 1:6, make(ZZ, -10:10))) + for f in (rand(m), rand(rng, m)) + @test f isa Generic.PuiseuxSeriesRingElem{BigInt} + end + end + R, x = PuiseuxSeriesField(RealField, 10, "x") f = rand(R, -12:12, 1:6, -1:1) @test f isa Generic.PuiseuxSeriesFieldElem f = rand(rng, R, -12:12, 1:6, -1:1) @test f isa Generic.PuiseuxSeriesFieldElem + + for m in (make(R, -12:12, 1:6, -1:1), + make(R, -12:12, 1:6, make(RealField, -1:1))) + for f in (rand(m), rand(rng, m)) + @test f isa Generic.PuiseuxSeriesFieldElem{BigFloat} + end + end end @testset "Generic.PuiseuxSeries.manipulation..." begin diff --git a/test/generic/RelSeries-test.jl b/test/generic/RelSeries-test.jl index 6816ff941b..dc83f38bbb 100644 --- a/test/generic/RelSeries-test.jl +++ b/test/generic/RelSeries-test.jl @@ -84,10 +84,12 @@ end @testset "Generic.RelSeries.rand..." begin R, x = PowerSeriesRing(ZZ, 10, "x") - f = rand(R, 0:12, -10:10) - @test f isa Generic.RelSeries - f = rand(rng, R, 0:12, -10:10) - @test f isa Generic.RelSeries + m = make(R, 0:12, -10:10) + for f in Any[rand(m), rand(rng, m), rand(m, 3)..., + rand(R, 0:12, -10:10), + rand(rng, R, 0:12, -10:10)] + @test f isa Generic.RelSeries + end end @testset "Generic.RelSeries.manipulation..." begin diff --git a/test/generic/Residue-test.jl b/test/generic/Residue-test.jl index c8e3a443ba..1237cdadb8 100644 --- a/test/generic/Residue-test.jl +++ b/test/generic/Residue-test.jl @@ -57,6 +57,17 @@ end @test f isa Generic.Res f = rand(rng, R, 1:9) @test f isa Generic.Res + m = make(R, 1:9) + for f = (rand(m), rand(rng, m)) + @test f isa Generic.Res + @test 1 <= f.data <= 9 + end + + # make with 3 arguments + P, x = PolynomialRing(RealField, "x") + R = Generic.ResidueRing(P, x^3) + m = make(R, 1:9, -3:3) + @test rand(m) isa Generic.Res{AbstractAlgebra.Generic.Poly{BigFloat}} end @testset "Generic.Res.manipulation..." begin diff --git a/test/generic/ResidueField-test.jl b/test/generic/ResidueField-test.jl index 7728cc727c..a2b418f0d7 100644 --- a/test/generic/ResidueField-test.jl +++ b/test/generic/ResidueField-test.jl @@ -55,6 +55,12 @@ end @test f isa Generic.ResF f = rand(rng, R, 1:9) @test f isa Generic.ResF + + m = make(R, 1:9) + for f in (rand(m), rand(rng, m)) + @test f isa Generic.ResF + @test 1 <= f.data <= 9 + end end @testset "Generic.ResF.manipulation..." begin diff --git a/test/julia/Floats-test.jl b/test/julia/Floats-test.jl index 9710e1935a..723a7d94ce 100644 --- a/test/julia/Floats-test.jl +++ b/test/julia/Floats-test.jl @@ -46,6 +46,15 @@ end @test f isa elem_type(R) f = rand(rng, R, UnitRange(big(1.0), big(9.0))) @test f isa elem_type(R) + + # make + for r in (1:9, UnitRange(1.0, 9.0), UnitRange(big(1.0), big(9.0))) + m = make(R, r) + @test rand(m) isa elem_type(R) + @test 1.0 <= rand(m) <= 9.0 + @test rand(rng, m) isa elem_type(R) + @test rand(m, 2, 3) isa Matrix{elem_type(R)} + end end @testset "Julia.Floats.manipulation..." begin diff --git a/test/julia/Integers-test.jl b/test/julia/Integers-test.jl index 6ddb603230..6948dc5e1d 100644 --- a/test/julia/Integers-test.jl +++ b/test/julia/Integers-test.jl @@ -52,6 +52,9 @@ end @test f isa elem_type(R) f = rand(rng, R, 0:22) @test f isa elem_type(R) + f = rand(make(R, 0:22)) + @test f isa elem_type(R) + @test f in 0:22 end @testset "Julia.Integers.modular_arithmetic..." begin diff --git a/test/julia/Rationals-test.jl b/test/julia/Rationals-test.jl index 546e8f9a6b..a7d7ce28f2 100644 --- a/test/julia/Rationals-test.jl +++ b/test/julia/Rationals-test.jl @@ -41,6 +41,14 @@ end @test f isa elem_type(R) f = rand(rng, R, 1:9) @test f isa elem_type(R) + + # make + m = make(R, 1:9) + for f = (rand(m), rand(rng, m)) + @test f isa elem_type(R) + @test 1 <= numerator(f) <= 9 + @test 1 <= denominator(f) <= 9 + end end @testset "Julia.Rationals.manipulation..." begin diff --git a/test/runtests.jl b/test/runtests.jl index bdc22998a7..0bacb555fb 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,6 +2,7 @@ using AbstractAlgebra using SparseArrays, LinearAlgebra using AbstractAlgebra: mul! # disambiguate from LinearAlgebra.mul! +using RandomExtensions: make if VERSION < v"0.7.0-DEV.2004" using Base.Test