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:
- One day one could use any (at least immutable) types in parameters. In this case no additional code is required, original should be generic enough for everything to work well.
- One day type inference would be improved enough so that no kludges like
typeof(oneunit(eltype(B)) / oneunit(eltype(F)))are needed, one can just sayreturn_type(/, eltype.((B,F)))which is much more generic. - Fight through the pain and rewrite all necessary things from
LinearAlgebraspecially forBigMod
Are there any other ways to reach the goal and what way is the best?
BigModyou posted. TheMod{N}approach in Mods.jl worked fine becauseInt64was allowed and more than big enough for most cases. Waiting for the core language to allow more things as type parameters isn't practical. At some point it was expanded from onlyIntandBoolto isbits types, so there must've been some intractable reason they didn't expand it further.