Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Is this a guaranteed signed/unsigned conversion?

Reply
Thread Tools

Is this a guaranteed signed/unsigned conversion?

 
 
CBFalconer
Guest
Posts: n/a
 
      05-20-2005
Consider:

#include <stdlib.h>

/* An elementary optimizer is expected to remove most code */
/* Return the absolute value */
unsigned long ulabs(long j)
{
if (0 == LONG_MIN + LONG_MAX) {
if (j < 0) return -j;
else return j;
}
else if (LONG_MIN == j) return 1U + j + ULONG_MAX;
else if (j < 0) return -j;
else return j;
} /* ulabs */

Is this guaranteed to convert all long values to their absolute
unsigned long equivalent, assuming that the desired result is
representable as an unsigned long. Does it work over 2's, 1's
complement and sign-magnitude? Is there a better method? labs()
is not guaranteed.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson

 
Reply With Quote
 
 
 
 
Michael Mair
Guest
Posts: n/a
 
      05-20-2005
CBFalconer wrote:
> Consider:
>
> #include <stdlib.h>
>
> /* An elementary optimizer is expected to remove most code */
> /* Return the absolute value */
> unsigned long ulabs(long j)
> {
> if (0 == LONG_MIN + LONG_MAX) {

Make that <=
> if (j < 0) return -j;
> else return j;
> }
> else if (LONG_MIN == j) return 1U + j + ULONG_MAX;

why not:
else if (j>0)
return j;
else if (j>= -LONG_MAX)
return -j;
else
return ((unsigned long)-(j-(LONG_MIN+LONG_MAX)))-(LONG_MIN+LONG_MAX);
> else if (j < 0) return -j;
> else return j;
> } /* ulabs */
>
> Is this guaranteed to convert all long values to their absolute
> unsigned long equivalent, assuming that the desired result is
> representable as an unsigned long. Does it work over 2's, 1's
> complement and sign-magnitude? Is there a better method? labs()
> is not guaranteed.


If you assume that all bits are used and symmetrically, your
code will work.
Otherwise: what about LONG_MIN < -LONG_MAX-1?

See my annotations. (Burned my dinner over it, so I hope I
did not goof )

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      05-20-2005


CBFalconer wrote:
> Consider:
>
> #include <stdlib.h>
>
> /* An elementary optimizer is expected to remove most code */
> /* Return the absolute value */
> unsigned long ulabs(long j)
> {
> if (0 == LONG_MIN + LONG_MAX) {
> if (j < 0) return -j;
> else return j;
> }
> else if (LONG_MIN == j) return 1U + j + ULONG_MAX;
> else if (j < 0) return -j;
> else return j;
> } /* ulabs */
>
> Is this guaranteed to convert all long values to their absolute
> unsigned long equivalent, assuming that the desired result is
> representable as an unsigned long. Does it work over 2's, 1's
> complement and sign-magnitude? Is there a better method? labs()
> is not guaranteed.


Let's see: The first part handles ones' complement and
signed magnitude, where negation of LONG_MIN is possible.
Straightforward, and correct as far as I can see. By the
way, the `0 == LONG_MIN + LONG_MAX' test could be made
with `#if' instead of with `if', reducing the reliance on
the optimizer's ability to eliminate dead code.

In the two's complement part, the conversion of LONG_MIN
seems wordier than need be: as far as I can tell, it gives
the same result as `return j'. Either way, the result should
be correct if ULONG_MAX == LONG_MAX * 2UL + 1UL, which is the
case on every implementation I've run into. However, I think
the Standard permits perversity, and two kinds of perversity
could cause trouble:

ULONG_MAX == LONG_MAX (that is, the sign bit of
`long' corresponds to a padding bit in `unsigned
long'). In this case your quest is hopeless --
but your assumption excludes it, so perhaps we
needn't worry. Another #if could trigger an
appropriate #error directive if desired.

ULONG_MAX == LONG_MAX * 4UL + 3UL (for example;
this happens if `long' has padding bits that
correspond to value bits of `unsigned long').
In this case, ulabs() would return much too
large a value.

I think there's a simple repair, though. For a negative
two's complement value, first add unity, then negate (this is
known to be safe), then convert to `unsigned long', and finally
add another unity to cancel the first (now negated) addition:

if (j < 0) return -(j + 1) + 1UL;
else return j;

(Note that the first `return' expression is *not* equivalent
to `1UL - (j + 1)', because the conversion to `unsigned long'
occurs at the wrong point in the proceedings. I'd recommend
a goodly block of comments here to discourage tidy-minded
people from making the "obvious" rearrangement -- either that,
or write it as `-++j+1UL' to scare them all away.

As far as I can see, this will cover all cases except
ULONG_MAX == LONG_MAX, already excluded by assumption. It
would even handle ones' complement and signed magnitude,
eliminating the special case at the cost of a smidgen of
unnecessary code.

Of course, I may have overlooked something. "Trust,
but verify."

--


 
Reply With Quote
 
Christian Bau
Guest
Posts: n/a
 
      05-20-2005
In article <>,
CBFalconer <> wrote:

> Consider:
>
> #include <stdlib.h>
>
> /* An elementary optimizer is expected to remove most code */
> /* Return the absolute value */
> unsigned long ulabs(long j)
> {
> if (0 == LONG_MIN + LONG_MAX) {
> if (j < 0) return -j;
> else return j;
> }
> else if (LONG_MIN == j) return 1U + j + ULONG_MAX;
> else if (j < 0) return -j;
> else return j;
> } /* ulabs */
>
> Is this guaranteed to convert all long values to their absolute
> unsigned long equivalent, assuming that the desired result is
> representable as an unsigned long. Does it work over 2's, 1's
> complement and sign-magnitude? Is there a better method? labs()
> is not guaranteed.


I think it will work; I believe it is guaranteed that LONG_MIN +
LONG_MAX is either 0 or -1.

What about this:

unsigned long ulabs (long j) {
return j >= 0 ? (unsigned long) j : 0ul - j;
}

I think this should work. The case j >= 0 is obviously fine. If j < 0,
then evaluating (0ul - j) will convert j to unsigned long; since the
value of j cannot be represented ULONG_MAX + 1 will be added as often as
needed (that is once) giving (j + ULONG_MAX + 1). The subtract operation
gives - (j + ULONG_MAX + 1) and since the result is negative, ULONG_MAX
+ 1 is again added as often as necessary (that is once), giving -j.
 
Reply With Quote
 
Lawrence Kirby
Guest
Posts: n/a
 
      05-21-2005
On Fri, 20 May 2005 20:08:26 +0000, CBFalconer wrote:

> Consider:
>
> #include <stdlib.h>
>
> /* An elementary optimizer is expected to remove most code */
> /* Return the absolute value */
> unsigned long ulabs(long j)
> {
> if (0 == LONG_MIN + LONG_MAX) {
> if (j < 0) return -j;
> else return j;
> }
> else if (LONG_MIN == j) return 1U + j + ULONG_MAX;


That's incorrect if ULONG_MAX is over twice as large as LONG_MAX.
Why not just return 1UL + LONG_MAX.

> else if (j < 0) return -j;
> else return j;
> } /* ulabs */
>
> Is this guaranteed to convert all long values to their absolute
> unsigned long equivalent, assuming that the desired result is
> representable as an unsigned long. Does it work over 2's, 1's
> complement and sign-magnitude? Is there a better method? labs()
> is not guaranteed.


I've used similar to the following in the past:

unsigned long ulabs(long j)
{
return j>=0 ? (unsigned long)j : -(unsigned long)j;
}

Lawrence
 
Reply With Quote
 
Simon Biber
Guest
Posts: n/a
 
      05-21-2005
Lawrence Kirby wrote:
> I've used similar to the following in the past:
>
> unsigned long ulabs(long j)
> {
> return j>=0 ? (unsigned long)j : -(unsigned long)j;
> }


I wonder if anyone ever made a C implementation that allows you to
choose at compile-time whether integers are stored as one's complement,
two's complement or signed magnitude? Of course, emulating operations on
a data type that is not native to the underlying hardware would be very
slow, but I imagine it would be useful for testing your code's
portability to esoteric computers without having them available on the
desktop.

The closest I know of is how GCC allows you to choose whether char is
signed or unsigned.

--
Simon.
 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      05-22-2005
Lawrence Kirby wrote:
> On Fri, 20 May 2005 20:08:26 +0000, CBFalconer wrote:
>

.... snip ...
>>
>> Is this guaranteed to convert all long values to their absolute
>> unsigned long equivalent, assuming that the desired result is
>> representable as an unsigned long. Does it work over 2's, 1's
>> complement and sign-magnitude? Is there a better method? labs()
>> is not guaranteed.

>
> I've used similar to the following in the past:
>
> unsigned long ulabs(long j)
> {
> return j>=0 ? (unsigned long)j : -(unsigned long)j;
> }


I can see nothing wrong with that. Why did I make it so
complicated?

--
Some informative links:
news:news.announce.newusers
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html


 
Reply With Quote
 
Malcolm
Guest
Posts: n/a
 
      05-22-2005

"Simon Biber" <> wrote
> I wonder if anyone ever made a C implementation that allows you to choose
> at compile-time whether integers are stored as one's complement, two's
> complement or signed magnitude?

That would be a really useful tool. Something that compiles C to byte code,
and then produces output based on all sorts of configurable and maybe
eccentric assumptions about type representation.


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Microsoft, Cisco, Comptia, Oracle, Solaris -(Pay after check result) 100% Exam Pass Guaranteed vinay MCSE 1 04-12-2006 08:20 PM
Session ID's - Are these guaranteed unique Ben Fidge ASP .Net 2 09-07-2005 05:45 PM
Pass ANY CISCO exams GUARANTEED! Jason Brennan Cisco 4 06-07-2004 09:41 PM
$5 INSTANT PAYMENTS GUARANTEED mick ASP .Net 0 01-09-2004 03:03 AM
$5 INSTANT PAYMENTS GUARANTEED mick Firefox 0 01-09-2004 02:57 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57