From: "Francois G. Dorais" <dorais@gauss.dartmouth.edu>
Subject: Re: Bitmanipulation in Ada
Date: Thu, 19 Aug 2004 17:24:17 -0400
Date: 2004-08-19T21:24:17+00:00 [thread overview]
Message-ID: <cg35q1$vfj$1@merrimack.Dartmouth.EDU> (raw)
In-Reply-To: <Xns954AC8912E35DBerndSpechgmxcom@151.189.20.10>
Bernd Specht wrote:
> Always? What do you think about bitscrambling software which has to treat
> data alternating as bitvector and as integer value in a loop like this (not
> exeactly this for securitity reasons):
>
> ...
> loop
> declare
> x : boolean;
> begin
> x := b(k);
> b(k) := b(32 - k);
> b (32 - k) := x;
> I := I * prime1 mod prime2;
> end;
> end loop;
>
>
> Can you find an equivalent algorithm where you can separate the bit-ops and
> the integer-ops?
A generic solution for the above is to encapsulate the bit
fiddling in an inlined procedure. For example, consider the
following where I replaced your bit operation by one which
doesn't implicitly need a copy (to store the K-th bit in
your example.)
with Ada.Unchecked_Conversion;
[...]
type Unsigned_32 is mod 2 ** 32;
for Unsigned_32'Size use 32;
subtype Bit_Index_32 is Integer range 0 .. 31;
-- This avoids many range checks...
procedure Bit_Fiddle
(U : in out Unsigned_32;
K : in Bit_Index_32) is
type Bits_32 is array (Bit_Index_32) of Boolean;
for Bits_32'Component_Size use 1;
function To_Unsigned is new Ada.Unchecked_Conversion
(Bits_32, Unsigned_32);
function To_Bits is new Ada.Unchecked_Conversion
(Unsigned_32, Bits_32);
B : Bits_32 := To_Bits(U);
begin
B(K) := B(31 - K);
U := To_Unsigned(B);
end Bit_Fiddle;
pragma Inline (Bit_Fiddle);
[...]
GNAT compiles the above without copy instructions if it
doesn't need to. For example, try
[...]
for K in Bit_Index_32 loop
Bit_Fiddle(X, K);
X := X + 16#39A2_D071#;
end loop;
[...]
I got the following x86 asm code from gnat 3.15p (with
options "-S -O2 -gnaton") It uses register ebx for the loop
counter K, it stores value 31 in edi throughout and X is
initially in register esi.
[...]
xorl %ebx,%ebx
addl $16,%esp
movl $31,%edi
.align 4
.L65:
movl $1,%eax
movl %ebx,%ecx
sall %cl,%eax
notl %eax
movl %esi,%edx
andl %eax,%edx
movl %edi,%eax
subl %ebx,%eax
movl %eax,%ecx
shrl %cl,%esi
movl %esi,%eax
andl $1,%eax
movl %ebx,%ecx
sall %cl,%eax
movl %edx,%esi
orl %eax,%esi
addl $966971505,%esi
incl %ebx
cmpl $31,%ebx
jle .L65
[...]
This is not necessarily optimal code, but it's pretty decent.
But since your example already needs a copy to save the k-th
bit and probably more for the mul/mod, it's propbably more
efficient to force the bit array B to be distinct from the
integer I. The following should do what you want pretty
efficiently. (I took the liberty to replace your mul/mod by
an arithmetically correct one...)
[...]
type Unsigned_32 is mod 2 ** 32;
for Unsigned_32'Size use 32;
subtype Bit_Index_32 is Integer range 0 .. 31;
type Bits_32 is array (Bit_Index_32) of Boolean;
for Bits_32'Component_Size use 1;
function To_Unsigned is new Ada.Unchecked_Conversion
(Bits_32, Unsigned_32);
function To_Bits is new Ada.Unchecked_Conversion
(Unsigned_32, Bits_32);
function Mul_Mod (Op_1, Op_2, Modulus : Unsigned_32) return
Unsigned_32 is
type Unsigned_64 is mod 2 ** 64;
begin
return Unsigned_32((Unsigned_64(Op_1) *
Unsigned_64(Op_2)) mod Unsigned_64(Modulus));
end Mul_Mod;
pragma Inline (Mul_Mod);
[...]
for K in Bit_Index_32 loop
declare
B : Bits_32 := To_Bits(I);
begin
B(K) := B(31 - K);
B(31 - K) := To_Bits(I)(K);
I := Mul_Mod(To_Unsigned(B), Prime_1, Prime_2);
end;
end loop;
[...]
Try it with GNAT and look at the generated code, you might
be surprized.
However, I know that bit arrays are usually not optimally
handled by most compilers (for any language.) GNAT seems to
do a pretty decent job in general, but when I have to do
this kind of thing and time optimization is very important,
I use the tools provided by package Interfaces and do the
bit-fiddling code myself (as one would do in C) or else I
use package System.Machine_Code to insert some hand
optimized assembly code where needed. Alas, there is no such
thing as a perfect compiler!
next prev parent reply other threads:[~2004-08-19 21:24 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-08-18 20:37 Bitmanipulation in Ada Bernd Specht
2004-08-18 20:51 ` Ludovic Brenta
2004-08-18 21:10 ` Bernd Specht
2004-08-18 21:16 ` Ludovic Brenta
2004-08-18 21:18 ` Ed Falis
2004-08-19 17:30 ` Bernd Specht
2004-08-19 17:44 ` Ed Falis
2004-08-19 0:53 ` Jeffrey Carter
2004-08-19 17:44 ` Bernd Specht
2004-08-19 18:09 ` Martin Dowie
2004-08-19 18:28 ` Bernd Specht
2004-08-19 19:31 ` Martin Dowie
2004-08-19 20:29 ` Martin Dowie
2004-08-20 21:31 ` Bernd Specht
2004-08-19 19:17 ` Jeffrey Carter
2004-08-19 19:57 ` Björn Persson
2004-08-20 0:52 ` Jeffrey Carter
2004-08-19 21:24 ` Francois G. Dorais [this message]
2004-08-20 8:55 ` Pascal Obry
2004-08-20 7:26 ` Jean-Pierre Rosen
2004-08-20 21:20 ` Bernd Specht
2004-08-20 21:39 ` Ed Falis
2004-08-18 21:14 ` (see below)
2004-08-18 21:56 ` Martin Dowie
2004-08-19 15:25 ` (see below)
2004-08-19 15:50 ` Martin Dowie
2004-08-18 21:53 ` Martin Dowie
2004-08-18 22:59 ` Björn Persson
2004-08-19 8:08 ` Egil H. H�vik
2004-08-19 17:46 ` Bernd Specht
2004-08-20 20:57 ` Bitordering? was " Alfred Hilscher
2004-08-21 11:34 ` Nick Roberts
2004-08-21 14:00 ` Jim Rogers
2004-08-21 16:54 ` Simon Wright
2004-08-21 16:55 ` Georg Bauhaus
2004-08-23 18:36 ` Alfred Hilscher
2004-08-23 18:47 ` Alfred Hilscher
2004-08-23 22:39 ` Nick Roberts
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox