comp.lang.ada
 help / color / mirror / Atom feed
From: geert@fozzie.sun3.iaf.nl (Geert Bosch)
Subject: Re: Help with type conversion needed
Date: 1996/01/09
Date: 1996-01-09T00:00:00+00:00	[thread overview]
Message-ID: <4cseli$epa@fozzie.sun3.iaf.nl> (raw)
In-Reply-To: 4cq6ku$l5a@flood.weeg.uiowa.edu

In article <4cq6ku$l5a@flood.weeg.uiowa.edu> Nate wrote:
`` Right, and this is why I don't want it to be a noop.  If I have 
   a range of values from -32768 to 32767, and I want to shift that 
   range to 0 to 65535, simply doing a noop is NOT sufficient..  
   i.e. -32768 maps to 0 : and 32767 maps to 65535. -1 should map 
   to 32767, NOT 65535.''

There are at least two logical solutions:

  1) I don't care about the way my conversion is done. I just
     specify the result I want and hope the compiler is smart.

  2) Compilers may be good, but this audio-sample processing software I
     am writing needs optimum peformance and I know how to handle
     this conversion: it can be done with one exclusive-or, so I'll
     show this in my algorithm.

For the first case it makes sense to declare an intermediate type,
which can have all values of both the signed and the unsigned type.
Once you have converted the signed integer to de intermediate type,
you can do the addition and then you can savely convert the new
value to the unsigned integer type. You want get errors with range
checking, but the compiler might insert range checks if it isn't smart.

For the second case the most logical way of doing the conversion is
to use a modular type. Modular types are very nice for doing bit-level
operations on integers. Any compiler should generate efficient code
for modulo 2**N types.

Below is a complete program which shows both approaches and 
does some checks to show the algorithms work well.

What I'm really interested in, is the relative efficiency
of both methods when compiled by actual Ada compilers. For
example, does Method_A use range checks in GNAT? Does
method B only generate a XOR instruction when used inline?

Greetings,
   Geert

BTW: test might not be such a good name for the program, 
     because it conflicts with the Unix command 'test'

=== cut here for test.adb =============================================
with Text_IO;
with Unchecked_Conversion;	-- only needed for Method_B

procedure Test is
   use Text_IO;

   type Signed_16 is range -2**15..2**15 - 1;
      for Signed_16'Size use 16;

   type Unsigned_16 is range 0..2**16 - 1;
      for Unsigned_16'Size use 16;

   -- One way to convert type Signed_16 to Unsigned_16

   function To_Unsigned_16_A(S : Signed_16) return Unsigned_16 is
      type Conversion_Range_16 is range -2**15..2**16 - 1;
   begin
      return Unsigned_16(Conversion_Range_16(S) + 2**15);
   end To_Unsigned_16_A;

   -- Another way to convert type Signed_16 to Unsigned_16

   function To_Unsigned_16_B(S : Signed_16) return Unsigned_16 is
      type Modular_16 is mod 2**16;
      function To_Modular is 
         new Unchecked_Conversion(Signed_16, Modular_16);
      function To_Unsigned is 
         new Unchecked_Conversion(Modular_16, Unsigned_16);
   begin
      return To_Unsigned(To_Modular(S) xor 16#8000#);
   end To_Unsigned_16_B;
   
   -- Function that only does a conversion if both methods' results agree
   
   function To_Unsigned_16(S : Signed_16) return Unsigned_16 is
      U_A : Unsigned_16 := To_Unsigned_16_A(S);
      U_B : Unsigned_16 := To_Unsigned_16_B(S);
   begin
      if U_A /= U_B then
         Put_Line("Conversion functions disagree on signed integer "
            & Signed_16'Image(S));
         raise Program_Error;
      end if;
      return U_A;
   end To_Unsigned_16;
   
   Test_Cases  : array (Integer range <>) of Signed_16
                   := (-32768, -32767, -1, 0, 1, 32767);
                   
   U, U_A, U_B : Unsigned_16;
   S           : Signed_16;

begin
   Put_Line("Checking test cases:");
   for I in Test_Cases'Range loop
      S := Test_Cases(I);
      Put_Line("   Converting signed 16-bit integer "
         & Signed_16'Image(S) & " to an unsigned 16-bit integer");
      
      U_A := To_Unsigned_16_A(S);
      U_B := To_Unsigned_16_B(S);
      
      Put_Line( "   Method A gives " & Unsigned_16'Image(U_A) & ", " &
         "Method B gives " & Unsigned_16'Image(U_B) );
   end loop;
   
   Put_Line("Checking complete range");
   for I in Signed_16'Range loop
      U := To_Unsigned_16(I);
   end loop;
   Put_Line("Method A produces same results as Method B");
end Test;

--
 -- E-Mail: geert@sun3.iaf.nl 
 --  Phone: +31-53-4303054
-- 
E-Mail: geert@sun3.iaf.nl 
 Phone: +31-53-4303054




  parent reply	other threads:[~1996-01-09  0:00 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <4ckmb7$vo0@flood.weeg.uiowa.edu>
     [not found] ` <DKrJpC.9HE.0.-s@inmet.camb.inmet.com>
     [not found]   ` <4cnivs$m1k@flood.weeg.uiowa.edu>
     [not found]     ` <dewar.821029372@schonberg>
1996-01-08  0:00       ` Help with type conversion needed Nate Bohlmann
1996-01-08  0:00         ` Robert Dewar
1996-01-08  0:00           ` Keith Thompson
1996-01-09  0:00         ` Geert Bosch [this message]
     [not found]           ` <dewar.821197198@schonberg>
1996-01-09  0:00             ` Nate Bohlmann
1996-01-08  0:00     ` Tucker Taft
replies disabled

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