我使用SHA3规范作为Ada编程语言的学习示例。
规范包含一系列数据结构,调用排列,其中有七个,它们只有通过能够处理不同数量的数据才会有所不同。它们包含一个三维的“状态阵列”,其中第一个二维总是mod 5,第三维空间是mod N,其中N仅限于这几个值: 25、50、100、200、400、800和1600。
我通常认为使用泛型来区分每个包的变化,但区别是一个数字,而不是一个类型。
如何明智地设计包/记录类型?
我能想到的唯一方法就是简单地做一组显式类型..。
package Perm_25 is...
package Perm_50 is...
package Perm_100 is...
package Perm_200 is...
package Perm_400 is...
package Perm_800 is...
package Perm_1600 is...显然,这是荒谬的,因为这很辛苦,需要我复制大量的代码,这将导致不一致。
另外,我不相信OOP在这里会有所帮助,因为除了某些数组维度之外,类型实际上并没有什么不同。
我应该如何处理这个问题?
编辑:感谢user @flyx让提示使用Static_Predicate子类型和区分的记录类型。使用这个建议,我成功地获得了下面的代码来编译..。
package body SHA3 is
subtype Perm_w_Coeff_Type is Positive
with Static_Predicate
=> Perm_w_Coeff_Type in 1 | 2 | 4 | 8 | 16 | 32 | 64;
subtype Perm_l_Coeff_Type is Natural range 0 .. 6;
type State_Array_Type is array (Natural range <>, Natural range <>, Natural range <>) of Boolean;
-- (see FIPS202 section 3)
type KECCAK_p_Permutation (bPW : b_Permutation_Width; numRounds : Positive; W_Coeff : Perm_w_Coeff_Type) is
record
b : b_Permutation_Width := bPW;
-- initialise w based on a lookup table using b as its index
-- (see FIPS202 section 3.1, table 1)
w : Perm_w_Coeff_Type := (
case bPW is
when 25 => 1,
when 50 => 2,
when 100 => 4,
when 200 => 8,
when 400 => 16,
when 800 => 32,
when 1600 => 64
);
-- initialise l based on a lookup table using b as its index
-- (see FIPS202 section 3.1, table 1)
l : Perm_l_Coeff_Type := (
case bPW is
when 25 => 0,
when 50 => 1,
when 100 => 2,
when 200 => 3,
when 400 => 4,
when 800 => 5,
when 1600 => 6
);
n_sub_r : Positive := numRounds;
State_Array : State_Array_Type (0 .. 4, 0 .. 4, 0 .. W_Coeff);
end record;
procedure Run is
begin
null;
end Run;
end SHA3;发布于 2019-09-13 12:22:09
subtype Third_Dimension_Type is Natural with
Static_Predicate => Third_Dimension_Type in 25 | 50 | 100 | 200 | 400 | 800 | 1600;我不知道您所说的“前两个维度始终是mod 5”是什么意思,但假设它们有5个条目,结果的数据类型应该如下所示:
type Permutation (Third_Dimension : Third_Dimension_Type) is record
State : array (1..5, 1..5, 1..Third_Dimension) of Item_Type;
end record;请注意,您不能指定采用两个离散范围和一个不确定范围的数组类型(例如,Third_Dimension_Type range <>),因此需要使用区分记录。
发布于 2019-09-15 10:06:40
我没有回答你问题的细节,但我正在回答一些吸引我注意的问题:你说你不能使用泛型,因为变化的参数不是类型。但是,您可以用值参数化泛型(不是说这是最好的方法,而是可以这样做):
generic
Foo : Integer := 5; -- Or any other type.
package Bar is ...https://stackoverflow.com/questions/57922955
复制相似问题