The problem arose while I was working with Mods.jl. This package does not support arbitrary-precision arithmetic because only primitive types can be passed as parameters, i.e. Mod{17}
works fine, but Mod{big"17"}
not.
Due to this I decided to implement something like BigMod
with two BigInt
fields
struct BigMod <: AbstractMod
value::BigInt
modulus::BigInt
end
Then I had to solve system of linear comparisons, and whilst it worked pretty good for Mod{N}
(A \ b
with some additional magic) it didn't worked for BigMod
at all.
The reason was that LinearAlgebra
package uses oneunit
function to inference types, but there's no way to define oneunit(::Type{BigMod})
, because we don't know modulus in this case (but we do know it for Mod{N}
). However this function could be defined for variable of the type BigMod
, i.e. oneunit(x::BigMod)
.
This problem can be solved using Base.return_types
inside of LinearAlgebra
for type inference, however it seems to be type unstable as well as it returns a collection of possible return types.
I can see only three ways to solve this:
typeof(oneunit(eltype(B)) / oneunit(eltype(F)))
are needed, one can just say return_type(/, eltype.((B,F)))
which is much more generic.LinearAlgebra
specially for BigMod
Are there any other ways to reach the goal and what way is the best?
The parametric types can only contain isbits
or Symbol
s. Hence, you could use a very easy to implement, yet extremely dirty and inefficient workaround.
struct MyBigMod{S} <: AbstractMod
value::BigInt
end
Base.oneunit(::MyBigMod{S}) where S = parse(BigInt, string(S))
And now you could use it as:
julia> oneunit(MyBigMod{Symbol("55555555555555555555555")}(big"222222"))
55555555555555555555555
Perhaps your big ints are not that big after all and you could consider using BitIntegers
? Than you could do something like:
julia> MyBigMod{int1024"55555555555555555555555"}
MyBigMod{55555555555555555555555}