Ada - SHA3 实现的合理代码结构
Ada - Sensible code structure for SHA3 implementation
我正在使用 SHA3 规范作为 Ada 编程语言的学习示例。
该规范包含一组称为排列的数据结构,共有七种,它们的区别仅在于能够处理不同数量的数据。它们包含三维 "State Array",其中前两个维度总是 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 会在这里有所帮助,因为除了某些数组维度之外,类型确实没有什么不同。
我该如何解决这个问题?
编辑:感谢用户@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;
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 <>
),因此您需要使用可区分的记录。
我没有详细了解您的问题,但我正在回答引起我注意的问题:您说您不能使用泛型,因为更改的参数不是类型。但是,您可以使用值参数化泛型(并不是说这是这种情况下的最佳方法,而是您可以做到):
generic
Foo : Integer := 5; -- Or any other type.
package Bar is ...
我正在使用 SHA3 规范作为 Ada 编程语言的学习示例。
该规范包含一组称为排列的数据结构,共有七种,它们的区别仅在于能够处理不同数量的数据。它们包含三维 "State Array",其中前两个维度总是 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 会在这里有所帮助,因为除了某些数组维度之外,类型确实没有什么不同。
我该如何解决这个问题?
编辑:感谢用户@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;
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 <>
),因此您需要使用可区分的记录。
我没有详细了解您的问题,但我正在回答引起我注意的问题:您说您不能使用泛型,因为更改的参数不是类型。但是,您可以使用值参数化泛型(并不是说这是这种情况下的最佳方法,而是您可以做到):
generic
Foo : Integer := 5; -- Or any other type.
package Bar is ...