comp.lang.ada
 help / color / mirror / Atom feed
* Re: Help with type conversion needed
       [not found]     ` <dewar.821029372@schonberg>
@ 1996-01-08  0:00       ` Nate Bohlmann
  1996-01-08  0:00         ` Robert Dewar
  1996-01-09  0:00         ` Geert Bosch
  0 siblings, 2 replies; 6+ messages in thread
From: Nate Bohlmann @ 1996-01-08  0:00 UTC (permalink / raw)


Robert Dewar (dewar@cs.nyu.edu) wrote:
: Nathan keeps worrying about some bias that needs to be added when
: converting unsigned values to signed and vice versa. The whole point
: of 2's complement notation is that no such bias is required.

: For example 16#FFFF# is either -1 or 65_535 depending on how you
: interprete it (signed or unsigned).

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.   

If I simply interpret the bit pattern as signed or unsigned I will not
keep the relative values that I need.. 

I guess this isn't really a type conversion question so much as a range
conversion question.  I fooled the 2.07 GNAT complier by adding 32767 and 1
and the compiler spit out the proper add but the 3.01 compiler complains
that the addition is out of range (as I think it probably should).

As far as a real example, I'm not quite sure I could give one other than
what I've said above.  It would just be a simple addition that fails in
the semantic checker because what I'm trying to add is out of range.

I think probably the best answer so far is to use a bigger (in terms of
bits).  Is this just a nasty side effect of the strong typing? (btw, I'm
a very strong supporter of the strong typing paradigm lest any of you
get the wrong idea.. :-)  I just would like to be able to do this eloquently
and can't seem to find a way to do it.

Nate

--
Nathan Bohlmann                           preferred->   njb@res.eng.uiowa.edu
Computer Engineering Graduate Student              njb@vu-alumni.elfwerks.com
University of Iowa, Iowa City, IA                           njb@eng.uiowa.edu
use PH at uiowa.edu for more info..                             (319)354-2634
   Dr. Alan Keyes for President! '96      http://sandh.com/keyes/index.html
                  http://vu-alumni.elfwerks.com/~njb




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

* Re: Help with type conversion needed
  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
  1 sibling, 1 reply; 6+ messages in thread
From: Robert Dewar @ 1996-01-08  0:00 UTC (permalink / raw)


iNathan finally explains::

"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."

In otherwords what he wants to do is not a type conversion at all, in that
the result value is different from the input value.

The algorithm is perfectly trivial

Take your original signed value

Uncheck convert to 16-bit modular

add 32768

that's all there is to it!

You do not need to use a larger type at all. Note that the addition of
32768 in modular arithmetic wraps just as you need it to, that is what
modular arithmetic is all about!





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

* Re: Help with type conversion needed
       [not found]   ` <4cnivs$m1k@flood.weeg.uiowa.edu>
       [not found]     ` <dewar.821029372@schonberg>
@ 1996-01-08  0:00     ` Tucker Taft
  1 sibling, 0 replies; 6+ messages in thread
From: Tucker Taft @ 1996-01-08  0:00 UTC (permalink / raw)


Nate Bohlmann (njb@res.eng.uiowa.edu) wrote:
: Tucker Taft (stt@henning.camb.inmet.com) wrote:

: : Unchecked conversion is the reliable way to convert between
: : a 16-bit signed and 16-bit unsigned value.  This is entirely
: : portable, and safe so long as both signed and unsigned subtypes
: : are unconstrained (i.e. cover the full range of values).

: I'm not sure what you mean here..  Obviously unchecked conversion would
: preserve the bit patterns but that's not where I'm having problems.

: Say I have some types as follows:

: type SignedInt is range -32768..32767;
: for SignedInt'Size use 16;

: type UnsignedInt is mod 65536;
: for UnsignedInt'Size use 16;


: Assume the SignedInt is coming off an A/D converter and I want to use
: unsigned values in my calculations and I can't convince the A/D converter
: to return unsigned values.  I believe that in order to keep relative 
: values correct, I would need to add 32768 to the SignedInt variable to 
: get a proper value for the UnsignedInt variable.  

"... to keep relative values correct ..."
This seems to be a critical requirement, which I didn't understand before.
I presumed you wanted to simply interpret the bits as an unsigned number.

In any case, if you have 32-bit ints, then your problem is easy.
Just convert to a 32-bit signed int, add 32768, and convert to
the 16-bit unsigned type.  

However, if you can't do that, then use unchecked conversion to convert 
to the unsigned type, and then add (or subtract) 32768 using unsigned 
modular arithmetic, which wraps around.

: ... How do I go about doing
: this properly and portably?  The added twist of course is that the SignedInt
: is in little-endian format and I'm working on a big-endian machine.  I've 
: solved the twist  ...

This is presumably done with unchecked conversion, or multiply
and add.  If so, then just convert directly to the unsigned modular 
type, and then add 32768.  

There is no need to ever go through a signed type; that is what
is creating your problems.  Use unsigned types exclusively if you
need to do this kind of biasing or bit/byte-level fiddling.
You won't get any overflows.  As soon as you use a signed type,
you can run into overflow problems when trying to do biasing, etc.

: Thanks again..

: Nathan Bohlmann                           preferred->   njb@res.eng.uiowa.edu

-Tucker Taft  stt@inmet.com




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

* Re: Help with type conversion needed
  1996-01-08  0:00         ` Robert Dewar
@ 1996-01-08  0:00           ` Keith Thompson
  0 siblings, 0 replies; 6+ messages in thread
From: Keith Thompson @ 1996-01-08  0:00 UTC (permalink / raw)


In <dewar.821111786@schonberg> dewar@cs.nyu.edu (Robert Dewar) writes:
[...]
> You do not need to use a larger type at all. Note that the addition of
> 32768 in modular arithmetic wraps just as you need it to, that is what
> modular arithmetic is all about!

Assuming that the original poster is using an Ada 95 compiler.  Yes, "Ada"
should now mean "Ada 95" unless otherwise specified, but not everyone
is aware of that.

-- 
Keith Thompson (The_Other_Keith)  kst@thomsoft.com (kst@alsys.com still works)
TeleSoft^H^H^H^H^H^H^H^H Alsys^H^H^H^H^H Thomson Software Products
10251 Vista Sorrento Parkway, Suite 300, San Diego, CA, USA, 92121-2718
Et tu, Barada Nikto?




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

* Re: Help with type conversion needed
  1996-01-08  0:00       ` Help with type conversion needed Nate Bohlmann
  1996-01-08  0:00         ` Robert Dewar
@ 1996-01-09  0:00         ` Geert Bosch
       [not found]           ` <dewar.821197198@schonberg>
  1 sibling, 1 reply; 6+ messages in thread
From: Geert Bosch @ 1996-01-09  0:00 UTC (permalink / raw)


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




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

* Re: Help with type conversion needed
       [not found]           ` <dewar.821197198@schonberg>
@ 1996-01-09  0:00             ` Nate Bohlmann
  0 siblings, 0 replies; 6+ messages in thread
From: Nate Bohlmann @ 1996-01-09  0:00 UTC (permalink / raw)


First of all, let me thank everyone who has been trying to help with this
problem.  This is an area of Ada I am not well versed in at all and I 
appreciate the willingness to wade through a poorly specified problem.

Robert Dewar (dewar@cs.nyu.edu) wrote:
: Geert suggests

:    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;

: I find the use of xor obscure here, and it illustrates a danger of making
: such logical operations available, they tend to get overused.

: In the logical statement of the problem, the issue is to add 32768 to the
: result, so it is much clearer to write:

:       return To_Unsigned (To_Modular(S) + 32_768);


After twiddling with the bits, I now understand why this works.. :-) Thanks
again to everyone who helped out on this..

Nate

--
Nathan Bohlmann                           preferred->   njb@res.eng.uiowa.edu
Computer Engineering Graduate Student              njb@vu-alumni.elfwerks.com
University of Iowa, Iowa City, IA                           njb@eng.uiowa.edu
use PH at uiowa.edu for more info..                             (319)354-2634
   Dr. Alan Keyes for President! '96      http://sandh.com/keyes/index.html
                  http://vu-alumni.elfwerks.com/~njb




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

end of thread, other threads:[~1996-01-09  0:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [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
     [not found]           ` <dewar.821197198@schonberg>
1996-01-09  0:00             ` Nate Bohlmann
1996-01-08  0:00     ` Tucker Taft

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