在参数类型中使用结构,而不仅仅是原始类型

Using structs in parametric types, not only primitive types

我在使用 Mods.jl 时出现了问题。这个包不支持任意精度算法,因为只有原始类型可以作为参数传递,即 Mod{17} 工作正常,但 Mod{big"17"} 不行。

因此,我决定用两个 BigInt 字段

实现类似 BigMod 的东西
struct BigMod <: AbstractMod
    value::BigInt
    modulus::BigInt
end

然后我不得不解决线性比较系统,虽然它在 Mod{N} 上工作得很好(A \ b 有一些额外的魔法)但它在 BigMod 上不起作用全部.

原因是LinearAlgebrausesoneunit函数推断类型,但是没有办法定义oneunit(::Type{BigMod}),因为我们不知道模数这种情况(但我们确实知道 Mod{N})。但是,可以为 BigMod 类型的变量定义此函数,即 oneunit(x::BigMod).

这个问题可以使用 LinearAlgebra 内部的 Base.return_types 进行类型推断来解决,但是它似乎类型不稳定,而且它 return 是可能的 return类型。

我只能看到三种解决方法:

  1. 总有一天我们可以在参数中使用任何类型(至少是不可变的)。在这种情况下,不需要额外的代码,原始代码应该足够通用,一切都可以正常工作。
  2. 有一天类型推断会得到足够的改进,以至于不需要像 typeof(oneunit(eltype(B)) / oneunit(eltype(F))) 这样的拼凑,可以只说 return_type(/, eltype.((B,F))) 更通用。
  3. 克服痛苦,重写LinearAlgebra中所有必要的东西,专门为BigMod

还有其他方法可以达到目标吗?哪种方法最好?

参数类型只能包含 isbitsSymbol。因此,您可以使用一个非常容易实现但极其肮脏和低效的解决方法。

struct MyBigMod{S} <: AbstractMod
    value::BigInt
end

Base.oneunit(::MyBigMod{S}) where S = parse(BigInt, string(S))

现在您可以将其用作:

julia> oneunit(MyBigMod{Symbol("55555555555555555555555")}(big"222222"))
55555555555555555555555

也许你的大整数毕竟不是那么大,你可以考虑using BitIntegers?你可以做类似的事情:

julia> MyBigMod{int1024"55555555555555555555555"}
MyBigMod{55555555555555555555555}