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