在 Ada 中,有没有办法让枚举类型像模数类型一样工作——在它的最后一个范围之后换行到 0?
In Ada, is there a way to make an enumeration type act like a modulus type -- to wrap to 0 after the last of it's range?
我正在重写一个 encryption/compression 库,似乎每个处理的字节都需要大量处理。在选择加密可以采用的几种有限方式(正确方式)中的哪一种时,我更愿意使用枚举类型,但是当这些路径变得循环时,我必须添加额外的代码来测试 type'last 和 type'first。我总是可以为类型编写这样的条件,或者为类型分配 addition/subtraction 运算符一个函数来环绕结果,但这是更多的代码和处理,当它必须 运行 每八个字节以及其他所有内容。有没有办法让操作像简单的 "mod" 类型一样高效,比如
type Modular is mod 64 ....;
for ......;
pragma ....;
type Frequency_Counter is array(Modular) of Long_Integer;
Head : Modular := (others => 0);
Freq : Frequency_Counter(Size) := (others => 0);
Encryption_Label : Modular := Hash3;
Block_Sample : Modular := Hash5;
...
Hash3 := Hash3 + 1;
Freq (Hash3):= Freq(Hash3) + 1; -- Here is where my made-on-the-fly example is focused
我认为我可以使整个算法更高效并使用枚举类型,如果我可以让枚举类型在处理器中以与 mod 类型数学相同的周期数进行数学运算。我在想办法时有点创意,但它们显然不适合我使用它们中的任何一个作为示例。我唯一能想到的可能超出我的技能,那就是使用内联 ASM(gas 汇编语言语法)制作一个过程,使操作非常直接地针对处理器。
PS:我知道这是一个小小的收获,一个人。任何增益都适合应用。
不确定这会有多大不同!
鉴于此
package Cyclic is
type Enum is (A, B, C, D, E);
type Modular is mod 5;
function Next_Enum (En : Enum) return Enum is
(if En = Enum'Last then Enum'First else Enum'Succ (En)) --'
with Inline_Always;
end Cyclic;
和
with Cyclic; use Cyclic;
procedure Cyclic_Use (N : Natural; E : in out Enum; M : in out Modular) is
begin
begin
for J in 1 .. N loop
E := Next_Enum (E);
end loop;
end;
begin
for J in 1 .. N loop
M := M + 1;
end loop;
end;
end Cyclic_Use;
并使用带有 -O3 (gnatmake -O3 -c -u -f cyclic_use.adb -cargs -S
) 的 GCC 5.2.0 进行编译,为两个循环生成的 x86_64 汇编器是
(枚举)
L3:
leal 1(%rsi), %ecx
addl , %eax
cmpb , %sil
cmove %r8d, %ecx
cmpl %eax, %edi
movl %ecx, %esi
jne L3
(模块化)
L4:
leal -4(%rdx), %ecx
addl , %eax
cmpb , %dl
leal 1(%rdx), %r8d
movl %ecx, %edx
cmovle %r8d, %edx
cmpl %eax, %edi
jne L4
我不装不懂x86_64汇编,也不知道为什么枚举版比4,模块化版比3,但这些和我很像!但是枚举版本短了一条指令...
我正在重写一个 encryption/compression 库,似乎每个处理的字节都需要大量处理。在选择加密可以采用的几种有限方式(正确方式)中的哪一种时,我更愿意使用枚举类型,但是当这些路径变得循环时,我必须添加额外的代码来测试 type'last 和 type'first。我总是可以为类型编写这样的条件,或者为类型分配 addition/subtraction 运算符一个函数来环绕结果,但这是更多的代码和处理,当它必须 运行 每八个字节以及其他所有内容。有没有办法让操作像简单的 "mod" 类型一样高效,比如
type Modular is mod 64 ....;
for ......;
pragma ....;
type Frequency_Counter is array(Modular) of Long_Integer;
Head : Modular := (others => 0);
Freq : Frequency_Counter(Size) := (others => 0);
Encryption_Label : Modular := Hash3;
Block_Sample : Modular := Hash5;
...
Hash3 := Hash3 + 1;
Freq (Hash3):= Freq(Hash3) + 1; -- Here is where my made-on-the-fly example is focused
我认为我可以使整个算法更高效并使用枚举类型,如果我可以让枚举类型在处理器中以与 mod 类型数学相同的周期数进行数学运算。我在想办法时有点创意,但它们显然不适合我使用它们中的任何一个作为示例。我唯一能想到的可能超出我的技能,那就是使用内联 ASM(gas 汇编语言语法)制作一个过程,使操作非常直接地针对处理器。
PS:我知道这是一个小小的收获,一个人。任何增益都适合应用。
不确定这会有多大不同!
鉴于此
package Cyclic is
type Enum is (A, B, C, D, E);
type Modular is mod 5;
function Next_Enum (En : Enum) return Enum is
(if En = Enum'Last then Enum'First else Enum'Succ (En)) --'
with Inline_Always;
end Cyclic;
和
with Cyclic; use Cyclic;
procedure Cyclic_Use (N : Natural; E : in out Enum; M : in out Modular) is
begin
begin
for J in 1 .. N loop
E := Next_Enum (E);
end loop;
end;
begin
for J in 1 .. N loop
M := M + 1;
end loop;
end;
end Cyclic_Use;
并使用带有 -O3 (gnatmake -O3 -c -u -f cyclic_use.adb -cargs -S
) 的 GCC 5.2.0 进行编译,为两个循环生成的 x86_64 汇编器是
(枚举)
L3:
leal 1(%rsi), %ecx
addl , %eax
cmpb , %sil
cmove %r8d, %ecx
cmpl %eax, %edi
movl %ecx, %esi
jne L3
(模块化)
L4:
leal -4(%rdx), %ecx
addl , %eax
cmpb , %dl
leal 1(%rdx), %r8d
movl %ecx, %edx
cmovle %r8d, %edx
cmpl %eax, %edi
jne L4
我不装不懂x86_64汇编,也不知道为什么枚举版比4,模块化版比3,但这些和我很像!但是枚举版本短了一条指令...