[comp.unix.questions] Re^2: Bit Switching - How?

maart@cs.vu.nl (Maarten Litmaath) (04/07/89)

sl@van-bc.UUCP (pri=-10 Stuart Lynne) writes:
\For fast generic swapping I use:

\#define	swap(a,b) {a^=b;b^=a;a^= b;}

Generic? How about floats?
-- 
 "If it isn't aesthetically pleasing, |Maarten Litmaath @ VU Amsterdam:
  it's probably wrong." (jim@bilpin). |maart@cs.vu.nl, mcvax!botter!maart

jlw@lznv.ATT.COM (J.L.WOOD) (04/08/89)

> sl@van-bc.UUCP (pri=-10 Stuart Lynne) writes:
> \For fast generic swapping I use:
> 
> \#define	swap(a,b) {a^=b;b^=a;a^= b;}
> 

Also be careful how you use this algorithm if you are using pointers.
I once used this method in a sorting routine as my basic exchange and
got badly burned.

If a and b point to the same location, you get zero as in 0, nada, goose egg.

Joe Wood
jlw@lznv.ATT.COM

frank@zen.co.uk (Frank Wales) (04/10/89)

In article <1574@lznv.ATT.COM> jlw@lznv.ATT.COM (J.L.WOOD) writes:
>> sl@van-bc.UUCP (pri=-10 Stuart Lynne) writes:
>> \For fast generic swapping I use:
>> 
>> \#define	swap(a,b) {a^=b;b^=a;a^= b;}
>> 
>
>Also be careful how you use this algorithm if you are using pointers.
>I once used this method in a sorting routine as my basic exchange and
>got badly burned.
>
>If a and b point to the same location, you get zero as in 0, nada, goose egg.

Well, this surprised me, since blurfl^blurfl does give 0, but blurfl^0
gives blurfl again, so you should get it back, unless some pretty funky
pointer-to-int conversion is taking place.  I tried the following
myself (admittedly on a fairly well-behaved machine from HP),

#include<stdio.h>
#define ptr_swap(a,b)  (a=(void *)((unsigned long)a^(unsigned long)b),\
			b=(void *)((unsigned long)a^(unsigned long)b),\
			a=(void *)((unsigned long)a^(unsigned long)b))

main(argc,argv)
char *argv[];
{
  char *a=argv[0],*b=argv[0];

  (void)printf("a=%lx, b=%lx\n",(unsigned long)a,(unsigned long)b);
  ptr_swap(a,b);
  (void)printf("a=%lx, b=%lx\n",(unsigned long)a,(unsigned long)b);
  return 0;
}

and got:

a=68023000, b=68023000
a=68023000, b=68023000

I'd be interested to find out the machine on which this XOR trick
fails to swap integral values correctly.  [I hardly ever use it, but
I'd still expect it to work.]  Or is there some portability problem
lurking here that my Monday morning mind has missed?
--
Frank Wales, Systems Manager,        [frank@zen.co.uk<->mcvax!zen.co.uk!frank]
Zengrange Ltd., Greenfield Rd., Leeds, ENGLAND, LS9 8DB. (+44) 532 489048 x217 

frank@zen.co.uk (Frank Wales) (04/11/89)

In article <1558@zen.UUCP> I wrote:
>In article <1574@lznv.ATT.COM> jlw@lznv.ATT.COM (J.L.WOOD) writes:
>>> sl@van-bc.UUCP (pri=-10 Stuart Lynne) writes:
>>> \For fast generic swapping I use:
>>> 
>>> \#define	swap(a,b) {a^=b;b^=a;a^= b;}
>>> 
>>
>>Also be careful how you use this algorithm if you are using pointers.
>>I once used this method in a sorting routine as my basic exchange and
>>got badly burned.
>>
>>If a and b point to the same location, you get zero as in 0, nada, goose egg.
>
>Well, this surprised me, 
[example of why I thought there was no problem deleted]

>I'd be interested to find out the machine on which this XOR trick
>fails to swap integral values correctly.  [I hardly ever use it, but
>I'd still expect it to work.]

And indeed it does, except when a and b are the *same* (not the same
value, but the same object), because the first a^=b toasts both a and b,
and you've lost your recovery information.

>Or is there some portability problem
>lurking here that my Monday morning mind has missed?

Well, it's Tuesday now -- thanks to those who mailed me with a wake-up
call [I did say I hardly used the trick myself; good job, too ;-)].
--
Frank Wales, Systems Manager,        [frank@zen.co.uk<->mcvax!zen.co.uk!frank]
Zengrange Ltd., Greenfield Rd., Leeds, ENGLAND, LS9 8DB. (+44) 532 489048 x217 

chasm@killer.Dallas.TX.US (Charles Marslett) (04/11/89)

In article <1558@zen.UUCP>, frank@zen.co.uk (Frank Wales) writes:
:: In article <1574@lznv.ATT.COM> jlw@lznv.ATT.COM (J.L.WOOD) writes:
:: >> sl@van-bc.UUCP (pri=-10 Stuart Lynne) writes:
:: >> \For fast generic swapping I use:
:: >> 
:: >> \#define	swap(a,b) {a^=b;b^=a;a^= b;}
:: >> 
:: >
:: >Also be careful how you use this algorithm if you are using pointers.
:: >I once used this method in a sorting routine as my basic exchange and
:: >got badly burned.
:: >
:: >If a and b point to the same location, you get zero as in 0, nada, goose egg.
:: 
:: Well, this surprised me, since blurfl^blurfl does give 0, but blurfl^0
:: gives blurfl again, so you should get it back, unless some pretty funky
:: pointer-to-int conversion is taking place.  I tried the following
:: myself (admittedly on a fairly well-behaved machine from HP),

The problem is that the second part "blurfl^0" is really "0^0" and if the
original algorithm works at all, the result of swapping "blurfl" with
"blurfl" will be zero.

:: #include<stdio.h>
:: #define ptr_swap(a,b)  (a=(void *)((unsigned long)a^(unsigned long)b),\
:: 			b=(void *)((unsigned long)a^(unsigned long)b),\
:: 			a=(void *)((unsigned long)a^(unsigned long)b))
:: 
:: main(argc,argv)
:: char *argv[];
:: {
::   char *a=argv[0],*b=argv[0];
:: 
::   (void)printf("a=%lx, b=%lx\n",(unsigned long)a,(unsigned long)b);
::   ptr_swap(a,b);

The mistake you made here is that you are swapping "a" and "b", too uncover
the problem with the macro, try substituting the following line:

    ptr_swap(a,a);

The problem arises with pointers because that is where aliasing (and calling
a subroutine with two arguments that are the same address) becomes a problem,
not because the swapped values are pointers.  What I mean to say, is that the
problem is an aliasing one, not a pointer one (Fie!, I can't say anything
clearly today...).

::   (void)printf("a=%lx, b=%lx\n",(unsigned long)a,(unsigned long)b);
::   return 0;
:: }
:: --
:: Frank Wales, Systems Manager,        [frank@zen.co.uk<->mcvax!zen.co.uk!frank]
:: Zengrange Ltd., Greenfield Rd., Leeds, ENGLAND, LS9 8DB. (+44) 532 489048 x217 

Charles
===========================================================================
Charles Marslett
STB Systems, Inc.  <== Apply all standard disclaimers
Wordmark Systems   <== No disclaimers required -- that's just me
chasm@killer.dallas.tx.us

pinkas@hobbit.intel.com (Israel Pinkas ~) (04/12/89)

In article <1558@zen.UUCP> frank@zen.co.uk (Frank Wales) writes:

> In article <1574@lznv.ATT.COM> jlw@lznv.ATT.COM (J.L.WOOD) writes:
> >> sl@van-bc.UUCP (pri=-10 Stuart Lynne) writes:
> >> \For fast generic swapping I use:
> >> 
> >> \#define	swap(a,b) {a^=b;b^=a;a^= b;}
> >> 
> >
> >Also be careful how you use this algorithm if you are using pointers.
> >I once used this method in a sorting routine as my basic exchange and
> >got badly burned.
> >
> >If a and b point to the same location, you get zero as in 0, nada...
>
> Well, this surprised me, since blurfl^blurfl does give 0, but blurfl^0
> gives blurfl again, so you should get it back, unless some pretty funky
> pointer-to-int conversion is taking place.  I tried the following
> myself (admittedly on a fairly well-behaved machine from HP),

[Code deleted]

> I'd be interested to find out the machine on which this XOR trick
> fails to swap integral values correctly.  [I hardly ever use it, but
> I'd still expect it to work.]  Or is there some portability problem
> lurking here that my Monday morning mind has missed?

This fails if you pass the same object to swap() for both arguments.  The
code that Frank posted passed two copies of the object:

#include <stdio.h>

#define	swap(a,b) {a^=b;b^=a;a^= b;}

main()

{
    int a = 10, b = 10, c = 10;

    printf("a = %x   b = %x   c = %x\n", a, b, c);
    swap(a,a)
    swap(b,c)
    printf("a = %x   b = %x   c = %x\n", a, b, c);
}

Results in:

a = a   b = a   c = a
a = 0   b = a   c = a


A compiler that gives different results is probably broken.

-Israel Pinkas
--
--------------------------------------
Disclaimer: The above are my personal opinions, and in no way represent
the opinions of Intel Corporation.  In no way should the above be taken
to be a statement of Intel.

UUCP:	{amdcad,decwrl,hplabs,oliveb,pur-ee,qantel}!intelca!mipos3!cadev4!pinkas
ARPA:	pinkas%cadev4.intel.com@relay.cs.net
CSNET:	pinkas@cadev4.intel.com

maart@cs.vu.nl (Maarten Litmaath) (04/13/89)

dg@lakart.UUCP (David Goodenough) writes:
\#define	swap(a, b, n)	((a) ^= ((b) & (n)), (b) ^= ((a) & (n)), \
\							(a) ^= ((b) & (n)))

This one still suffers from the following:

	swap(*p, *q, ~0);

where p and q point at the same location.
-- 
 "If it isn't aesthetically pleasing, |Maarten Litmaath @ VU Amsterdam:
  it's probably wrong." (jim@bilpin). |maart@cs.vu.nl, mcvax!botter!maart