Reputation: 386
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?
Upvotes: 4
Views: 85
Reputation: 42214
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}
Upvotes: 3