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 ...