comp.lang.ada
 help / color / mirror / Atom feed
* Minimum Record Size?  LONG
@ 2003-04-25 16:33 Dr Nancy's Sweetie
  2003-04-25 17:35 ` Stephen Leake
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Dr Nancy's Sweetie @ 2003-04-25 16:33 UTC (permalink / raw)



I'm working on a program which has to take four six-bit hunks of data
and regroup them into three eight-bit hunks.  My first pass looked like
this:

      Code_Value : String :=
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-";
      Clear : Unbounded_String := To_Unbounded_String("");

      Part_1     : Unsigned_32 := 0;
      Part_2     : Unsigned_32 := 0;
      Part_3     : Unsigned_32 := 0;
      Part_4     : Unsigned_32 := 0;

      Segment    : Unsigned_32 := 0;

      Val_1      : Unsigned_32;
      Val_2      : Unsigned_32;
      Val_3      : Unsigned_32;

 (some more vars and such)

      while Spot <= Coded'Last loop
         -- take four six-bit hunks
         Part_1 := Unsigned_32(Index(Code_Value, Coded(Spot  ..Spot  )) -1);
         Part_2 := Unsigned_32(Index(Code_Value, Coded(Spot+1..Spot+1)) -1);
         Part_3 := Unsigned_32(Index(Code_Value, Coded(Spot+2..Spot+2)) -1);
         Part_4 := Unsigned_32(Index(Code_Value, Coded(Spot+3..Spot+3)) -1);

         -- assemble them into one segment
         Segment := (Shift_Left(Part_1, 18) and 16#fc0000#) or
                    (Shift_Left(Part_2, 12) and 16#03f000#) or
                    (Shift_Left(Part_3,  6) and 16#000fc0#) or
                    (Shift_left(Part_4,  0) and 16#00003f#)   ;

         -- split segment into three eight-bit hunks
         Val_1 := (Shift_Right(Segment and 16#ff0000#, 16));
         Val_2 := (Shift_Right(Segment and 16#00ff00#,  8));
         Val_3 := (Shift_Right(Segment and 16#0000ff#,  0));

         -- (now do some more stuff)
      end loop;

This worked, but it seemed a little klunky.  Figuring there ought to
be a better way, I tried an Unchecked_Conversion:

      type Six_Bits is mod 2**6;
      type Four_Sixes is array (0..3) of Six_Bits;
      type Four_Group is record
         Part : Four_Sixes;
      end record;
      for Four_Group'Size use 24;

      type Eight_Bits is mod 2**8;
      type Three_Eights is array (0..2) of Eight_Bits;
      type Three_Group is record
         Part : Three_Eights;
      end record;
      for Three_Group'Size use 24;

But the compiler (gnat 3.13p) won't let me do this: it says:

    size for "Four_Group" too small, minimum allowed is 32


Well, I figure, maybe there's some array overhead that I didn't account
for.  Except that it doesn't have any problem with the Three_Group being
24 bits, and that's also an array.  But anyway, as a test, I rewrote it
like this:

      type Six_Bits is mod 2**6;
      type Four_Sixes is array (0..3) of Six_Bits;
      type Four_Group is record
         Part1, Part2, Part3, Part4 : Six_Bits;
      end record;
      for Four_Group'Size use 24;

      type Eight_Bits is mod 2**8;
      type Three_Eights is array (0..2) of Eight_Bits;
      type Three_Group is record
         Part1, Part2, Part3 : Eight_Bits;
      end record;
      for Three_Group'Size use 24;


It still won't let me do that: the minimum size for a Four_Group is
still 32 bits.  Okay, so I set the Four_Group'Size to 32.  Now it
quite reasonably complains that the sizes for my Unchecked_Conversion
are different.

My best guess at this point was that it insisted on using a full byte
to represent the Six_Bits type, but when I put in:

    for Six_Bits'Size use 6;

there was no complaint.  But four six-bit things require 32 bits to
store, even though three eight-bit things fits in 24.


When I turn on debugging (Ada.Command_Line, Getopt, and a -D switch
can save a lot of time), I discover that after the Unchecked_Conversion,
the three eight-bit elements have the exact same values as the first
three six-bit elements.  So my only guess now is that even though the
six-bit things are six bits big, they're being byte-aligned.

ANYWAY, I got to the point where I was throwing in things such as

    pragma Pack(Four_Sixes);
    for Four_Sixes'Size use 24;

And it still doesn't make any difference.  The four-element array of
six bit objects is 24 bits without a complaint, but the record still
has to be 32 bits.


So that led me to one more try: dispense with the records, and just
do an Unchecked_Conversion directly on the arrays.  The compiler is
happy with it, both array sizes are 24 bits, and the code runs without
crashing.  But the results make no sense.

If I put in C3zY, which map to 28, 55, 25, and 50, I see this:

    Put in:       28     55     25     50
              011100 110111 011001 110010

    Expect:      115      118      114
            01110011 01110110 01110010

    Actual:      220      157      201
            11011100 10011101 11001001

I can't see where the resulting bits that actually come out are from.
They don't seem to bear any relation to the bits that went in.


Suggestions?  (Yes, this can be done in C, but I'm trying to learn a
new language, not write everything in the old one.)


Darren Provine ! kilroy@elvis.rowan.edu ! http://www.rowan.edu/~kilroy
"There's nothing in human experience compared to which a sendmail config
 file could be considered simple." -- anonymous



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Minimum Record Size?  LONG
  2003-04-25 16:33 Minimum Record Size? LONG Dr Nancy's Sweetie
@ 2003-04-25 17:35 ` Stephen Leake
  2003-04-25 17:36 ` Mark Johnson
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 13+ messages in thread
From: Stephen Leake @ 2003-04-25 17:35 UTC (permalink / raw)


Dr Nancy's Sweetie <kilroy@elvis.rowan.edu> writes:

> I'm working on a program which has to take four six-bit hunks of data
> and regroup them into three eight-bit hunks.  

Ok

> My first pass looked like this:
> <snipped>
> 
> This worked, but it seemed a little klunky.  Figuring there ought to
> be a better way, I tried an Unchecked_Conversion:

Please post actual, complete, compilable code. That makes it easier
for us to compile it, add the necessary changes, and post it back.

>       type Six_Bits is mod 2**6;

you probably need a size clause here.

>       type Four_Sixes is array (0..3) of Six_Bits;

and here you need a component size clause, and/or a pragma Pack.

same for Three_Group.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Minimum Record Size?  LONG
  2003-04-25 16:33 Minimum Record Size? LONG Dr Nancy's Sweetie
  2003-04-25 17:35 ` Stephen Leake
@ 2003-04-25 17:36 ` Mark Johnson
  2003-04-25 21:54   ` tmoran
  2003-04-25 18:51 ` David C. Hoos
  2003-04-26  2:12 ` Steve
  3 siblings, 1 reply; 13+ messages in thread
From: Mark Johnson @ 2003-04-25 17:36 UTC (permalink / raw)


Dr Nancy's Sweetie wrote:
> 
> I'm working on a program which has to take four six-bit hunks of data
> and regroup them into three eight-bit hunks.
[snip - long explanation]

> If I put in C3zY, which map to 28, 55, 25, and 50, I see this:
> 
>     Put in:       28     55     25     50
>               011100 110111 011001 110010
                aaaaaa bbbbbb cccccc dddddd
> 
>     Expect:      115      118      114
>             01110011 01110110 01110010
> 
>     Actual:      220      157      201
>             11011100 10011101 11001001
              bbaaaaaa ccccbbbb ddddddcc
> 
> I can't see where the resulting bits that actually come out are from.
> They don't seem to bear any relation to the bits that went in.
> 
The bits look good to me - they just don't match what you expected. The
packing I see is shown in line with your original message.

You don't mention the machine you are using and you don't post the
actual code you are using. Both would be a greater help in analyzing the
specific problem and solution.

This may also be a big / little endian problem. You have to read very
carefully the ARM when it talks about placement of bits in fields and so
on. You could also try using representation specifications (section 13)
to place each field precisely where you want it. You may find that some
of the combinations you are attempting to do are "not contiguous" and
have to be handled in a special way.

  --Mark



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Minimum Record Size?  LONG
  2003-04-25 16:33 Minimum Record Size? LONG Dr Nancy's Sweetie
  2003-04-25 17:35 ` Stephen Leake
  2003-04-25 17:36 ` Mark Johnson
@ 2003-04-25 18:51 ` David C. Hoos
  2003-04-25 21:51   ` tmoran
  2003-04-26  2:12 ` Steve
  3 siblings, 1 reply; 13+ messages in thread
From: David C. Hoos @ 2003-04-25 18:51 UTC (permalink / raw)


----- Original Message -----
From: "Dr Nancy's Sweetie" <kilroy@elvis.rowan.edu>
Newsgroups: comp.lang.ada
To: <comp.lang.ada@ada.eu.org>
Sent: Friday, April 25, 2003 11:33 AM
Subject: Minimum Record Size? LONG


>
> I'm working on a program which has to take four six-bit hunks of data
> and regroup them into three eight-bit hunks.  My first pass looked like
> this:
<snip>

Here is an approach that, while verbose, is written to be understandable
by the reader.

The reason for the difference between your expected and actual results
is the failure to take into account the machine endianness.

Obviously, you are doing this on a little-endian machine.

This is taken care of by the conditionally-called Reversed_Bits function.

-- Begin Ada source code
with Ada.Text_IO;
with Ada.Unchecked_Conversion;
with System;
procedure Kilroy
is
   type Eight is mod 2 ** 8;
   type Three_Eights is array (1 .. 3) of Eight;
   for Three_Eights'Size use 24;
   type Six is mod 2 ** 6;
   type Four_Sixes is array (1 .. 4) of Six;
   function Four_Sixes_To_Three_Eights (X : Four_Sixes)
     return Three_Eights
   is
      type Bit is mod 2;
      for Bit'Size use 1;
      type Bit_Array is array (Positive range <>) of Bit;
      pragma Pack (Bit_Array);
      subtype Twenty_Four_Bits is Bit_Array (1 .. 24);
      subtype Six_Bits is Bit_Array (1 .. 6);
      subtype Eight_Bits is Bit_Array (1 .. 8);
      function To_Bits is new Ada.Unchecked_Conversion
        (Source => Six,
         Target => Six_Bits);
      function To_Bits is new Ada.Unchecked_Conversion
        (Source => Eight,
         Target => Eight_Bits);
      function From_Bits is new Ada.Unchecked_Conversion
        (Source => Six_Bits,
         Target => Six);
      function From_Bits is new Ada.Unchecked_Conversion
        (Source => Eight_Bits,
         Target => Eight);
      function From_Bits is new Ada.Unchecked_Conversion
        (Source => Twenty_Four_Bits,
         Target => Three_Eights);
      function Reversed_Bits (X : Bit_Array) return Bit_Array
      is
         Result : Bit_Array (1 .. X'Length);
      begin
         for I in Result'Range loop
            Result (I) := X (X'Length - I + 1);
         end loop;
         return Result;
      end Reversed_Bits;
      Input  : Four_Sixes := X;
      Temp   : Twenty_Four_Bits;
      Result : Three_Eights;
      use type System.Bit_Order;
   begin
      if System.Default_Bit_Order = System.Low_Order_First then
         for I in Input'Range loop
            Input (I) :=
              From_Bits (Reversed_Bits (To_Bits (Input (I))));
         end loop;
      end if;
      for I in Input'Range loop
         Temp (6 * (I - 1) + 1  .. 6 * I) := To_Bits (Input (I));
      end loop;
      Result := From_Bits (Temp);
      if System.Default_Bit_Order = System.Low_Order_First then
         for I in Result'Range loop
            Result (I) :=
              From_Bits (Reversed_Bits (To_Bits (Result (I))));
         end loop;
      end if;
      return Result;
   end Four_Sixes_To_Three_Eights;
   package Six_IO is new Ada.Text_IO.Modular_IO (Six);
   package Eight_IO is new Ada.Text_IO.Modular_IO (Eight);
   Input  : constant Four_Sixes := (28, 55, 25, 50);
   Result : Three_Eights;
begin
   Result := Four_Sixes_To_Three_Eights (Input);
   Ada.Text_IO.Put ("Input : ");
   for I in Input'Range loop
      Six_IO.Put (Item => Input (I));
   end loop;
   Ada.Text_IO.New_Line;
   Ada.Text_IO.Put ("Result: ");
   for I in Result'Range loop
      Eight_IO.Put (Item => Result (I));
   end loop;
   Ada.Text_IO.New_Line;
end Kilroy;
-- End Ada source code

I hope this helps.

David





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Minimum Record Size?  LONG
  2003-04-25 18:51 ` David C. Hoos
@ 2003-04-25 21:51   ` tmoran
  2003-04-26  3:00     ` David C. Hoos
  0 siblings, 1 reply; 13+ messages in thread
From: tmoran @ 2003-04-25 21:51 UTC (permalink / raw)


>Here is an approach that, while verbose, is written to be understandable
>by the reader.
  If the reader is careful and willing to study a shorter piece of code,
then, in the spirit of the OP's first try
>>       -- assemble them into one segment
>>       Segment := (Shift_Left(Part_1, 18) and 16#fc0000#) or
>>                  (Shift_Left(Part_2, 12) and 16#03f000#) or
>>                  (Shift_Left(Part_3,  6) and 16#000fc0#) or
>>                  (Shift_left(Part_4,  0) and 16#00003f#)   ;
>>
>>       -- split segment into three eight-bit hunks
>>       Val_1 := (Shift_Right(Segment and 16#ff0000#, 16));
>>       Val_2 := (Shift_Right(Segment and 16#00ff00#,  8));
>>       Val_3 := (Shift_Right(Segment and 16#0000ff#,  0));

we can modify the function to:
>  function Four_Sixes_To_Three_Eights (X : Four_Sixes)
>    return Three_Eights
>  is
>  begin
     return (1=>  Eight(x(1))*4          + Eight(x(2))/16,
             2=> (Eight(x(2)) mod 16)*16 + Eight(x(3))/4,
             3=> (Eight(x(3)) mod 4)*64  + Eight(x(4)));
>  end Four_Sixes_To_Three_Eights;



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Minimum Record Size?  LONG
  2003-04-25 17:36 ` Mark Johnson
@ 2003-04-25 21:54   ` tmoran
  0 siblings, 0 replies; 13+ messages in thread
From: tmoran @ 2003-04-25 21:54 UTC (permalink / raw)


>This may also be a big / little endian problem.
  As becomes apparent if you try to write a layout rep spec for
>>    type Four_Group is record
>>       Part1, Part2, Part3, Part4 : Six_Bits;
>>    end record;
>>    for Four_Group'Size use 24;
      for Four_Group use record
        Part1 at 0 range ...



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Minimum Record Size?  LONG
  2003-04-25 16:33 Minimum Record Size? LONG Dr Nancy's Sweetie
                   ` (2 preceding siblings ...)
  2003-04-25 18:51 ` David C. Hoos
@ 2003-04-26  2:12 ` Steve
  2003-04-27  1:57   ` Rick Stikkers
  2003-04-27 12:06   ` David C. Hoos
  3 siblings, 2 replies; 13+ messages in thread
From: Steve @ 2003-04-26  2:12 UTC (permalink / raw)



Here's an approach taking advantage of using "Slices" of arrays (tested
w/Gnat3.15p-nt):

with Ada.Text_Io;
with Ada.Unchecked_Conversion;

procedure Shift6to8 is

  type Six_Bits_Type is mod 2**6;
  for Six_Bits_Type'Size use 6;

  type Eight_Bits_Type is mod 2**8;
  for Eight_Bits_Type'Size use 8;

  package Eight_Bits_Io is
    new Ada.Text_Io.Modular_Io( Eight_Bits_Type );

  procedure Conv_4x6_to_8x3( in1, in2, in3, in4 : Six_Bits_Type;
                             out1, out2, out3   : out Eight_Bits_Type ) is
    type Bit_Array_Type is array( positive range <> ) of Boolean;
    pragma pack( Bit_Array_Type );

    subtype Six_Bits_Array_Type is Bit_Array_Type( 1 .. 6 );
    subtype Eight_Bits_Array_Type is Bit_Array_Type( 1 .. 8 );

    function Conv is
      new Ada.Unchecked_Conversion( Six_Bits_Type, Six_Bits_Array_Type );
    function Conv is
      new Ada.Unchecked_Conversion( Eight_Bits_Array_Type,
Eight_Bits_Type );

    combined : Bit_Array_Type := Conv( in1 ) & Conv( in2 ) & Conv( in3 ) &
Conv( in4 );
  begin
    out1 := Conv( combined( 1 .. 8 ) );
    out2 := Conv( combined( 9 .. 16 ) );
    out3 := Conv( combined( 17 .. 24 ) );
  end Conv_4x6_to_8x3;

  sb1, sb2, sb3, sb4 : Six_Bits_Type;
  eb1, eb2, eb3 : Eight_Bits_Type;

begin
  sb1 := 1;
  sb2 := 1;
  sb3 := 1;
  sb4 := 1;
  Conv_4x6_to_8x3( sb1, sb2, sb3, sb4, eb1, eb2, eb3 );
  Eight_Bits_Io.Put( eb1, 4, 2 );
  Ada.Text_Io.New_Line;
  Eight_Bits_Io.Put( eb2, 4, 2 );
  Ada.Text_Io.New_Line;
  Eight_Bits_Io.Put( eb3, 4, 2 );
  Ada.Text_Io.New_Line;
end Shift6to8;


"Dr Nancy's Sweetie" <kilroy@elvis.rowan.edu> wrote in message
news:Hrdqa.9680$io.307974@iad-read.news.verio.net...
>
> I'm working on a program which has to take four six-bit hunks of data
> and regroup them into three eight-bit hunks.  My first pass looked like
> this:
>
>       Code_Value : String :=
>
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-";
>       Clear : Unbounded_String := To_Unbounded_String("");
>
>       Part_1     : Unsigned_32 := 0;
>       Part_2     : Unsigned_32 := 0;
>       Part_3     : Unsigned_32 := 0;
>       Part_4     : Unsigned_32 := 0;
>
>       Segment    : Unsigned_32 := 0;
>
>       Val_1      : Unsigned_32;
>       Val_2      : Unsigned_32;
>       Val_3      : Unsigned_32;
>
>  (some more vars and such)
>
>       while Spot <= Coded'Last loop
>          -- take four six-bit hunks
>          Part_1 := Unsigned_32(Index(Code_Value, Coded(Spot
 ..Spot  )) -1);
>          Part_2 := Unsigned_32(Index(Code_Value,
Coded(Spot+1..Spot+1)) -1);
>          Part_3 := Unsigned_32(Index(Code_Value,
Coded(Spot+2..Spot+2)) -1);
>          Part_4 := Unsigned_32(Index(Code_Value,
Coded(Spot+3..Spot+3)) -1);
>
>          -- assemble them into one segment
>          Segment := (Shift_Left(Part_1, 18) and 16#fc0000#) or
>                     (Shift_Left(Part_2, 12) and 16#03f000#) or
>                     (Shift_Left(Part_3,  6) and 16#000fc0#) or
>                     (Shift_left(Part_4,  0) and 16#00003f#)   ;
>
>          -- split segment into three eight-bit hunks
>          Val_1 := (Shift_Right(Segment and 16#ff0000#, 16));
>          Val_2 := (Shift_Right(Segment and 16#00ff00#,  8));
>          Val_3 := (Shift_Right(Segment and 16#0000ff#,  0));
>
>          -- (now do some more stuff)
>       end loop;
>
> This worked, but it seemed a little klunky.  Figuring there ought to
> be a better way, I tried an Unchecked_Conversion:
>
>       type Six_Bits is mod 2**6;
>       type Four_Sixes is array (0..3) of Six_Bits;
>       type Four_Group is record
>          Part : Four_Sixes;
>       end record;
>       for Four_Group'Size use 24;
>
>       type Eight_Bits is mod 2**8;
>       type Three_Eights is array (0..2) of Eight_Bits;
>       type Three_Group is record
>          Part : Three_Eights;
>       end record;
>       for Three_Group'Size use 24;
>
> But the compiler (gnat 3.13p) won't let me do this: it says:
>
>     size for "Four_Group" too small, minimum allowed is 32
>
>
> Well, I figure, maybe there's some array overhead that I didn't account
> for.  Except that it doesn't have any problem with the Three_Group being
> 24 bits, and that's also an array.  But anyway, as a test, I rewrote it
> like this:
>
>       type Six_Bits is mod 2**6;
>       type Four_Sixes is array (0..3) of Six_Bits;
>       type Four_Group is record
>          Part1, Part2, Part3, Part4 : Six_Bits;
>       end record;
>       for Four_Group'Size use 24;
>
>       type Eight_Bits is mod 2**8;
>       type Three_Eights is array (0..2) of Eight_Bits;
>       type Three_Group is record
>          Part1, Part2, Part3 : Eight_Bits;
>       end record;
>       for Three_Group'Size use 24;
>
>
> It still won't let me do that: the minimum size for a Four_Group is
> still 32 bits.  Okay, so I set the Four_Group'Size to 32.  Now it
> quite reasonably complains that the sizes for my Unchecked_Conversion
> are different.
>
> My best guess at this point was that it insisted on using a full byte
> to represent the Six_Bits type, but when I put in:
>
>     for Six_Bits'Size use 6;
>
> there was no complaint.  But four six-bit things require 32 bits to
> store, even though three eight-bit things fits in 24.
>
>
> When I turn on debugging (Ada.Command_Line, Getopt, and a -D switch
> can save a lot of time), I discover that after the Unchecked_Conversion,
> the three eight-bit elements have the exact same values as the first
> three six-bit elements.  So my only guess now is that even though the
> six-bit things are six bits big, they're being byte-aligned.
>
> ANYWAY, I got to the point where I was throwing in things such as
>
>     pragma Pack(Four_Sixes);
>     for Four_Sixes'Size use 24;
>
> And it still doesn't make any difference.  The four-element array of
> six bit objects is 24 bits without a complaint, but the record still
> has to be 32 bits.
>
>
> So that led me to one more try: dispense with the records, and just
> do an Unchecked_Conversion directly on the arrays.  The compiler is
> happy with it, both array sizes are 24 bits, and the code runs without
> crashing.  But the results make no sense.
>
> If I put in C3zY, which map to 28, 55, 25, and 50, I see this:
>
>     Put in:       28     55     25     50
>               011100 110111 011001 110010
>
>     Expect:      115      118      114
>             01110011 01110110 01110010
>
>     Actual:      220      157      201
>             11011100 10011101 11001001
>
> I can't see where the resulting bits that actually come out are from.
> They don't seem to bear any relation to the bits that went in.
>
>
> Suggestions?  (Yes, this can be done in C, but I'm trying to learn a
> new language, not write everything in the old one.)
>
>
> Darren Provine ! kilroy@elvis.rowan.edu ! http://www.rowan.edu/~kilroy
> "There's nothing in human experience compared to which a sendmail config
>  file could be considered simple." -- anonymous





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Minimum Record Size?  LONG
  2003-04-25 21:51   ` tmoran
@ 2003-04-26  3:00     ` David C. Hoos
  0 siblings, 0 replies; 13+ messages in thread
From: David C. Hoos @ 2003-04-26  3:00 UTC (permalink / raw)


<tmoran@acm.org> wrote in message news:H5iqa.621548$L1.175962@sccrnsc02...
> >Here is an approach that, while verbose, is written to be understandable
> >by the reader.
>   If the reader is careful and willing to study a shorter piece of code,
> then, in the spirit of the OP's first try
<snip>
> we can modify the function to:
> >  function Four_Sixes_To_Three_Eights (X : Four_Sixes)
> >    return Three_Eights
> >  is
> >  begin
>      return (1=>  Eight(x(1))*4          + Eight(x(2))/16,
>              2=> (Eight(x(2)) mod 16)*16 + Eight(x(3))/4,
>              3=> (Eight(x(3)) mod 4)*64  + Eight(x(4)));
> >  end Four_Sixes_To_Three_Eights;

Very nice.  I overlooked the fact that arithmetic operations
instead of shifts and masks would take care of the endianness problem
in a very elegant way.



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Minimum Record Size?  LONG
  2003-04-26  2:12 ` Steve
@ 2003-04-27  1:57   ` Rick Stikkers
  2003-04-27 12:06   ` David C. Hoos
  1 sibling, 0 replies; 13+ messages in thread
From: Rick Stikkers @ 2003-04-27  1:57 UTC (permalink / raw)




Steve wrote:

>Here's an approach taking advantage of using "Slices" of arrays (tested
>w/Gnat3.15p-nt):
>
>  
>
If you're not worried about machine cross compatibility, the other 
option would be to just give in to the endianness of the machine and 
swap everything so that the endianness is fully preserved.  The 
following code segment gives the desired results.

with TEXT_IO;
procedure comp is

type six_bits is range 0..2**6-1;
for six_bits'SIZE use 6;
type four_sixes is record
  six_bits_0 : six_bits;
  six_bits_1 : six_bits;
  six_bits_2 : six_bits;
  six_bits_3 : six_bits;
end record;
for four_sixes use record
  six_bits_0 at 0 range 18..23;
  six_bits_1 at 0 range 12..17;
  six_bits_2 at 0 range 6..11;
  six_bits_3 at 0 range 0..5;
end record;
for four_sixes'SIZE use 24;

type eight_bits is range 0..2**8-1;
for eight_bits'SIZE use 8;
type three_eights is record
  eight_bits_0 : eight_bits;
  eight_bits_1 : eight_bits;
  eight_bits_2 : eight_bits;
end record;
for three_eights use record
  eight_bits_0 at 2 range 0..7;
  eight_bits_1 at 1 range 0..7;
  eight_bits_2 at 0 range 0..7;
end record;
for three_eights'SIZE use 24;

six_var : four_sixes;
eight_var : three_eights;
for eight_var use at six_var'ADDRESS;

begin
  six_var.six_bits_0 := 28;
  six_var.six_bits_1 := 55;
  six_var.six_bits_2 := 25;
  six_var.six_bits_3 := 50;
  text_io.put_line(eight_bits'IMAGE(eight_var.eight_bits_0)&"  "&
                          eight_bits'IMAGE(eight_var.eight_bits_1)&"   "&
                          eight_bits'IMAGE(eight_var.eight_bits_2));
end;




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Minimum Record Size?  LONG
  2003-04-26  2:12 ` Steve
  2003-04-27  1:57   ` Rick Stikkers
@ 2003-04-27 12:06   ` David C. Hoos
  2003-04-27 14:17     ` Steve
  1 sibling, 1 reply; 13+ messages in thread
From: David C. Hoos @ 2003-04-27 12:06 UTC (permalink / raw)


The problem with this approach is that it gives incorrect results.

If you put in the original poster's input values, you get the
same incorrect results that he did.

Testing with four inputs having only one bit set is not really
"tested."

"Steve" <nospam_steved94@attbi.com> wrote in message
news:UVlqa.620033$3D1.340565@sccrnsc01...
>
> Here's an approach taking advantage of using "Slices" of arrays (tested
> w/Gnat3.15p-nt):
>
> with Ada.Text_Io;
> with Ada.Unchecked_Conversion;
>
> procedure Shift6to8 is
>
>   type Six_Bits_Type is mod 2**6;
>   for Six_Bits_Type'Size use 6;
>
>   type Eight_Bits_Type is mod 2**8;
>   for Eight_Bits_Type'Size use 8;
>
>   package Eight_Bits_Io is
>     new Ada.Text_Io.Modular_Io( Eight_Bits_Type );
>
>   procedure Conv_4x6_to_8x3( in1, in2, in3, in4 : Six_Bits_Type;
>                              out1, out2, out3   : out Eight_Bits_Type ) is
>     type Bit_Array_Type is array( positive range <> ) of Boolean;
>     pragma pack( Bit_Array_Type );
>
>     subtype Six_Bits_Array_Type is Bit_Array_Type( 1 .. 6 );
>     subtype Eight_Bits_Array_Type is Bit_Array_Type( 1 .. 8 );
>
>     function Conv is
>       new Ada.Unchecked_Conversion( Six_Bits_Type, Six_Bits_Array_Type );
>     function Conv is
>       new Ada.Unchecked_Conversion( Eight_Bits_Array_Type,
> Eight_Bits_Type );
>
>     combined : Bit_Array_Type := Conv( in1 ) & Conv( in2 ) & Conv( in3 ) &
> Conv( in4 );
>   begin
>     out1 := Conv( combined( 1 .. 8 ) );
>     out2 := Conv( combined( 9 .. 16 ) );
>     out3 := Conv( combined( 17 .. 24 ) );
>   end Conv_4x6_to_8x3;
>
>   sb1, sb2, sb3, sb4 : Six_Bits_Type;
>   eb1, eb2, eb3 : Eight_Bits_Type;
>
> begin
>   sb1 := 1;
>   sb2 := 1;
>   sb3 := 1;
>   sb4 := 1;
>   Conv_4x6_to_8x3( sb1, sb2, sb3, sb4, eb1, eb2, eb3 );
>   Eight_Bits_Io.Put( eb1, 4, 2 );
>   Ada.Text_Io.New_Line;
>   Eight_Bits_Io.Put( eb2, 4, 2 );
>   Ada.Text_Io.New_Line;
>   Eight_Bits_Io.Put( eb3, 4, 2 );
>   Ada.Text_Io.New_Line;
> end Shift6to8;
>
>
> "Dr Nancy's Sweetie" <kilroy@elvis.rowan.edu> wrote in message
> news:Hrdqa.9680$io.307974@iad-read.news.verio.net...
> >
> > I'm working on a program which has to take four six-bit hunks of data
> > and regroup them into three eight-bit hunks.  My first pass looked like
> > this:
> >
> >       Code_Value : String :=
> >
> "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-";
> >       Clear : Unbounded_String := To_Unbounded_String("");
> >
> >       Part_1     : Unsigned_32 := 0;
> >       Part_2     : Unsigned_32 := 0;
> >       Part_3     : Unsigned_32 := 0;
> >       Part_4     : Unsigned_32 := 0;
> >
> >       Segment    : Unsigned_32 := 0;
> >
> >       Val_1      : Unsigned_32;
> >       Val_2      : Unsigned_32;
> >       Val_3      : Unsigned_32;
> >
> >  (some more vars and such)
> >
> >       while Spot <= Coded'Last loop
> >          -- take four six-bit hunks
> >          Part_1 := Unsigned_32(Index(Code_Value, Coded(Spot
>  ..Spot  )) -1);
> >          Part_2 := Unsigned_32(Index(Code_Value,
> Coded(Spot+1..Spot+1)) -1);
> >          Part_3 := Unsigned_32(Index(Code_Value,
> Coded(Spot+2..Spot+2)) -1);
> >          Part_4 := Unsigned_32(Index(Code_Value,
> Coded(Spot+3..Spot+3)) -1);
> >
> >          -- assemble them into one segment
> >          Segment := (Shift_Left(Part_1, 18) and 16#fc0000#) or
> >                     (Shift_Left(Part_2, 12) and 16#03f000#) or
> >                     (Shift_Left(Part_3,  6) and 16#000fc0#) or
> >                     (Shift_left(Part_4,  0) and 16#00003f#)   ;
> >
> >          -- split segment into three eight-bit hunks
> >          Val_1 := (Shift_Right(Segment and 16#ff0000#, 16));
> >          Val_2 := (Shift_Right(Segment and 16#00ff00#,  8));
> >          Val_3 := (Shift_Right(Segment and 16#0000ff#,  0));
> >
> >          -- (now do some more stuff)
> >       end loop;
> >
> > This worked, but it seemed a little klunky.  Figuring there ought to
> > be a better way, I tried an Unchecked_Conversion:
> >
> >       type Six_Bits is mod 2**6;
> >       type Four_Sixes is array (0..3) of Six_Bits;
> >       type Four_Group is record
> >          Part : Four_Sixes;
> >       end record;
> >       for Four_Group'Size use 24;
> >
> >       type Eight_Bits is mod 2**8;
> >       type Three_Eights is array (0..2) of Eight_Bits;
> >       type Three_Group is record
> >          Part : Three_Eights;
> >       end record;
> >       for Three_Group'Size use 24;
> >
> > But the compiler (gnat 3.13p) won't let me do this: it says:
> >
> >     size for "Four_Group" too small, minimum allowed is 32
> >
> >
> > Well, I figure, maybe there's some array overhead that I didn't account
> > for.  Except that it doesn't have any problem with the Three_Group being
> > 24 bits, and that's also an array.  But anyway, as a test, I rewrote it
> > like this:
> >
> >       type Six_Bits is mod 2**6;
> >       type Four_Sixes is array (0..3) of Six_Bits;
> >       type Four_Group is record
> >          Part1, Part2, Part3, Part4 : Six_Bits;
> >       end record;
> >       for Four_Group'Size use 24;
> >
> >       type Eight_Bits is mod 2**8;
> >       type Three_Eights is array (0..2) of Eight_Bits;
> >       type Three_Group is record
> >          Part1, Part2, Part3 : Eight_Bits;
> >       end record;
> >       for Three_Group'Size use 24;
> >
> >
> > It still won't let me do that: the minimum size for a Four_Group is
> > still 32 bits.  Okay, so I set the Four_Group'Size to 32.  Now it
> > quite reasonably complains that the sizes for my Unchecked_Conversion
> > are different.
> >
> > My best guess at this point was that it insisted on using a full byte
> > to represent the Six_Bits type, but when I put in:
> >
> >     for Six_Bits'Size use 6;
> >
> > there was no complaint.  But four six-bit things require 32 bits to
> > store, even though three eight-bit things fits in 24.
> >
> >
> > When I turn on debugging (Ada.Command_Line, Getopt, and a -D switch
> > can save a lot of time), I discover that after the Unchecked_Conversion,
> > the three eight-bit elements have the exact same values as the first
> > three six-bit elements.  So my only guess now is that even though the
> > six-bit things are six bits big, they're being byte-aligned.
> >
> > ANYWAY, I got to the point where I was throwing in things such as
> >
> >     pragma Pack(Four_Sixes);
> >     for Four_Sixes'Size use 24;
> >
> > And it still doesn't make any difference.  The four-element array of
> > six bit objects is 24 bits without a complaint, but the record still
> > has to be 32 bits.
> >
> >
> > So that led me to one more try: dispense with the records, and just
> > do an Unchecked_Conversion directly on the arrays.  The compiler is
> > happy with it, both array sizes are 24 bits, and the code runs without
> > crashing.  But the results make no sense.
> >
> > If I put in C3zY, which map to 28, 55, 25, and 50, I see this:
> >
> >     Put in:       28     55     25     50
> >               011100 110111 011001 110010
> >
> >     Expect:      115      118      114
> >             01110011 01110110 01110010
> >
> >     Actual:      220      157      201
> >             11011100 10011101 11001001
> >
> > I can't see where the resulting bits that actually come out are from.
> > They don't seem to bear any relation to the bits that went in.
> >
> >
> > Suggestions?  (Yes, this can be done in C, but I'm trying to learn a
> > new language, not write everything in the old one.)
> >
> >
> > Darren Provine ! kilroy@elvis.rowan.edu ! http://www.rowan.edu/~kilroy
> > "There's nothing in human experience compared to which a sendmail config
> >  file could be considered simple." -- anonymous
>
>
> _______________________________________________
> comp.lang.ada mailing list
> comp.lang.ada@ada.eu.org
> http://ada.eu.org/mailman/listinfo/comp.lang.ada
>
>





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Minimum Record Size?  LONG
  2003-04-27 12:06   ` David C. Hoos
@ 2003-04-27 14:17     ` Steve
  2003-04-27 20:25       ` David C. Hoos
  0 siblings, 1 reply; 13+ messages in thread
From: Steve @ 2003-04-27 14:17 UTC (permalink / raw)


If I add the function:
  function To_Eight_Bits_String( value : Eight_Bits_Type ) return String is
    use Ada.Strings;
    use Ada.Strings.Fixed;
    temp_string : String( 1 .. 32 );
    result : String( 1 .. 8 );
    first  : Positive;
    last   : Positive;
  begin
    Eight_Bits_Io.Put( temp_String, value, 2 );
    first := Index( temp_string, "#" ) + 1;
    last  := Index( temp_String, "#", Backward ) - 1;
    Move( Source  => temp_string( first .. last ),
          Target  => result,
          Drop    => left,
          Justify => right,
          Pad     => '0' );
    return result;
  end To_Eight_Bits_String;

And the modify the main to read:

  for idx in 0 .. 23 loop
    sb1 := 0;
    sb2 := 0;
    sb3 := 0;
    sb4 := 0;
    case idx is
      when 0 .. 5 =>
        sb1 := 2 ** idx;
      when 6 .. 11 =>
        sb2 := 2 ** (idx - 6);
      when 12 .. 17 =>
        sb3 := 2 ** (idx - 12);
      when 18 .. 23 =>
        sb4 := 2 ** (idx - 18);
    end case;
    Conv_4x6_to_8x3( sb1, sb2, sb3, sb4, eb1, eb2, eb3 );
    Ada.Text_Io.Put( To_Eight_Bits_String( eb3 ) & " " );
    Ada.Text_Io.Put( To_Eight_Bits_String( eb2 ) & " " );
    Ada.Text_Io.Put_Line( To_Eight_Bits_String( eb1 ) );
  end loop;

I get the result:
00000000 00000000 00000001
00000000 00000000 00000010
00000000 00000000 00000100
00000000 00000000 00001000
00000000 00000000 00010000
00000000 00000000 00100000
00000000 00000000 01000000
00000000 00000000 10000000
00000000 00000001 00000000
00000000 00000010 00000000
00000000 00000100 00000000
00000000 00001000 00000000
00000000 00010000 00000000
00000000 00100000 00000000
00000000 01000000 00000000
00000000 10000000 00000000
00000001 00000000 00000000
00000010 00000000 00000000
00000100 00000000 00000000
00001000 00000000 00000000
00010000 00000000 00000000
00100000 00000000 00000000
01000000 00000000 00000000
10000000 00000000 00000000

Which is what I expect.  If a different ordering of the combination
of 3 six bit values to 8 bit values is desired, the function arguments
may be re-ordered.

Steve
(The Duck)

"David C. Hoos" <david.c.hoos.sr@ada95.com> wrote in message
news:NzPqa.24413$C%4.24334@fe10.atl2.webusenet.com...
> The problem with this approach is that it gives incorrect results.
>
> If you put in the original poster's input values, you get the
> same incorrect results that he did.
>
> Testing with four inputs having only one bit set is not really
> "tested."
>
> "Steve" <nospam_steved94@attbi.com> wrote in message
> news:UVlqa.620033$3D1.340565@sccrnsc01...
> >
> > Here's an approach taking advantage of using "Slices" of arrays (tested
> > w/Gnat3.15p-nt):
> >
> > with Ada.Text_Io;
> > with Ada.Unchecked_Conversion;
> >
> > procedure Shift6to8 is
> >
> >   type Six_Bits_Type is mod 2**6;
> >   for Six_Bits_Type'Size use 6;
> >
> >   type Eight_Bits_Type is mod 2**8;
> >   for Eight_Bits_Type'Size use 8;
> >
> >   package Eight_Bits_Io is
> >     new Ada.Text_Io.Modular_Io( Eight_Bits_Type );
> >
> >   procedure Conv_4x6_to_8x3( in1, in2, in3, in4 : Six_Bits_Type;
> >                              out1, out2, out3   : out Eight_Bits_Type )
is
> >     type Bit_Array_Type is array( positive range <> ) of Boolean;
> >     pragma pack( Bit_Array_Type );
> >
> >     subtype Six_Bits_Array_Type is Bit_Array_Type( 1 .. 6 );
> >     subtype Eight_Bits_Array_Type is Bit_Array_Type( 1 .. 8 );
> >
> >     function Conv is
> >       new Ada.Unchecked_Conversion( Six_Bits_Type,
Six_Bits_Array_Type );
> >     function Conv is
> >       new Ada.Unchecked_Conversion( Eight_Bits_Array_Type,
> > Eight_Bits_Type );
> >
> >     combined : Bit_Array_Type := Conv( in1 ) & Conv( in2 ) & Conv( in3 )
&
> > Conv( in4 );
> >   begin
> >     out1 := Conv( combined( 1 .. 8 ) );
> >     out2 := Conv( combined( 9 .. 16 ) );
> >     out3 := Conv( combined( 17 .. 24 ) );
> >   end Conv_4x6_to_8x3;
> >
> >   sb1, sb2, sb3, sb4 : Six_Bits_Type;
> >   eb1, eb2, eb3 : Eight_Bits_Type;
> >
> > begin
> >   sb1 := 1;
> >   sb2 := 1;
> >   sb3 := 1;
> >   sb4 := 1;
> >   Conv_4x6_to_8x3( sb1, sb2, sb3, sb4, eb1, eb2, eb3 );
> >   Eight_Bits_Io.Put( eb1, 4, 2 );
> >   Ada.Text_Io.New_Line;
> >   Eight_Bits_Io.Put( eb2, 4, 2 );
> >   Ada.Text_Io.New_Line;
> >   Eight_Bits_Io.Put( eb3, 4, 2 );
> >   Ada.Text_Io.New_Line;
> > end Shift6to8;
> >
> >
> > "Dr Nancy's Sweetie" <kilroy@elvis.rowan.edu> wrote in message
> > news:Hrdqa.9680$io.307974@iad-read.news.verio.net...
> > >
> > > I'm working on a program which has to take four six-bit hunks of data
> > > and regroup them into three eight-bit hunks.  My first pass looked
like
> > > this:
> > >
> > >       Code_Value : String :=
> > >
> > "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-";
> > >       Clear : Unbounded_String := To_Unbounded_String("");
> > >
> > >       Part_1     : Unsigned_32 := 0;
> > >       Part_2     : Unsigned_32 := 0;
> > >       Part_3     : Unsigned_32 := 0;
> > >       Part_4     : Unsigned_32 := 0;
> > >
> > >       Segment    : Unsigned_32 := 0;
> > >
> > >       Val_1      : Unsigned_32;
> > >       Val_2      : Unsigned_32;
> > >       Val_3      : Unsigned_32;
> > >
> > >  (some more vars and such)
> > >
> > >       while Spot <= Coded'Last loop
> > >          -- take four six-bit hunks
> > >          Part_1 := Unsigned_32(Index(Code_Value, Coded(Spot
> >  ..Spot  )) -1);
> > >          Part_2 := Unsigned_32(Index(Code_Value,
> > Coded(Spot+1..Spot+1)) -1);
> > >          Part_3 := Unsigned_32(Index(Code_Value,
> > Coded(Spot+2..Spot+2)) -1);
> > >          Part_4 := Unsigned_32(Index(Code_Value,
> > Coded(Spot+3..Spot+3)) -1);
> > >
> > >          -- assemble them into one segment
> > >          Segment := (Shift_Left(Part_1, 18) and 16#fc0000#) or
> > >                     (Shift_Left(Part_2, 12) and 16#03f000#) or
> > >                     (Shift_Left(Part_3,  6) and 16#000fc0#) or
> > >                     (Shift_left(Part_4,  0) and 16#00003f#)   ;
> > >
> > >          -- split segment into three eight-bit hunks
> > >          Val_1 := (Shift_Right(Segment and 16#ff0000#, 16));
> > >          Val_2 := (Shift_Right(Segment and 16#00ff00#,  8));
> > >          Val_3 := (Shift_Right(Segment and 16#0000ff#,  0));
> > >
> > >          -- (now do some more stuff)
> > >       end loop;
> > >
> > > This worked, but it seemed a little klunky.  Figuring there ought to
> > > be a better way, I tried an Unchecked_Conversion:
> > >
> > >       type Six_Bits is mod 2**6;
> > >       type Four_Sixes is array (0..3) of Six_Bits;
> > >       type Four_Group is record
> > >          Part : Four_Sixes;
> > >       end record;
> > >       for Four_Group'Size use 24;
> > >
> > >       type Eight_Bits is mod 2**8;
> > >       type Three_Eights is array (0..2) of Eight_Bits;
> > >       type Three_Group is record
> > >          Part : Three_Eights;
> > >       end record;
> > >       for Three_Group'Size use 24;
> > >
> > > But the compiler (gnat 3.13p) won't let me do this: it says:
> > >
> > >     size for "Four_Group" too small, minimum allowed is 32
> > >
> > >
> > > Well, I figure, maybe there's some array overhead that I didn't
account
> > > for.  Except that it doesn't have any problem with the Three_Group
being
> > > 24 bits, and that's also an array.  But anyway, as a test, I rewrote
it
> > > like this:
> > >
> > >       type Six_Bits is mod 2**6;
> > >       type Four_Sixes is array (0..3) of Six_Bits;
> > >       type Four_Group is record
> > >          Part1, Part2, Part3, Part4 : Six_Bits;
> > >       end record;
> > >       for Four_Group'Size use 24;
> > >
> > >       type Eight_Bits is mod 2**8;
> > >       type Three_Eights is array (0..2) of Eight_Bits;
> > >       type Three_Group is record
> > >          Part1, Part2, Part3 : Eight_Bits;
> > >       end record;
> > >       for Three_Group'Size use 24;
> > >
> > >
> > > It still won't let me do that: the minimum size for a Four_Group is
> > > still 32 bits.  Okay, so I set the Four_Group'Size to 32.  Now it
> > > quite reasonably complains that the sizes for my Unchecked_Conversion
> > > are different.
> > >
> > > My best guess at this point was that it insisted on using a full byte
> > > to represent the Six_Bits type, but when I put in:
> > >
> > >     for Six_Bits'Size use 6;
> > >
> > > there was no complaint.  But four six-bit things require 32 bits to
> > > store, even though three eight-bit things fits in 24.
> > >
> > >
> > > When I turn on debugging (Ada.Command_Line, Getopt, and a -D switch
> > > can save a lot of time), I discover that after the
Unchecked_Conversion,
> > > the three eight-bit elements have the exact same values as the first
> > > three six-bit elements.  So my only guess now is that even though the
> > > six-bit things are six bits big, they're being byte-aligned.
> > >
> > > ANYWAY, I got to the point where I was throwing in things such as
> > >
> > >     pragma Pack(Four_Sixes);
> > >     for Four_Sixes'Size use 24;
> > >
> > > And it still doesn't make any difference.  The four-element array of
> > > six bit objects is 24 bits without a complaint, but the record still
> > > has to be 32 bits.
> > >
> > >
> > > So that led me to one more try: dispense with the records, and just
> > > do an Unchecked_Conversion directly on the arrays.  The compiler is
> > > happy with it, both array sizes are 24 bits, and the code runs without
> > > crashing.  But the results make no sense.
> > >
> > > If I put in C3zY, which map to 28, 55, 25, and 50, I see this:
> > >
> > >     Put in:       28     55     25     50
> > >               011100 110111 011001 110010
> > >
> > >     Expect:      115      118      114
> > >             01110011 01110110 01110010
> > >
> > >     Actual:      220      157      201
> > >             11011100 10011101 11001001
> > >
> > > I can't see where the resulting bits that actually come out are from.
> > > They don't seem to bear any relation to the bits that went in.
> > >
> > >
> > > Suggestions?  (Yes, this can be done in C, but I'm trying to learn a
> > > new language, not write everything in the old one.)
> > >
> > >
> > > Darren Provine ! kilroy@elvis.rowan.edu ! http://www.rowan.edu/~kilroy
> > > "There's nothing in human experience compared to which a sendmail
config
> > >  file could be considered simple." -- anonymous
> >
> >
> > _______________________________________________
> > comp.lang.ada mailing list
> > comp.lang.ada@ada.eu.org
> > http://ada.eu.org/mailman/listinfo/comp.lang.ada
> >
> >
>
>





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Minimum Record Size?  LONG
  2003-04-27 14:17     ` Steve
@ 2003-04-27 20:25       ` David C. Hoos
  2003-04-28  5:04         ` Steve
  0 siblings, 1 reply; 13+ messages in thread
From: David C. Hoos @ 2003-04-27 20:25 UTC (permalink / raw)


I haven't communicated my point very well.

The slice approach is not endianness-independent.

The arithmetic approach given by Tom Moran which was an
improvement on my original submission is endianness-independent
(as was my original submission).

The point is that merely re-ordering the parameters to
your procedure will not work on a big-endian machine
without re-coding the procedure itself.

The bit orders need to be reversed, as well.

"Steve" <nospam_steved94@attbi.com> wrote in message
news:yDRqa.638235$3D1.352789@sccrnsc01...
> If I add the function:
>   function To_Eight_Bits_String( value : Eight_Bits_Type ) return String
is
>     use Ada.Strings;
>     use Ada.Strings.Fixed;
>     temp_string : String( 1 .. 32 );
>     result : String( 1 .. 8 );
>     first  : Positive;
>     last   : Positive;
>   begin
>     Eight_Bits_Io.Put( temp_String, value, 2 );
>     first := Index( temp_string, "#" ) + 1;
>     last  := Index( temp_String, "#", Backward ) - 1;
>     Move( Source  => temp_string( first .. last ),
>           Target  => result,
>           Drop    => left,
>           Justify => right,
>           Pad     => '0' );
>     return result;
>   end To_Eight_Bits_String;
>
> And the modify the main to read:
>
>   for idx in 0 .. 23 loop
>     sb1 := 0;
>     sb2 := 0;
>     sb3 := 0;
>     sb4 := 0;
>     case idx is
>       when 0 .. 5 =>
>         sb1 := 2 ** idx;
>       when 6 .. 11 =>
>         sb2 := 2 ** (idx - 6);
>       when 12 .. 17 =>
>         sb3 := 2 ** (idx - 12);
>       when 18 .. 23 =>
>         sb4 := 2 ** (idx - 18);
>     end case;
>     Conv_4x6_to_8x3( sb1, sb2, sb3, sb4, eb1, eb2, eb3 );
>     Ada.Text_Io.Put( To_Eight_Bits_String( eb3 ) & " " );
>     Ada.Text_Io.Put( To_Eight_Bits_String( eb2 ) & " " );
>     Ada.Text_Io.Put_Line( To_Eight_Bits_String( eb1 ) );
>   end loop;
>
> I get the result:
> 00000000 00000000 00000001
> 00000000 00000000 00000010
> 00000000 00000000 00000100
> 00000000 00000000 00001000
> 00000000 00000000 00010000
> 00000000 00000000 00100000
> 00000000 00000000 01000000
> 00000000 00000000 10000000
> 00000000 00000001 00000000
> 00000000 00000010 00000000
> 00000000 00000100 00000000
> 00000000 00001000 00000000
> 00000000 00010000 00000000
> 00000000 00100000 00000000
> 00000000 01000000 00000000
> 00000000 10000000 00000000
> 00000001 00000000 00000000
> 00000010 00000000 00000000
> 00000100 00000000 00000000
> 00001000 00000000 00000000
> 00010000 00000000 00000000
> 00100000 00000000 00000000
> 01000000 00000000 00000000
> 10000000 00000000 00000000
>
> Which is what I expect.  If a different ordering of the combination
> of 3 six bit values to 8 bit values is desired, the function arguments
> may be re-ordered.
>
> Steve
> (The Duck)
>
> "David C. Hoos" <david.c.hoos.sr@ada95.com> wrote in message
> news:NzPqa.24413$C%4.24334@fe10.atl2.webusenet.com...
> > The problem with this approach is that it gives incorrect results.
> >
> > If you put in the original poster's input values, you get the
> > same incorrect results that he did.
> >
> > Testing with four inputs having only one bit set is not really
> > "tested."
> >
> > "Steve" <nospam_steved94@attbi.com> wrote in message
> > news:UVlqa.620033$3D1.340565@sccrnsc01...
> > >
> > > Here's an approach taking advantage of using "Slices" of arrays
(tested
> > > w/Gnat3.15p-nt):
> > >
> > > with Ada.Text_Io;
> > > with Ada.Unchecked_Conversion;
> > >
> > > procedure Shift6to8 is
> > >
> > >   type Six_Bits_Type is mod 2**6;
> > >   for Six_Bits_Type'Size use 6;
> > >
> > >   type Eight_Bits_Type is mod 2**8;
> > >   for Eight_Bits_Type'Size use 8;
> > >
> > >   package Eight_Bits_Io is
> > >     new Ada.Text_Io.Modular_Io( Eight_Bits_Type );
> > >
> > >   procedure Conv_4x6_to_8x3( in1, in2, in3, in4 : Six_Bits_Type;
> > >                              out1, out2, out3   : out
Eight_Bits_Type )
> is
> > >     type Bit_Array_Type is array( positive range <> ) of Boolean;
> > >     pragma pack( Bit_Array_Type );
> > >
> > >     subtype Six_Bits_Array_Type is Bit_Array_Type( 1 .. 6 );
> > >     subtype Eight_Bits_Array_Type is Bit_Array_Type( 1 .. 8 );
> > >
> > >     function Conv is
> > >       new Ada.Unchecked_Conversion( Six_Bits_Type,
> Six_Bits_Array_Type );
> > >     function Conv is
> > >       new Ada.Unchecked_Conversion( Eight_Bits_Array_Type,
> > > Eight_Bits_Type );
> > >
> > >     combined : Bit_Array_Type := Conv( in1 ) & Conv( in2 ) & Conv(
in3 )
> &
> > > Conv( in4 );
> > >   begin
> > >     out1 := Conv( combined( 1 .. 8 ) );
> > >     out2 := Conv( combined( 9 .. 16 ) );
> > >     out3 := Conv( combined( 17 .. 24 ) );
> > >   end Conv_4x6_to_8x3;
> > >
> > >   sb1, sb2, sb3, sb4 : Six_Bits_Type;
> > >   eb1, eb2, eb3 : Eight_Bits_Type;
> > >
> > > begin
> > >   sb1 := 1;
> > >   sb2 := 1;
> > >   sb3 := 1;
> > >   sb4 := 1;
> > >   Conv_4x6_to_8x3( sb1, sb2, sb3, sb4, eb1, eb2, eb3 );
> > >   Eight_Bits_Io.Put( eb1, 4, 2 );
> > >   Ada.Text_Io.New_Line;
> > >   Eight_Bits_Io.Put( eb2, 4, 2 );
> > >   Ada.Text_Io.New_Line;
> > >   Eight_Bits_Io.Put( eb3, 4, 2 );
> > >   Ada.Text_Io.New_Line;
> > > end Shift6to8;
> > >
> > >
> > > "Dr Nancy's Sweetie" <kilroy@elvis.rowan.edu> wrote in message
> > > news:Hrdqa.9680$io.307974@iad-read.news.verio.net...
> > > >
> > > > I'm working on a program which has to take four six-bit hunks of
data
> > > > and regroup them into three eight-bit hunks.  My first pass looked
> like
> > > > this:
> > > >
> > > >       Code_Value : String :=
> > > >
> > > "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-";
> > > >       Clear : Unbounded_String := To_Unbounded_String("");
> > > >
> > > >       Part_1     : Unsigned_32 := 0;
> > > >       Part_2     : Unsigned_32 := 0;
> > > >       Part_3     : Unsigned_32 := 0;
> > > >       Part_4     : Unsigned_32 := 0;
> > > >
> > > >       Segment    : Unsigned_32 := 0;
> > > >
> > > >       Val_1      : Unsigned_32;
> > > >       Val_2      : Unsigned_32;
> > > >       Val_3      : Unsigned_32;
> > > >
> > > >  (some more vars and such)
> > > >
> > > >       while Spot <= Coded'Last loop
> > > >          -- take four six-bit hunks
> > > >          Part_1 := Unsigned_32(Index(Code_Value, Coded(Spot
> > >  ..Spot  )) -1);
> > > >          Part_2 := Unsigned_32(Index(Code_Value,
> > > Coded(Spot+1..Spot+1)) -1);
> > > >          Part_3 := Unsigned_32(Index(Code_Value,
> > > Coded(Spot+2..Spot+2)) -1);
> > > >          Part_4 := Unsigned_32(Index(Code_Value,
> > > Coded(Spot+3..Spot+3)) -1);
> > > >
> > > >          -- assemble them into one segment
> > > >          Segment := (Shift_Left(Part_1, 18) and 16#fc0000#) or
> > > >                     (Shift_Left(Part_2, 12) and 16#03f000#) or
> > > >                     (Shift_Left(Part_3,  6) and 16#000fc0#) or
> > > >                     (Shift_left(Part_4,  0) and 16#00003f#)   ;
> > > >
> > > >          -- split segment into three eight-bit hunks
> > > >          Val_1 := (Shift_Right(Segment and 16#ff0000#, 16));
> > > >          Val_2 := (Shift_Right(Segment and 16#00ff00#,  8));
> > > >          Val_3 := (Shift_Right(Segment and 16#0000ff#,  0));
> > > >
> > > >          -- (now do some more stuff)
> > > >       end loop;
> > > >
> > > > This worked, but it seemed a little klunky.  Figuring there ought to
> > > > be a better way, I tried an Unchecked_Conversion:
> > > >
> > > >       type Six_Bits is mod 2**6;
> > > >       type Four_Sixes is array (0..3) of Six_Bits;
> > > >       type Four_Group is record
> > > >          Part : Four_Sixes;
> > > >       end record;
> > > >       for Four_Group'Size use 24;
> > > >
> > > >       type Eight_Bits is mod 2**8;
> > > >       type Three_Eights is array (0..2) of Eight_Bits;
> > > >       type Three_Group is record
> > > >          Part : Three_Eights;
> > > >       end record;
> > > >       for Three_Group'Size use 24;
> > > >
> > > > But the compiler (gnat 3.13p) won't let me do this: it says:
> > > >
> > > >     size for "Four_Group" too small, minimum allowed is 32
> > > >
> > > >
> > > > Well, I figure, maybe there's some array overhead that I didn't
> account
> > > > for.  Except that it doesn't have any problem with the Three_Group
> being
> > > > 24 bits, and that's also an array.  But anyway, as a test, I rewrote
> it
> > > > like this:
> > > >
> > > >       type Six_Bits is mod 2**6;
> > > >       type Four_Sixes is array (0..3) of Six_Bits;
> > > >       type Four_Group is record
> > > >          Part1, Part2, Part3, Part4 : Six_Bits;
> > > >       end record;
> > > >       for Four_Group'Size use 24;
> > > >
> > > >       type Eight_Bits is mod 2**8;
> > > >       type Three_Eights is array (0..2) of Eight_Bits;
> > > >       type Three_Group is record
> > > >          Part1, Part2, Part3 : Eight_Bits;
> > > >       end record;
> > > >       for Three_Group'Size use 24;
> > > >
> > > >
> > > > It still won't let me do that: the minimum size for a Four_Group is
> > > > still 32 bits.  Okay, so I set the Four_Group'Size to 32.  Now it
> > > > quite reasonably complains that the sizes for my
Unchecked_Conversion
> > > > are different.
> > > >
> > > > My best guess at this point was that it insisted on using a full
byte
> > > > to represent the Six_Bits type, but when I put in:
> > > >
> > > >     for Six_Bits'Size use 6;
> > > >
> > > > there was no complaint.  But four six-bit things require 32 bits to
> > > > store, even though three eight-bit things fits in 24.
> > > >
> > > >
> > > > When I turn on debugging (Ada.Command_Line, Getopt, and a -D switch
> > > > can save a lot of time), I discover that after the
> Unchecked_Conversion,
> > > > the three eight-bit elements have the exact same values as the first
> > > > three six-bit elements.  So my only guess now is that even though
the
> > > > six-bit things are six bits big, they're being byte-aligned.
> > > >
> > > > ANYWAY, I got to the point where I was throwing in things such as
> > > >
> > > >     pragma Pack(Four_Sixes);
> > > >     for Four_Sixes'Size use 24;
> > > >
> > > > And it still doesn't make any difference.  The four-element array of
> > > > six bit objects is 24 bits without a complaint, but the record still
> > > > has to be 32 bits.
> > > >
> > > >
> > > > So that led me to one more try: dispense with the records, and just
> > > > do an Unchecked_Conversion directly on the arrays.  The compiler is
> > > > happy with it, both array sizes are 24 bits, and the code runs
without
> > > > crashing.  But the results make no sense.
> > > >
> > > > If I put in C3zY, which map to 28, 55, 25, and 50, I see this:
> > > >
> > > >     Put in:       28     55     25     50
> > > >               011100 110111 011001 110010
> > > >
> > > >     Expect:      115      118      114
> > > >             01110011 01110110 01110010
> > > >
> > > >     Actual:      220      157      201
> > > >             11011100 10011101 11001001
> > > >
> > > > I can't see where the resulting bits that actually come out are
from.
> > > > They don't seem to bear any relation to the bits that went in.
> > > >
> > > >
> > > > Suggestions?  (Yes, this can be done in C, but I'm trying to learn a
> > > > new language, not write everything in the old one.)
> > > >
> > > >
> > > > Darren Provine ! kilroy@elvis.rowan.edu !
http://www.rowan.edu/~kilroy
> > > > "There's nothing in human experience compared to which a sendmail
> config
> > > >  file could be considered simple." -- anonymous
> > >
> > >
> > > _______________________________________________
> > > comp.lang.ada mailing list
> > > comp.lang.ada@ada.eu.org
> > > http://ada.eu.org/mailman/listinfo/comp.lang.ada
> > >
> > >
> >
> >
>
>
> _______________________________________________
> comp.lang.ada mailing list
> comp.lang.ada@ada.eu.org
> http://ada.eu.org/mailman/listinfo/comp.lang.ada
>
>





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Minimum Record Size?  LONG
  2003-04-27 20:25       ` David C. Hoos
@ 2003-04-28  5:04         ` Steve
  0 siblings, 0 replies; 13+ messages in thread
From: Steve @ 2003-04-28  5:04 UTC (permalink / raw)


Maybe I'm dense, but I just can't see why the slice approach isn't endian
independent.  I would expect the mapping to be something like:

  Sixbit(1) bit 0 => Eightbit(1) bit 0
  Sixbit(1) bit 1 => Eightbit(1) bit 1
  Sixbit(1) bit 2 => Eightbit(1) bit 2
  Sixbit(1) bit 3 => Eightbit(1) bit 3
  Sixbit(1) bit 4 => Eightbit(1) bit 4
  Sixbit(1) bit 5 => Eightbit(1) bit 5
  Sixbit(2) bit 0 => Eightbit(1) bit 6
  Sixbit(2) bit 1 => Eightbit(1) bit 7
  Sixbit(2) bit 2 => Eightbit(2) bit 0
  Sixbit(2) bit 3 => Eightbit(2) bit 1
  Sixbit(2) bit 4 => Eightbit(2) bit 2
  Sixbit(2) bit 5 => Eightbit(2) bit 3
  Sixbit(3) bit 0 => Eightbit(2) bit 4
  Sixbit(3) bit 1 => Eightbit(2) bit 5
  Sixbit(3) bit 2 => Eightbit(2) bit 6
  Sixbit(3) bit 3 => Eightbit(2) bit 7
  Sixbit(3) bit 4 => Eightbit(3) bit 0
  Sixbit(3) bit 5 => Eightbit(3) bit 1
  Sixbit(4) bit 0 => Eightbit(3) bit 2
  Sixbit(4) bit 1 => Eightbit(3) bit 3
  Sixbit(4) bit 2 => Eightbit(3) bit 4
  Sixbit(4) bit 3 => Eightbit(3) bit 5
  Sixbit(4) bit 4 => Eightbit(3) bit 6
  Sixbit(4) bit 5 => Eightbit(3) bit 7

If you want to look at which "bytes" the results fall into, yes I agree that
it is endian independant, thus my remark about re-arranging the result.  I
still think my slice solution works for both endian machines.

I also find the use of shifts an accepatable answer.  I personally don't
like using multiplciation to do shifts.  Use the operation that describes
what you're doing.  Not something that gives the same result.

Steve
(The Duck)


"David C. Hoos" <david.c.hoos.sr@ada95.com> wrote in message
news:4VWqa.39167$b9.13645@fe07.atl2.webusenet.com...
> I haven't communicated my point very well.
>
> The slice approach is not endianness-independent.
>
> The arithmetic approach given by Tom Moran which was an
> improvement on my original submission is endianness-independent
> (as was my original submission).
>
> The point is that merely re-ordering the parameters to
> your procedure will not work on a big-endian machine
> without re-coding the procedure itself.
>
> The bit orders need to be reversed, as well.
>
[snip]





^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2003-04-28  5:04 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-04-25 16:33 Minimum Record Size? LONG Dr Nancy's Sweetie
2003-04-25 17:35 ` Stephen Leake
2003-04-25 17:36 ` Mark Johnson
2003-04-25 21:54   ` tmoran
2003-04-25 18:51 ` David C. Hoos
2003-04-25 21:51   ` tmoran
2003-04-26  3:00     ` David C. Hoos
2003-04-26  2:12 ` Steve
2003-04-27  1:57   ` Rick Stikkers
2003-04-27 12:06   ` David C. Hoos
2003-04-27 14:17     ` Steve
2003-04-27 20:25       ` David C. Hoos
2003-04-28  5:04         ` Steve

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox