Looks more or less like how Nemo.jl wraps FLINT’s fmpz: Nemo.jl/src/flint/FlintTypes.jl at master · wbhart/Nemo.jl · GitHub
I was imagining something more on the Julia side, which wouldn’t need finalizers to manage memory allocated in another language:
struct MaybeBig{I<:Integer}
inline::I # except typemax as overflow flag
overflow::BigInt # must trail for incomplete new #36789
MaybeBig{I}(i::I) where I = new(i)
MaybeBig{I}(i::BigInt) where I = new(typemax(I), i)
end
MaybeBig(i::I) where I = MaybeBig{I}(i)
# then all the Number arithmetic methods
except I’m not actually sure if the incomplete initialization manages zero allocation, hopefully someone can explain if I’m just benchmarking wrong:
julia> @btime MaybeBig($1) # allocates?
5.500 ns (1 allocation: 32 bytes)
MaybeBig{Int64}(1, #undef)
julia> Base.one(::Type{MaybeBig{I}}) where I = MaybeBig{I}(one(I))
julia> @btime ones($(MaybeBig{Int}), $5) # only allocates Array
126.988 ns (2 allocations: 96 bytes)
5-element Vector{MaybeBig{Int64}}:
MaybeBig{Int64}(1, #undef)
MaybeBig{Int64}(1, #undef)
MaybeBig{Int64}(1, #undef)
MaybeBig{Int64}(1, #undef)
MaybeBig{Int64}(1, #undef)