* Re: Help with type conversion needed [not found] ` <4cnivs$m1k@flood.weeg.uiowa.edu> @ 1996-01-08 0:00 ` Tucker Taft [not found] ` <dewar.821029372@schonberg> 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
[parent not found: <dewar.821029372@schonberg>]
* 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 ` 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 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 ` 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
[parent not found: <dewar.821197198@schonberg>]
* 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> 1996-01-08 0:00 ` Help with type conversion needed Tucker Taft [not found] ` <dewar.821029372@schonberg> 1996-01-08 0:00 ` 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
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox