在参数类型中使用结构,而不仅仅是原始类型
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
上不起作用全部.
原因是LinearAlgebra
包usesoneunit
函数推断类型,但是没有办法定义oneunit(::Type{BigMod})
,因为我们不知道模数这种情况(但我们确实知道 Mod{N}
)。但是,可以为 BigMod
类型的变量定义此函数,即 oneunit(x::BigMod)
.
这个问题可以使用 LinearAlgebra
内部的 Base.return_types
进行类型推断来解决,但是它似乎类型不稳定,而且它 return 是可能的 return类型。
我只能看到三种解决方法:
- 总有一天我们可以在参数中使用任何类型(至少是不可变的)。在这种情况下,不需要额外的代码,原始代码应该足够通用,一切都可以正常工作。
- 有一天类型推断会得到足够的改进,以至于不需要像
typeof(oneunit(eltype(B)) / oneunit(eltype(F)))
这样的拼凑,可以只说 return_type(/, eltype.((B,F)))
更通用。
- 克服痛苦,重写
LinearAlgebra
中所有必要的东西,专门为BigMod
还有其他方法可以达到目标吗?哪种方法最好?
参数类型只能包含 isbits
或 Symbol
。因此,您可以使用一个非常容易实现但极其肮脏和低效的解决方法。
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}
我在使用 Mods.jl 时出现了问题。这个包不支持任意精度算法,因为只有原始类型可以作为参数传递,即 Mod{17}
工作正常,但 Mod{big"17"}
不行。
因此,我决定用两个 BigInt
字段
BigMod
的东西
struct BigMod <: AbstractMod
value::BigInt
modulus::BigInt
end
然后我不得不解决线性比较系统,虽然它在 Mod{N}
上工作得很好(A \ b
有一些额外的魔法)但它在 BigMod
上不起作用全部.
原因是LinearAlgebra
包usesoneunit
函数推断类型,但是没有办法定义oneunit(::Type{BigMod})
,因为我们不知道模数这种情况(但我们确实知道 Mod{N}
)。但是,可以为 BigMod
类型的变量定义此函数,即 oneunit(x::BigMod)
.
这个问题可以使用 LinearAlgebra
内部的 Base.return_types
进行类型推断来解决,但是它似乎类型不稳定,而且它 return 是可能的 return类型。
我只能看到三种解决方法:
- 总有一天我们可以在参数中使用任何类型(至少是不可变的)。在这种情况下,不需要额外的代码,原始代码应该足够通用,一切都可以正常工作。
- 有一天类型推断会得到足够的改进,以至于不需要像
typeof(oneunit(eltype(B)) / oneunit(eltype(F)))
这样的拼凑,可以只说return_type(/, eltype.((B,F)))
更通用。 - 克服痛苦,重写
LinearAlgebra
中所有必要的东西,专门为BigMod
还有其他方法可以达到目标吗?哪种方法最好?
参数类型只能包含 isbits
或 Symbol
。因此,您可以使用一个非常容易实现但极其肮脏和低效的解决方法。
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}