Package evaluation of CSTParser on Julia 1.12.0-DEV.2044 (c78016e4dc*) started at 2025-02-25T21:58:50.284 ################################################################################ # Set-up # Installing PkgEval dependencies (TestEnv)... Set-up completed after 8.54s ################################################################################ # Installation # Installing CSTParser... Resolving package versions... Installed Tokenize ── v0.5.29 Installed CSTParser ─ v3.4.3 Updating `~/.julia/environments/v1.12/Project.toml` [00ebfdb7] + CSTParser v3.4.3 Updating `~/.julia/environments/v1.12/Manifest.toml` [00ebfdb7] + CSTParser v3.4.3 [0796e94c] + Tokenize v0.5.29 Installation completed after 0.95s ################################################################################ # Precompilation # Precompiling PkgEval dependencies... Precompiling packages... 6407.7 ms ✓ TestEnv 1 dependency successfully precompiled in 9 seconds. 25 already precompiled. Precompiling package dependencies... Precompilation completed after 63.72s ################################################################################ # Testing # Testing CSTParser Status `/tmp/jl_udbCMJ/Project.toml` [00ebfdb7] CSTParser v3.4.3 [f8b46487] TestItemRunner v1.1.0 [0796e94c] Tokenize v0.5.29 [8dfed614] Test v1.11.0 Status `/tmp/jl_udbCMJ/Manifest.toml` [00ebfdb7] CSTParser v3.4.3 [f8b46487] TestItemRunner v1.1.0 [1c621080] TestItems v1.0.0 [0796e94c] Tokenize v0.5.29 [0dad84c5] ArgTools v1.1.2 [56f22d72] Artifacts v1.11.0 [2a0f44e3] Base64 v1.11.0 [ade2ca70] Dates v1.11.0 [f43a241f] Downloads v1.6.0 [7b1f6079] FileWatching v1.11.0 [b77e0a4c] InteractiveUtils v1.11.0 [ac6e5ff7] JuliaSyntaxHighlighting v1.12.0 [b27032c2] LibCURL v0.6.4 [76f85450] LibGit2 v1.11.0 [8f399da3] Libdl v1.11.0 [56ddb016] Logging v1.11.0 [d6f4376e] Markdown v1.11.0 [ca575930] NetworkOptions v1.3.0 [44cfe95a] Pkg v1.12.0 [de0858da] Printf v1.11.0 [9a3f8284] Random v1.11.0 [ea8e919c] SHA v0.7.0 [9e88b42a] Serialization v1.11.0 [f489334b] StyledStrings v1.11.0 [fa267f1f] TOML v1.0.3 [a4e569a6] Tar v1.10.0 [8dfed614] Test v1.11.0 [cf7118a7] UUIDs v1.11.0 [4ec0a83e] Unicode v1.11.0 [deac9b47] LibCURL_jll v8.11.1+1 [e37daf67] LibGit2_jll v1.9.0+0 [29816b5a] LibSSH2_jll v1.11.3+1 [14a3606d] MozillaCACerts_jll v2024.12.31 [458c3c95] OpenSSL_jll v3.0.16+0 [83775a58] Zlib_jll v1.3.1+2 [8e850ede] nghttp2_jll v1.64.0+1 [3f19e933] p7zip_jll v17.5.0+2 Testing Running tests... ┌ Error: parsing difference │ file = "/opt/julia/bin/../share/julia/base/gmp.jl" └ @ Main.var"##327" ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:157 begin RoundToZero end RoundToZero $(Expr(:kw, :(::typeof(RoundToZero)), quote RoundToZero end)) $(Expr(:kw, :(::typeof(RoundToZero)), :RoundToZero)) divrem(x::BigInt, y::BigInt, ::typeof(RoundToZero) = begin RoundToZero end) divrem(x::BigInt, y::BigInt, ::typeof(RoundToZero) = RoundToZero) divrem(x::BigInt, y::BigInt, ::typeof(RoundToZero) = begin RoundToZero end) = begin MPZ.tdiv_qr(x, y) end divrem(x::BigInt, y::BigInt, ::typeof(RoundToZero) = RoundToZero) = begin MPZ.tdiv_qr(x, y) end begin RoundToZero end RoundToZero $(Expr(:kw, :(::typeof(RoundToZero)), quote RoundToZero end)) $(Expr(:kw, :(::typeof(RoundToZero)), :RoundToZero)) divrem(x::BigInt, y::Integer, ::typeof(RoundToZero) = begin RoundToZero end) divrem(x::BigInt, y::Integer, ::typeof(RoundToZero) = RoundToZero) divrem(x::BigInt, y::Integer, ::typeof(RoundToZero) = begin RoundToZero end) = begin MPZ.tdiv_qr(x, BigInt(y)) end divrem(x::BigInt, y::Integer, ::typeof(RoundToZero) = RoundToZero) = begin MPZ.tdiv_qr(x, BigInt(y)) end begin export BigInt import .Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, ~, &, |, xor, nand, nor, binomial, cmp, convert, div, divrem, factorial, cld, fld, gcd, gcdx, lcm, mod, ndigits, promote_rule, rem, show, isqrt, string, powermod, sum, prod, trailing_zeros, trailing_ones, count_ones, count_zeros, tryparse_internal, bin, oct, dec, hex, isequal, invmod, _prevpow2, _nextpow2, ndigits0zpb, widen, signed, unsafe_trunc, trunc, iszero, isone, big, flipsign, signbit, sign, hastypemax, isodd, iseven, digits!, hash, hash_integer, top_set_bit, clamp, unsafe_takestring import Core: Signed, Float16, Float32, Float64 if Clong == Int32 const ClongMax = Union{Int8, Int16, Int32} const CulongMax = Union{UInt8, UInt16, UInt32} else const ClongMax = Union{Int8, Int16, Int32, Int64} const CulongMax = Union{UInt8, UInt16, UInt32, UInt64} end const CdoubleMax = Union{Float16, Float32, Float64} if Sys.iswindows() const libgmp = "libgmp-10.dll" elseif Sys.isapple() const libgmp = "@rpath/libgmp.10.dylib" else const libgmp = "libgmp.so.10" end _version() = begin unsafe_string(unsafe_load(cglobal((:__gmp_version, libgmp), Ptr{Cchar}))) end version() = begin VersionNumber(_version()) end major_version() = begin (_version())[1] end bits_per_limb() = begin Int(unsafe_load(cglobal((:__gmp_bits_per_limb, libgmp), Cint))) end const VERSION = version() const MAJOR_VERSION = major_version() const BITS_PER_LIMB = bits_per_limb() if BITS_PER_LIMB == 32 const Limb = UInt32 const SLimbMax = Union{Int8, Int16, Int32} const ULimbMax = Union{UInt8, UInt16, UInt32} elseif BITS_PER_LIMB == 64 const Limb = UInt64 const SLimbMax = Union{Int8, Int16, Int32, Int64} const ULimbMax = Union{UInt8, UInt16, UInt32, UInt64} else error("GMP: cannot determine the type mp_limb_t (__gmp_bits_per_limb == $(BITS_PER_LIMB))") end Core.@doc " BigInt <: Signed\n\nArbitrary precision integer type.\n" mutable struct BigInt <: Signed alloc::Cint size::Cint d::Ptr{Limb} function BigInt(; nbits::Integer = 0) b = MPZ.init2!(new(), nbits) finalizer(cglobal((:__gmpz_clear, libgmp)), b) return b end end Core.@doc " BigInt(x)\n\nCreate an arbitrary precision integer. `x` may be an `Int` (or anything that can be\nconverted to an `Int`). The usual mathematical operators are defined for this type, and\nresults are promoted to a [`BigInt`](@ref).\n\nInstances can be constructed from strings via [`parse`](@ref), or using the `big`\nstring literal.\n\n# Examples\n```jldoctest\njulia> parse(BigInt, \"42\")\n42\n\njulia> big\"313\"\n313\n\njulia> BigInt(10)^19\n10000000000000000000\n```\n" BigInt(x) Core.@doc " ALLOC_OVERFLOW_FUNCTION\n\nA reference that holds a boolean, if true, indicating julia is linked with a patched GMP that\ndoes not abort on huge allocation and throws OutOfMemoryError instead.\n" const ALLOC_OVERFLOW_FUNCTION = Ref(false) function __init__() try if major_version() != MAJOR_VERSION || bits_per_limb() != BITS_PER_LIMB msg = "The dynamically loaded GMP library (v\"$(version())\" with __gmp_bits_per_limb == $(bits_per_limb()))\ndoes not correspond to the compile time version (v\"$(VERSION)\" with __gmp_bits_per_limb == $(BITS_PER_LIMB)).\nPlease rebuild Julia." if bits_per_limb() != BITS_PER_LIMB @error msg else @warn msg end end ccall((:__gmp_set_memory_functions, libgmp), Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), cglobal(:jl_gc_counted_malloc), cglobal(:jl_gc_counted_realloc_with_old_size), cglobal(:jl_gc_counted_free_with_size)) (ZERO.alloc, ZERO.size, ZERO.d) = (0, 0, C_NULL) (ONE.alloc, ONE.size, ONE.d) = (1, 1, pointer(_ONE)) catch ex Base.showerror_nostdio(ex, "WARNING: Error during initialization of module GMP") end try ccall((:__gmp_set_alloc_overflow_function, libgmp), Cvoid, (Ptr{Cvoid},), cglobal(:jl_throw_out_of_memory_error)) ALLOC_OVERFLOW_FUNCTION[] = true catch ex if typeof(ex) != ErrorException rethrow() end end end module MPZ using ..GMP: BigInt, Limb, BITS_PER_LIMB, libgmp const mpz_t = Ref{BigInt} const bitcnt_t = Culong gmpz(op::Symbol) = begin (Symbol(:__gmpz_, op), libgmp) end init!(x::BigInt) = begin ccall((:__gmpz_init, libgmp), Cvoid, (mpz_t,), x) x end init2!(x::BigInt, a) = begin ccall((:__gmpz_init2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end realloc2!(x, a) = begin ccall((:__gmpz_realloc2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end realloc2(a) = begin realloc2!(BigInt(), a) end sizeinbase(a::BigInt, b) = begin Int(ccall((:__gmpz_sizeinbase, libgmp), Csize_t, (mpz_t, Cint), a, b)) end for (op, nbits) = (:add => :(BITS_PER_LIMB * (1 + max(abs(a.size), abs(b.size)))), :sub => :(BITS_PER_LIMB * (1 + max(abs(a.size), abs(b.size)))), :mul => 0, :fdiv_q => 0, :tdiv_q => 0, :cdiv_q => 0, :fdiv_r => 0, :tdiv_r => 0, :cdiv_r => 0, :gcd => 0, :lcm => 0, :and => 0, :ior => 0, :xor => 0) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt, b::BigInt) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t, mpz_t), x, a, b) x end ($op)(a::BigInt, b::BigInt) = begin ($op!)(BigInt(nbits = $nbits), a, b) end ($op!)(x::BigInt, b::BigInt) = begin ($op!)(x, x, b) end end end invert!(x::BigInt, a::BigInt, b::BigInt) = begin ccall((:__gmpz_invert, libgmp), Cint, (mpz_t, mpz_t, mpz_t), x, a, b) end invert!(x::BigInt, b::BigInt) = begin invert!(x, x, b) end invert(a::BigInt, b::BigInt) = begin ret = BigInt() invert!(ret, a, b) ret end for op = (:add_ui, :sub_ui, :mul_ui, :mul_2exp, :fdiv_q_2exp, :pow_ui, :bin_ui) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt, b) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t, Culong), x, a, b) x end ($op)(a::BigInt, b) = begin ($op!)(BigInt(), a, b) end ($op!)(x::BigInt, b) = begin ($op!)(x, x, b) end end end ui_sub!(x::BigInt, a, b::BigInt) = begin ccall((:__gmpz_ui_sub, libgmp), Cvoid, (mpz_t, Culong, mpz_t), x, a, b) x end ui_sub(a, b::BigInt) = begin ui_sub!(BigInt(), a, b) end for op = (:scan1, :scan0) @eval ($op)(a::BigInt, b) = begin Int(signed(ccall($(gmpz(op)), Culong, (mpz_t, Culong), a, b))) end end mul_si!(x::BigInt, a::BigInt, b) = begin ccall((:__gmpz_mul_si, libgmp), Cvoid, (mpz_t, mpz_t, Clong), x, a, b) x end mul_si(a::BigInt, b) = begin mul_si!(BigInt(), a, b) end mul_si!(x::BigInt, b) = begin mul_si!(x, x, b) end for op = (:neg, :com, :sqrt, :set) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t), x, a) x end ($op)(a::BigInt) = begin ($op!)(BigInt(), a) end end op === :set && continue @eval ($op!)(x::BigInt) = begin ($op!)(x, x) end end for (op, T) = ((:fac_ui, Culong), (:set_ui, Culong), (:set_si, Clong), (:set_d, Cdouble)) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, $T), x, a) x end ($op)(a) = begin ($op!)(BigInt(), a) end end end popcount(a::BigInt) = begin Int(signed(ccall((:__gmpz_popcount, libgmp), Culong, (mpz_t,), a))) end mpn_popcount(d::Ptr{Limb}, s::Integer) = begin Int(ccall((:__gmpn_popcount, libgmp), Culong, (Ptr{Limb}, Csize_t), d, s)) end mpn_popcount(a::BigInt) = begin mpn_popcount(a.d, abs(a.size)) end function tdiv_qr!(x::BigInt, y::BigInt, a::BigInt, b::BigInt) ccall((:__gmpz_tdiv_qr, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, y, a, b) (x, y) end tdiv_qr(a::BigInt, b::BigInt) = begin tdiv_qr!(BigInt(), BigInt(), a, b) end powm!(x::BigInt, a::BigInt, b::BigInt, c::BigInt) = begin ccall((:__gmpz_powm, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, a, b, c) x end powm(a::BigInt, b::BigInt, c::BigInt) = begin powm!(BigInt(), a, b, c) end powm!(x::BigInt, b::BigInt, c::BigInt) = begin powm!(x, x, b, c) end function gcdext!(x::BigInt, y::BigInt, z::BigInt, a::BigInt, b::BigInt) ccall((:__gmpz_gcdext, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t, mpz_t), x, y, z, a, b) (x, y, z) end gcdext(a::BigInt, b::BigInt) = begin gcdext!(BigInt(), BigInt(), BigInt(), a, b) end cmp(a::BigInt, b::BigInt) = begin Int(ccall((:__gmpz_cmp, libgmp), Cint, (mpz_t, mpz_t), a, b)) end cmp_si(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_si, libgmp), Cint, (mpz_t, Clong), a, b)) end cmp_ui(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_ui, libgmp), Cint, (mpz_t, Culong), a, b)) end cmp_d(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_d, libgmp), Cint, (mpz_t, Cdouble), a, b)) end mpn_cmp(a::Ptr{Limb}, b::Ptr{Limb}, c) = begin ccall((:__gmpn_cmp, libgmp), Cint, (Ptr{Limb}, Ptr{Limb}, Clong), a, b, c) end mpn_cmp(a::BigInt, b::BigInt, c) = begin mpn_cmp(a.d, b.d, c) end get_str!(x, a, b::BigInt) = begin ccall((:__gmpz_get_str, libgmp), Ptr{Cchar}, (Ptr{Cchar}, Cint, mpz_t), x, a, b) x end set_str!(x::BigInt, a, b) = begin Int(ccall((:__gmpz_set_str, libgmp), Cint, (mpz_t, Ptr{UInt8}, Cint), x, a, b)) end get_d(a::BigInt) = begin ccall((:__gmpz_get_d, libgmp), Cdouble, (mpz_t,), a) end function export!(a::AbstractVector{T}, n::BigInt; order::Integer = -1, nails::Integer = 0, endian::Integer = 0) where T <: Base.BitInteger stride(a, 1) == 1 || throw(ArgumentError("a must have stride 1")) ndigits = cld(sizeinbase(n, 2), 8 * sizeof(T) - nails) length(a) < ndigits && resize!(a, ndigits) count = Ref{Csize_t}() ccall((:__gmpz_export, libgmp), Ptr{T}, (Ptr{T}, Ref{Csize_t}, Cint, Csize_t, Cint, Csize_t, mpz_t), a, count, order, sizeof(T), endian, nails, n) @assert count[] ≤ length(a) return (a, Int(count[])) end limbs_write!(x::BigInt, a) = begin ccall((:__gmpz_limbs_write, libgmp), Ptr{Limb}, (mpz_t, Clong), x, a) end limbs_finish!(x::BigInt, a) = begin ccall((:__gmpz_limbs_finish, libgmp), Cvoid, (mpz_t, Clong), x, a) end setbit!(x, a) = begin ccall((:__gmpz_setbit, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end tstbit(a::BigInt, b) = begin ccall((:__gmpz_tstbit, libgmp), Cint, (mpz_t, bitcnt_t), a, b) % Bool end end const ZERO = BigInt() const ONE = BigInt() const _ONE = Limb[1] widen(::Type{Int128}) = begin BigInt end widen(::Type{UInt128}) = begin BigInt end widen(::Type{BigInt}) = begin BigInt end signed(x::BigInt) = begin x end BigInt(x::BigInt) = begin x end Signed(x::BigInt) = begin x end hastypemax(::Type{BigInt}) = begin false end function tryparse_internal(::Type{BigInt}, s::AbstractString, startpos::Int, endpos::Int, base_::Integer, raise::Bool) bstr = if startpos == firstindex(s) && endpos == lastindex(s) String(s) else String(SubString(s, startpos, endpos)) end (sgn, base, i) = Base.parseint_preamble(true, Int(base_), bstr, firstindex(bstr), lastindex(bstr)) if !(2 <= base <= 62) raise && throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $(base)")) return nothing end if i == 0 raise && throw(ArgumentError("premature end of integer: $(repr(bstr))")) return nothing end z = BigInt() if Base.containsnul(bstr) err = -1 else err = GC.@preserve(bstr, MPZ.set_str!(z, pointer(bstr) + (i - firstindex(bstr)), base)) end if err != 0 raise && throw(ArgumentError("invalid BigInt: $(repr(bstr))")) return nothing end flipsign!(z, sgn) end BigInt(x::Union{Clong, Int32}) = begin MPZ.set_si(x) end BigInt(x::Union{Culong, UInt32}) = begin MPZ.set_ui(x) end BigInt(x::Bool) = begin BigInt(UInt(x)) end unsafe_trunc(::Type{BigInt}, x::Union{Float16, Float32, Float64}) = begin MPZ.set_d(x) end function BigInt(x::Float64) isinteger(x) || throw(InexactError(:BigInt, BigInt, x)) unsafe_trunc(BigInt, x) end BigInt(x::Float16) = begin BigInt(Float64(x)) end BigInt(x::Float32) = begin BigInt(Float64(x)) end function BigInt(x::Integer) isbits(x) && (typemin(Clong) <= x <= typemax(Clong) && return BigInt((x % Clong)::Clong)) nd = ndigits(x, base = 2) z = MPZ.realloc2(nd) ux = unsigned(if x < 0 -x else x end) size = 0 limbnbits = sizeof(Limb) << 3 while nd > 0 size += 1 unsafe_store!(z.d, ux % Limb, size) ux >>= limbnbits nd -= limbnbits end z.size = if x < 0 -size else size end z end rem(x::BigInt, ::Type{Bool}) = begin (!(iszero(x)) & unsafe_load(x.d)) % Bool end (rem(x::BigInt, ::Type{T}) where T <: Union{SLimbMax, ULimbMax}) = begin if iszero(x) zero(T) else flipsign(unsafe_load(x.d) % T, x.size) end end function rem(x::BigInt, ::Type{T}) where T <: Union{Base.BitUnsigned, Base.BitSigned} u = zero(T) for l = 1:min(abs(x.size), cld(sizeof(T), sizeof(Limb))) u += (unsafe_load(x.d, l) % T) << (sizeof(Limb) << 3 * (l - 1)) end flipsign(u, x.size) end rem(x::Integer, ::Type{BigInt}) = begin BigInt(x) end clamp(x, ::Type{BigInt}) = begin convert(BigInt, x) end isodd(x::BigInt) = begin MPZ.tstbit(x, 0) end iseven(x::BigInt) = begin !(isodd(x)) end function (::Type{T})(x::BigInt) where T <: Base.BitUnsigned if sizeof(T) < sizeof(Limb) convert(T, convert(Limb, x)) else 0 <= x.size <= cld(sizeof(T), sizeof(Limb)) || throw(InexactError(nameof(T), T, x)) x % T end end function (::Type{T})(x::BigInt) where T <: Base.BitSigned n = abs(x.size) if sizeof(T) < sizeof(Limb) SLimb = typeof(Signed(one(Limb))) convert(T, convert(SLimb, x)) else 0 <= n <= cld(sizeof(T), sizeof(Limb)) || throw(InexactError(nameof(T), T, x)) y = x % T ispos(x) ⊻ (y > 0) && throw(InexactError(nameof(T), T, x)) y end end Float64(n::BigInt, ::RoundingMode{:ToZero}) = begin MPZ.get_d(n) end function (::Type{T})(n::BigInt, ::RoundingMode{:ToZero}) where T <: Union{Float16, Float32} T(Float64(n, RoundToZero), RoundToZero) end function (::Type{T})(n::BigInt, ::RoundingMode{:Down}) where T <: CdoubleMax x = T(n, RoundToZero) if x > n prevfloat(x) else x end end function (::Type{T})(n::BigInt, ::RoundingMode{:Up}) where T <: CdoubleMax x = T(n, RoundToZero) if x < n nextfloat(x) else x end end function Float64(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return 0.0 xsize = abs(x.size) if xsize * BITS_PER_LIMB > 1024 z = Inf64 elseif xsize == 1 z = Float64(unsafe_load(x.d)) elseif Limb == UInt32 && xsize == 2 z = Float64((unsafe_load(x.d, 2) % UInt64) << BITS_PER_LIMB + unsafe_load(x.d)) else y1 = unsafe_load(x.d, xsize) % UInt64 n = top_set_bit(y1) y = y1 >> (n - (precision(Float64) + 1)) if Limb == UInt64 y += if n > precision(Float64) 0 else unsafe_load(x.d, xsize - 1) >> (10 + n) end else y += (unsafe_load(x.d, xsize - 1) % UInt64) >> (n - 22) y += if n > precision(Float64) - 32 0 else unsafe_load(x.d, xsize - 2) >> (10 + n) end end y = (y + 1) >> 1 y &= ~(UInt64(trailing_zeros(x) == (n - 54) + (xsize - 1) * BITS_PER_LIMB)) d = ((n + 1021) % UInt64) << 52 z = reinterpret(Float64, d + y) z = ldexp(z, (xsize - 1) * BITS_PER_LIMB) end return flipsign(z, x.size) end function Float32(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return 0.0f0 xsize = abs(x.size) if xsize * BITS_PER_LIMB > 128 z = Inf32 elseif xsize == 1 z = Float32(unsafe_load(x.d)) else y1 = unsafe_load(x.d, xsize) n = BITS_PER_LIMB - leading_zeros(y1) y = y1 >> (n - (precision(Float32) + 1)) % UInt32 y += if n > precision(Float32) 0 else unsafe_load(x.d, xsize - 1) >> (BITS_PER_LIMB - -25) end % UInt32 y = (y + one(UInt32)) >> 1 y &= ~(UInt32(trailing_zeros(x) == (n - 25) + (xsize - 1) * BITS_PER_LIMB)) d = ((n + 125) % UInt32) << 23 z = reinterpret(Float32, d + y) z = ldexp(z, (xsize - 1) * BITS_PER_LIMB) end return flipsign(z, x.size) end function Float16(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return Float16(0.0) y1 = unsafe_load(x.d) n = BITS_PER_LIMB - leading_zeros(y1) if n > 16 || abs(x.size) > 1 z = Inf16 else y = y1 >> (n - (precision(Float16) + 1)) % UInt16 y = (y + one(UInt16)) >> 1 y &= ~(UInt16(trailing_zeros(x) == n - 12)) d = ((n + 13) % UInt16) << 10 z = reinterpret(Float16, d + y) end return flipsign(z, x.size) end Float64(n::BigInt) = begin Float64(n, RoundNearest) end Float32(n::BigInt) = begin Float32(n, RoundNearest) end Float16(n::BigInt) = begin Float16(n, RoundNearest) end promote_rule(::Type{BigInt}, ::Type{<:Integer}) = begin BigInt end Core.@doc " big(x)\n\nConvert a number to a maximum precision representation (typically [`BigInt`](@ref) or\n`BigFloat`). See [`BigFloat`](@ref BigFloat(::Any, rounding::RoundingMode)) for\ninformation about some pitfalls with floating-point numbers.\n" function big end big(::Type{<:Integer}) = begin BigInt end big(::Type{<:Rational}) = begin Rational{BigInt} end big(n::Integer) = begin convert(BigInt, n) end for (fJ, fC) = ((:+, :add), (:-, :sub), (:*, :mul), (:mod, :fdiv_r), (:rem, :tdiv_r), (:gcd, :gcd), (:lcm, :lcm), (:&, :and), (:|, :ior), (:xor, :xor)) @eval begin ($fJ)(x::BigInt, y::BigInt) = begin MPZ.:($fC)(x, y) end end end for (r, f) = ((RoundToZero, :tdiv_q), (RoundDown, :fdiv_q), (RoundUp, :cdiv_q)) @eval div(x::BigInt, y::BigInt, ::typeof($r)) = begin MPZ.:($f)(x, y) end end div(x::BigInt, y::BigInt) = begin div(x, y, RoundToZero) end fld(x::BigInt, y::BigInt) = begin div(x, y, RoundDown) end cld(x::BigInt, y::BigInt) = begin div(x, y, RoundUp) end x::BigInt / y::BigInt = begin float(x) / float(y) end function invmod(x::BigInt, y::BigInt) z = zero(BigInt) ya = abs(y) if ya == 1 return z end if y == 0 || MPZ.invert!(z, x, ya) == 0 throw(DomainError(y)) end if y < 0 MPZ.add!(z, y) end return z end for (fJ, fC) = ((:+, :add), (:*, :mul), (:&, :and), (:|, :ior), (:xor, :xor)) fC! = Symbol(fC, :!) @eval begin ($fJ)(a::BigInt, b::BigInt, c::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC)(a, b), c) end ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC)(a, b), c), d) end ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC)(a, b), c), d), e) end end end x::BigInt + c::CulongMax = begin MPZ.add_ui(x, c) end c::CulongMax + x::BigInt = begin x + c end x::BigInt - c::CulongMax = begin MPZ.sub_ui(x, c) end c::CulongMax - x::BigInt = begin MPZ.ui_sub(c, x) end x::BigInt + c::ClongMax = begin if c < 0 x - -(c % Culong) else x + convert(Culong, c) end end c::ClongMax + x::BigInt = begin if c < 0 x - -(c % Culong) else x + convert(Culong, c) end end x::BigInt - c::ClongMax = begin if c < 0 x + -(c % Culong) else x - convert(Culong, c) end end c::ClongMax - x::BigInt = begin if c < 0 -((x + -(c % Culong))) else convert(Culong, c) - x end end x::BigInt * c::CulongMax = begin MPZ.mul_ui(x, c) end c::CulongMax * x::BigInt = begin x * c end x::BigInt * c::ClongMax = begin MPZ.mul_si(x, c) end c::ClongMax * x::BigInt = begin x * c end x::BigInt / y::Union{ClongMax, CulongMax} = begin float(x) / y end x::Union{ClongMax, CulongMax} / y::BigInt = begin x / float(y) end -(x::BigInt) = begin MPZ.neg(x) end ~(x::BigInt) = begin MPZ.com(x) end x::BigInt << c::UInt = begin if c == 0 x else MPZ.mul_2exp(x, c) end end x::BigInt >> c::UInt = begin if c == 0 x else MPZ.fdiv_q_2exp(x, c) end end x::BigInt >>> c::UInt = begin x >> c end function trailing_zeros(x::BigInt) c = MPZ.scan1(x, 0) c == -1 && throw(DomainError(x, "`x` must be non-zero")) c end function trailing_ones(x::BigInt) c = MPZ.scan0(x, 0) c == -1 && throw(DomainError(x, "`x` must not be equal to -1")) c end function count_ones(x::BigInt) c = MPZ.popcount(x) c == -1 && throw(DomainError(x, "`x` cannot be negative")) c end function count_zeros(x::BigInt) c = MPZ.popcount(~x) c == -1 && throw(DomainError(x, "`x` must be negative")) c end Core.@doc " count_ones_abs(x::BigInt)\n\nNumber of ones in the binary representation of abs(x).\n" count_ones_abs(x::BigInt) = begin if iszero(x) 0 else MPZ.mpn_popcount(x) end end function top_set_bit(x::BigInt) isneg(x) && throw(DomainError(x, "top_set_bit only supports negative arguments when they have type BitSigned.")) iszero(x) && return 0 x.size * sizeof(Limb) << 3 - leading_zeros(GC.@preserve(x, unsafe_load(x.d, x.size))) end divrem(x::BigInt, y::BigInt, ::typeof(RoundToZero) = begin RoundToZero end) = begin MPZ.tdiv_qr(x, y) end divrem(x::BigInt, y::Integer, ::typeof(RoundToZero) = begin RoundToZero end) = begin MPZ.tdiv_qr(x, BigInt(y)) end cmp(x::BigInt, y::BigInt) = begin sign(MPZ.cmp(x, y)) end cmp(x::BigInt, y::ClongMax) = begin sign(MPZ.cmp_si(x, y)) end cmp(x::BigInt, y::CulongMax) = begin sign(MPZ.cmp_ui(x, y)) end cmp(x::BigInt, y::Integer) = begin cmp(x, big(y)) end cmp(x::Integer, y::BigInt) = begin -(cmp(y, x)) end cmp(x::BigInt, y::CdoubleMax) = begin if isnan(y) -1 else sign(MPZ.cmp_d(x, y)) end end cmp(x::CdoubleMax, y::BigInt) = begin -(cmp(y, x)) end isqrt(x::BigInt) = begin MPZ.sqrt(x) end x::BigInt ^ y::Culong = begin MPZ.pow_ui(x, y) end function bigint_pow(x::BigInt, y::Integer) x == 1 && return x x == -1 && return if isodd(y) x else -x end if y < 0 throw(DomainError(y, "`y` cannot be negative.")) end @noinline throw1(y) = begin throw(OverflowError("exponent $(y) is too large and computation will overflow")) end if y > typemax(Culong) x == 0 && return x throw1(y) end return x ^ convert(Culong, y) end x::BigInt ^ y::BigInt = begin bigint_pow(x, y) end x::BigInt ^ y::Bool = begin if y x else one(x) end end x::BigInt ^ y::Integer = begin bigint_pow(x, y) end x::Integer ^ y::BigInt = begin bigint_pow(BigInt(x), y) end x::Bool ^ y::BigInt = begin Base.power_by_squaring(x, y) end function powermod(x::BigInt, p::BigInt, m::BigInt) r = MPZ.powm(x, p, m) return if m < 0 && r > 0 MPZ.add!(r, m) else r end end powermod(x::Integer, p::Integer, m::BigInt) = begin powermod(big(x), big(p), m) end function gcdx(a::BigInt, b::BigInt) (g, s, t) = MPZ.gcdext(a, b) if t == 0 if a == b return (g, t, s) elseif abs(a) == abs(b) return (g, t, -s) end end (g, s, t) end +(x::BigInt, y::BigInt, rest::BigInt...) = begin sum(tuple(x, y, rest...)) end sum(arr::Union{AbstractArray{BigInt}, Tuple{BigInt, Vararg{BigInt}}}) = begin foldl(MPZ.add!, arr; init = BigInt(0)) end function prod(arr::AbstractArray{BigInt}) nbits = BITS_PER_LIMB for x = arr iszero(x) && return zero(BigInt) xsize = abs(x.size) lz = GC.@preserve(x, leading_zeros(unsafe_load(x.d, xsize))) nbits += xsize * BITS_PER_LIMB - lz end init = BigInt(; nbits) MPZ.set_si!(init, 1) foldl(MPZ.mul!, arr; init) end factorial(n::BigInt) = begin if !(isneg(n)) MPZ.fac_ui(n) else throw(DomainError(n, "`n` must not be negative.")) end end function binomial(n::BigInt, k::Integer) k < 0 && return BigInt(0) k <= typemax(Culong) && return binomial(n, Culong(k)) n < 0 && return if isodd(k) -(binomial((k - n) - 1, k)) else binomial((k - n) - 1, k) end κ = n - k κ < 0 && return BigInt(0) κ <= typemax(Culong) && return binomial(n, Culong(κ)) throw(OverflowError("Computation would exceed memory")) end binomial(n::BigInt, k::Culong) = begin MPZ.bin_ui(n, k) end x::BigInt == y::BigInt = begin cmp(x, y) == 0 end x::BigInt == i::Integer = begin cmp(x, i) == 0 end i::Integer == x::BigInt = begin cmp(x, i) == 0 end x::BigInt == f::CdoubleMax = begin if isnan(f) false else cmp(x, f) == 0 end end f::CdoubleMax == x::BigInt = begin if isnan(f) false else cmp(x, f) == 0 end end iszero(x::BigInt) = begin x.size == 0 end isone(x::BigInt) = begin x == Culong(1) end x::BigInt <= y::BigInt = begin cmp(x, y) <= 0 end x::BigInt <= i::Integer = begin cmp(x, i) <= 0 end i::Integer <= x::BigInt = begin cmp(x, i) >= 0 end x::BigInt <= f::CdoubleMax = begin if isnan(f) false else cmp(x, f) <= 0 end end f::CdoubleMax <= x::BigInt = begin if isnan(f) false else cmp(x, f) >= 0 end end x::BigInt < y::BigInt = begin cmp(x, y) < 0 end x::BigInt < i::Integer = begin cmp(x, i) < 0 end i::Integer < x::BigInt = begin cmp(x, i) > 0 end x::BigInt < f::CdoubleMax = begin if isnan(f) false else cmp(x, f) < 0 end end f::CdoubleMax < x::BigInt = begin if isnan(f) false else cmp(x, f) > 0 end end isneg(x::BigInt) = begin x.size < 0 end ispos(x::BigInt) = begin x.size > 0 end signbit(x::BigInt) = begin isneg(x) end flipsign!(x::BigInt, y::Integer) = begin signbit(y) && (x.size = -(x.size)) x end flipsign(x::BigInt, y::Integer) = begin if signbit(y) -x else x end end flipsign(x::BigInt, y::BigInt) = begin if signbit(y) -x else x end end function sign(x::BigInt) isneg(x) && return -(one(x)) ispos(x) && return one(x) return x end show(io::IO, x::BigInt) = begin print(io, string(x)) end function string(n::BigInt; base::Integer = 10, pad::Integer = 1) base < 0 && return Base._base(Int(base), n, pad, (base > 0) & (n.size < 0)) 2 <= base <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $(base)")) iszero(n) && (pad < 1 && return "") nd1 = ndigits(n, base = base) nd = max(nd1, pad) sv = Base.StringMemory(nd + isneg(n)) GC.@preserve sv MPZ.get_str!((pointer(sv) + nd) - nd1, base, n) @inbounds for i = (1:nd - nd1) .+ isneg(n) sv[i] = '0' % UInt8 end isneg(n) && (sv[1] = '-' % UInt8) unsafe_takestring(sv) end function digits!(a::AbstractVector{T}, n::BigInt; base::Integer = 10) where T <: Integer if base ≥ 2 if base ≤ 62 s = codeunits(string(n; base)) (i, j) = (firstindex(a) - 1, length(s) + 1) lasti = min(lastindex(a), ((firstindex(a) + length(s)) - 1) - isneg(n)) while i < lasti x = s[j -= 1] a[i += 1] = if base ≤ 36 if x > 0x39 x - 0x57 else x - 0x30 end else if x > 0x39 if x > 0x60 x - 0x3d else x - 0x37 end else x - 0x30 end end end lasti = lastindex(a) while i < lasti a[i += 1] = zero(T) end return if isneg(n) map!(-, a, a) else a end elseif a isa StridedVector{<:Base.BitInteger} && (stride(a, 1) == 1 && (ispow2(base) && base - 1 ≤ typemax(T))) origlen = length(a) (_, writelen) = MPZ.export!(a, n; nails = 8 * sizeof(T) - trailing_zeros(base)) length(a) != origlen && resize!(a, origlen) a[begin + writelen:end] .= zero(T) return if isneg(n) map!(-, a, a) else a end end end return invoke(digits!, Tuple{typeof(a), Integer}, a, n; base) end function ndigits0zpb(x::BigInt, b::Integer) b < 2 && throw(DomainError(b, "`b` cannot be less than 2.")) x.size == 0 && return 0 if ispow2(b) && 2 <= b <= 62 MPZ.sizeinbase(x, b) else n = MPZ.sizeinbase(x, 2) lb = log2(b) (q, r) = divrem(n, lb) iq = Int(q) maxerr = q * eps(lb) if r - 1.0 < maxerr if abs(x) >= big(b) ^ iq iq + 1 else iq end elseif lb - r < maxerr if abs(x) >= big(b) ^ (iq + 1) iq + 2 else iq + 1 end else iq + 1 end end end _prevpow2(x::BigInt) = begin if -2 <= x <= 2 x else flipsign!(ONE << (ndigits(x, base = 2) - 1), x) end end _nextpow2(x::BigInt) = begin if count_ones_abs(x) <= 1 x else flipsign!(ONE << ndigits(x, base = 2), x) end end Base.checked_abs(x::BigInt) = begin abs(x) end Base.checked_neg(x::BigInt) = begin -x end Base.checked_add(a::BigInt, b::BigInt) = begin a + b end Base.checked_sub(a::BigInt, b::BigInt) = begin a - b end Base.checked_mul(a::BigInt, b::BigInt) = begin a * b end Base.checked_div(a::BigInt, b::BigInt) = begin div(a, b) end Base.checked_rem(a::BigInt, b::BigInt) = begin rem(a, b) end Base.checked_fld(a::BigInt, b::BigInt) = begin fld(a, b) end Base.checked_mod(a::BigInt, b::BigInt) = begin mod(a, b) end Base.checked_cld(a::BigInt, b::BigInt) = begin cld(a, b) end Base.add_with_overflow(a::BigInt, b::BigInt) = begin (a + b, false) end Base.sub_with_overflow(a::BigInt, b::BigInt) = begin (a - b, false) end Base.mul_with_overflow(a::BigInt, b::BigInt) = begin (a * b, false) end Base.checked_pow(x::BigInt, p::Integer) = begin x ^ p end Base.checked_pow(x::Integer, p::BigInt) = begin x ^ p end Base.checked_pow(x::BigInt, p::BigInt) = begin x ^ p end Base.deepcopy_internal(x::BigInt, stackdict::IdDict) = begin get!((()->begin MPZ.set(x) end), stackdict, x)::BigInt end if Limb === UInt64 === UInt using .Base: hash_uint function hash_integer(n::BigInt, h::UInt) GC.@preserve n begin s = n.size s == 0 && return hash_integer(0, h) p = convert(Ptr{UInt64}, n.d) b = unsafe_load(p) h ⊻= hash_uint(ifelse(s < 0, -b, b) ⊻ h) for k = 2:abs(s) h ⊻= hash_uint(unsafe_load(p, k) ⊻ h) end return h end end function hash(x::BigInt, h::UInt) GC.@preserve x begin sz = x.size sz == 0 && return hash(0, h) ptr = Ptr{UInt64}(x.d) if sz == 1 return hash(unsafe_load(ptr), h) elseif sz == -1 limb = unsafe_load(ptr) limb <= typemin(Int) % UInt && return hash(-(limb % Int), h) end pow = trailing_zeros(x) nd = Base.ndigits0z(x, 2) idx = pow >>> 6 + 1 shift = (pow & 63) % UInt upshift = BITS_PER_LIMB - shift asz = abs(sz) if shift == 0 limb = unsafe_load(ptr, idx) else limb1 = unsafe_load(ptr, idx) limb2 = if idx < asz unsafe_load(ptr, idx + 1) else UInt(0) end limb = limb2 << upshift | limb1 >> shift end if nd <= 1024 && nd - pow <= 53 return hash(ldexp(flipsign(Float64(limb), sz), pow), h) end h = hash_integer(pow, h) h ⊻= hash_uint(flipsign(limb, sz) ⊻ h) for idx = idx + 1:asz if shift == 0 limb = unsafe_load(ptr, idx) else limb1 = limb2 if idx == asz limb = limb1 >> shift limb == 0 && break else limb2 = unsafe_load(ptr, idx + 1) limb = limb2 << upshift | limb1 >> shift end end h ⊻= hash_uint(limb ⊻ h) end return h end end end module MPQ import .Base: unsafe_rational, __throw_rational_argerror_zero import ..GMP: BigInt, MPZ, Limb, isneg, libgmp gmpq(op::Symbol) = begin (Symbol(:__gmpq_, op), libgmp) end mutable struct _MPQ num_alloc::Cint num_size::Cint num_d::Ptr{Limb} den_alloc::Cint den_size::Cint den_d::Ptr{Limb} rat::Rational{BigInt} end const mpq_t = Ref{_MPQ} _MPQ(x::BigInt, y::BigInt) = begin _MPQ(x.alloc, x.size, x.d, y.alloc, y.size, y.d, unsafe_rational(BigInt, x, y)) end _MPQ() = begin _MPQ(BigInt(), BigInt()) end _MPQ(x::Rational{BigInt}) = begin _MPQ(x.num, x.den) end function sync_rational!(xq::_MPQ) xq.rat.num.alloc = xq.num_alloc xq.rat.num.size = xq.num_size xq.rat.num.d = xq.num_d xq.rat.den.alloc = xq.den_alloc xq.rat.den.size = xq.den_size xq.rat.den.d = xq.den_d return xq.rat end function Rational{BigInt}(num::BigInt, den::BigInt) if iszero(den) iszero(num) && __throw_rational_argerror_zero(BigInt) return set_si(flipsign(1, num), 0) end xq = _MPQ(MPZ.set(num), MPZ.set(den)) ccall((:__gmpq_canonicalize, libgmp), Cvoid, (mpq_t,), xq) return sync_rational!(xq) end function set!(z::Rational{BigInt}, x::Rational{BigInt}) zq = _MPQ(z) ccall((:__gmpq_set, libgmp), Cvoid, (mpq_t, mpq_t), zq, _MPQ(x)) return sync_rational!(zq) end function set_z!(z::Rational{BigInt}, x::BigInt) zq = _MPQ(z) ccall((:__gmpq_set_z, libgmp), Cvoid, (mpq_t, MPZ.mpz_t), zq, x) return sync_rational!(zq) end for (op, T) = ((:set, Rational{BigInt}), (:set_z, BigInt)) op! = Symbol(op, :!) @eval ($op)(a::$T) = begin ($op!)(unsafe_rational(BigInt(), BigInt()), a) end end for (op, T1, T2) = ((:set_ui, Culong, Culong), (:set_si, Clong, Culong)) op! = Symbol(op, :!) @eval begin function ($op!)(z::Rational{BigInt}, a, b) zq = _MPQ(z) ccall($(gmpq(op)), Cvoid, (mpq_t, $T1, $T2), zq, a, b) return sync_rational!(zq) end ($op)(a, b) = begin ($op!)(unsafe_rational(BigInt(), BigInt()), a, b) end end end function add!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && (iszero(y.den) && isneg(x.num) != isneg(y.num)) throw(DivideError()) end return set!(z, if iszero(x.den) x else y end) end zq = _MPQ(z) ccall((:__gmpq_add, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function sub!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && (iszero(y.den) && isneg(x.num) == isneg(y.num)) throw(DivideError()) end iszero(x.den) && return set!(z, x) return set_si!(z, flipsign(-1, y.num), 0) end zq = _MPQ(z) ccall((:__gmpq_sub, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function mul!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.num) || iszero(y.num) throw(DivideError()) end return set_si!(z, ifelse(xor(isneg(x.num), isneg(y.num)), -1, 1), 0) end zq = _MPQ(z) ccall((:__gmpq_mul, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function div!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) if iszero(y.den) throw(DivideError()) end isneg(y.num) || return set!(z, x) return set_si!(z, flipsign(-1, x.num), 0) elseif iszero(y.den) return set_si!(z, 0, 1) elseif iszero(y.num) if iszero(x.num) throw(DivideError()) end return set_si!(z, flipsign(1, x.num), 0) end zq = _MPQ(z) ccall((:__gmpq_div, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end for (fJ, fC) = ((:+, :add), (:-, :sub), (:*, :mul), (://, :div)) fC! = Symbol(fC, :!) @eval begin ($fC!)(x::Rational{BigInt}, y::Rational{BigInt}) = begin ($fC!)(x, x, y) end Base.:($fJ)(x::Rational{BigInt}, y::Rational{BigInt}) = begin ($fC!)(unsafe_rational(BigInt(), BigInt()), x, y) end end end function Base.cmp(x::Rational{BigInt}, y::Rational{BigInt}) Int(ccall((:__gmpq_cmp, libgmp), Cint, (mpq_t, mpq_t), _MPQ(x), _MPQ(y))) end end end begin export BigInt import .Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, ~, &, |, xor, nand, nor, binomial, cmp, convert, div, divrem, factorial, cld, fld, gcd, gcdx, lcm, mod, ndigits, promote_rule, rem, show, isqrt, string, powermod, sum, prod, trailing_zeros, trailing_ones, count_ones, count_zeros, tryparse_internal, bin, oct, dec, hex, isequal, invmod, _prevpow2, _nextpow2, ndigits0zpb, widen, signed, unsafe_trunc, trunc, iszero, isone, big, flipsign, signbit, sign, hastypemax, isodd, iseven, digits!, hash, hash_integer, top_set_bit, clamp, unsafe_takestring import Core: Signed, Float16, Float32, Float64 if Clong == Int32 const ClongMax = Union{Int8, Int16, Int32} const CulongMax = Union{UInt8, UInt16, UInt32} else const ClongMax = Union{Int8, Int16, Int32, Int64} const CulongMax = Union{UInt8, UInt16, UInt32, UInt64} end const CdoubleMax = Union{Float16, Float32, Float64} if Sys.iswindows() const libgmp = "libgmp-10.dll" elseif Sys.isapple() const libgmp = "@rpath/libgmp.10.dylib" else const libgmp = "libgmp.so.10" end _version() = begin unsafe_string(unsafe_load(cglobal((:__gmp_version, libgmp), Ptr{Cchar}))) end version() = begin VersionNumber(_version()) end major_version() = begin (_version())[1] end bits_per_limb() = begin Int(unsafe_load(cglobal((:__gmp_bits_per_limb, libgmp), Cint))) end const VERSION = version() const MAJOR_VERSION = major_version() const BITS_PER_LIMB = bits_per_limb() if BITS_PER_LIMB == 32 const Limb = UInt32 const SLimbMax = Union{Int8, Int16, Int32} const ULimbMax = Union{UInt8, UInt16, UInt32} elseif BITS_PER_LIMB == 64 const Limb = UInt64 const SLimbMax = Union{Int8, Int16, Int32, Int64} const ULimbMax = Union{UInt8, UInt16, UInt32, UInt64} else error("GMP: cannot determine the type mp_limb_t (__gmp_bits_per_limb == $(BITS_PER_LIMB))") end Core.@doc " BigInt <: Signed\n\nArbitrary precision integer type.\n" mutable struct BigInt <: Signed alloc::Cint size::Cint d::Ptr{Limb} function BigInt(; nbits::Integer = 0) b = MPZ.init2!(new(), nbits) finalizer(cglobal((:__gmpz_clear, libgmp)), b) return b end end Core.@doc " BigInt(x)\n\nCreate an arbitrary precision integer. `x` may be an `Int` (or anything that can be\nconverted to an `Int`). The usual mathematical operators are defined for this type, and\nresults are promoted to a [`BigInt`](@ref).\n\nInstances can be constructed from strings via [`parse`](@ref), or using the `big`\nstring literal.\n\n# Examples\n```jldoctest\njulia> parse(BigInt, \"42\")\n42\n\njulia> big\"313\"\n313\n\njulia> BigInt(10)^19\n10000000000000000000\n```\n" BigInt(x) Core.@doc " ALLOC_OVERFLOW_FUNCTION\n\nA reference that holds a boolean, if true, indicating julia is linked with a patched GMP that\ndoes not abort on huge allocation and throws OutOfMemoryError instead.\n" const ALLOC_OVERFLOW_FUNCTION = Ref(false) function __init__() try if major_version() != MAJOR_VERSION || bits_per_limb() != BITS_PER_LIMB msg = "The dynamically loaded GMP library (v\"$(version())\" with __gmp_bits_per_limb == $(bits_per_limb()))\ndoes not correspond to the compile time version (v\"$(VERSION)\" with __gmp_bits_per_limb == $(BITS_PER_LIMB)).\nPlease rebuild Julia." if bits_per_limb() != BITS_PER_LIMB @error msg else @warn msg end end ccall((:__gmp_set_memory_functions, libgmp), Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), cglobal(:jl_gc_counted_malloc), cglobal(:jl_gc_counted_realloc_with_old_size), cglobal(:jl_gc_counted_free_with_size)) (ZERO.alloc, ZERO.size, ZERO.d) = (0, 0, C_NULL) (ONE.alloc, ONE.size, ONE.d) = (1, 1, pointer(_ONE)) catch ex Base.showerror_nostdio(ex, "WARNING: Error during initialization of module GMP") end try ccall((:__gmp_set_alloc_overflow_function, libgmp), Cvoid, (Ptr{Cvoid},), cglobal(:jl_throw_out_of_memory_error)) ALLOC_OVERFLOW_FUNCTION[] = true catch ex if typeof(ex) != ErrorException rethrow() end end end module MPZ using ..GMP: BigInt, Limb, BITS_PER_LIMB, libgmp const mpz_t = Ref{BigInt} const bitcnt_t = Culong gmpz(op::Symbol) = begin (Symbol(:__gmpz_, op), libgmp) end init!(x::BigInt) = begin ccall((:__gmpz_init, libgmp), Cvoid, (mpz_t,), x) x end init2!(x::BigInt, a) = begin ccall((:__gmpz_init2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end realloc2!(x, a) = begin ccall((:__gmpz_realloc2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end realloc2(a) = begin realloc2!(BigInt(), a) end sizeinbase(a::BigInt, b) = begin Int(ccall((:__gmpz_sizeinbase, libgmp), Csize_t, (mpz_t, Cint), a, b)) end for (op, nbits) = (:add => :(BITS_PER_LIMB * (1 + max(abs(a.size), abs(b.size)))), :sub => :(BITS_PER_LIMB * (1 + max(abs(a.size), abs(b.size)))), :mul => 0, :fdiv_q => 0, :tdiv_q => 0, :cdiv_q => 0, :fdiv_r => 0, :tdiv_r => 0, :cdiv_r => 0, :gcd => 0, :lcm => 0, :and => 0, :ior => 0, :xor => 0) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt, b::BigInt) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t, mpz_t), x, a, b) x end ($op)(a::BigInt, b::BigInt) = begin ($op!)(BigInt(nbits = $nbits), a, b) end ($op!)(x::BigInt, b::BigInt) = begin ($op!)(x, x, b) end end end invert!(x::BigInt, a::BigInt, b::BigInt) = begin ccall((:__gmpz_invert, libgmp), Cint, (mpz_t, mpz_t, mpz_t), x, a, b) end invert!(x::BigInt, b::BigInt) = begin invert!(x, x, b) end invert(a::BigInt, b::BigInt) = begin ret = BigInt() invert!(ret, a, b) ret end for op = (:add_ui, :sub_ui, :mul_ui, :mul_2exp, :fdiv_q_2exp, :pow_ui, :bin_ui) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt, b) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t, Culong), x, a, b) x end ($op)(a::BigInt, b) = begin ($op!)(BigInt(), a, b) end ($op!)(x::BigInt, b) = begin ($op!)(x, x, b) end end end ui_sub!(x::BigInt, a, b::BigInt) = begin ccall((:__gmpz_ui_sub, libgmp), Cvoid, (mpz_t, Culong, mpz_t), x, a, b) x end ui_sub(a, b::BigInt) = begin ui_sub!(BigInt(), a, b) end for op = (:scan1, :scan0) @eval ($op)(a::BigInt, b) = begin Int(signed(ccall($(gmpz(op)), Culong, (mpz_t, Culong), a, b))) end end mul_si!(x::BigInt, a::BigInt, b) = begin ccall((:__gmpz_mul_si, libgmp), Cvoid, (mpz_t, mpz_t, Clong), x, a, b) x end mul_si(a::BigInt, b) = begin mul_si!(BigInt(), a, b) end mul_si!(x::BigInt, b) = begin mul_si!(x, x, b) end for op = (:neg, :com, :sqrt, :set) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t), x, a) x end ($op)(a::BigInt) = begin ($op!)(BigInt(), a) end end op === :set && continue @eval ($op!)(x::BigInt) = begin ($op!)(x, x) end end for (op, T) = ((:fac_ui, Culong), (:set_ui, Culong), (:set_si, Clong), (:set_d, Cdouble)) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, $T), x, a) x end ($op)(a) = begin ($op!)(BigInt(), a) end end end popcount(a::BigInt) = begin Int(signed(ccall((:__gmpz_popcount, libgmp), Culong, (mpz_t,), a))) end mpn_popcount(d::Ptr{Limb}, s::Integer) = begin Int(ccall((:__gmpn_popcount, libgmp), Culong, (Ptr{Limb}, Csize_t), d, s)) end mpn_popcount(a::BigInt) = begin mpn_popcount(a.d, abs(a.size)) end function tdiv_qr!(x::BigInt, y::BigInt, a::BigInt, b::BigInt) ccall((:__gmpz_tdiv_qr, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, y, a, b) (x, y) end tdiv_qr(a::BigInt, b::BigInt) = begin tdiv_qr!(BigInt(), BigInt(), a, b) end powm!(x::BigInt, a::BigInt, b::BigInt, c::BigInt) = begin ccall((:__gmpz_powm, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, a, b, c) x end powm(a::BigInt, b::BigInt, c::BigInt) = begin powm!(BigInt(), a, b, c) end powm!(x::BigInt, b::BigInt, c::BigInt) = begin powm!(x, x, b, c) end function gcdext!(x::BigInt, y::BigInt, z::BigInt, a::BigInt, b::BigInt) ccall((:__gmpz_gcdext, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t, mpz_t), x, y, z, a, b) (x, y, z) end gcdext(a::BigInt, b::BigInt) = begin gcdext!(BigInt(), BigInt(), BigInt(), a, b) end cmp(a::BigInt, b::BigInt) = begin Int(ccall((:__gmpz_cmp, libgmp), Cint, (mpz_t, mpz_t), a, b)) end cmp_si(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_si, libgmp), Cint, (mpz_t, Clong), a, b)) end cmp_ui(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_ui, libgmp), Cint, (mpz_t, Culong), a, b)) end cmp_d(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_d, libgmp), Cint, (mpz_t, Cdouble), a, b)) end mpn_cmp(a::Ptr{Limb}, b::Ptr{Limb}, c) = begin ccall((:__gmpn_cmp, libgmp), Cint, (Ptr{Limb}, Ptr{Limb}, Clong), a, b, c) end mpn_cmp(a::BigInt, b::BigInt, c) = begin mpn_cmp(a.d, b.d, c) end get_str!(x, a, b::BigInt) = begin ccall((:__gmpz_get_str, libgmp), Ptr{Cchar}, (Ptr{Cchar}, Cint, mpz_t), x, a, b) x end set_str!(x::BigInt, a, b) = begin Int(ccall((:__gmpz_set_str, libgmp), Cint, (mpz_t, Ptr{UInt8}, Cint), x, a, b)) end get_d(a::BigInt) = begin ccall((:__gmpz_get_d, libgmp), Cdouble, (mpz_t,), a) end function export!(a::AbstractVector{T}, n::BigInt; order::Integer = -1, nails::Integer = 0, endian::Integer = 0) where T <: Base.BitInteger stride(a, 1) == 1 || throw(ArgumentError("a must have stride 1")) ndigits = cld(sizeinbase(n, 2), 8 * sizeof(T) - nails) length(a) < ndigits && resize!(a, ndigits) count = Ref{Csize_t}() ccall((:__gmpz_export, libgmp), Ptr{T}, (Ptr{T}, Ref{Csize_t}, Cint, Csize_t, Cint, Csize_t, mpz_t), a, count, order, sizeof(T), endian, nails, n) @assert count[] ≤ length(a) return (a, Int(count[])) end limbs_write!(x::BigInt, a) = begin ccall((:__gmpz_limbs_write, libgmp), Ptr{Limb}, (mpz_t, Clong), x, a) end limbs_finish!(x::BigInt, a) = begin ccall((:__gmpz_limbs_finish, libgmp), Cvoid, (mpz_t, Clong), x, a) end setbit!(x, a) = begin ccall((:__gmpz_setbit, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end tstbit(a::BigInt, b) = begin ccall((:__gmpz_tstbit, libgmp), Cint, (mpz_t, bitcnt_t), a, b) % Bool end end const ZERO = BigInt() const ONE = BigInt() const _ONE = Limb[1] widen(::Type{Int128}) = begin BigInt end widen(::Type{UInt128}) = begin BigInt end widen(::Type{BigInt}) = begin BigInt end signed(x::BigInt) = begin x end BigInt(x::BigInt) = begin x end Signed(x::BigInt) = begin x end hastypemax(::Type{BigInt}) = begin false end function tryparse_internal(::Type{BigInt}, s::AbstractString, startpos::Int, endpos::Int, base_::Integer, raise::Bool) bstr = if startpos == firstindex(s) && endpos == lastindex(s) String(s) else String(SubString(s, startpos, endpos)) end (sgn, base, i) = Base.parseint_preamble(true, Int(base_), bstr, firstindex(bstr), lastindex(bstr)) if !(2 <= base <= 62) raise && throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $(base)")) return nothing end if i == 0 raise && throw(ArgumentError("premature end of integer: $(repr(bstr))")) return nothing end z = BigInt() if Base.containsnul(bstr) err = -1 else err = GC.@preserve(bstr, MPZ.set_str!(z, pointer(bstr) + (i - firstindex(bstr)), base)) end if err != 0 raise && throw(ArgumentError("invalid BigInt: $(repr(bstr))")) return nothing end flipsign!(z, sgn) end BigInt(x::Union{Clong, Int32}) = begin MPZ.set_si(x) end BigInt(x::Union{Culong, UInt32}) = begin MPZ.set_ui(x) end BigInt(x::Bool) = begin BigInt(UInt(x)) end unsafe_trunc(::Type{BigInt}, x::Union{Float16, Float32, Float64}) = begin MPZ.set_d(x) end function BigInt(x::Float64) isinteger(x) || throw(InexactError(:BigInt, BigInt, x)) unsafe_trunc(BigInt, x) end BigInt(x::Float16) = begin BigInt(Float64(x)) end BigInt(x::Float32) = begin BigInt(Float64(x)) end function BigInt(x::Integer) isbits(x) && (typemin(Clong) <= x <= typemax(Clong) && return BigInt((x % Clong)::Clong)) nd = ndigits(x, base = 2) z = MPZ.realloc2(nd) ux = unsigned(if x < 0 -x else x end) size = 0 limbnbits = sizeof(Limb) << 3 while nd > 0 size += 1 unsafe_store!(z.d, ux % Limb, size) ux >>= limbnbits nd -= limbnbits end z.size = if x < 0 -size else size end z end rem(x::BigInt, ::Type{Bool}) = begin (!(iszero(x)) & unsafe_load(x.d)) % Bool end (rem(x::BigInt, ::Type{T}) where T <: Union{SLimbMax, ULimbMax}) = begin if iszero(x) zero(T) else flipsign(unsafe_load(x.d) % T, x.size) end end function rem(x::BigInt, ::Type{T}) where T <: Union{Base.BitUnsigned, Base.BitSigned} u = zero(T) for l = 1:min(abs(x.size), cld(sizeof(T), sizeof(Limb))) u += (unsafe_load(x.d, l) % T) << (sizeof(Limb) << 3 * (l - 1)) end flipsign(u, x.size) end rem(x::Integer, ::Type{BigInt}) = begin BigInt(x) end clamp(x, ::Type{BigInt}) = begin convert(BigInt, x) end isodd(x::BigInt) = begin MPZ.tstbit(x, 0) end iseven(x::BigInt) = begin !(isodd(x)) end function (::Type{T})(x::BigInt) where T <: Base.BitUnsigned if sizeof(T) < sizeof(Limb) convert(T, convert(Limb, x)) else 0 <= x.size <= cld(sizeof(T), sizeof(Limb)) || throw(InexactError(nameof(T), T, x)) x % T end end function (::Type{T})(x::BigInt) where T <: Base.BitSigned n = abs(x.size) if sizeof(T) < sizeof(Limb) SLimb = typeof(Signed(one(Limb))) convert(T, convert(SLimb, x)) else 0 <= n <= cld(sizeof(T), sizeof(Limb)) || throw(InexactError(nameof(T), T, x)) y = x % T ispos(x) ⊻ (y > 0) && throw(InexactError(nameof(T), T, x)) y end end Float64(n::BigInt, ::RoundingMode{:ToZero}) = begin MPZ.get_d(n) end function (::Type{T})(n::BigInt, ::RoundingMode{:ToZero}) where T <: Union{Float16, Float32} T(Float64(n, RoundToZero), RoundToZero) end function (::Type{T})(n::BigInt, ::RoundingMode{:Down}) where T <: CdoubleMax x = T(n, RoundToZero) if x > n prevfloat(x) else x end end function (::Type{T})(n::BigInt, ::RoundingMode{:Up}) where T <: CdoubleMax x = T(n, RoundToZero) if x < n nextfloat(x) else x end end function Float64(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return 0.0 xsize = abs(x.size) if xsize * BITS_PER_LIMB > 1024 z = Inf64 elseif xsize == 1 z = Float64(unsafe_load(x.d)) elseif Limb == UInt32 && xsize == 2 z = Float64((unsafe_load(x.d, 2) % UInt64) << BITS_PER_LIMB + unsafe_load(x.d)) else y1 = unsafe_load(x.d, xsize) % UInt64 n = top_set_bit(y1) y = y1 >> (n - (precision(Float64) + 1)) if Limb == UInt64 y += if n > precision(Float64) 0 else unsafe_load(x.d, xsize - 1) >> (10 + n) end else y += (unsafe_load(x.d, xsize - 1) % UInt64) >> (n - 22) y += if n > precision(Float64) - 32 0 else unsafe_load(x.d, xsize - 2) >> (10 + n) end end y = (y + 1) >> 1 y &= ~(UInt64(trailing_zeros(x) == (n - 54) + (xsize - 1) * BITS_PER_LIMB)) d = ((n + 1021) % UInt64) << 52 z = reinterpret(Float64, d + y) z = ldexp(z, (xsize - 1) * BITS_PER_LIMB) end return flipsign(z, x.size) end function Float32(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return 0.0f0 xsize = abs(x.size) if xsize * BITS_PER_LIMB > 128 z = Inf32 elseif xsize == 1 z = Float32(unsafe_load(x.d)) else y1 = unsafe_load(x.d, xsize) n = BITS_PER_LIMB - leading_zeros(y1) y = y1 >> (n - (precision(Float32) + 1)) % UInt32 y += if n > precision(Float32) 0 else unsafe_load(x.d, xsize - 1) >> (BITS_PER_LIMB - -25) end % UInt32 y = (y + one(UInt32)) >> 1 y &= ~(UInt32(trailing_zeros(x) == (n - 25) + (xsize - 1) * BITS_PER_LIMB)) d = ((n + 125) % UInt32) << 23 z = reinterpret(Float32, d + y) z = ldexp(z, (xsize - 1) * BITS_PER_LIMB) end return flipsign(z, x.size) end function Float16(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return Float16(0.0) y1 = unsafe_load(x.d) n = BITS_PER_LIMB - leading_zeros(y1) if n > 16 || abs(x.size) > 1 z = Inf16 else y = y1 >> (n - (precision(Float16) + 1)) % UInt16 y = (y + one(UInt16)) >> 1 y &= ~(UInt16(trailing_zeros(x) == n - 12)) d = ((n + 13) % UInt16) << 10 z = reinterpret(Float16, d + y) end return flipsign(z, x.size) end Float64(n::BigInt) = begin Float64(n, RoundNearest) end Float32(n::BigInt) = begin Float32(n, RoundNearest) end Float16(n::BigInt) = begin Float16(n, RoundNearest) end promote_rule(::Type{BigInt}, ::Type{<:Integer}) = begin BigInt end Core.@doc " big(x)\n\nConvert a number to a maximum precision representation (typically [`BigInt`](@ref) or\n`BigFloat`). See [`BigFloat`](@ref BigFloat(::Any, rounding::RoundingMode)) for\ninformation about some pitfalls with floating-point numbers.\n" function big end big(::Type{<:Integer}) = begin BigInt end big(::Type{<:Rational}) = begin Rational{BigInt} end big(n::Integer) = begin convert(BigInt, n) end for (fJ, fC) = ((:+, :add), (:-, :sub), (:*, :mul), (:mod, :fdiv_r), (:rem, :tdiv_r), (:gcd, :gcd), (:lcm, :lcm), (:&, :and), (:|, :ior), (:xor, :xor)) @eval begin ($fJ)(x::BigInt, y::BigInt) = begin MPZ.:($fC)(x, y) end end end for (r, f) = ((RoundToZero, :tdiv_q), (RoundDown, :fdiv_q), (RoundUp, :cdiv_q)) @eval div(x::BigInt, y::BigInt, ::typeof($r)) = begin MPZ.:($f)(x, y) end end div(x::BigInt, y::BigInt) = begin div(x, y, RoundToZero) end fld(x::BigInt, y::BigInt) = begin div(x, y, RoundDown) end cld(x::BigInt, y::BigInt) = begin div(x, y, RoundUp) end x::BigInt / y::BigInt = begin float(x) / float(y) end function invmod(x::BigInt, y::BigInt) z = zero(BigInt) ya = abs(y) if ya == 1 return z end if y == 0 || MPZ.invert!(z, x, ya) == 0 throw(DomainError(y)) end if y < 0 MPZ.add!(z, y) end return z end for (fJ, fC) = ((:+, :add), (:*, :mul), (:&, :and), (:|, :ior), (:xor, :xor)) fC! = Symbol(fC, :!) @eval begin ($fJ)(a::BigInt, b::BigInt, c::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC)(a, b), c) end ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC)(a, b), c), d) end ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC)(a, b), c), d), e) end end end x::BigInt + c::CulongMax = begin MPZ.add_ui(x, c) end c::CulongMax + x::BigInt = begin x + c end x::BigInt - c::CulongMax = begin MPZ.sub_ui(x, c) end c::CulongMax - x::BigInt = begin MPZ.ui_sub(c, x) end x::BigInt + c::ClongMax = begin if c < 0 x - -(c % Culong) else x + convert(Culong, c) end end c::ClongMax + x::BigInt = begin if c < 0 x - -(c % Culong) else x + convert(Culong, c) end end x::BigInt - c::ClongMax = begin if c < 0 x + -(c % Culong) else x - convert(Culong, c) end end c::ClongMax - x::BigInt = begin if c < 0 -((x + -(c % Culong))) else convert(Culong, c) - x end end x::BigInt * c::CulongMax = begin MPZ.mul_ui(x, c) end c::CulongMax * x::BigInt = begin x * c end x::BigInt * c::ClongMax = begin MPZ.mul_si(x, c) end c::ClongMax * x::BigInt = begin x * c end x::BigInt / y::Union{ClongMax, CulongMax} = begin float(x) / y end x::Union{ClongMax, CulongMax} / y::BigInt = begin x / float(y) end -(x::BigInt) = begin MPZ.neg(x) end ~(x::BigInt) = begin MPZ.com(x) end x::BigInt << c::UInt = begin if c == 0 x else MPZ.mul_2exp(x, c) end end x::BigInt >> c::UInt = begin if c == 0 x else MPZ.fdiv_q_2exp(x, c) end end x::BigInt >>> c::UInt = begin x >> c end function trailing_zeros(x::BigInt) c = MPZ.scan1(x, 0) c == -1 && throw(DomainError(x, "`x` must be non-zero")) c end function trailing_ones(x::BigInt) c = MPZ.scan0(x, 0) c == -1 && throw(DomainError(x, "`x` must not be equal to -1")) c end function count_ones(x::BigInt) c = MPZ.popcount(x) c == -1 && throw(DomainError(x, "`x` cannot be negative")) c end function count_zeros(x::BigInt) c = MPZ.popcount(~x) c == -1 && throw(DomainError(x, "`x` must be negative")) c end Core.@doc " count_ones_abs(x::BigInt)\n\nNumber of ones in the binary representation of abs(x).\n" count_ones_abs(x::BigInt) = begin if iszero(x) 0 else MPZ.mpn_popcount(x) end end function top_set_bit(x::BigInt) isneg(x) && throw(DomainError(x, "top_set_bit only supports negative arguments when they have type BitSigned.")) iszero(x) && return 0 x.size * sizeof(Limb) << 3 - leading_zeros(GC.@preserve(x, unsafe_load(x.d, x.size))) end divrem(x::BigInt, y::BigInt, ::typeof(RoundToZero) = RoundToZero) = begin MPZ.tdiv_qr(x, y) end divrem(x::BigInt, y::Integer, ::typeof(RoundToZero) = RoundToZero) = begin MPZ.tdiv_qr(x, BigInt(y)) end cmp(x::BigInt, y::BigInt) = begin sign(MPZ.cmp(x, y)) end cmp(x::BigInt, y::ClongMax) = begin sign(MPZ.cmp_si(x, y)) end cmp(x::BigInt, y::CulongMax) = begin sign(MPZ.cmp_ui(x, y)) end cmp(x::BigInt, y::Integer) = begin cmp(x, big(y)) end cmp(x::Integer, y::BigInt) = begin -(cmp(y, x)) end cmp(x::BigInt, y::CdoubleMax) = begin if isnan(y) -1 else sign(MPZ.cmp_d(x, y)) end end cmp(x::CdoubleMax, y::BigInt) = begin -(cmp(y, x)) end isqrt(x::BigInt) = begin MPZ.sqrt(x) end x::BigInt ^ y::Culong = begin MPZ.pow_ui(x, y) end function bigint_pow(x::BigInt, y::Integer) x == 1 && return x x == -1 && return if isodd(y) x else -x end if y < 0 throw(DomainError(y, "`y` cannot be negative.")) end @noinline throw1(y) = begin throw(OverflowError("exponent $(y) is too large and computation will overflow")) end if y > typemax(Culong) x == 0 && return x throw1(y) end return x ^ convert(Culong, y) end x::BigInt ^ y::BigInt = begin bigint_pow(x, y) end x::BigInt ^ y::Bool = begin if y x else one(x) end end x::BigInt ^ y::Integer = begin bigint_pow(x, y) end x::Integer ^ y::BigInt = begin bigint_pow(BigInt(x), y) end x::Bool ^ y::BigInt = begin Base.power_by_squaring(x, y) end function powermod(x::BigInt, p::BigInt, m::BigInt) r = MPZ.powm(x, p, m) return if m < 0 && r > 0 MPZ.add!(r, m) else r end end powermod(x::Integer, p::Integer, m::BigInt) = begin powermod(big(x), big(p), m) end function gcdx(a::BigInt, b::BigInt) (g, s, t) = MPZ.gcdext(a, b) if t == 0 if a == b return (g, t, s) elseif abs(a) == abs(b) return (g, t, -s) end end (g, s, t) end +(x::BigInt, y::BigInt, rest::BigInt...) = begin sum(tuple(x, y, rest...)) end sum(arr::Union{AbstractArray{BigInt}, Tuple{BigInt, Vararg{BigInt}}}) = begin foldl(MPZ.add!, arr; init = BigInt(0)) end function prod(arr::AbstractArray{BigInt}) nbits = BITS_PER_LIMB for x = arr iszero(x) && return zero(BigInt) xsize = abs(x.size) lz = GC.@preserve(x, leading_zeros(unsafe_load(x.d, xsize))) nbits += xsize * BITS_PER_LIMB - lz end init = BigInt(; nbits) MPZ.set_si!(init, 1) foldl(MPZ.mul!, arr; init) end factorial(n::BigInt) = begin if !(isneg(n)) MPZ.fac_ui(n) else throw(DomainError(n, "`n` must not be negative.")) end end function binomial(n::BigInt, k::Integer) k < 0 && return BigInt(0) k <= typemax(Culong) && return binomial(n, Culong(k)) n < 0 && return if isodd(k) -(binomial((k - n) - 1, k)) else binomial((k - n) - 1, k) end κ = n - k κ < 0 && return BigInt(0) κ <= typemax(Culong) && return binomial(n, Culong(κ)) throw(OverflowError("Computation would exceed memory")) end binomial(n::BigInt, k::Culong) = begin MPZ.bin_ui(n, k) end x::BigInt == y::BigInt = begin cmp(x, y) == 0 end x::BigInt == i::Integer = begin cmp(x, i) == 0 end i::Integer == x::BigInt = begin cmp(x, i) == 0 end x::BigInt == f::CdoubleMax = begin if isnan(f) false else cmp(x, f) == 0 end end f::CdoubleMax == x::BigInt = begin if isnan(f) false else cmp(x, f) == 0 end end iszero(x::BigInt) = begin x.size == 0 end isone(x::BigInt) = begin x == Culong(1) end x::BigInt <= y::BigInt = begin cmp(x, y) <= 0 end x::BigInt <= i::Integer = begin cmp(x, i) <= 0 end i::Integer <= x::BigInt = begin cmp(x, i) >= 0 end x::BigInt <= f::CdoubleMax = begin if isnan(f) false else cmp(x, f) <= 0 end end f::CdoubleMax <= x::BigInt = begin if isnan(f) false else cmp(x, f) >= 0 end end x::BigInt < y::BigInt = begin cmp(x, y) < 0 end x::BigInt < i::Integer = begin cmp(x, i) < 0 end i::Integer < x::BigInt = begin cmp(x, i) > 0 end x::BigInt < f::CdoubleMax = begin if isnan(f) false else cmp(x, f) < 0 end end f::CdoubleMax < x::BigInt = begin if isnan(f) false else cmp(x, f) > 0 end end isneg(x::BigInt) = begin x.size < 0 end ispos(x::BigInt) = begin x.size > 0 end signbit(x::BigInt) = begin isneg(x) end flipsign!(x::BigInt, y::Integer) = begin signbit(y) && (x.size = -(x.size)) x end flipsign(x::BigInt, y::Integer) = begin if signbit(y) -x else x end end flipsign(x::BigInt, y::BigInt) = begin if signbit(y) -x else x end end function sign(x::BigInt) isneg(x) && return -(one(x)) ispos(x) && return one(x) return x end show(io::IO, x::BigInt) = begin print(io, string(x)) end function string(n::BigInt; base::Integer = 10, pad::Integer = 1) base < 0 && return Base._base(Int(base), n, pad, (base > 0) & (n.size < 0)) 2 <= base <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $(base)")) iszero(n) && (pad < 1 && return "") nd1 = ndigits(n, base = base) nd = max(nd1, pad) sv = Base.StringMemory(nd + isneg(n)) GC.@preserve sv MPZ.get_str!((pointer(sv) + nd) - nd1, base, n) @inbounds for i = (1:nd - nd1) .+ isneg(n) sv[i] = '0' % UInt8 end isneg(n) && (sv[1] = '-' % UInt8) unsafe_takestring(sv) end function digits!(a::AbstractVector{T}, n::BigInt; base::Integer = 10) where T <: Integer if base ≥ 2 if base ≤ 62 s = codeunits(string(n; base)) (i, j) = (firstindex(a) - 1, length(s) + 1) lasti = min(lastindex(a), ((firstindex(a) + length(s)) - 1) - isneg(n)) while i < lasti x = s[j -= 1] a[i += 1] = if base ≤ 36 if x > 0x39 x - 0x57 else x - 0x30 end else if x > 0x39 if x > 0x60 x - 0x3d else x - 0x37 end else x - 0x30 end end end lasti = lastindex(a) while i < lasti a[i += 1] = zero(T) end return if isneg(n) map!(-, a, a) else a end elseif a isa StridedVector{<:Base.BitInteger} && (stride(a, 1) == 1 && (ispow2(base) && base - 1 ≤ typemax(T))) origlen = length(a) (_, writelen) = MPZ.export!(a, n; nails = 8 * sizeof(T) - trailing_zeros(base)) length(a) != origlen && resize!(a, origlen) a[begin + writelen:end] .= zero(T) return if isneg(n) map!(-, a, a) else a end end end return invoke(digits!, Tuple{typeof(a), Integer}, a, n; base) end function ndigits0zpb(x::BigInt, b::Integer) b < 2 && throw(DomainError(b, "`b` cannot be less than 2.")) x.size == 0 && return 0 if ispow2(b) && 2 <= b <= 62 MPZ.sizeinbase(x, b) else n = MPZ.sizeinbase(x, 2) lb = log2(b) (q, r) = divrem(n, lb) iq = Int(q) maxerr = q * eps(lb) if r - 1.0 < maxerr if abs(x) >= big(b) ^ iq iq + 1 else iq end elseif lb - r < maxerr if abs(x) >= big(b) ^ (iq + 1) iq + 2 else iq + 1 end else iq + 1 end end end _prevpow2(x::BigInt) = begin if -2 <= x <= 2 x else flipsign!(ONE << (ndigits(x, base = 2) - 1), x) end end _nextpow2(x::BigInt) = begin if count_ones_abs(x) <= 1 x else flipsign!(ONE << ndigits(x, base = 2), x) end end Base.checked_abs(x::BigInt) = begin abs(x) end Base.checked_neg(x::BigInt) = begin -x end Base.checked_add(a::BigInt, b::BigInt) = begin a + b end Base.checked_sub(a::BigInt, b::BigInt) = begin a - b end Base.checked_mul(a::BigInt, b::BigInt) = begin a * b end Base.checked_div(a::BigInt, b::BigInt) = begin div(a, b) end Base.checked_rem(a::BigInt, b::BigInt) = begin rem(a, b) end Base.checked_fld(a::BigInt, b::BigInt) = begin fld(a, b) end Base.checked_mod(a::BigInt, b::BigInt) = begin mod(a, b) end Base.checked_cld(a::BigInt, b::BigInt) = begin cld(a, b) end Base.add_with_overflow(a::BigInt, b::BigInt) = begin (a + b, false) end Base.sub_with_overflow(a::BigInt, b::BigInt) = begin (a - b, false) end Base.mul_with_overflow(a::BigInt, b::BigInt) = begin (a * b, false) end Base.checked_pow(x::BigInt, p::Integer) = begin x ^ p end Base.checked_pow(x::Integer, p::BigInt) = begin x ^ p end Base.checked_pow(x::BigInt, p::BigInt) = begin x ^ p end Base.deepcopy_internal(x::BigInt, stackdict::IdDict) = begin get!((()->begin MPZ.set(x) end), stackdict, x)::BigInt end if Limb === UInt64 === UInt using .Base: hash_uint function hash_integer(n::BigInt, h::UInt) GC.@preserve n begin s = n.size s == 0 && return hash_integer(0, h) p = convert(Ptr{UInt64}, n.d) b = unsafe_load(p) h ⊻= hash_uint(ifelse(s < 0, -b, b) ⊻ h) for k = 2:abs(s) h ⊻= hash_uint(unsafe_load(p, k) ⊻ h) end return h end end function hash(x::BigInt, h::UInt) GC.@preserve x begin sz = x.size sz == 0 && return hash(0, h) ptr = Ptr{UInt64}(x.d) if sz == 1 return hash(unsafe_load(ptr), h) elseif sz == -1 limb = unsafe_load(ptr) limb <= typemin(Int) % UInt && return hash(-(limb % Int), h) end pow = trailing_zeros(x) nd = Base.ndigits0z(x, 2) idx = pow >>> 6 + 1 shift = (pow & 63) % UInt upshift = BITS_PER_LIMB - shift asz = abs(sz) if shift == 0 limb = unsafe_load(ptr, idx) else limb1 = unsafe_load(ptr, idx) limb2 = if idx < asz unsafe_load(ptr, idx + 1) else UInt(0) end limb = limb2 << upshift | limb1 >> shift end if nd <= 1024 && nd - pow <= 53 return hash(ldexp(flipsign(Float64(limb), sz), pow), h) end h = hash_integer(pow, h) h ⊻= hash_uint(flipsign(limb, sz) ⊻ h) for idx = idx + 1:asz if shift == 0 limb = unsafe_load(ptr, idx) else limb1 = limb2 if idx == asz limb = limb1 >> shift limb == 0 && break else limb2 = unsafe_load(ptr, idx + 1) limb = limb2 << upshift | limb1 >> shift end end h ⊻= hash_uint(limb ⊻ h) end return h end end end module MPQ import .Base: unsafe_rational, __throw_rational_argerror_zero import ..GMP: BigInt, MPZ, Limb, isneg, libgmp gmpq(op::Symbol) = begin (Symbol(:__gmpq_, op), libgmp) end mutable struct _MPQ num_alloc::Cint num_size::Cint num_d::Ptr{Limb} den_alloc::Cint den_size::Cint den_d::Ptr{Limb} rat::Rational{BigInt} end const mpq_t = Ref{_MPQ} _MPQ(x::BigInt, y::BigInt) = begin _MPQ(x.alloc, x.size, x.d, y.alloc, y.size, y.d, unsafe_rational(BigInt, x, y)) end _MPQ() = begin _MPQ(BigInt(), BigInt()) end _MPQ(x::Rational{BigInt}) = begin _MPQ(x.num, x.den) end function sync_rational!(xq::_MPQ) xq.rat.num.alloc = xq.num_alloc xq.rat.num.size = xq.num_size xq.rat.num.d = xq.num_d xq.rat.den.alloc = xq.den_alloc xq.rat.den.size = xq.den_size xq.rat.den.d = xq.den_d return xq.rat end function Rational{BigInt}(num::BigInt, den::BigInt) if iszero(den) iszero(num) && __throw_rational_argerror_zero(BigInt) return set_si(flipsign(1, num), 0) end xq = _MPQ(MPZ.set(num), MPZ.set(den)) ccall((:__gmpq_canonicalize, libgmp), Cvoid, (mpq_t,), xq) return sync_rational!(xq) end function set!(z::Rational{BigInt}, x::Rational{BigInt}) zq = _MPQ(z) ccall((:__gmpq_set, libgmp), Cvoid, (mpq_t, mpq_t), zq, _MPQ(x)) return sync_rational!(zq) end function set_z!(z::Rational{BigInt}, x::BigInt) zq = _MPQ(z) ccall((:__gmpq_set_z, libgmp), Cvoid, (mpq_t, MPZ.mpz_t), zq, x) return sync_rational!(zq) end for (op, T) = ((:set, Rational{BigInt}), (:set_z, BigInt)) op! = Symbol(op, :!) @eval ($op)(a::$T) = begin ($op!)(unsafe_rational(BigInt(), BigInt()), a) end end for (op, T1, T2) = ((:set_ui, Culong, Culong), (:set_si, Clong, Culong)) op! = Symbol(op, :!) @eval begin function ($op!)(z::Rational{BigInt}, a, b) zq = _MPQ(z) ccall($(gmpq(op)), Cvoid, (mpq_t, $T1, $T2), zq, a, b) return sync_rational!(zq) end ($op)(a, b) = begin ($op!)(unsafe_rational(BigInt(), BigInt()), a, b) end end end function add!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && (iszero(y.den) && isneg(x.num) != isneg(y.num)) throw(DivideError()) end return set!(z, if iszero(x.den) x else y end) end zq = _MPQ(z) ccall((:__gmpq_add, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function sub!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && (iszero(y.den) && isneg(x.num) == isneg(y.num)) throw(DivideError()) end iszero(x.den) && return set!(z, x) return set_si!(z, flipsign(-1, y.num), 0) end zq = _MPQ(z) ccall((:__gmpq_sub, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function mul!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.num) || iszero(y.num) throw(DivideError()) end return set_si!(z, ifelse(xor(isneg(x.num), isneg(y.num)), -1, 1), 0) end zq = _MPQ(z) ccall((:__gmpq_mul, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function div!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) if iszero(y.den) throw(DivideError()) end isneg(y.num) || return set!(z, x) return set_si!(z, flipsign(-1, x.num), 0) elseif iszero(y.den) return set_si!(z, 0, 1) elseif iszero(y.num) if iszero(x.num) throw(DivideError()) end return set_si!(z, flipsign(1, x.num), 0) end zq = _MPQ(z) ccall((:__gmpq_div, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end for (fJ, fC) = ((:+, :add), (:-, :sub), (:*, :mul), (://, :div)) fC! = Symbol(fC, :!) @eval begin ($fC!)(x::Rational{BigInt}, y::Rational{BigInt}) = begin ($fC!)(x, x, y) end Base.:($fJ)(x::Rational{BigInt}, y::Rational{BigInt}) = begin ($fC!)(unsafe_rational(BigInt(), BigInt()), x, y) end end end function Base.cmp(x::Rational{BigInt}, y::Rational{BigInt}) Int(ccall((:__gmpq_cmp, libgmp), Cint, (mpq_t, mpq_t), _MPQ(x), _MPQ(y))) end end end module GMP export BigInt import .Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, ~, &, |, xor, nand, nor, binomial, cmp, convert, div, divrem, factorial, cld, fld, gcd, gcdx, lcm, mod, ndigits, promote_rule, rem, show, isqrt, string, powermod, sum, prod, trailing_zeros, trailing_ones, count_ones, count_zeros, tryparse_internal, bin, oct, dec, hex, isequal, invmod, _prevpow2, _nextpow2, ndigits0zpb, widen, signed, unsafe_trunc, trunc, iszero, isone, big, flipsign, signbit, sign, hastypemax, isodd, iseven, digits!, hash, hash_integer, top_set_bit, clamp, unsafe_takestring import Core: Signed, Float16, Float32, Float64 if Clong == Int32 const ClongMax = Union{Int8, Int16, Int32} const CulongMax = Union{UInt8, UInt16, UInt32} else const ClongMax = Union{Int8, Int16, Int32, Int64} const CulongMax = Union{UInt8, UInt16, UInt32, UInt64} end const CdoubleMax = Union{Float16, Float32, Float64} if Sys.iswindows() const libgmp = "libgmp-10.dll" elseif Sys.isapple() const libgmp = "@rpath/libgmp.10.dylib" else const libgmp = "libgmp.so.10" end _version() = begin unsafe_string(unsafe_load(cglobal((:__gmp_version, libgmp), Ptr{Cchar}))) end version() = begin VersionNumber(_version()) end major_version() = begin (_version())[1] end bits_per_limb() = begin Int(unsafe_load(cglobal((:__gmp_bits_per_limb, libgmp), Cint))) end const VERSION = version() const MAJOR_VERSION = major_version() const BITS_PER_LIMB = bits_per_limb() if BITS_PER_LIMB == 32 const Limb = UInt32 const SLimbMax = Union{Int8, Int16, Int32} const ULimbMax = Union{UInt8, UInt16, UInt32} elseif BITS_PER_LIMB == 64 const Limb = UInt64 const SLimbMax = Union{Int8, Int16, Int32, Int64} const ULimbMax = Union{UInt8, UInt16, UInt32, UInt64} else error("GMP: cannot determine the type mp_limb_t (__gmp_bits_per_limb == $(BITS_PER_LIMB))") end Core.@doc " BigInt <: Signed\n\nArbitrary precision integer type.\n" mutable struct BigInt <: Signed alloc::Cint size::Cint d::Ptr{Limb} function BigInt(; nbits::Integer = 0) b = MPZ.init2!(new(), nbits) finalizer(cglobal((:__gmpz_clear, libgmp)), b) return b end end Core.@doc " BigInt(x)\n\nCreate an arbitrary precision integer. `x` may be an `Int` (or anything that can be\nconverted to an `Int`). The usual mathematical operators are defined for this type, and\nresults are promoted to a [`BigInt`](@ref).\n\nInstances can be constructed from strings via [`parse`](@ref), or using the `big`\nstring literal.\n\n# Examples\n```jldoctest\njulia> parse(BigInt, \"42\")\n42\n\njulia> big\"313\"\n313\n\njulia> BigInt(10)^19\n10000000000000000000\n```\n" BigInt(x) Core.@doc " ALLOC_OVERFLOW_FUNCTION\n\nA reference that holds a boolean, if true, indicating julia is linked with a patched GMP that\ndoes not abort on huge allocation and throws OutOfMemoryError instead.\n" const ALLOC_OVERFLOW_FUNCTION = Ref(false) function __init__() try if major_version() != MAJOR_VERSION || bits_per_limb() != BITS_PER_LIMB msg = "The dynamically loaded GMP library (v\"$(version())\" with __gmp_bits_per_limb == $(bits_per_limb()))\ndoes not correspond to the compile time version (v\"$(VERSION)\" with __gmp_bits_per_limb == $(BITS_PER_LIMB)).\nPlease rebuild Julia." if bits_per_limb() != BITS_PER_LIMB @error msg else @warn msg end end ccall((:__gmp_set_memory_functions, libgmp), Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), cglobal(:jl_gc_counted_malloc), cglobal(:jl_gc_counted_realloc_with_old_size), cglobal(:jl_gc_counted_free_with_size)) (ZERO.alloc, ZERO.size, ZERO.d) = (0, 0, C_NULL) (ONE.alloc, ONE.size, ONE.d) = (1, 1, pointer(_ONE)) catch ex Base.showerror_nostdio(ex, "WARNING: Error during initialization of module GMP") end try ccall((:__gmp_set_alloc_overflow_function, libgmp), Cvoid, (Ptr{Cvoid},), cglobal(:jl_throw_out_of_memory_error)) ALLOC_OVERFLOW_FUNCTION[] = true catch ex if typeof(ex) != ErrorException rethrow() end end end module MPZ using ..GMP: BigInt, Limb, BITS_PER_LIMB, libgmp const mpz_t = Ref{BigInt} const bitcnt_t = Culong gmpz(op::Symbol) = begin (Symbol(:__gmpz_, op), libgmp) end init!(x::BigInt) = begin ccall((:__gmpz_init, libgmp), Cvoid, (mpz_t,), x) x end init2!(x::BigInt, a) = begin ccall((:__gmpz_init2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end realloc2!(x, a) = begin ccall((:__gmpz_realloc2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end realloc2(a) = begin realloc2!(BigInt(), a) end sizeinbase(a::BigInt, b) = begin Int(ccall((:__gmpz_sizeinbase, libgmp), Csize_t, (mpz_t, Cint), a, b)) end for (op, nbits) = (:add => :(BITS_PER_LIMB * (1 + max(abs(a.size), abs(b.size)))), :sub => :(BITS_PER_LIMB * (1 + max(abs(a.size), abs(b.size)))), :mul => 0, :fdiv_q => 0, :tdiv_q => 0, :cdiv_q => 0, :fdiv_r => 0, :tdiv_r => 0, :cdiv_r => 0, :gcd => 0, :lcm => 0, :and => 0, :ior => 0, :xor => 0) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt, b::BigInt) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t, mpz_t), x, a, b) x end ($op)(a::BigInt, b::BigInt) = begin ($op!)(BigInt(nbits = $nbits), a, b) end ($op!)(x::BigInt, b::BigInt) = begin ($op!)(x, x, b) end end end invert!(x::BigInt, a::BigInt, b::BigInt) = begin ccall((:__gmpz_invert, libgmp), Cint, (mpz_t, mpz_t, mpz_t), x, a, b) end invert!(x::BigInt, b::BigInt) = begin invert!(x, x, b) end invert(a::BigInt, b::BigInt) = begin ret = BigInt() invert!(ret, a, b) ret end for op = (:add_ui, :sub_ui, :mul_ui, :mul_2exp, :fdiv_q_2exp, :pow_ui, :bin_ui) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt, b) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t, Culong), x, a, b) x end ($op)(a::BigInt, b) = begin ($op!)(BigInt(), a, b) end ($op!)(x::BigInt, b) = begin ($op!)(x, x, b) end end end ui_sub!(x::BigInt, a, b::BigInt) = begin ccall((:__gmpz_ui_sub, libgmp), Cvoid, (mpz_t, Culong, mpz_t), x, a, b) x end ui_sub(a, b::BigInt) = begin ui_sub!(BigInt(), a, b) end for op = (:scan1, :scan0) @eval ($op)(a::BigInt, b) = begin Int(signed(ccall($(gmpz(op)), Culong, (mpz_t, Culong), a, b))) end end mul_si!(x::BigInt, a::BigInt, b) = begin ccall((:__gmpz_mul_si, libgmp), Cvoid, (mpz_t, mpz_t, Clong), x, a, b) x end mul_si(a::BigInt, b) = begin mul_si!(BigInt(), a, b) end mul_si!(x::BigInt, b) = begin mul_si!(x, x, b) end for op = (:neg, :com, :sqrt, :set) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t), x, a) x end ($op)(a::BigInt) = begin ($op!)(BigInt(), a) end end op === :set && continue @eval ($op!)(x::BigInt) = begin ($op!)(x, x) end end for (op, T) = ((:fac_ui, Culong), (:set_ui, Culong), (:set_si, Clong), (:set_d, Cdouble)) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, $T), x, a) x end ($op)(a) = begin ($op!)(BigInt(), a) end end end popcount(a::BigInt) = begin Int(signed(ccall((:__gmpz_popcount, libgmp), Culong, (mpz_t,), a))) end mpn_popcount(d::Ptr{Limb}, s::Integer) = begin Int(ccall((:__gmpn_popcount, libgmp), Culong, (Ptr{Limb}, Csize_t), d, s)) end mpn_popcount(a::BigInt) = begin mpn_popcount(a.d, abs(a.size)) end function tdiv_qr!(x::BigInt, y::BigInt, a::BigInt, b::BigInt) ccall((:__gmpz_tdiv_qr, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, y, a, b) (x, y) end tdiv_qr(a::BigInt, b::BigInt) = begin tdiv_qr!(BigInt(), BigInt(), a, b) end powm!(x::BigInt, a::BigInt, b::BigInt, c::BigInt) = begin ccall((:__gmpz_powm, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, a, b, c) x end powm(a::BigInt, b::BigInt, c::BigInt) = begin powm!(BigInt(), a, b, c) end powm!(x::BigInt, b::BigInt, c::BigInt) = begin powm!(x, x, b, c) end function gcdext!(x::BigInt, y::BigInt, z::BigInt, a::BigInt, b::BigInt) ccall((:__gmpz_gcdext, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t, mpz_t), x, y, z, a, b) (x, y, z) end gcdext(a::BigInt, b::BigInt) = begin gcdext!(BigInt(), BigInt(), BigInt(), a, b) end cmp(a::BigInt, b::BigInt) = begin Int(ccall((:__gmpz_cmp, libgmp), Cint, (mpz_t, mpz_t), a, b)) end cmp_si(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_si, libgmp), Cint, (mpz_t, Clong), a, b)) end cmp_ui(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_ui, libgmp), Cint, (mpz_t, Culong), a, b)) end cmp_d(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_d, libgmp), Cint, (mpz_t, Cdouble), a, b)) end mpn_cmp(a::Ptr{Limb}, b::Ptr{Limb}, c) = begin ccall((:__gmpn_cmp, libgmp), Cint, (Ptr{Limb}, Ptr{Limb}, Clong), a, b, c) end mpn_cmp(a::BigInt, b::BigInt, c) = begin mpn_cmp(a.d, b.d, c) end get_str!(x, a, b::BigInt) = begin ccall((:__gmpz_get_str, libgmp), Ptr{Cchar}, (Ptr{Cchar}, Cint, mpz_t), x, a, b) x end set_str!(x::BigInt, a, b) = begin Int(ccall((:__gmpz_set_str, libgmp), Cint, (mpz_t, Ptr{UInt8}, Cint), x, a, b)) end get_d(a::BigInt) = begin ccall((:__gmpz_get_d, libgmp), Cdouble, (mpz_t,), a) end function export!(a::AbstractVector{T}, n::BigInt; order::Integer = -1, nails::Integer = 0, endian::Integer = 0) where T <: Base.BitInteger stride(a, 1) == 1 || throw(ArgumentError("a must have stride 1")) ndigits = cld(sizeinbase(n, 2), 8 * sizeof(T) - nails) length(a) < ndigits && resize!(a, ndigits) count = Ref{Csize_t}() ccall((:__gmpz_export, libgmp), Ptr{T}, (Ptr{T}, Ref{Csize_t}, Cint, Csize_t, Cint, Csize_t, mpz_t), a, count, order, sizeof(T), endian, nails, n) @assert count[] ≤ length(a) return (a, Int(count[])) end limbs_write!(x::BigInt, a) = begin ccall((:__gmpz_limbs_write, libgmp), Ptr{Limb}, (mpz_t, Clong), x, a) end limbs_finish!(x::BigInt, a) = begin ccall((:__gmpz_limbs_finish, libgmp), Cvoid, (mpz_t, Clong), x, a) end setbit!(x, a) = begin ccall((:__gmpz_setbit, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end tstbit(a::BigInt, b) = begin ccall((:__gmpz_tstbit, libgmp), Cint, (mpz_t, bitcnt_t), a, b) % Bool end end const ZERO = BigInt() const ONE = BigInt() const _ONE = Limb[1] widen(::Type{Int128}) = begin BigInt end widen(::Type{UInt128}) = begin BigInt end widen(::Type{BigInt}) = begin BigInt end signed(x::BigInt) = begin x end BigInt(x::BigInt) = begin x end Signed(x::BigInt) = begin x end hastypemax(::Type{BigInt}) = begin false end function tryparse_internal(::Type{BigInt}, s::AbstractString, startpos::Int, endpos::Int, base_::Integer, raise::Bool) bstr = if startpos == firstindex(s) && endpos == lastindex(s) String(s) else String(SubString(s, startpos, endpos)) end (sgn, base, i) = Base.parseint_preamble(true, Int(base_), bstr, firstindex(bstr), lastindex(bstr)) if !(2 <= base <= 62) raise && throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $(base)")) return nothing end if i == 0 raise && throw(ArgumentError("premature end of integer: $(repr(bstr))")) return nothing end z = BigInt() if Base.containsnul(bstr) err = -1 else err = GC.@preserve(bstr, MPZ.set_str!(z, pointer(bstr) + (i - firstindex(bstr)), base)) end if err != 0 raise && throw(ArgumentError("invalid BigInt: $(repr(bstr))")) return nothing end flipsign!(z, sgn) end BigInt(x::Union{Clong, Int32}) = begin MPZ.set_si(x) end BigInt(x::Union{Culong, UInt32}) = begin MPZ.set_ui(x) end BigInt(x::Bool) = begin BigInt(UInt(x)) end unsafe_trunc(::Type{BigInt}, x::Union{Float16, Float32, Float64}) = begin MPZ.set_d(x) end function BigInt(x::Float64) isinteger(x) || throw(InexactError(:BigInt, BigInt, x)) unsafe_trunc(BigInt, x) end BigInt(x::Float16) = begin BigInt(Float64(x)) end BigInt(x::Float32) = begin BigInt(Float64(x)) end function BigInt(x::Integer) isbits(x) && (typemin(Clong) <= x <= typemax(Clong) && return BigInt((x % Clong)::Clong)) nd = ndigits(x, base = 2) z = MPZ.realloc2(nd) ux = unsigned(if x < 0 -x else x end) size = 0 limbnbits = sizeof(Limb) << 3 while nd > 0 size += 1 unsafe_store!(z.d, ux % Limb, size) ux >>= limbnbits nd -= limbnbits end z.size = if x < 0 -size else size end z end rem(x::BigInt, ::Type{Bool}) = begin (!(iszero(x)) & unsafe_load(x.d)) % Bool end (rem(x::BigInt, ::Type{T}) where T <: Union{SLimbMax, ULimbMax}) = begin if iszero(x) zero(T) else flipsign(unsafe_load(x.d) % T, x.size) end end function rem(x::BigInt, ::Type{T}) where T <: Union{Base.BitUnsigned, Base.BitSigned} u = zero(T) for l = 1:min(abs(x.size), cld(sizeof(T), sizeof(Limb))) u += (unsafe_load(x.d, l) % T) << (sizeof(Limb) << 3 * (l - 1)) end flipsign(u, x.size) end rem(x::Integer, ::Type{BigInt}) = begin BigInt(x) end clamp(x, ::Type{BigInt}) = begin convert(BigInt, x) end isodd(x::BigInt) = begin MPZ.tstbit(x, 0) end iseven(x::BigInt) = begin !(isodd(x)) end function (::Type{T})(x::BigInt) where T <: Base.BitUnsigned if sizeof(T) < sizeof(Limb) convert(T, convert(Limb, x)) else 0 <= x.size <= cld(sizeof(T), sizeof(Limb)) || throw(InexactError(nameof(T), T, x)) x % T end end function (::Type{T})(x::BigInt) where T <: Base.BitSigned n = abs(x.size) if sizeof(T) < sizeof(Limb) SLimb = typeof(Signed(one(Limb))) convert(T, convert(SLimb, x)) else 0 <= n <= cld(sizeof(T), sizeof(Limb)) || throw(InexactError(nameof(T), T, x)) y = x % T ispos(x) ⊻ (y > 0) && throw(InexactError(nameof(T), T, x)) y end end Float64(n::BigInt, ::RoundingMode{:ToZero}) = begin MPZ.get_d(n) end function (::Type{T})(n::BigInt, ::RoundingMode{:ToZero}) where T <: Union{Float16, Float32} T(Float64(n, RoundToZero), RoundToZero) end function (::Type{T})(n::BigInt, ::RoundingMode{:Down}) where T <: CdoubleMax x = T(n, RoundToZero) if x > n prevfloat(x) else x end end function (::Type{T})(n::BigInt, ::RoundingMode{:Up}) where T <: CdoubleMax x = T(n, RoundToZero) if x < n nextfloat(x) else x end end function Float64(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return 0.0 xsize = abs(x.size) if xsize * BITS_PER_LIMB > 1024 z = Inf64 elseif xsize == 1 z = Float64(unsafe_load(x.d)) elseif Limb == UInt32 && xsize == 2 z = Float64((unsafe_load(x.d, 2) % UInt64) << BITS_PER_LIMB + unsafe_load(x.d)) else y1 = unsafe_load(x.d, xsize) % UInt64 n = top_set_bit(y1) y = y1 >> (n - (precision(Float64) + 1)) if Limb == UInt64 y += if n > precision(Float64) 0 else unsafe_load(x.d, xsize - 1) >> (10 + n) end else y += (unsafe_load(x.d, xsize - 1) % UInt64) >> (n - 22) y += if n > precision(Float64) - 32 0 else unsafe_load(x.d, xsize - 2) >> (10 + n) end end y = (y + 1) >> 1 y &= ~(UInt64(trailing_zeros(x) == (n - 54) + (xsize - 1) * BITS_PER_LIMB)) d = ((n + 1021) % UInt64) << 52 z = reinterpret(Float64, d + y) z = ldexp(z, (xsize - 1) * BITS_PER_LIMB) end return flipsign(z, x.size) end function Float32(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return 0.0f0 xsize = abs(x.size) if xsize * BITS_PER_LIMB > 128 z = Inf32 elseif xsize == 1 z = Float32(unsafe_load(x.d)) else y1 = unsafe_load(x.d, xsize) n = BITS_PER_LIMB - leading_zeros(y1) y = y1 >> (n - (precision(Float32) + 1)) % UInt32 y += if n > precision(Float32) 0 else unsafe_load(x.d, xsize - 1) >> (BITS_PER_LIMB - -25) end % UInt32 y = (y + one(UInt32)) >> 1 y &= ~(UInt32(trailing_zeros(x) == (n - 25) + (xsize - 1) * BITS_PER_LIMB)) d = ((n + 125) % UInt32) << 23 z = reinterpret(Float32, d + y) z = ldexp(z, (xsize - 1) * BITS_PER_LIMB) end return flipsign(z, x.size) end function Float16(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return Float16(0.0) y1 = unsafe_load(x.d) n = BITS_PER_LIMB - leading_zeros(y1) if n > 16 || abs(x.size) > 1 z = Inf16 else y = y1 >> (n - (precision(Float16) + 1)) % UInt16 y = (y + one(UInt16)) >> 1 y &= ~(UInt16(trailing_zeros(x) == n - 12)) d = ((n + 13) % UInt16) << 10 z = reinterpret(Float16, d + y) end return flipsign(z, x.size) end Float64(n::BigInt) = begin Float64(n, RoundNearest) end Float32(n::BigInt) = begin Float32(n, RoundNearest) end Float16(n::BigInt) = begin Float16(n, RoundNearest) end promote_rule(::Type{BigInt}, ::Type{<:Integer}) = begin BigInt end Core.@doc " big(x)\n\nConvert a number to a maximum precision representation (typically [`BigInt`](@ref) or\n`BigFloat`). See [`BigFloat`](@ref BigFloat(::Any, rounding::RoundingMode)) for\ninformation about some pitfalls with floating-point numbers.\n" function big end big(::Type{<:Integer}) = begin BigInt end big(::Type{<:Rational}) = begin Rational{BigInt} end big(n::Integer) = begin convert(BigInt, n) end for (fJ, fC) = ((:+, :add), (:-, :sub), (:*, :mul), (:mod, :fdiv_r), (:rem, :tdiv_r), (:gcd, :gcd), (:lcm, :lcm), (:&, :and), (:|, :ior), (:xor, :xor)) @eval begin ($fJ)(x::BigInt, y::BigInt) = begin MPZ.:($fC)(x, y) end end end for (r, f) = ((RoundToZero, :tdiv_q), (RoundDown, :fdiv_q), (RoundUp, :cdiv_q)) @eval div(x::BigInt, y::BigInt, ::typeof($r)) = begin MPZ.:($f)(x, y) end end div(x::BigInt, y::BigInt) = begin div(x, y, RoundToZero) end fld(x::BigInt, y::BigInt) = begin div(x, y, RoundDown) end cld(x::BigInt, y::BigInt) = begin div(x, y, RoundUp) end x::BigInt / y::BigInt = begin float(x) / float(y) end function invmod(x::BigInt, y::BigInt) z = zero(BigInt) ya = abs(y) if ya == 1 return z end if y == 0 || MPZ.invert!(z, x, ya) == 0 throw(DomainError(y)) end if y < 0 MPZ.add!(z, y) end return z end for (fJ, fC) = ((:+, :add), (:*, :mul), (:&, :and), (:|, :ior), (:xor, :xor)) fC! = Symbol(fC, :!) @eval begin ($fJ)(a::BigInt, b::BigInt, c::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC)(a, b), c) end ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC)(a, b), c), d) end ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC)(a, b), c), d), e) end end end x::BigInt + c::CulongMax = begin MPZ.add_ui(x, c) end c::CulongMax + x::BigInt = begin x + c end x::BigInt - c::CulongMax = begin MPZ.sub_ui(x, c) end c::CulongMax - x::BigInt = begin MPZ.ui_sub(c, x) end x::BigInt + c::ClongMax = begin if c < 0 x - -(c % Culong) else x + convert(Culong, c) end end c::ClongMax + x::BigInt = begin if c < 0 x - -(c % Culong) else x + convert(Culong, c) end end x::BigInt - c::ClongMax = begin if c < 0 x + -(c % Culong) else x - convert(Culong, c) end end c::ClongMax - x::BigInt = begin if c < 0 -((x + -(c % Culong))) else convert(Culong, c) - x end end x::BigInt * c::CulongMax = begin MPZ.mul_ui(x, c) end c::CulongMax * x::BigInt = begin x * c end x::BigInt * c::ClongMax = begin MPZ.mul_si(x, c) end c::ClongMax * x::BigInt = begin x * c end x::BigInt / y::Union{ClongMax, CulongMax} = begin float(x) / y end x::Union{ClongMax, CulongMax} / y::BigInt = begin x / float(y) end -(x::BigInt) = begin MPZ.neg(x) end ~(x::BigInt) = begin MPZ.com(x) end x::BigInt << c::UInt = begin if c == 0 x else MPZ.mul_2exp(x, c) end end x::BigInt >> c::UInt = begin if c == 0 x else MPZ.fdiv_q_2exp(x, c) end end x::BigInt >>> c::UInt = begin x >> c end function trailing_zeros(x::BigInt) c = MPZ.scan1(x, 0) c == -1 && throw(DomainError(x, "`x` must be non-zero")) c end function trailing_ones(x::BigInt) c = MPZ.scan0(x, 0) c == -1 && throw(DomainError(x, "`x` must not be equal to -1")) c end function count_ones(x::BigInt) c = MPZ.popcount(x) c == -1 && throw(DomainError(x, "`x` cannot be negative")) c end function count_zeros(x::BigInt) c = MPZ.popcount(~x) c == -1 && throw(DomainError(x, "`x` must be negative")) c end Core.@doc " count_ones_abs(x::BigInt)\n\nNumber of ones in the binary representation of abs(x).\n" count_ones_abs(x::BigInt) = begin if iszero(x) 0 else MPZ.mpn_popcount(x) end end function top_set_bit(x::BigInt) isneg(x) && throw(DomainError(x, "top_set_bit only supports negative arguments when they have type BitSigned.")) iszero(x) && return 0 x.size * sizeof(Limb) << 3 - leading_zeros(GC.@preserve(x, unsafe_load(x.d, x.size))) end divrem(x::BigInt, y::BigInt, ::typeof(RoundToZero) = begin RoundToZero end) = begin MPZ.tdiv_qr(x, y) end divrem(x::BigInt, y::Integer, ::typeof(RoundToZero) = begin RoundToZero end) = begin MPZ.tdiv_qr(x, BigInt(y)) end cmp(x::BigInt, y::BigInt) = begin sign(MPZ.cmp(x, y)) end cmp(x::BigInt, y::ClongMax) = begin sign(MPZ.cmp_si(x, y)) end cmp(x::BigInt, y::CulongMax) = begin sign(MPZ.cmp_ui(x, y)) end cmp(x::BigInt, y::Integer) = begin cmp(x, big(y)) end cmp(x::Integer, y::BigInt) = begin -(cmp(y, x)) end cmp(x::BigInt, y::CdoubleMax) = begin if isnan(y) -1 else sign(MPZ.cmp_d(x, y)) end end cmp(x::CdoubleMax, y::BigInt) = begin -(cmp(y, x)) end isqrt(x::BigInt) = begin MPZ.sqrt(x) end x::BigInt ^ y::Culong = begin MPZ.pow_ui(x, y) end function bigint_pow(x::BigInt, y::Integer) x == 1 && return x x == -1 && return if isodd(y) x else -x end if y < 0 throw(DomainError(y, "`y` cannot be negative.")) end @noinline throw1(y) = begin throw(OverflowError("exponent $(y) is too large and computation will overflow")) end if y > typemax(Culong) x == 0 && return x throw1(y) end return x ^ convert(Culong, y) end x::BigInt ^ y::BigInt = begin bigint_pow(x, y) end x::BigInt ^ y::Bool = begin if y x else one(x) end end x::BigInt ^ y::Integer = begin bigint_pow(x, y) end x::Integer ^ y::BigInt = begin bigint_pow(BigInt(x), y) end x::Bool ^ y::BigInt = begin Base.power_by_squaring(x, y) end function powermod(x::BigInt, p::BigInt, m::BigInt) r = MPZ.powm(x, p, m) return if m < 0 && r > 0 MPZ.add!(r, m) else r end end powermod(x::Integer, p::Integer, m::BigInt) = begin powermod(big(x), big(p), m) end function gcdx(a::BigInt, b::BigInt) (g, s, t) = MPZ.gcdext(a, b) if t == 0 if a == b return (g, t, s) elseif abs(a) == abs(b) return (g, t, -s) end end (g, s, t) end +(x::BigInt, y::BigInt, rest::BigInt...) = begin sum(tuple(x, y, rest...)) end sum(arr::Union{AbstractArray{BigInt}, Tuple{BigInt, Vararg{BigInt}}}) = begin foldl(MPZ.add!, arr; init = BigInt(0)) end function prod(arr::AbstractArray{BigInt}) nbits = BITS_PER_LIMB for x = arr iszero(x) && return zero(BigInt) xsize = abs(x.size) lz = GC.@preserve(x, leading_zeros(unsafe_load(x.d, xsize))) nbits += xsize * BITS_PER_LIMB - lz end init = BigInt(; nbits) MPZ.set_si!(init, 1) foldl(MPZ.mul!, arr; init) end factorial(n::BigInt) = begin if !(isneg(n)) MPZ.fac_ui(n) else throw(DomainError(n, "`n` must not be negative.")) end end function binomial(n::BigInt, k::Integer) k < 0 && return BigInt(0) k <= typemax(Culong) && return binomial(n, Culong(k)) n < 0 && return if isodd(k) -(binomial((k - n) - 1, k)) else binomial((k - n) - 1, k) end κ = n - k κ < 0 && return BigInt(0) κ <= typemax(Culong) && return binomial(n, Culong(κ)) throw(OverflowError("Computation would exceed memory")) end binomial(n::BigInt, k::Culong) = begin MPZ.bin_ui(n, k) end x::BigInt == y::BigInt = begin cmp(x, y) == 0 end x::BigInt == i::Integer = begin cmp(x, i) == 0 end i::Integer == x::BigInt = begin cmp(x, i) == 0 end x::BigInt == f::CdoubleMax = begin if isnan(f) false else cmp(x, f) == 0 end end f::CdoubleMax == x::BigInt = begin if isnan(f) false else cmp(x, f) == 0 end end iszero(x::BigInt) = begin x.size == 0 end isone(x::BigInt) = begin x == Culong(1) end x::BigInt <= y::BigInt = begin cmp(x, y) <= 0 end x::BigInt <= i::Integer = begin cmp(x, i) <= 0 end i::Integer <= x::BigInt = begin cmp(x, i) >= 0 end x::BigInt <= f::CdoubleMax = begin if isnan(f) false else cmp(x, f) <= 0 end end f::CdoubleMax <= x::BigInt = begin if isnan(f) false else cmp(x, f) >= 0 end end x::BigInt < y::BigInt = begin cmp(x, y) < 0 end x::BigInt < i::Integer = begin cmp(x, i) < 0 end i::Integer < x::BigInt = begin cmp(x, i) > 0 end x::BigInt < f::CdoubleMax = begin if isnan(f) false else cmp(x, f) < 0 end end f::CdoubleMax < x::BigInt = begin if isnan(f) false else cmp(x, f) > 0 end end isneg(x::BigInt) = begin x.size < 0 end ispos(x::BigInt) = begin x.size > 0 end signbit(x::BigInt) = begin isneg(x) end flipsign!(x::BigInt, y::Integer) = begin signbit(y) && (x.size = -(x.size)) x end flipsign(x::BigInt, y::Integer) = begin if signbit(y) -x else x end end flipsign(x::BigInt, y::BigInt) = begin if signbit(y) -x else x end end function sign(x::BigInt) isneg(x) && return -(one(x)) ispos(x) && return one(x) return x end show(io::IO, x::BigInt) = begin print(io, string(x)) end function string(n::BigInt; base::Integer = 10, pad::Integer = 1) base < 0 && return Base._base(Int(base), n, pad, (base > 0) & (n.size < 0)) 2 <= base <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $(base)")) iszero(n) && (pad < 1 && return "") nd1 = ndigits(n, base = base) nd = max(nd1, pad) sv = Base.StringMemory(nd + isneg(n)) GC.@preserve sv MPZ.get_str!((pointer(sv) + nd) - nd1, base, n) @inbounds for i = (1:nd - nd1) .+ isneg(n) sv[i] = '0' % UInt8 end isneg(n) && (sv[1] = '-' % UInt8) unsafe_takestring(sv) end function digits!(a::AbstractVector{T}, n::BigInt; base::Integer = 10) where T <: Integer if base ≥ 2 if base ≤ 62 s = codeunits(string(n; base)) (i, j) = (firstindex(a) - 1, length(s) + 1) lasti = min(lastindex(a), ((firstindex(a) + length(s)) - 1) - isneg(n)) while i < lasti x = s[j -= 1] a[i += 1] = if base ≤ 36 if x > 0x39 x - 0x57 else x - 0x30 end else if x > 0x39 if x > 0x60 x - 0x3d else x - 0x37 end else x - 0x30 end end end lasti = lastindex(a) while i < lasti a[i += 1] = zero(T) end return if isneg(n) map!(-, a, a) else a end elseif a isa StridedVector{<:Base.BitInteger} && (stride(a, 1) == 1 && (ispow2(base) && base - 1 ≤ typemax(T))) origlen = length(a) (_, writelen) = MPZ.export!(a, n; nails = 8 * sizeof(T) - trailing_zeros(base)) length(a) != origlen && resize!(a, origlen) a[begin + writelen:end] .= zero(T) return if isneg(n) map!(-, a, a) else a end end end return invoke(digits!, Tuple{typeof(a), Integer}, a, n; base) end function ndigits0zpb(x::BigInt, b::Integer) b < 2 && throw(DomainError(b, "`b` cannot be less than 2.")) x.size == 0 && return 0 if ispow2(b) && 2 <= b <= 62 MPZ.sizeinbase(x, b) else n = MPZ.sizeinbase(x, 2) lb = log2(b) (q, r) = divrem(n, lb) iq = Int(q) maxerr = q * eps(lb) if r - 1.0 < maxerr if abs(x) >= big(b) ^ iq iq + 1 else iq end elseif lb - r < maxerr if abs(x) >= big(b) ^ (iq + 1) iq + 2 else iq + 1 end else iq + 1 end end end _prevpow2(x::BigInt) = begin if -2 <= x <= 2 x else flipsign!(ONE << (ndigits(x, base = 2) - 1), x) end end _nextpow2(x::BigInt) = begin if count_ones_abs(x) <= 1 x else flipsign!(ONE << ndigits(x, base = 2), x) end end Base.checked_abs(x::BigInt) = begin abs(x) end Base.checked_neg(x::BigInt) = begin -x end Base.checked_add(a::BigInt, b::BigInt) = begin a + b end Base.checked_sub(a::BigInt, b::BigInt) = begin a - b end Base.checked_mul(a::BigInt, b::BigInt) = begin a * b end Base.checked_div(a::BigInt, b::BigInt) = begin div(a, b) end Base.checked_rem(a::BigInt, b::BigInt) = begin rem(a, b) end Base.checked_fld(a::BigInt, b::BigInt) = begin fld(a, b) end Base.checked_mod(a::BigInt, b::BigInt) = begin mod(a, b) end Base.checked_cld(a::BigInt, b::BigInt) = begin cld(a, b) end Base.add_with_overflow(a::BigInt, b::BigInt) = begin (a + b, false) end Base.sub_with_overflow(a::BigInt, b::BigInt) = begin (a - b, false) end Base.mul_with_overflow(a::BigInt, b::BigInt) = begin (a * b, false) end Base.checked_pow(x::BigInt, p::Integer) = begin x ^ p end Base.checked_pow(x::Integer, p::BigInt) = begin x ^ p end Base.checked_pow(x::BigInt, p::BigInt) = begin x ^ p end Base.deepcopy_internal(x::BigInt, stackdict::IdDict) = begin get!((()->begin MPZ.set(x) end), stackdict, x)::BigInt end if Limb === UInt64 === UInt using .Base: hash_uint function hash_integer(n::BigInt, h::UInt) GC.@preserve n begin s = n.size s == 0 && return hash_integer(0, h) p = convert(Ptr{UInt64}, n.d) b = unsafe_load(p) h ⊻= hash_uint(ifelse(s < 0, -b, b) ⊻ h) for k = 2:abs(s) h ⊻= hash_uint(unsafe_load(p, k) ⊻ h) end return h end end function hash(x::BigInt, h::UInt) GC.@preserve x begin sz = x.size sz == 0 && return hash(0, h) ptr = Ptr{UInt64}(x.d) if sz == 1 return hash(unsafe_load(ptr), h) elseif sz == -1 limb = unsafe_load(ptr) limb <= typemin(Int) % UInt && return hash(-(limb % Int), h) end pow = trailing_zeros(x) nd = Base.ndigits0z(x, 2) idx = pow >>> 6 + 1 shift = (pow & 63) % UInt upshift = BITS_PER_LIMB - shift asz = abs(sz) if shift == 0 limb = unsafe_load(ptr, idx) else limb1 = unsafe_load(ptr, idx) limb2 = if idx < asz unsafe_load(ptr, idx + 1) else UInt(0) end limb = limb2 << upshift | limb1 >> shift end if nd <= 1024 && nd - pow <= 53 return hash(ldexp(flipsign(Float64(limb), sz), pow), h) end h = hash_integer(pow, h) h ⊻= hash_uint(flipsign(limb, sz) ⊻ h) for idx = idx + 1:asz if shift == 0 limb = unsafe_load(ptr, idx) else limb1 = limb2 if idx == asz limb = limb1 >> shift limb == 0 && break else limb2 = unsafe_load(ptr, idx + 1) limb = limb2 << upshift | limb1 >> shift end end h ⊻= hash_uint(limb ⊻ h) end return h end end end module MPQ import .Base: unsafe_rational, __throw_rational_argerror_zero import ..GMP: BigInt, MPZ, Limb, isneg, libgmp gmpq(op::Symbol) = begin (Symbol(:__gmpq_, op), libgmp) end mutable struct _MPQ num_alloc::Cint num_size::Cint num_d::Ptr{Limb} den_alloc::Cint den_size::Cint den_d::Ptr{Limb} rat::Rational{BigInt} end const mpq_t = Ref{_MPQ} _MPQ(x::BigInt, y::BigInt) = begin _MPQ(x.alloc, x.size, x.d, y.alloc, y.size, y.d, unsafe_rational(BigInt, x, y)) end _MPQ() = begin _MPQ(BigInt(), BigInt()) end _MPQ(x::Rational{BigInt}) = begin _MPQ(x.num, x.den) end function sync_rational!(xq::_MPQ) xq.rat.num.alloc = xq.num_alloc xq.rat.num.size = xq.num_size xq.rat.num.d = xq.num_d xq.rat.den.alloc = xq.den_alloc xq.rat.den.size = xq.den_size xq.rat.den.d = xq.den_d return xq.rat end function Rational{BigInt}(num::BigInt, den::BigInt) if iszero(den) iszero(num) && __throw_rational_argerror_zero(BigInt) return set_si(flipsign(1, num), 0) end xq = _MPQ(MPZ.set(num), MPZ.set(den)) ccall((:__gmpq_canonicalize, libgmp), Cvoid, (mpq_t,), xq) return sync_rational!(xq) end function set!(z::Rational{BigInt}, x::Rational{BigInt}) zq = _MPQ(z) ccall((:__gmpq_set, libgmp), Cvoid, (mpq_t, mpq_t), zq, _MPQ(x)) return sync_rational!(zq) end function set_z!(z::Rational{BigInt}, x::BigInt) zq = _MPQ(z) ccall((:__gmpq_set_z, libgmp), Cvoid, (mpq_t, MPZ.mpz_t), zq, x) return sync_rational!(zq) end for (op, T) = ((:set, Rational{BigInt}), (:set_z, BigInt)) op! = Symbol(op, :!) @eval ($op)(a::$T) = begin ($op!)(unsafe_rational(BigInt(), BigInt()), a) end end for (op, T1, T2) = ((:set_ui, Culong, Culong), (:set_si, Clong, Culong)) op! = Symbol(op, :!) @eval begin function ($op!)(z::Rational{BigInt}, a, b) zq = _MPQ(z) ccall($(gmpq(op)), Cvoid, (mpq_t, $T1, $T2), zq, a, b) return sync_rational!(zq) end ($op)(a, b) = begin ($op!)(unsafe_rational(BigInt(), BigInt()), a, b) end end end function add!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && (iszero(y.den) && isneg(x.num) != isneg(y.num)) throw(DivideError()) end return set!(z, if iszero(x.den) x else y end) end zq = _MPQ(z) ccall((:__gmpq_add, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function sub!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && (iszero(y.den) && isneg(x.num) == isneg(y.num)) throw(DivideError()) end iszero(x.den) && return set!(z, x) return set_si!(z, flipsign(-1, y.num), 0) end zq = _MPQ(z) ccall((:__gmpq_sub, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function mul!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.num) || iszero(y.num) throw(DivideError()) end return set_si!(z, ifelse(xor(isneg(x.num), isneg(y.num)), -1, 1), 0) end zq = _MPQ(z) ccall((:__gmpq_mul, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function div!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) if iszero(y.den) throw(DivideError()) end isneg(y.num) || return set!(z, x) return set_si!(z, flipsign(-1, x.num), 0) elseif iszero(y.den) return set_si!(z, 0, 1) elseif iszero(y.num) if iszero(x.num) throw(DivideError()) end return set_si!(z, flipsign(1, x.num), 0) end zq = _MPQ(z) ccall((:__gmpq_div, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end for (fJ, fC) = ((:+, :add), (:-, :sub), (:*, :mul), (://, :div)) fC! = Symbol(fC, :!) @eval begin ($fC!)(x::Rational{BigInt}, y::Rational{BigInt}) = begin ($fC!)(x, x, y) end Base.:($fJ)(x::Rational{BigInt}, y::Rational{BigInt}) = begin ($fC!)(unsafe_rational(BigInt(), BigInt()), x, y) end end end function Base.cmp(x::Rational{BigInt}, y::Rational{BigInt}) Int(ccall((:__gmpq_cmp, libgmp), Cint, (mpq_t, mpq_t), _MPQ(x), _MPQ(y))) end end end module GMP export BigInt import .Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, ~, &, |, xor, nand, nor, binomial, cmp, convert, div, divrem, factorial, cld, fld, gcd, gcdx, lcm, mod, ndigits, promote_rule, rem, show, isqrt, string, powermod, sum, prod, trailing_zeros, trailing_ones, count_ones, count_zeros, tryparse_internal, bin, oct, dec, hex, isequal, invmod, _prevpow2, _nextpow2, ndigits0zpb, widen, signed, unsafe_trunc, trunc, iszero, isone, big, flipsign, signbit, sign, hastypemax, isodd, iseven, digits!, hash, hash_integer, top_set_bit, clamp, unsafe_takestring import Core: Signed, Float16, Float32, Float64 if Clong == Int32 const ClongMax = Union{Int8, Int16, Int32} const CulongMax = Union{UInt8, UInt16, UInt32} else const ClongMax = Union{Int8, Int16, Int32, Int64} const CulongMax = Union{UInt8, UInt16, UInt32, UInt64} end const CdoubleMax = Union{Float16, Float32, Float64} if Sys.iswindows() const libgmp = "libgmp-10.dll" elseif Sys.isapple() const libgmp = "@rpath/libgmp.10.dylib" else const libgmp = "libgmp.so.10" end _version() = begin unsafe_string(unsafe_load(cglobal((:__gmp_version, libgmp), Ptr{Cchar}))) end version() = begin VersionNumber(_version()) end major_version() = begin (_version())[1] end bits_per_limb() = begin Int(unsafe_load(cglobal((:__gmp_bits_per_limb, libgmp), Cint))) end const VERSION = version() const MAJOR_VERSION = major_version() const BITS_PER_LIMB = bits_per_limb() if BITS_PER_LIMB == 32 const Limb = UInt32 const SLimbMax = Union{Int8, Int16, Int32} const ULimbMax = Union{UInt8, UInt16, UInt32} elseif BITS_PER_LIMB == 64 const Limb = UInt64 const SLimbMax = Union{Int8, Int16, Int32, Int64} const ULimbMax = Union{UInt8, UInt16, UInt32, UInt64} else error("GMP: cannot determine the type mp_limb_t (__gmp_bits_per_limb == $(BITS_PER_LIMB))") end Core.@doc " BigInt <: Signed\n\nArbitrary precision integer type.\n" mutable struct BigInt <: Signed alloc::Cint size::Cint d::Ptr{Limb} function BigInt(; nbits::Integer = 0) b = MPZ.init2!(new(), nbits) finalizer(cglobal((:__gmpz_clear, libgmp)), b) return b end end Core.@doc " BigInt(x)\n\nCreate an arbitrary precision integer. `x` may be an `Int` (or anything that can be\nconverted to an `Int`). The usual mathematical operators are defined for this type, and\nresults are promoted to a [`BigInt`](@ref).\n\nInstances can be constructed from strings via [`parse`](@ref), or using the `big`\nstring literal.\n\n# Examples\n```jldoctest\njulia> parse(BigInt, \"42\")\n42\n\njulia> big\"313\"\n313\n\njulia> BigInt(10)^19\n10000000000000000000\n```\n" BigInt(x) Core.@doc " ALLOC_OVERFLOW_FUNCTION\n\nA reference that holds a boolean, if true, indicating julia is linked with a patched GMP that\ndoes not abort on huge allocation and throws OutOfMemoryError instead.\n" const ALLOC_OVERFLOW_FUNCTION = Ref(false) function __init__() try if major_version() != MAJOR_VERSION || bits_per_limb() != BITS_PER_LIMB msg = "The dynamically loaded GMP library (v\"$(version())\" with __gmp_bits_per_limb == $(bits_per_limb()))\ndoes not correspond to the compile time version (v\"$(VERSION)\" with __gmp_bits_per_limb == $(BITS_PER_LIMB)).\nPlease rebuild Julia." if bits_per_limb() != BITS_PER_LIMB @error msg else @warn msg end end ccall((:__gmp_set_memory_functions, libgmp), Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), cglobal(:jl_gc_counted_malloc), cglobal(:jl_gc_counted_realloc_with_old_size), cglobal(:jl_gc_counted_free_with_size)) (ZERO.alloc, ZERO.size, ZERO.d) = (0, 0, C_NULL) (ONE.alloc, ONE.size, ONE.d) = (1, 1, pointer(_ONE)) catch ex Base.showerror_nostdio(ex, "WARNING: Error during initialization of module GMP") end try ccall((:__gmp_set_alloc_overflow_function, libgmp), Cvoid, (Ptr{Cvoid},), cglobal(:jl_throw_out_of_memory_error)) ALLOC_OVERFLOW_FUNCTION[] = true catch ex if typeof(ex) != ErrorException rethrow() end end end module MPZ using ..GMP: BigInt, Limb, BITS_PER_LIMB, libgmp const mpz_t = Ref{BigInt} const bitcnt_t = Culong gmpz(op::Symbol) = begin (Symbol(:__gmpz_, op), libgmp) end init!(x::BigInt) = begin ccall((:__gmpz_init, libgmp), Cvoid, (mpz_t,), x) x end init2!(x::BigInt, a) = begin ccall((:__gmpz_init2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end realloc2!(x, a) = begin ccall((:__gmpz_realloc2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end realloc2(a) = begin realloc2!(BigInt(), a) end sizeinbase(a::BigInt, b) = begin Int(ccall((:__gmpz_sizeinbase, libgmp), Csize_t, (mpz_t, Cint), a, b)) end for (op, nbits) = (:add => :(BITS_PER_LIMB * (1 + max(abs(a.size), abs(b.size)))), :sub => :(BITS_PER_LIMB * (1 + max(abs(a.size), abs(b.size)))), :mul => 0, :fdiv_q => 0, :tdiv_q => 0, :cdiv_q => 0, :fdiv_r => 0, :tdiv_r => 0, :cdiv_r => 0, :gcd => 0, :lcm => 0, :and => 0, :ior => 0, :xor => 0) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt, b::BigInt) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t, mpz_t), x, a, b) x end ($op)(a::BigInt, b::BigInt) = begin ($op!)(BigInt(nbits = $nbits), a, b) end ($op!)(x::BigInt, b::BigInt) = begin ($op!)(x, x, b) end end end invert!(x::BigInt, a::BigInt, b::BigInt) = begin ccall((:__gmpz_invert, libgmp), Cint, (mpz_t, mpz_t, mpz_t), x, a, b) end invert!(x::BigInt, b::BigInt) = begin invert!(x, x, b) end invert(a::BigInt, b::BigInt) = begin ret = BigInt() invert!(ret, a, b) ret end for op = (:add_ui, :sub_ui, :mul_ui, :mul_2exp, :fdiv_q_2exp, :pow_ui, :bin_ui) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt, b) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t, Culong), x, a, b) x end ($op)(a::BigInt, b) = begin ($op!)(BigInt(), a, b) end ($op!)(x::BigInt, b) = begin ($op!)(x, x, b) end end end ui_sub!(x::BigInt, a, b::BigInt) = begin ccall((:__gmpz_ui_sub, libgmp), Cvoid, (mpz_t, Culong, mpz_t), x, a, b) x end ui_sub(a, b::BigInt) = begin ui_sub!(BigInt(), a, b) end for op = (:scan1, :scan0) @eval ($op)(a::BigInt, b) = begin Int(signed(ccall($(gmpz(op)), Culong, (mpz_t, Culong), a, b))) end end mul_si!(x::BigInt, a::BigInt, b) = begin ccall((:__gmpz_mul_si, libgmp), Cvoid, (mpz_t, mpz_t, Clong), x, a, b) x end mul_si(a::BigInt, b) = begin mul_si!(BigInt(), a, b) end mul_si!(x::BigInt, b) = begin mul_si!(x, x, b) end for op = (:neg, :com, :sqrt, :set) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a::BigInt) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t), x, a) x end ($op)(a::BigInt) = begin ($op!)(BigInt(), a) end end op === :set && continue @eval ($op!)(x::BigInt) = begin ($op!)(x, x) end end for (op, T) = ((:fac_ui, Culong), (:set_ui, Culong), (:set_si, Clong), (:set_d, Cdouble)) op! = Symbol(op, :!) @eval begin ($op!)(x::BigInt, a) = begin ccall($(gmpz(op)), Cvoid, (mpz_t, $T), x, a) x end ($op)(a) = begin ($op!)(BigInt(), a) end end end popcount(a::BigInt) = begin Int(signed(ccall((:__gmpz_popcount, libgmp), Culong, (mpz_t,), a))) end mpn_popcount(d::Ptr{Limb}, s::Integer) = begin Int(ccall((:__gmpn_popcount, libgmp), Culong, (Ptr{Limb}, Csize_t), d, s)) end mpn_popcount(a::BigInt) = begin mpn_popcount(a.d, abs(a.size)) end function tdiv_qr!(x::BigInt, y::BigInt, a::BigInt, b::BigInt) ccall((:__gmpz_tdiv_qr, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, y, a, b) (x, y) end tdiv_qr(a::BigInt, b::BigInt) = begin tdiv_qr!(BigInt(), BigInt(), a, b) end powm!(x::BigInt, a::BigInt, b::BigInt, c::BigInt) = begin ccall((:__gmpz_powm, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, a, b, c) x end powm(a::BigInt, b::BigInt, c::BigInt) = begin powm!(BigInt(), a, b, c) end powm!(x::BigInt, b::BigInt, c::BigInt) = begin powm!(x, x, b, c) end function gcdext!(x::BigInt, y::BigInt, z::BigInt, a::BigInt, b::BigInt) ccall((:__gmpz_gcdext, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t, mpz_t), x, y, z, a, b) (x, y, z) end gcdext(a::BigInt, b::BigInt) = begin gcdext!(BigInt(), BigInt(), BigInt(), a, b) end cmp(a::BigInt, b::BigInt) = begin Int(ccall((:__gmpz_cmp, libgmp), Cint, (mpz_t, mpz_t), a, b)) end cmp_si(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_si, libgmp), Cint, (mpz_t, Clong), a, b)) end cmp_ui(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_ui, libgmp), Cint, (mpz_t, Culong), a, b)) end cmp_d(a::BigInt, b) = begin Int(ccall((:__gmpz_cmp_d, libgmp), Cint, (mpz_t, Cdouble), a, b)) end mpn_cmp(a::Ptr{Limb}, b::Ptr{Limb}, c) = begin ccall((:__gmpn_cmp, libgmp), Cint, (Ptr{Limb}, Ptr{Limb}, Clong), a, b, c) end mpn_cmp(a::BigInt, b::BigInt, c) = begin mpn_cmp(a.d, b.d, c) end get_str!(x, a, b::BigInt) = begin ccall((:__gmpz_get_str, libgmp), Ptr{Cchar}, (Ptr{Cchar}, Cint, mpz_t), x, a, b) x end set_str!(x::BigInt, a, b) = begin Int(ccall((:__gmpz_set_str, libgmp), Cint, (mpz_t, Ptr{UInt8}, Cint), x, a, b)) end get_d(a::BigInt) = begin ccall((:__gmpz_get_d, libgmp), Cdouble, (mpz_t,), a) end function export!(a::AbstractVector{T}, n::BigInt; order::Integer = -1, nails::Integer = 0, endian::Integer = 0) where T <: Base.BitInteger stride(a, 1) == 1 || throw(ArgumentError("a must have stride 1")) ndigits = cld(sizeinbase(n, 2), 8 * sizeof(T) - nails) length(a) < ndigits && resize!(a, ndigits) count = Ref{Csize_t}() ccall((:__gmpz_export, libgmp), Ptr{T}, (Ptr{T}, Ref{Csize_t}, Cint, Csize_t, Cint, Csize_t, mpz_t), a, count, order, sizeof(T), endian, nails, n) @assert count[] ≤ length(a) return (a, Int(count[])) end limbs_write!(x::BigInt, a) = begin ccall((:__gmpz_limbs_write, libgmp), Ptr{Limb}, (mpz_t, Clong), x, a) end limbs_finish!(x::BigInt, a) = begin ccall((:__gmpz_limbs_finish, libgmp), Cvoid, (mpz_t, Clong), x, a) end setbit!(x, a) = begin ccall((:__gmpz_setbit, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a) x end tstbit(a::BigInt, b) = begin ccall((:__gmpz_tstbit, libgmp), Cint, (mpz_t, bitcnt_t), a, b) % Bool end end const ZERO = BigInt() const ONE = BigInt() const _ONE = Limb[1] widen(::Type{Int128}) = begin BigInt end widen(::Type{UInt128}) = begin BigInt end widen(::Type{BigInt}) = begin BigInt end signed(x::BigInt) = begin x end BigInt(x::BigInt) = begin x end Signed(x::BigInt) = begin x end hastypemax(::Type{BigInt}) = begin false end function tryparse_internal(::Type{BigInt}, s::AbstractString, startpos::Int, endpos::Int, base_::Integer, raise::Bool) bstr = if startpos == firstindex(s) && endpos == lastindex(s) String(s) else String(SubString(s, startpos, endpos)) end (sgn, base, i) = Base.parseint_preamble(true, Int(base_), bstr, firstindex(bstr), lastindex(bstr)) if !(2 <= base <= 62) raise && throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $(base)")) return nothing end if i == 0 raise && throw(ArgumentError("premature end of integer: $(repr(bstr))")) return nothing end z = BigInt() if Base.containsnul(bstr) err = -1 else err = GC.@preserve(bstr, MPZ.set_str!(z, pointer(bstr) + (i - firstindex(bstr)), base)) end if err != 0 raise && throw(ArgumentError("invalid BigInt: $(repr(bstr))")) return nothing end flipsign!(z, sgn) end BigInt(x::Union{Clong, Int32}) = begin MPZ.set_si(x) end BigInt(x::Union{Culong, UInt32}) = begin MPZ.set_ui(x) end BigInt(x::Bool) = begin BigInt(UInt(x)) end unsafe_trunc(::Type{BigInt}, x::Union{Float16, Float32, Float64}) = begin MPZ.set_d(x) end function BigInt(x::Float64) isinteger(x) || throw(InexactError(:BigInt, BigInt, x)) unsafe_trunc(BigInt, x) end BigInt(x::Float16) = begin BigInt(Float64(x)) end BigInt(x::Float32) = begin BigInt(Float64(x)) end function BigInt(x::Integer) isbits(x) && (typemin(Clong) <= x <= typemax(Clong) && return BigInt((x % Clong)::Clong)) nd = ndigits(x, base = 2) z = MPZ.realloc2(nd) ux = unsigned(if x < 0 -x else x end) size = 0 limbnbits = sizeof(Limb) << 3 while nd > 0 size += 1 unsafe_store!(z.d, ux % Limb, size) ux >>= limbnbits nd -= limbnbits end z.size = if x < 0 -size else size end z end rem(x::BigInt, ::Type{Bool}) = begin (!(iszero(x)) & unsafe_load(x.d)) % Bool end (rem(x::BigInt, ::Type{T}) where T <: Union{SLimbMax, ULimbMax}) = begin if iszero(x) zero(T) else flipsign(unsafe_load(x.d) % T, x.size) end end function rem(x::BigInt, ::Type{T}) where T <: Union{Base.BitUnsigned, Base.BitSigned} u = zero(T) for l = 1:min(abs(x.size), cld(sizeof(T), sizeof(Limb))) u += (unsafe_load(x.d, l) % T) << (sizeof(Limb) << 3 * (l - 1)) end flipsign(u, x.size) end rem(x::Integer, ::Type{BigInt}) = begin BigInt(x) end clamp(x, ::Type{BigInt}) = begin convert(BigInt, x) end isodd(x::BigInt) = begin MPZ.tstbit(x, 0) end iseven(x::BigInt) = begin !(isodd(x)) end function (::Type{T})(x::BigInt) where T <: Base.BitUnsigned if sizeof(T) < sizeof(Limb) convert(T, convert(Limb, x)) else 0 <= x.size <= cld(sizeof(T), sizeof(Limb)) || throw(InexactError(nameof(T), T, x)) x % T end end function (::Type{T})(x::BigInt) where T <: Base.BitSigned n = abs(x.size) if sizeof(T) < sizeof(Limb) SLimb = typeof(Signed(one(Limb))) convert(T, convert(SLimb, x)) else 0 <= n <= cld(sizeof(T), sizeof(Limb)) || throw(InexactError(nameof(T), T, x)) y = x % T ispos(x) ⊻ (y > 0) && throw(InexactError(nameof(T), T, x)) y end end Float64(n::BigInt, ::RoundingMode{:ToZero}) = begin MPZ.get_d(n) end function (::Type{T})(n::BigInt, ::RoundingMode{:ToZero}) where T <: Union{Float16, Float32} T(Float64(n, RoundToZero), RoundToZero) end function (::Type{T})(n::BigInt, ::RoundingMode{:Down}) where T <: CdoubleMax x = T(n, RoundToZero) if x > n prevfloat(x) else x end end function (::Type{T})(n::BigInt, ::RoundingMode{:Up}) where T <: CdoubleMax x = T(n, RoundToZero) if x < n nextfloat(x) else x end end function Float64(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return 0.0 xsize = abs(x.size) if xsize * BITS_PER_LIMB > 1024 z = Inf64 elseif xsize == 1 z = Float64(unsafe_load(x.d)) elseif Limb == UInt32 && xsize == 2 z = Float64((unsafe_load(x.d, 2) % UInt64) << BITS_PER_LIMB + unsafe_load(x.d)) else y1 = unsafe_load(x.d, xsize) % UInt64 n = top_set_bit(y1) y = y1 >> (n - (precision(Float64) + 1)) if Limb == UInt64 y += if n > precision(Float64) 0 else unsafe_load(x.d, xsize - 1) >> (10 + n) end else y += (unsafe_load(x.d, xsize - 1) % UInt64) >> (n - 22) y += if n > precision(Float64) - 32 0 else unsafe_load(x.d, xsize - 2) >> (10 + n) end end y = (y + 1) >> 1 y &= ~(UInt64(trailing_zeros(x) == (n - 54) + (xsize - 1) * BITS_PER_LIMB)) d = ((n + 1021) % UInt64) << 52 z = reinterpret(Float64, d + y) z = ldexp(z, (xsize - 1) * BITS_PER_LIMB) end return flipsign(z, x.size) end function Float32(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return 0.0f0 xsize = abs(x.size) if xsize * BITS_PER_LIMB > 128 z = Inf32 elseif xsize == 1 z = Float32(unsafe_load(x.d)) else y1 = unsafe_load(x.d, xsize) n = BITS_PER_LIMB - leading_zeros(y1) y = y1 >> (n - (precision(Float32) + 1)) % UInt32 y += if n > precision(Float32) 0 else unsafe_load(x.d, xsize - 1) >> (BITS_PER_LIMB - -25) end % UInt32 y = (y + one(UInt32)) >> 1 y &= ~(UInt32(trailing_zeros(x) == (n - 25) + (xsize - 1) * BITS_PER_LIMB)) d = ((n + 125) % UInt32) << 23 z = reinterpret(Float32, d + y) z = ldexp(z, (xsize - 1) * BITS_PER_LIMB) end return flipsign(z, x.size) end function Float16(x::BigInt, ::RoundingMode{:Nearest}) x == 0 && return Float16(0.0) y1 = unsafe_load(x.d) n = BITS_PER_LIMB - leading_zeros(y1) if n > 16 || abs(x.size) > 1 z = Inf16 else y = y1 >> (n - (precision(Float16) + 1)) % UInt16 y = (y + one(UInt16)) >> 1 y &= ~(UInt16(trailing_zeros(x) == n - 12)) d = ((n + 13) % UInt16) << 10 z = reinterpret(Float16, d + y) end return flipsign(z, x.size) end Float64(n::BigInt) = begin Float64(n, RoundNearest) end Float32(n::BigInt) = begin Float32(n, RoundNearest) end Float16(n::BigInt) = begin Float16(n, RoundNearest) end promote_rule(::Type{BigInt}, ::Type{<:Integer}) = begin BigInt end Core.@doc " big(x)\n\nConvert a number to a maximum precision representation (typically [`BigInt`](@ref) or\n`BigFloat`). See [`BigFloat`](@ref BigFloat(::Any, rounding::RoundingMode)) for\ninformation about some pitfalls with floating-point numbers.\n" function big end big(::Type{<:Integer}) = begin BigInt end big(::Type{<:Rational}) = begin Rational{BigInt} end big(n::Integer) = begin convert(BigInt, n) end for (fJ, fC) = ((:+, :add), (:-, :sub), (:*, :mul), (:mod, :fdiv_r), (:rem, :tdiv_r), (:gcd, :gcd), (:lcm, :lcm), (:&, :and), (:|, :ior), (:xor, :xor)) @eval begin ($fJ)(x::BigInt, y::BigInt) = begin MPZ.:($fC)(x, y) end end end for (r, f) = ((RoundToZero, :tdiv_q), (RoundDown, :fdiv_q), (RoundUp, :cdiv_q)) @eval div(x::BigInt, y::BigInt, ::typeof($r)) = begin MPZ.:($f)(x, y) end end div(x::BigInt, y::BigInt) = begin div(x, y, RoundToZero) end fld(x::BigInt, y::BigInt) = begin div(x, y, RoundDown) end cld(x::BigInt, y::BigInt) = begin div(x, y, RoundUp) end x::BigInt / y::BigInt = begin float(x) / float(y) end function invmod(x::BigInt, y::BigInt) z = zero(BigInt) ya = abs(y) if ya == 1 return z end if y == 0 || MPZ.invert!(z, x, ya) == 0 throw(DomainError(y)) end if y < 0 MPZ.add!(z, y) end return z end for (fJ, fC) = ((:+, :add), (:*, :mul), (:&, :and), (:|, :ior), (:xor, :xor)) fC! = Symbol(fC, :!) @eval begin ($fJ)(a::BigInt, b::BigInt, c::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC)(a, b), c) end ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC)(a, b), c), d) end ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt) = begin MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC!)(MPZ.:($fC)(a, b), c), d), e) end end end x::BigInt + c::CulongMax = begin MPZ.add_ui(x, c) end c::CulongMax + x::BigInt = begin x + c end x::BigInt - c::CulongMax = begin MPZ.sub_ui(x, c) end c::CulongMax - x::BigInt = begin MPZ.ui_sub(c, x) end x::BigInt + c::ClongMax = begin if c < 0 x - -(c % Culong) else x + convert(Culong, c) end end c::ClongMax + x::BigInt = begin if c < 0 x - -(c % Culong) else x + convert(Culong, c) end end x::BigInt - c::ClongMax = begin if c < 0 x + -(c % Culong) else x - convert(Culong, c) end end c::ClongMax - x::BigInt = begin if c < 0 -((x + -(c % Culong))) else convert(Culong, c) - x end end x::BigInt * c::CulongMax = begin MPZ.mul_ui(x, c) end c::CulongMax * x::BigInt = begin x * c end x::BigInt * c::ClongMax = begin MPZ.mul_si(x, c) end c::ClongMax * x::BigInt = begin x * c end x::BigInt / y::Union{ClongMax, CulongMax} = begin float(x) / y end x::Union{ClongMax, CulongMax} / y::BigInt = begin x / float(y) end -(x::BigInt) = begin MPZ.neg(x) end ~(x::BigInt) = begin MPZ.com(x) end x::BigInt << c::UInt = begin if c == 0 x else MPZ.mul_2exp(x, c) end end x::BigInt >> c::UInt = begin if c == 0 x else MPZ.fdiv_q_2exp(x, c) end end x::BigInt >>> c::UInt = begin x >> c end function trailing_zeros(x::BigInt) c = MPZ.scan1(x, 0) c == -1 && throw(DomainError(x, "`x` must be non-zero")) c end function trailing_ones(x::BigInt) c = MPZ.scan0(x, 0) c == -1 && throw(DomainError(x, "`x` must not be equal to -1")) c end function count_ones(x::BigInt) c = MPZ.popcount(x) c == -1 && throw(DomainError(x, "`x` cannot be negative")) c end function count_zeros(x::BigInt) c = MPZ.popcount(~x) c == -1 && throw(DomainError(x, "`x` must be negative")) c end Core.@doc " count_ones_abs(x::BigInt)\n\nNumber of ones in the binary representation of abs(x).\n" count_ones_abs(x::BigInt) = begin if iszero(x) 0 else MPZ.mpn_popcount(x) end end function top_set_bit(x::BigInt) isneg(x) && throw(DomainError(x, "top_set_bit only supports negative arguments when they have type BitSigned.")) iszero(x) && return 0 x.size * sizeof(Limb) << 3 - leading_zeros(GC.@preserve(x, unsafe_load(x.d, x.size))) end divrem(x::BigInt, y::BigInt, ::typeof(RoundToZero) = RoundToZero) = begin MPZ.tdiv_qr(x, y) end divrem(x::BigInt, y::Integer, ::typeof(RoundToZero) = RoundToZero) = begin MPZ.tdiv_qr(x, BigInt(y)) end cmp(x::BigInt, y::BigInt) = begin sign(MPZ.cmp(x, y)) end cmp(x::BigInt, y::ClongMax) = begin sign(MPZ.cmp_si(x, y)) end cmp(x::BigInt, y::CulongMax) = begin sign(MPZ.cmp_ui(x, y)) end cmp(x::BigInt, y::Integer) = begin cmp(x, big(y)) end cmp(x::Integer, y::BigInt) = begin -(cmp(y, x)) end cmp(x::BigInt, y::CdoubleMax) = begin if isnan(y) -1 else sign(MPZ.cmp_d(x, y)) end end cmp(x::CdoubleMax, y::BigInt) = begin -(cmp(y, x)) end isqrt(x::BigInt) = begin MPZ.sqrt(x) end x::BigInt ^ y::Culong = begin MPZ.pow_ui(x, y) end function bigint_pow(x::BigInt, y::Integer) x == 1 && return x x == -1 && return if isodd(y) x else -x end if y < 0 throw(DomainError(y, "`y` cannot be negative.")) end @noinline throw1(y) = begin throw(OverflowError("exponent $(y) is too large and computation will overflow")) end if y > typemax(Culong) x == 0 && return x throw1(y) end return x ^ convert(Culong, y) end x::BigInt ^ y::BigInt = begin bigint_pow(x, y) end x::BigInt ^ y::Bool = begin if y x else one(x) end end x::BigInt ^ y::Integer = begin bigint_pow(x, y) end x::Integer ^ y::BigInt = begin bigint_pow(BigInt(x), y) end x::Bool ^ y::BigInt = begin Base.power_by_squaring(x, y) end function powermod(x::BigInt, p::BigInt, m::BigInt) r = MPZ.powm(x, p, m) return if m < 0 && r > 0 MPZ.add!(r, m) else r end end powermod(x::Integer, p::Integer, m::BigInt) = begin powermod(big(x), big(p), m) end function gcdx(a::BigInt, b::BigInt) (g, s, t) = MPZ.gcdext(a, b) if t == 0 if a == b return (g, t, s) elseif abs(a) == abs(b) return (g, t, -s) end end (g, s, t) end +(x::BigInt, y::BigInt, rest::BigInt...) = begin sum(tuple(x, y, rest...)) end sum(arr::Union{AbstractArray{BigInt}, Tuple{BigInt, Vararg{BigInt}}}) = begin foldl(MPZ.add!, arr; init = BigInt(0)) end function prod(arr::AbstractArray{BigInt}) nbits = BITS_PER_LIMB for x = arr iszero(x) && return zero(BigInt) xsize = abs(x.size) lz = GC.@preserve(x, leading_zeros(unsafe_load(x.d, xsize))) nbits += xsize * BITS_PER_LIMB - lz end init = BigInt(; nbits) MPZ.set_si!(init, 1) foldl(MPZ.mul!, arr; init) end factorial(n::BigInt) = begin if !(isneg(n)) MPZ.fac_ui(n) else throw(DomainError(n, "`n` must not be negative.")) end end function binomial(n::BigInt, k::Integer) k < 0 && return BigInt(0) k <= typemax(Culong) && return binomial(n, Culong(k)) n < 0 && return if isodd(k) -(binomial((k - n) - 1, k)) else binomial((k - n) - 1, k) end κ = n - k κ < 0 && return BigInt(0) κ <= typemax(Culong) && return binomial(n, Culong(κ)) throw(OverflowError("Computation would exceed memory")) end binomial(n::BigInt, k::Culong) = begin MPZ.bin_ui(n, k) end x::BigInt == y::BigInt = begin cmp(x, y) == 0 end x::BigInt == i::Integer = begin cmp(x, i) == 0 end i::Integer == x::BigInt = begin cmp(x, i) == 0 end x::BigInt == f::CdoubleMax = begin if isnan(f) false else cmp(x, f) == 0 end end f::CdoubleMax == x::BigInt = begin if isnan(f) false else cmp(x, f) == 0 end end iszero(x::BigInt) = begin x.size == 0 end isone(x::BigInt) = begin x == Culong(1) end x::BigInt <= y::BigInt = begin cmp(x, y) <= 0 end x::BigInt <= i::Integer = begin cmp(x, i) <= 0 end i::Integer <= x::BigInt = begin cmp(x, i) >= 0 end x::BigInt <= f::CdoubleMax = begin if isnan(f) false else cmp(x, f) <= 0 end end f::CdoubleMax <= x::BigInt = begin if isnan(f) false else cmp(x, f) >= 0 end end x::BigInt < y::BigInt = begin cmp(x, y) < 0 end x::BigInt < i::Integer = begin cmp(x, i) < 0 end i::Integer < x::BigInt = begin cmp(x, i) > 0 end x::BigInt < f::CdoubleMax = begin if isnan(f) false else cmp(x, f) < 0 end end f::CdoubleMax < x::BigInt = begin if isnan(f) false else cmp(x, f) > 0 end end isneg(x::BigInt) = begin x.size < 0 end ispos(x::BigInt) = begin x.size > 0 end signbit(x::BigInt) = begin isneg(x) end flipsign!(x::BigInt, y::Integer) = begin signbit(y) && (x.size = -(x.size)) x end flipsign(x::BigInt, y::Integer) = begin if signbit(y) -x else x end end flipsign(x::BigInt, y::BigInt) = begin if signbit(y) -x else x end end function sign(x::BigInt) isneg(x) && return -(one(x)) ispos(x) && return one(x) return x end show(io::IO, x::BigInt) = begin print(io, string(x)) end function string(n::BigInt; base::Integer = 10, pad::Integer = 1) base < 0 && return Base._base(Int(base), n, pad, (base > 0) & (n.size < 0)) 2 <= base <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $(base)")) iszero(n) && (pad < 1 && return "") nd1 = ndigits(n, base = base) nd = max(nd1, pad) sv = Base.StringMemory(nd + isneg(n)) GC.@preserve sv MPZ.get_str!((pointer(sv) + nd) - nd1, base, n) @inbounds for i = (1:nd - nd1) .+ isneg(n) sv[i] = '0' % UInt8 end isneg(n) && (sv[1] = '-' % UInt8) unsafe_takestring(sv) end function digits!(a::AbstractVector{T}, n::BigInt; base::Integer = 10) where T <: Integer if base ≥ 2 if base ≤ 62 s = codeunits(string(n; base)) (i, j) = (firstindex(a) - 1, length(s) + 1) lasti = min(lastindex(a), ((firstindex(a) + length(s)) - 1) - isneg(n)) while i < lasti x = s[j -= 1] a[i += 1] = if base ≤ 36 if x > 0x39 x - 0x57 else x - 0x30 end else if x > 0x39 if x > 0x60 x - 0x3d else x - 0x37 end else x - 0x30 end end end lasti = lastindex(a) while i < lasti a[i += 1] = zero(T) end return if isneg(n) map!(-, a, a) else a end elseif a isa StridedVector{<:Base.BitInteger} && (stride(a, 1) == 1 && (ispow2(base) && base - 1 ≤ typemax(T))) origlen = length(a) (_, writelen) = MPZ.export!(a, n; nails = 8 * sizeof(T) - trailing_zeros(base)) length(a) != origlen && resize!(a, origlen) a[begin + writelen:end] .= zero(T) return if isneg(n) map!(-, a, a) else a end end end return invoke(digits!, Tuple{typeof(a), Integer}, a, n; base) end function ndigits0zpb(x::BigInt, b::Integer) b < 2 && throw(DomainError(b, "`b` cannot be less than 2.")) x.size == 0 && return 0 if ispow2(b) && 2 <= b <= 62 MPZ.sizeinbase(x, b) else n = MPZ.sizeinbase(x, 2) lb = log2(b) (q, r) = divrem(n, lb) iq = Int(q) maxerr = q * eps(lb) if r - 1.0 < maxerr if abs(x) >= big(b) ^ iq iq + 1 else iq end elseif lb - r < maxerr if abs(x) >= big(b) ^ (iq + 1) iq + 2 else iq + 1 end else iq + 1 end end end _prevpow2(x::BigInt) = begin if -2 <= x <= 2 x else flipsign!(ONE << (ndigits(x, base = 2) - 1), x) end end _nextpow2(x::BigInt) = begin if count_ones_abs(x) <= 1 x else flipsign!(ONE << ndigits(x, base = 2), x) end end Base.checked_abs(x::BigInt) = begin abs(x) end Base.checked_neg(x::BigInt) = begin -x end Base.checked_add(a::BigInt, b::BigInt) = begin a + b end Base.checked_sub(a::BigInt, b::BigInt) = begin a - b end Base.checked_mul(a::BigInt, b::BigInt) = begin a * b end Base.checked_div(a::BigInt, b::BigInt) = begin div(a, b) end Base.checked_rem(a::BigInt, b::BigInt) = begin rem(a, b) end Base.checked_fld(a::BigInt, b::BigInt) = begin fld(a, b) end Base.checked_mod(a::BigInt, b::BigInt) = begin mod(a, b) end Base.checked_cld(a::BigInt, b::BigInt) = begin cld(a, b) end Base.add_with_overflow(a::BigInt, b::BigInt) = begin (a + b, false) end Base.sub_with_overflow(a::BigInt, b::BigInt) = begin (a - b, false) end Base.mul_with_overflow(a::BigInt, b::BigInt) = begin (a * b, false) end Base.checked_pow(x::BigInt, p::Integer) = begin x ^ p end Base.checked_pow(x::Integer, p::BigInt) = begin x ^ p end Base.checked_pow(x::BigInt, p::BigInt) = begin x ^ p end Base.deepcopy_internal(x::BigInt, stackdict::IdDict) = begin get!((()->begin MPZ.set(x) end), stackdict, x)::BigInt end if Limb === UInt64 === UInt using .Base: hash_uint function hash_integer(n::BigInt, h::UInt) GC.@preserve n begin s = n.size s == 0 && return hash_integer(0, h) p = convert(Ptr{UInt64}, n.d) b = unsafe_load(p) h ⊻= hash_uint(ifelse(s < 0, -b, b) ⊻ h) for k = 2:abs(s) h ⊻= hash_uint(unsafe_load(p, k) ⊻ h) end return h end end function hash(x::BigInt, h::UInt) GC.@preserve x begin sz = x.size sz == 0 && return hash(0, h) ptr = Ptr{UInt64}(x.d) if sz == 1 return hash(unsafe_load(ptr), h) elseif sz == -1 limb = unsafe_load(ptr) limb <= typemin(Int) % UInt && return hash(-(limb % Int), h) end pow = trailing_zeros(x) nd = Base.ndigits0z(x, 2) idx = pow >>> 6 + 1 shift = (pow & 63) % UInt upshift = BITS_PER_LIMB - shift asz = abs(sz) if shift == 0 limb = unsafe_load(ptr, idx) else limb1 = unsafe_load(ptr, idx) limb2 = if idx < asz unsafe_load(ptr, idx + 1) else UInt(0) end limb = limb2 << upshift | limb1 >> shift end if nd <= 1024 && nd - pow <= 53 return hash(ldexp(flipsign(Float64(limb), sz), pow), h) end h = hash_integer(pow, h) h ⊻= hash_uint(flipsign(limb, sz) ⊻ h) for idx = idx + 1:asz if shift == 0 limb = unsafe_load(ptr, idx) else limb1 = limb2 if idx == asz limb = limb1 >> shift limb == 0 && break else limb2 = unsafe_load(ptr, idx + 1) limb = limb2 << upshift | limb1 >> shift end end h ⊻= hash_uint(limb ⊻ h) end return h end end end module MPQ import .Base: unsafe_rational, __throw_rational_argerror_zero import ..GMP: BigInt, MPZ, Limb, isneg, libgmp gmpq(op::Symbol) = begin (Symbol(:__gmpq_, op), libgmp) end mutable struct _MPQ num_alloc::Cint num_size::Cint num_d::Ptr{Limb} den_alloc::Cint den_size::Cint den_d::Ptr{Limb} rat::Rational{BigInt} end const mpq_t = Ref{_MPQ} _MPQ(x::BigInt, y::BigInt) = begin _MPQ(x.alloc, x.size, x.d, y.alloc, y.size, y.d, unsafe_rational(BigInt, x, y)) end _MPQ() = begin _MPQ(BigInt(), BigInt()) end _MPQ(x::Rational{BigInt}) = begin _MPQ(x.num, x.den) end function sync_rational!(xq::_MPQ) xq.rat.num.alloc = xq.num_alloc xq.rat.num.size = xq.num_size xq.rat.num.d = xq.num_d xq.rat.den.alloc = xq.den_alloc xq.rat.den.size = xq.den_size xq.rat.den.d = xq.den_d return xq.rat end function Rational{BigInt}(num::BigInt, den::BigInt) if iszero(den) iszero(num) && __throw_rational_argerror_zero(BigInt) return set_si(flipsign(1, num), 0) end xq = _MPQ(MPZ.set(num), MPZ.set(den)) ccall((:__gmpq_canonicalize, libgmp), Cvoid, (mpq_t,), xq) return sync_rational!(xq) end function set!(z::Rational{BigInt}, x::Rational{BigInt}) zq = _MPQ(z) ccall((:__gmpq_set, libgmp), Cvoid, (mpq_t, mpq_t), zq, _MPQ(x)) return sync_rational!(zq) end function set_z!(z::Rational{BigInt}, x::BigInt) zq = _MPQ(z) ccall((:__gmpq_set_z, libgmp), Cvoid, (mpq_t, MPZ.mpz_t), zq, x) return sync_rational!(zq) end for (op, T) = ((:set, Rational{BigInt}), (:set_z, BigInt)) op! = Symbol(op, :!) @eval ($op)(a::$T) = begin ($op!)(unsafe_rational(BigInt(), BigInt()), a) end end for (op, T1, T2) = ((:set_ui, Culong, Culong), (:set_si, Clong, Culong)) op! = Symbol(op, :!) @eval begin function ($op!)(z::Rational{BigInt}, a, b) zq = _MPQ(z) ccall($(gmpq(op)), Cvoid, (mpq_t, $T1, $T2), zq, a, b) return sync_rational!(zq) end ($op)(a, b) = begin ($op!)(unsafe_rational(BigInt(), BigInt()), a, b) end end end function add!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && (iszero(y.den) && isneg(x.num) != isneg(y.num)) throw(DivideError()) end return set!(z, if iszero(x.den) x else y end) end zq = _MPQ(z) ccall((:__gmpq_add, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function sub!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.den) && (iszero(y.den) && isneg(x.num) == isneg(y.num)) throw(DivideError()) end iszero(x.den) && return set!(z, x) return set_si!(z, flipsign(-1, y.num), 0) end zq = _MPQ(z) ccall((:__gmpq_sub, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function mul!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) || iszero(y.den) if iszero(x.num) || iszero(y.num) throw(DivideError()) end return set_si!(z, ifelse(xor(isneg(x.num), isneg(y.num)), -1, 1), 0) end zq = _MPQ(z) ccall((:__gmpq_mul, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end function div!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) if iszero(x.den) if iszero(y.den) throw(DivideError()) end isneg(y.num) || return set!(z, x) return set_si!(z, flipsign(-1, x.num), 0) elseif iszero(y.den) return set_si!(z, 0, 1) elseif iszero(y.num) if iszero(x.num) throw(DivideError()) end return set_si!(z, flipsign(1, x.num), 0) end zq = _MPQ(z) ccall((:__gmpq_div, libgmp), Cvoid, (mpq_t, mpq_t, mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end for (fJ, fC) = ((:+, :add), (:-, :sub), (:*, :mul), (://, :div)) fC! = Symbol(fC, :!) @eval begin ($fC!)(x::Rational{BigInt}, y::Rational{BigInt}) = begin ($fC!)(x, x, y) end Base.:($fJ)(x::Rational{BigInt}, y::Rational{BigInt}) = begin ($fC!)(unsafe_rational(BigInt(), BigInt()), x, y) end end end function Base.cmp(x::Rational{BigInt}, y::Rational{BigInt}) Int(ccall((:__gmpq_cmp, libgmp), Cint, (mpq_t, mpq_t), _MPQ(x), _MPQ(y))) end end end Parsing files in Base: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 Expression: false Stacktrace: [1] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 [2] macro expansion @ /opt/julia/share/julia/stdlib/v1.12/Test/src/Test.jl:679 [inlined] ┌ Error: parsing difference │ file = "/opt/julia/bin/../share/julia/stdlib/v1.12/Distributed/src/workerpool.jl" └ @ Main.var"##327" ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:157 false begin end try wait(x) finally put!(pool, worker) end try wait(x) catch finally put!(pool, worker) end Threads.@spawn Threads.threadpool() try wait(x) finally put!(pool, worker) end Threads.@spawn Threads.threadpool() try wait(x) catch finally put!(pool, worker) end t = Threads.@spawn(Threads.threadpool(), try wait(x) finally put!(pool, worker) end) t = Threads.@spawn(Threads.threadpool(), try wait(x) catch finally put!(pool, worker) end) begin worker = take!(pool) local x try x = rc_f(f, worker, args...; kwargs...) catch put!(pool, worker) rethrow() end t = Threads.@spawn(Threads.threadpool(), try wait(x) finally put!(pool, worker) end) errormonitor(t) return x end begin worker = take!(pool) local x try x = rc_f(f, worker, args...; kwargs...) catch put!(pool, worker) rethrow() end t = Threads.@spawn(Threads.threadpool(), try wait(x) catch finally put!(pool, worker) end) errormonitor(t) return x end function remotecall_pool(rc_f::typeof(remotecall), f, pool::AbstractWorkerPool, args...; kwargs...) worker = take!(pool) local x try x = rc_f(f, worker, args...; kwargs...) catch put!(pool, worker) rethrow() end t = Threads.@spawn(Threads.threadpool(), try wait(x) finally put!(pool, worker) end) errormonitor(t) return x end function remotecall_pool(rc_f::typeof(remotecall), f, pool::AbstractWorkerPool, args...; kwargs...) worker = take!(pool) local x try x = rc_f(f, worker, args...; kwargs...) catch put!(pool, worker) rethrow() end t = Threads.@spawn(Threads.threadpool(), try wait(x) catch finally put!(pool, worker) end) errormonitor(t) return x end false begin end try wait(x) finally put!(pool, worker) end try wait(x) catch finally put!(pool, worker) end Threads.@spawn Threads.threadpool() try wait(x) finally put!(pool, worker) end Threads.@spawn Threads.threadpool() try wait(x) catch finally put!(pool, worker) end t = Threads.@spawn(Threads.threadpool(), try wait(x) finally put!(pool, worker) end) t = Threads.@spawn(Threads.threadpool(), try wait(x) catch finally put!(pool, worker) end) begin worker = take!(pool) f_ref = get(pool.map_obj2ref, (worker, f), (f, RemoteChannel(worker))) f_ref isa Tuple && (pool.map_obj2ref[(worker, f)] = f_ref[2]) local x try x = rc_f(exec_from_cache, worker, f_ref, args...; kwargs...) catch put!(pool, worker) rethrow() end t = Threads.@spawn(Threads.threadpool(), try wait(x) finally put!(pool, worker) end) errormonitor(t) return x end begin worker = take!(pool) f_ref = get(pool.map_obj2ref, (worker, f), (f, RemoteChannel(worker))) f_ref isa Tuple && (pool.map_obj2ref[(worker, f)] = f_ref[2]) local x try x = rc_f(exec_from_cache, worker, f_ref, args...; kwargs...) catch put!(pool, worker) rethrow() end t = Threads.@spawn(Threads.threadpool(), try wait(x) catch finally put!(pool, worker) end) errormonitor(t) return x end function remotecall_pool(rc_f::typeof(remotecall), f, pool::CachingPool, args...; kwargs...) worker = take!(pool) f_ref = get(pool.map_obj2ref, (worker, f), (f, RemoteChannel(worker))) f_ref isa Tuple && (pool.map_obj2ref[(worker, f)] = f_ref[2]) local x try x = rc_f(exec_from_cache, worker, f_ref, args...; kwargs...) catch put!(pool, worker) rethrow() end t = Threads.@spawn(Threads.threadpool(), try wait(x) finally put!(pool, worker) end) errormonitor(t) return x end function remotecall_pool(rc_f::typeof(remotecall), f, pool::CachingPool, args...; kwargs...) worker = take!(pool) f_ref = get(pool.map_obj2ref, (worker, f), (f, RemoteChannel(worker))) f_ref isa Tuple && (pool.map_obj2ref[(worker, f)] = f_ref[2]) local x try x = rc_f(exec_from_cache, worker, f_ref, args...; kwargs...) catch put!(pool, worker) rethrow() end t = Threads.@spawn(Threads.threadpool(), try wait(x) catch finally put!(pool, worker) end) errormonitor(t) return x end Parsing files in Base: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 Expression: false Stacktrace: [1] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 [2] macro expansion @ /opt/julia/share/julia/stdlib/v1.12/Test/src/Test.jl:679 [inlined] Parsing files in Base: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:143 Expression: cst_err == meta_err Evaluated: true == false Stacktrace: [1] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:143 [2] macro expansion @ /opt/julia/share/julia/stdlib/v1.12/Test/src/Test.jl:679 [inlined] ┌ Error: CSTParser.parse errored, but Meta.parse didn't. │ file = "/opt/julia/bin/../share/julia/stdlib/v1.12/InteractiveUtils/src/macros.jl" └ @ Main.var"##327" ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:149 ┌ Error: parsing difference │ file = "/opt/julia/bin/../share/julia/test/core.jl" └ @ Main.var"##327" ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:157 begin 1:3 end 1:3 1:3 : begin 1:3 end 1:3 f() = begin 1:3 end f() = 1:3 for f() = begin 1:3 end push!(a, f()) push!(fs, f) end for f() = 1:3 push!(a, f()) push!(fs, f) end begin for f() = begin 1:3 end push!(a, f()) push!(fs, f) end @test a == [1, 2, 3] @test [f() for f = fs] == [1, 2, 3] end begin for f() = 1:3 push!(a, f()) push!(fs, f) end @test a == [1, 2, 3] @test [f() for f = fs] == [1, 2, 3] end let a = [], fs = [] for f() = begin 1:3 end push!(a, f()) push!(fs, f) end @test a == [1, 2, 3] @test [f() for f = fs] == [1, 2, 3] end let a = [], fs = [] for f() = 1:3 push!(a, f()) push!(fs, f) end @test a == [1, 2, 3] @test [f() for f = fs] == [1, 2, 3] end Parsing files in Base: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 Expression: false Stacktrace: [1] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 [2] macro expansion @ /opt/julia/share/julia/stdlib/v1.12/Test/src/Test.jl:679 [inlined] ┌ Error: parsing difference │ file = "/opt/julia/bin/../share/julia/test/math.jl" └ @ Main.var"##327" ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:157 prevfloat(1.0) ^ -(Int64(2)) prevfloat(1.0) ^ prevfloat prevfloat(1.0) 1.0 prevfloat(1.0) ^ -(Int64(2)) prevfloat(1.0) 62 -(Int64(2) ^ 62) (prevfloat(1.0) ^ -(Int64(2))) ^ 62 prevfloat(1.0) ^ -(Int64(2) ^ 62) (prevfloat(1.0) ^ -(Int64(2))) ^ 62 ≈ c53881 prevfloat(1.0) ^ -(Int64(2) ^ 62) ≈ c53881 @test (prevfloat(1.0) ^ -(Int64(2))) ^ 62 ≈ c53881 atol = 2 * eps(c53881) @test prevfloat(1.0) ^ -(Int64(2) ^ 62) ≈ c53881 atol = 2 * eps(c53881) begin POW_TOLS = Dict(Float16 => [0.51, 0.51, 0.51, 2.0, 1.5], Float32 => [0.51, 0.51, 0.51, 2.0, 1.5], Float64 => [0.55, 0.8, 1.5, 2.0, 1.5]) for T = (Float16, Float32, Float64) for x = (0.0, -0.0, 1.0, 10.0, 2.0, Inf, NaN, -Inf, -NaN) for y = (0.0, -0.0, 1.0, -3.0, -10.0, Inf, NaN, -Inf, -NaN) (got, expected) = (T(x) ^ T(y), T(big(x) ^ T(y))) if isnan(expected) @test isnan_type(T, got) || T.((x, y)) else @test got == expected || T.((x, y)) end end end for _ = 1:2 ^ 16 x = rand(T) * 100 y = rand(T) * 200 - 100 (got, expected) = (x ^ y, widen(x) ^ y) if isfinite(eps(T(expected))) if y == T(-2) @test abs(expected - got) <= (POW_TOLS[T])[4] * eps(T(expected)) || (x, y) elseif y == T(3) @test abs(expected - got) <= (POW_TOLS[T])[5] * eps(T(expected)) || (x, y) elseif issubnormal(got) @test abs(expected - got) <= (POW_TOLS[T])[2] * eps(T(expected)) || (x, y) else @test abs(expected - got) <= (POW_TOLS[T])[1] * eps(T(expected)) || (x, y) end end end for _ = 1:2 ^ 14 x = rand(T) * floatmin(T) y = rand(T) * 3 - T(1.2) (got, expected) = (x ^ y, widen(x) ^ y) if isfinite(eps(T(expected))) @test abs(expected - got) <= (POW_TOLS[T])[3] * eps(T(expected)) || (x, y) end end @test T(-1) ^ floatmax(T) === T(1) @test prevfloat(T(-1)) ^ floatmax(T) === T(Inf) @test nextfloat(T(-1)) ^ floatmax(T) === T(0.0) end @test 0.9999999955206014 ^ -1.0e8 == 1.565084574870928 @test 3.0e18 ^ 20 == Inf @test 0.0013653274095082324 ^ -97.60372292227069 == 4.088393948750035e279 @test 8.758520413376658e-5 ^ 70.55863059215994 == 5.052076767078296e-287 c53881 = 2.2844135865398217e222 @test (prevfloat(1.0) ^ -(Int64(2))) ^ 62 ≈ c53881 atol = 2 * eps(c53881) @test 2.0 ^ typemin(Int) == 0.0 @test (-1.0) ^ typemin(Int) == 1.0 Z = Int64(2) E = prevfloat(1.0) @test E ^ -(Z ^ 54) ≈ 7.38905609893065 @test E ^ -(Z ^ 62) ≈ 2.2844135865231613e222 @test E ^ -(Z ^ 63) == Inf @test abs(E ^ (Z ^ 62 - 1) * E ^ (-(Z ^ 62) + 1) - 1) <= eps(1.0) (n, x) = (-1065564664, 0.9999997040311492) @test abs(x ^ n - Float64(big(x) ^ n)) / eps(x ^ n) == 0 @test E ^ (big(2) ^ 100 + 1) == 0 @test E ^ 6705320061009595392 == nextfloat(0.0) n = Int64(1024 / log2(E)) @test E ^ n == Inf @test E ^ float(n) == Inf @testset "literal pow zero sign" begin @testset "T: $(T)" for T = (Float16, Float32, Float64, BigFloat) @testset "literal `-1`" begin @test -0.0 === Float64(T(-Inf) ^ -1) end @testset "`Int(-1)`" begin @test -0.0 === Float64(T(-Inf) ^ Int(-1)) end end end struct Issue55633_1 <: Number end struct Issue55633_3 <: Number end struct Issue55633_9 <: Number end Base.one(::Issue55633_3) = begin Issue55633_1() end Base.:*(::Issue55633_3, ::Issue55633_3) = begin Issue55633_9() end Base.promote_rule(::Type{Issue55633_1}, ::Type{Issue55633_3}) = begin Int end Base.promote_rule(::Type{Issue55633_3}, ::Type{Issue55633_9}) = begin Int end Base.promote_rule(::Type{Issue55633_1}, ::Type{Issue55633_9}) = begin Int end Base.promote_rule(::Type{Issue55633_1}, ::Type{Int}) = begin Int end Base.promote_rule(::Type{Issue55633_3}, ::Type{Int}) = begin Int end Base.promote_rule(::Type{Issue55633_9}, ::Type{Int}) = begin Int end Base.convert(::Type{Int}, ::Issue55633_1) = begin 1 end Base.convert(::Type{Int}, ::Issue55633_3) = begin 3 end Base.convert(::Type{Int}, ::Issue55633_9) = begin 9 end for x = (im, pi, Issue55633_3()) p = promote(one(x), x, x * x) for y = 0:2 @test all((t->begin (===)(t...) end), zip(x ^ y, p[y + 1])) end end end begin POW_TOLS = Dict(Float16 => [0.51, 0.51, 0.51, 2.0, 1.5], Float32 => [0.51, 0.51, 0.51, 2.0, 1.5], Float64 => [0.55, 0.8, 1.5, 2.0, 1.5]) for T = (Float16, Float32, Float64) for x = (0.0, -0.0, 1.0, 10.0, 2.0, Inf, NaN, -Inf, -NaN) for y = (0.0, -0.0, 1.0, -3.0, -10.0, Inf, NaN, -Inf, -NaN) (got, expected) = (T(x) ^ T(y), T(big(x) ^ T(y))) if isnan(expected) @test isnan_type(T, got) || T.((x, y)) else @test got == expected || T.((x, y)) end end end for _ = 1:2 ^ 16 x = rand(T) * 100 y = rand(T) * 200 - 100 (got, expected) = (x ^ y, widen(x) ^ y) if isfinite(eps(T(expected))) if y == T(-2) @test abs(expected - got) <= (POW_TOLS[T])[4] * eps(T(expected)) || (x, y) elseif y == T(3) @test abs(expected - got) <= (POW_TOLS[T])[5] * eps(T(expected)) || (x, y) elseif issubnormal(got) @test abs(expected - got) <= (POW_TOLS[T])[2] * eps(T(expected)) || (x, y) else @test abs(expected - got) <= (POW_TOLS[T])[1] * eps(T(expected)) || (x, y) end end end for _ = 1:2 ^ 14 x = rand(T) * floatmin(T) y = rand(T) * 3 - T(1.2) (got, expected) = (x ^ y, widen(x) ^ y) if isfinite(eps(T(expected))) @test abs(expected - got) <= (POW_TOLS[T])[3] * eps(T(expected)) || (x, y) end end @test T(-1) ^ floatmax(T) === T(1) @test prevfloat(T(-1)) ^ floatmax(T) === T(Inf) @test nextfloat(T(-1)) ^ floatmax(T) === T(0.0) end @test 0.9999999955206014 ^ -1.0e8 == 1.565084574870928 @test 3.0e18 ^ 20 == Inf @test 0.0013653274095082324 ^ -97.60372292227069 == 4.088393948750035e279 @test 8.758520413376658e-5 ^ 70.55863059215994 == 5.052076767078296e-287 c53881 = 2.2844135865398217e222 @test prevfloat(1.0) ^ -(Int64(2) ^ 62) ≈ c53881 atol = 2 * eps(c53881) @test 2.0 ^ typemin(Int) == 0.0 @test (-1.0) ^ typemin(Int) == 1.0 Z = Int64(2) E = prevfloat(1.0) @test E ^ -(Z ^ 54) ≈ 7.38905609893065 @test E ^ -(Z ^ 62) ≈ 2.2844135865231613e222 @test E ^ -(Z ^ 63) == Inf @test abs(E ^ (Z ^ 62 - 1) * E ^ (-(Z ^ 62) + 1) - 1) <= eps(1.0) (n, x) = (-1065564664, 0.9999997040311492) @test abs(x ^ n - Float64(big(x) ^ n)) / eps(x ^ n) == 0 @test E ^ (big(2) ^ 100 + 1) == 0 @test E ^ 6705320061009595392 == nextfloat(0.0) n = Int64(1024 / log2(E)) @test E ^ n == Inf @test E ^ float(n) == Inf @testset "literal pow zero sign" begin @testset "T: $(T)" for T = (Float16, Float32, Float64, BigFloat) @testset "literal `-1`" begin @test -0.0 === Float64(T(-Inf) ^ -1) end @testset "`Int(-1)`" begin @test -0.0 === Float64(T(-Inf) ^ Int(-1)) end end end struct Issue55633_1 <: Number end struct Issue55633_3 <: Number end struct Issue55633_9 <: Number end Base.one(::Issue55633_3) = begin Issue55633_1() end Base.:*(::Issue55633_3, ::Issue55633_3) = begin Issue55633_9() end Base.promote_rule(::Type{Issue55633_1}, ::Type{Issue55633_3}) = begin Int end Base.promote_rule(::Type{Issue55633_3}, ::Type{Issue55633_9}) = begin Int end Base.promote_rule(::Type{Issue55633_1}, ::Type{Issue55633_9}) = begin Int end Base.promote_rule(::Type{Issue55633_1}, ::Type{Int}) = begin Int end Base.promote_rule(::Type{Issue55633_3}, ::Type{Int}) = begin Int end Base.promote_rule(::Type{Issue55633_9}, ::Type{Int}) = begin Int end Base.convert(::Type{Int}, ::Issue55633_1) = begin 1 end Base.convert(::Type{Int}, ::Issue55633_3) = begin 3 end Base.convert(::Type{Int}, ::Issue55633_9) = begin 9 end for x = (im, pi, Issue55633_3()) p = promote(one(x), x, x * x) for y = 0:2 @test all((t->begin (===)(t...) end), zip(x ^ y, p[y + 1])) end end end @testset "pow" begin POW_TOLS = Dict(Float16 => [0.51, 0.51, 0.51, 2.0, 1.5], Float32 => [0.51, 0.51, 0.51, 2.0, 1.5], Float64 => [0.55, 0.8, 1.5, 2.0, 1.5]) for T = (Float16, Float32, Float64) for x = (0.0, -0.0, 1.0, 10.0, 2.0, Inf, NaN, -Inf, -NaN) for y = (0.0, -0.0, 1.0, -3.0, -10.0, Inf, NaN, -Inf, -NaN) (got, expected) = (T(x) ^ T(y), T(big(x) ^ T(y))) if isnan(expected) @test isnan_type(T, got) || T.((x, y)) else @test got == expected || T.((x, y)) end end end for _ = 1:2 ^ 16 x = rand(T) * 100 y = rand(T) * 200 - 100 (got, expected) = (x ^ y, widen(x) ^ y) if isfinite(eps(T(expected))) if y == T(-2) @test abs(expected - got) <= (POW_TOLS[T])[4] * eps(T(expected)) || (x, y) elseif y == T(3) @test abs(expected - got) <= (POW_TOLS[T])[5] * eps(T(expected)) || (x, y) elseif issubnormal(got) @test abs(expected - got) <= (POW_TOLS[T])[2] * eps(T(expected)) || (x, y) else @test abs(expected - got) <= (POW_TOLS[T])[1] * eps(T(expected)) || (x, y) end end end for _ = 1:2 ^ 14 x = rand(T) * floatmin(T) y = rand(T) * 3 - T(1.2) (got, expected) = (x ^ y, widen(x) ^ y) if isfinite(eps(T(expected))) @test abs(expected - got) <= (POW_TOLS[T])[3] * eps(T(expected)) || (x, y) end end @test T(-1) ^ floatmax(T) === T(1) @test prevfloat(T(-1)) ^ floatmax(T) === T(Inf) @test nextfloat(T(-1)) ^ floatmax(T) === T(0.0) end @test 0.9999999955206014 ^ -1.0e8 == 1.565084574870928 @test 3.0e18 ^ 20 == Inf @test 0.0013653274095082324 ^ -97.60372292227069 == 4.088393948750035e279 @test 8.758520413376658e-5 ^ 70.55863059215994 == 5.052076767078296e-287 c53881 = 2.2844135865398217e222 @test (prevfloat(1.0) ^ -(Int64(2))) ^ 62 ≈ c53881 atol = 2 * eps(c53881) @test 2.0 ^ typemin(Int) == 0.0 @test (-1.0) ^ typemin(Int) == 1.0 Z = Int64(2) E = prevfloat(1.0) @test E ^ -(Z ^ 54) ≈ 7.38905609893065 @test E ^ -(Z ^ 62) ≈ 2.2844135865231613e222 @test E ^ -(Z ^ 63) == Inf @test abs(E ^ (Z ^ 62 - 1) * E ^ (-(Z ^ 62) + 1) - 1) <= eps(1.0) (n, x) = (-1065564664, 0.9999997040311492) @test abs(x ^ n - Float64(big(x) ^ n)) / eps(x ^ n) == 0 @test E ^ (big(2) ^ 100 + 1) == 0 @test E ^ 6705320061009595392 == nextfloat(0.0) n = Int64(1024 / log2(E)) @test E ^ n == Inf @test E ^ float(n) == Inf @testset "literal pow zero sign" begin @testset "T: $(T)" for T = (Float16, Float32, Float64, BigFloat) @testset "literal `-1`" begin @test -0.0 === Float64(T(-Inf) ^ -1) end @testset "`Int(-1)`" begin @test -0.0 === Float64(T(-Inf) ^ Int(-1)) end end end struct Issue55633_1 <: Number end struct Issue55633_3 <: Number end struct Issue55633_9 <: Number end Base.one(::Issue55633_3) = begin Issue55633_1() end Base.:*(::Issue55633_3, ::Issue55633_3) = begin Issue55633_9() end Base.promote_rule(::Type{Issue55633_1}, ::Type{Issue55633_3}) = begin Int end Base.promote_rule(::Type{Issue55633_3}, ::Type{Issue55633_9}) = begin Int end Base.promote_rule(::Type{Issue55633_1}, ::Type{Issue55633_9}) = begin Int end Base.promote_rule(::Type{Issue55633_1}, ::Type{Int}) = begin Int end Base.promote_rule(::Type{Issue55633_3}, ::Type{Int}) = begin Int end Base.promote_rule(::Type{Issue55633_9}, ::Type{Int}) = begin Int end Base.convert(::Type{Int}, ::Issue55633_1) = begin 1 end Base.convert(::Type{Int}, ::Issue55633_3) = begin 3 end Base.convert(::Type{Int}, ::Issue55633_9) = begin 9 end for x = (im, pi, Issue55633_3()) p = promote(one(x), x, x * x) for y = 0:2 @test all((t->begin (===)(t...) end), zip(x ^ y, p[y + 1])) end end end @testset "pow" begin POW_TOLS = Dict(Float16 => [0.51, 0.51, 0.51, 2.0, 1.5], Float32 => [0.51, 0.51, 0.51, 2.0, 1.5], Float64 => [0.55, 0.8, 1.5, 2.0, 1.5]) for T = (Float16, Float32, Float64) for x = (0.0, -0.0, 1.0, 10.0, 2.0, Inf, NaN, -Inf, -NaN) for y = (0.0, -0.0, 1.0, -3.0, -10.0, Inf, NaN, -Inf, -NaN) (got, expected) = (T(x) ^ T(y), T(big(x) ^ T(y))) if isnan(expected) @test isnan_type(T, got) || T.((x, y)) else @test got == expected || T.((x, y)) end end end for _ = 1:2 ^ 16 x = rand(T) * 100 y = rand(T) * 200 - 100 (got, expected) = (x ^ y, widen(x) ^ y) if isfinite(eps(T(expected))) if y == T(-2) @test abs(expected - got) <= (POW_TOLS[T])[4] * eps(T(expected)) || (x, y) elseif y == T(3) @test abs(expected - got) <= (POW_TOLS[T])[5] * eps(T(expected)) || (x, y) elseif issubnormal(got) @test abs(expected - got) <= (POW_TOLS[T])[2] * eps(T(expected)) || (x, y) else @test abs(expected - got) <= (POW_TOLS[T])[1] * eps(T(expected)) || (x, y) end end end for _ = 1:2 ^ 14 x = rand(T) * floatmin(T) y = rand(T) * 3 - T(1.2) (got, expected) = (x ^ y, widen(x) ^ y) if isfinite(eps(T(expected))) @test abs(expected - got) <= (POW_TOLS[T])[3] * eps(T(expected)) || (x, y) end end @test T(-1) ^ floatmax(T) === T(1) @test prevfloat(T(-1)) ^ floatmax(T) === T(Inf) @test nextfloat(T(-1)) ^ floatmax(T) === T(0.0) end @test 0.9999999955206014 ^ -1.0e8 == 1.565084574870928 @test 3.0e18 ^ 20 == Inf @test 0.0013653274095082324 ^ -97.60372292227069 == 4.088393948750035e279 @test 8.758520413376658e-5 ^ 70.55863059215994 == 5.052076767078296e-287 c53881 = 2.2844135865398217e222 @test prevfloat(1.0) ^ -(Int64(2) ^ 62) ≈ c53881 atol = 2 * eps(c53881) @test 2.0 ^ typemin(Int) == 0.0 @test (-1.0) ^ typemin(Int) == 1.0 Z = Int64(2) E = prevfloat(1.0) @test E ^ -(Z ^ 54) ≈ 7.38905609893065 @test E ^ -(Z ^ 62) ≈ 2.2844135865231613e222 @test E ^ -(Z ^ 63) == Inf @test abs(E ^ (Z ^ 62 - 1) * E ^ (-(Z ^ 62) + 1) - 1) <= eps(1.0) (n, x) = (-1065564664, 0.9999997040311492) @test abs(x ^ n - Float64(big(x) ^ n)) / eps(x ^ n) == 0 @test E ^ (big(2) ^ 100 + 1) == 0 @test E ^ 6705320061009595392 == nextfloat(0.0) n = Int64(1024 / log2(E)) @test E ^ n == Inf @test E ^ float(n) == Inf @testset "literal pow zero sign" begin @testset "T: $(T)" for T = (Float16, Float32, Float64, BigFloat) @testset "literal `-1`" begin @test -0.0 === Float64(T(-Inf) ^ -1) end @testset "`Int(-1)`" begin @test -0.0 === Float64(T(-Inf) ^ Int(-1)) end end end struct Issue55633_1 <: Number end struct Issue55633_3 <: Number end struct Issue55633_9 <: Number end Base.one(::Issue55633_3) = begin Issue55633_1() end Base.:*(::Issue55633_3, ::Issue55633_3) = begin Issue55633_9() end Base.promote_rule(::Type{Issue55633_1}, ::Type{Issue55633_3}) = begin Int end Base.promote_rule(::Type{Issue55633_3}, ::Type{Issue55633_9}) = begin Int end Base.promote_rule(::Type{Issue55633_1}, ::Type{Issue55633_9}) = begin Int end Base.promote_rule(::Type{Issue55633_1}, ::Type{Int}) = begin Int end Base.promote_rule(::Type{Issue55633_3}, ::Type{Int}) = begin Int end Base.promote_rule(::Type{Issue55633_9}, ::Type{Int}) = begin Int end Base.convert(::Type{Int}, ::Issue55633_1) = begin 1 end Base.convert(::Type{Int}, ::Issue55633_3) = begin 3 end Base.convert(::Type{Int}, ::Issue55633_9) = begin 9 end for x = (im, pi, Issue55633_3()) p = promote(one(x), x, x * x) for y = 0:2 @test all((t->begin (===)(t...) end), zip(x ^ y, p[y + 1])) end end end Parsing files in Base: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 Expression: false Stacktrace: [1] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 [2] macro expansion @ /opt/julia/share/julia/stdlib/v1.12/Test/src/Test.jl:679 [inlined] ┌ Error: parsing difference │ file = "/opt/julia/bin/../share/julia/test/scopedvalues.jl" └ @ Main.var"##327" ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:157 false begin end try @with begin return end finally push!(ts, 2) end try @with begin return end catch err finally push!(ts, 2) end begin ts = Int[] try @with begin return end finally push!(ts, 2) end end begin ts = Int[] try @with begin return end catch err finally push!(ts, 2) end end @testset "issue #56062" begin ts = Int[] try @with begin return end finally push!(ts, 2) end end @testset "issue #56062" begin ts = Int[] try @with begin return end catch err finally push!(ts, 2) end end Parsing files in Base: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 Expression: false Stacktrace: [1] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 [2] macro expansion @ /opt/julia/share/julia/stdlib/v1.12/Test/src/Test.jl:679 [inlined] ┌ Error: parsing difference │ file = "/opt/julia/bin/../share/julia/test/syntax.jl" └ @ Main.var"##327" ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:157 `` QualifiedStringMacro.SubModule.@y_cmd "" QualifiedStringMacro.SubModule.@y_cmd `` QualifiedStringMacro.SubModule.@y_cmd("") === 2 QualifiedStringMacro.SubModule.@y_cmd(``) === 2 @test QualifiedStringMacro.SubModule.@y_cmd("") === 2 @test QualifiedStringMacro.SubModule.@y_cmd(``) === 2 begin x kw... end (x,; kw...) x $(Expr(:parameters, :(kw...))) kw... x begin x kw... end (x,; kw...) function x, kw... return (x, kw) end function (x,; kw...) return (x, kw) end f = function x, kw... return (x, kw) end f = function (x,; kw...) return (x, kw) end begin x a = 2 end (x,; a = 2) x $(Expr(:parameters, :($(Expr(:kw, :a, 2))))) a = 2 x begin x a = 2 end (x,; a = 2) function x, a = 2 return (x, a) end function (x,; a = 2) return (x, a) end g = function x, a = 2 return (x, a) end g = function (x,; a = 2) return (x, a) end begin f = function x, kw... return (x, kw) end g = function x, a = 2 return (x, a) end end begin f = function (x,; kw...) return (x, kw) end g = function (x,; a = 2) return (x, a) end end let f = function x, kw... return (x, kw) end, g = function x, a = 2 return (x, a) end @test f(1) == (1, pairs(NamedTuple())) @test g(1) == (1, 2) end let f = function (x,; kw...) return (x, kw) end, g = function (x,; a = 2) return (x, a) end @test f(1) == (1, pairs(NamedTuple())) @test g(1) == (1, 2) end begin 1:3 end 1:3 1:3 : begin 1:3 end 1:3 outer $ i = begin 1:3 end outer $ i = 1:3 for outer $ i = begin 1:3 end @test 1 $ 2 in 1:3 end for outer $ i = 1:3 @test 1 $ 2 in 1:3 end begin @test remove_linenums!(:(for $(Expr(:outer, :i)) = 1:3 end)) == Expr(:for, Expr(:(=), Expr(:outer, :i), :(1:3)), quote end) i = :i @test remove_linenums!(:(for $(Expr(:outer, :($(Expr(:$, :i))))) = 1:3 end)) == Expr(:for, Expr(:(=), Expr(:outer, :i), :(1:3)), quote end) @test remove_linenums!(:(for outer = 1:3 end)) == Expr(:for, Expr(:(=), :outer, :(1:3)), quote end) for outer $ i = begin 1:3 end @test 1 $ 2 in 1:3 end @test Meta.isexpr(Meta.parse("[i for i\nin 1:3]"), :comprehension) @test Meta.isexpr(Meta.parse("[i for outer\nin 1:3]"), :comprehension) @test Meta.isexpr(Meta.parse("[i for outer\ni in 1:3]"), :comprehension) @test Meta.isexpr((Meta.parse("f(i for i\nin 1:3)")).args[2], :generator) @test_parseerror "for i\n in 1:3\nend" end begin @test remove_linenums!(:(for $(Expr(:outer, :i)) = 1:3 end)) == Expr(:for, Expr(:(=), Expr(:outer, :i), :(1:3)), quote end) i = :i @test remove_linenums!(:(for $(Expr(:outer, :($(Expr(:$, :i))))) = 1:3 end)) == Expr(:for, Expr(:(=), Expr(:outer, :i), :(1:3)), quote end) @test remove_linenums!(:(for outer = 1:3 end)) == Expr(:for, Expr(:(=), :outer, :(1:3)), quote end) for outer $ i = 1:3 @test 1 $ 2 in 1:3 end @test Meta.isexpr(Meta.parse("[i for i\nin 1:3]"), :comprehension) @test Meta.isexpr(Meta.parse("[i for outer\nin 1:3]"), :comprehension) @test Meta.isexpr(Meta.parse("[i for outer\ni in 1:3]"), :comprehension) @test Meta.isexpr((Meta.parse("f(i for i\nin 1:3)")).args[2], :generator) @test_parseerror "for i\n in 1:3\nend" end @testset "issue #37393" begin @test remove_linenums!(:(for $(Expr(:outer, :i)) = 1:3 end)) == Expr(:for, Expr(:(=), Expr(:outer, :i), :(1:3)), quote end) i = :i @test remove_linenums!(:(for $(Expr(:outer, :($(Expr(:$, :i))))) = 1:3 end)) == Expr(:for, Expr(:(=), Expr(:outer, :i), :(1:3)), quote end) @test remove_linenums!(:(for outer = 1:3 end)) == Expr(:for, Expr(:(=), :outer, :(1:3)), quote end) for outer $ i = begin 1:3 end @test 1 $ 2 in 1:3 end @test Meta.isexpr(Meta.parse("[i for i\nin 1:3]"), :comprehension) @test Meta.isexpr(Meta.parse("[i for outer\nin 1:3]"), :comprehension) @test Meta.isexpr(Meta.parse("[i for outer\ni in 1:3]"), :comprehension) @test Meta.isexpr((Meta.parse("f(i for i\nin 1:3)")).args[2], :generator) @test_parseerror "for i\n in 1:3\nend" end @testset "issue #37393" begin @test remove_linenums!(:(for $(Expr(:outer, :i)) = 1:3 end)) == Expr(:for, Expr(:(=), Expr(:outer, :i), :(1:3)), quote end) i = :i @test remove_linenums!(:(for $(Expr(:outer, :($(Expr(:$, :i))))) = 1:3 end)) == Expr(:for, Expr(:(=), Expr(:outer, :i), :(1:3)), quote end) @test remove_linenums!(:(for outer = 1:3 end)) == Expr(:for, Expr(:(=), :outer, :(1:3)), quote end) for outer $ i = 1:3 @test 1 $ 2 in 1:3 end @test Meta.isexpr(Meta.parse("[i for i\nin 1:3]"), :comprehension) @test Meta.isexpr(Meta.parse("[i for outer\nin 1:3]"), :comprehension) @test Meta.isexpr(Meta.parse("[i for outer\ni in 1:3]"), :comprehension) @test Meta.isexpr((Meta.parse("f(i for i\nin 1:3)")).args[2], :generator) @test_parseerror "for i\n in 1:3\nend" end a => (b = 2) a => b = begin 2 end => a => b a begin 2 end a => (b = 2) a => b = begin 2 end @eval a => (b = 2) @eval a => b = begin 2 end @test_throws ErrorException @eval(a => (b = 2)) @test_throws ErrorException @eval(a => b = begin 2 end) a => (b = 2) a => b = begin 2 end => a => b a begin 2 end a => (b = 2) a => b = begin 2 end @eval a => (b = 2) @eval a => b = begin 2 end @test_throws "function Base.=> must be explicitly imported to be extended" @eval(a => (b = 2)) @test_throws "function Base.=> must be explicitly imported to be extended" @eval(a => b = begin 2 end) begin @test_throws ErrorException @eval(a => (b = 2)) @test_throws "function Base.=> must be explicitly imported to be extended" @eval(a => (b = 2)) end begin @test_throws ErrorException @eval(a => b = begin 2 end) @test_throws "function Base.=> must be explicitly imported to be extended" @eval(a => b = begin 2 end) end let x = 1 => 2 @test_throws ErrorException @eval(a => (b = 2)) @test_throws "function Base.=> must be explicitly imported to be extended" @eval(a => (b = 2)) end let x = 1 => 2 @test_throws ErrorException @eval(a => b = begin 2 end) @test_throws "function Base.=> must be explicitly imported to be extended" @eval(a => b = begin 2 end) end Parsing files in Base: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 Expression: false Stacktrace: [1] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/test_check_base.jl:166 [2] macro expansion @ /opt/julia/share/julia/stdlib/v1.12/Test/src/Test.jl:679 [inlined] Mismatch between flisp and CSTParser when parsing string for outer $ i = 1:3 end ParserState: ParseState at 23 last : INTEGER (1,19-1,19 INTEGER ) (ws) current : END (1,21-1,23 KEYWORD ) (empty) next : ENDMARKER (1,24-1,23 ENDMARKER ) (empty) CSTParser Expr: 1:23 for 1:16 1:2 OP: = 1:10 call 1:2 OP: $ 3:8 outer 9:10 i 11:14 block 11:14 call 11:11 OP: : 12:12 INTEGER: 1 13:14 INTEGER: 3 17:16 block Converted CSTParser Expr: for outer $ i = begin 1:3 end end Base EXPR: for outer $ i = 1:3 end for outer parsing: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/parser/test_keyword_blocks.jl:154 Expression: "for outer \$ i = 1:3 end" |> test_expr Stacktrace: [1] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/parser/test_keyword_blocks.jl:150 [2] macro expansion @ /opt/julia/share/julia/stdlib/v1.12/Test/src/Test.jl:1771 [inlined] [3] macro expansion @ ~/.julia/packages/CSTParser/0hXvH/test/parser/test_keyword_blocks.jl:154 [inlined] [4] macro expansion @ /opt/julia/share/julia/stdlib/v1.12/Test/src/Test.jl:679 [inlined] :kw: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/shared.jl:37 Expression: to_codeobject(x) == jl_parse(s) Evaluated: f(::typeof(a) = begin 1 end) == f(::typeof(a) = 1) Stacktrace: [1] macro expansion @ /opt/julia/share/julia/stdlib/v1.12/Test/src/Test.jl:679 [inlined] [2] test_expr(s::String, head::Symbol, n::Int64, endswithtrivia::Bool) @ Main.var"##368" ~/.julia/packages/CSTParser/0hXvH/test/shared.jl:37 [ Info: checking check_err_parse against ../docs/make.jl [ Info: checking check_err_parse against ../src/CSTParser.jl [ Info: checking check_err_parse against ../src/conversion.jl [ Info: checking check_err_parse against ../src/display.jl [ Info: checking check_err_parse against ../src/interface.jl [ Info: checking check_err_parse against ../src/iterate.jl [ Info: checking check_err_parse against ../src/lexer.jl [ Info: checking check_err_parse against ../src/packagedef.jl [ Info: checking check_err_parse against ../src/precompile.jl [ Info: checking check_err_parse against ../src/recovery.jl [ Info: checking check_err_parse against ../src/spec.jl [ Info: checking check_err_parse against ../src/utils.jl [ Info: checking check_err_parse against ../src/components/internals.jl [ Info: checking check_err_parse against ../src/components/keywords.jl [ Info: checking check_err_parse against ../src/components/lists.jl [ Info: checking check_err_parse against ../src/components/operators.jl [ Info: checking check_err_parse against ../src/components/strings.jl [ Info: checking check_err_parse against ../test/runtests.jl [ Info: checking check_err_parse against ../test/shared.jl [ Info: checking check_err_parse against ../test/test_check_base.jl [ Info: checking check_err_parse against ../test/test_display.jl [ Info: checking check_err_parse against ../test/test_errparse.jl [ Info: checking check_err_parse against ../test/test_interface.jl [ Info: checking check_err_parse against ../test/test_spec.jl [ Info: checking check_err_parse against ../test/iterate/test_iterators.jl [ Info: checking check_err_parse against ../test/iterate/test_selftest.jl [ Info: checking check_err_parse against ../test/parser/test_function_calls.jl [ Info: checking check_err_parse against ../test/parser/test_keyword_blocks.jl [ Info: checking check_err_parse against ../test/parser/test_modules.jl [ Info: checking check_err_parse against ../test/parser/test_operators.jl [ Info: checking check_err_parse against ../test/parser/test_parser.jl [ Info: checking check_err_parse against ../test/parser/test_square.jl [ Info: checking check_err_parse against ../test/parser/test_types.jl [ Info: checking check_reparse against ../docs/make.jl [ Info: checking check_reparse against ../src/CSTParser.jl [ Info: checking check_reparse against ../src/conversion.jl [ Info: checking check_reparse against ../src/display.jl [ Info: checking check_reparse against ../src/interface.jl [ Info: checking check_reparse against ../src/iterate.jl [ Info: checking check_reparse against ../src/lexer.jl [ Info: checking check_reparse against ../src/packagedef.jl [ Info: checking check_reparse against ../src/precompile.jl [ Info: checking check_reparse against ../src/recovery.jl [ Info: checking check_reparse against ../src/spec.jl [ Info: checking check_reparse against ../src/utils.jl [ Info: checking check_reparse against ../src/components/internals.jl [ Info: checking check_reparse against ../src/components/keywords.jl [ Info: checking check_reparse against ../src/components/lists.jl [ Info: checking check_reparse against ../src/components/operators.jl [ Info: checking check_reparse against ../src/components/strings.jl [ Info: checking check_reparse against ../test/runtests.jl [ Info: checking check_reparse against ../test/shared.jl [ Info: checking check_reparse against ../test/test_check_base.jl [ Info: checking check_reparse against ../test/test_display.jl [ Info: checking check_reparse against ../test/test_errparse.jl [ Info: checking check_reparse against ../test/test_interface.jl [ Info: checking check_reparse against ../test/test_spec.jl [ Info: checking check_reparse against ../test/iterate/test_iterators.jl [ Info: checking check_reparse against ../test/iterate/test_selftest.jl [ Info: checking check_reparse against ../test/parser/test_function_calls.jl [ Info: checking check_reparse against ../test/parser/test_keyword_blocks.jl [ Info: checking check_reparse against ../test/parser/test_modules.jl [ Info: checking check_reparse against ../test/parser/test_operators.jl [ Info: checking check_reparse against ../test/parser/test_parser.jl [ Info: checking check_reparse against ../test/parser/test_square.jl [ Info: checking check_reparse against ../test/parser/test_types.jl Mismatch between flisp and CSTParser when parsing string a.{1} ParserState: ParseState at 5 last : INTEGER (1,4-1,4 INTEGER ) (empty) current : RBRACE (1,5-1,5 RBRACE ) (empty) next : ENDMARKER (1,6-1,5 ENDMARKER ) (empty) CSTParser Expr: 1:5 1:1 OP: . 1:1 a 2:4 quote 2:4 braces 2:2 INTEGER: 1 Converted CSTParser Expr: a.:({1}) Base EXPR: a.:({1}) No longer broken things: Test Failed at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/parser/test_parser.jl:354 Expression: "a.{1}" |> test_expr Stacktrace: [1] top-level scope @ ~/.julia/packages/CSTParser/0hXvH/test/parser/test_parser.jl:515 [2] macro expansion @ /opt/julia/share/julia/stdlib/v1.12/Test/src/Test.jl:679 [inlined] Test Summary: | Pass Fail Broken Total Time Package | 149505 10 2 149517 4m02.1s test/iterate/test_iterators.jl | 500 500 30.3s test/test_display.jl | 1 1 0.1s test/test_check_base.jl | 4656 7 4663 51.6s Parsing files in Base | 4656 7 4663 51.6s test/parser/test_operators.jl | 2116 1 2117 5.7s test/parser/test_square.jl | 1322 1322 5.8s test/test_interface.jl | 48 48 0.9s test/parser/test_keyword_blocks.jl | 1241 1 1242 3.8s If | 326 326 0.6s Try | 510 510 0.6s For | 210 1 211 1.2s for outer parsing | 123 1 124 0.4s Let | 85 85 0.7s Do | 110 110 0.6s test/parser/test_types.jl | 495 495 1.9s test/test_spec.jl | 2890 1 2891 24.4s :local | 12 12 0.7s :global | 106 106 0.7s :const | 41 41 0.7s :return | 12 12 0.7s :abstract | 16 16 0.7s :primitive | 18 18 0.7s :call | 48 48 0.7s :brackets | 14 14 0.7s :begin | 180 180 0.7s :export | 28 28 0.7s :import | 169 169 0.7s :kw | 228 1 229 0.7s :tuple | 82 82 0.7s :curly | 36 36 0.7s operators | 422 422 0.9s :parameters | 27 27 0.6s lists :vect | 58 58 0.7s lists :vcat | 100 100 0.7s lists :hcat | 16 16 0.7s lists :ref | 36 36 0.7s lists :typed_hcat | 18 18 0.7s lists :typed_vcat | 18 18 0.7s :let | 73 73 0.7s :try | 222 222 0.7s :macrocall | 42 42 0.6s :if | 178 178 0.7s :do | 66 66 0.7s strings | 30 30 0.7s :string | 48 48 0.7s :for | 105 105 0.7s docs | 16 16 0.7s :generator | 291 291 0.7s :cmd | 29 29 0.6s macrocall | 68 68 1.0s _str | 37 37 0.7s test/iterate/test_selftest.jl | 118205 118205 0.5s test/test_errparse.jl | 298 298 1m22.2s test/parser/test_function_calls.jl | 904 904 3.3s test/parser/test_modules.jl | 247 247 1.3s test/parser/test_parser.jl | 16582 1 1 16584 30.2s Parser | 1 1 0.1s Type Annotations Curly | 202 202 0.7s Tuples | 207 207 0.7s Generators | 1036 1036 0.7s Macros | 576 576 0.7s Triple-quoted string | 81 81 0.7s raw strings with unicode | 34 34 0.6s weird string edge cases | 1073 1073 0.9s No longer broken things | 3652 1 3653 0.9s interpolation error catching | 4 4 0.1s string interpolation | 184 184 0.6s string whitespace handling | 36 36 0.6s cmd interpolation | 57 57 0.6s multiple ; in kwargs | 273 273 0.6s Broken things | 32 1 33 0.6s Spans | 0 0.1s Command or string with unicode | 18 18 0.6s conversion of floats with underscore | 6 6 0.5s errors | 9 9 0.1s colons | 84 84 0.6s tuple params | 122 122 0.7s docs | 230 230 0.7s braces | 130 130 0.6s import preceding dot whitespace | 48 48 0.6s issue #116 | 74 74 0.6s issue #165 | 2 2 0.1s issue #182 | 1 1 0.1s issue #198 | 12 12 0.6s vscode issue #1632 | 36 36 0.7s issue #210 | 32 32 0.7s suffixed ops | 36 36 0.6s import .. as .. syntax | 155 155 0.7s exor #201 | 17 17 0.6s @var #236 | 15 15 0.6s nonstandard identifier (var"blah") parsing | 69 69 0.6s bad uint | 1 1 0.1s endswithtrivia | 2 2 0.1s bad interp with following newline | 1 1 0.1s minimal_reparse | 1 1 0.1s primes | 129 129 0.6s end as id juxt | 52 52 0.7s last child is trivia for :string | 1 1 0.1s toplevel strings | 17 17 0.6s @doc cont | 32 32 0.7s char escape | 6117 6117 0.8s invalid char in string | 1 1 0.1s string macros | 91 91 0.6s number parsing | 462 462 0.7s #302 | 103 103 0.7s #304 | 540 540 0.6s #310 | 2 2 0.1s #311 | 23 23 0.6s kw interpolation | 70 70 0.6s broadcasted && and || | 68 68 0.6s normalized unicode ops | 66 66 0.6s pair tuple | 60 60 0.7s global | 81 81 0.6s dollar quote with prime | 118 118 0.6s ERROR: LoadError: Some tests did not pass: 149505 passed, 10 failed, 0 errored, 2 broken. in expression starting at /home/pkgeval/.julia/packages/CSTParser/0hXvH/test/runtests.jl:3 Testing failed after 293.0s ERROR: LoadError: Package CSTParser errored during testing Stacktrace: [1] pkgerror(msg::String) @ Pkg.Types /opt/julia/share/julia/stdlib/v1.12/Pkg/src/Types.jl:68 [2] test(ctx::Pkg.Types.Context, pkgs::Vector{Pkg.Types.PackageSpec}; coverage::Bool, julia_args::Cmd, test_args::Cmd, test_fn::Nothing, force_latest_compatible_version::Bool, allow_earlier_backwards_compatible_versions::Bool, allow_reresolve::Bool) @ Pkg.Operations /opt/julia/share/julia/stdlib/v1.12/Pkg/src/Operations.jl:2365 [3] test @ /opt/julia/share/julia/stdlib/v1.12/Pkg/src/Operations.jl:2220 [inlined] [4] test(ctx::Pkg.Types.Context, pkgs::Vector{Pkg.Types.PackageSpec}; coverage::Bool, test_fn::Nothing, julia_args::Cmd, test_args::Cmd, force_latest_compatible_version::Bool, allow_earlier_backwards_compatible_versions::Bool, allow_reresolve::Bool, kwargs::@Kwargs{io::IOContext{IO}}) @ Pkg.API /opt/julia/share/julia/stdlib/v1.12/Pkg/src/API.jl:486 [5] test(pkgs::Vector{Pkg.Types.PackageSpec}; io::IOContext{IO}, kwargs::@Kwargs{julia_args::Cmd}) @ Pkg.API /opt/julia/share/julia/stdlib/v1.12/Pkg/src/API.jl:164 [6] test(pkgs::Vector{String}; kwargs::@Kwargs{julia_args::Cmd}) @ Pkg.API /opt/julia/share/julia/stdlib/v1.12/Pkg/src/API.jl:152 [7] test @ /opt/julia/share/julia/stdlib/v1.12/Pkg/src/API.jl:152 [inlined] [8] #test#81 @ /opt/julia/share/julia/stdlib/v1.12/Pkg/src/API.jl:151 [inlined] [9] top-level scope @ /PkgEval.jl/scripts/evaluate.jl:219 [10] include(mod::Module, _path::String) @ Base ./Base.jl:307 [11] exec_options(opts::Base.JLOptions) @ Base ./client.jl:328 [12] _start() @ Base ./client.jl:560 in expression starting at /PkgEval.jl/scripts/evaluate.jl:210 PkgEval failed after 382.06s: package has test failures