Here is a naive test for a particular Gray code monotonic ordering (the binary reflected Gray code):
// convert Gray code binary number to base 2 binary number
int Base2(byte Gray){ Gray^=Gray>>4; Gray^=Gray>>2; return Gray^=Gray>>1; }
// test if Gray codes are consecutive using "normal" base 2 numbers
boolean GraysAdjacent(byte x, byte y){ return 1 == abs(Base2(x)-Base2(y)); }
see especially this answer (best):
How to find if two numbers are consecutive numbers in gray code sequence
coded in C as:
int GraysTouch(byte x, byte y){ return !( (x^y ^ 1) && ( x^y ^ (y&-y)<<1 ) ); }
// test x marks the spots! (where they touch!)
for(int i=31; i>-1; --i )
for(int j=31; j>-1; --j )
Serial.print((String)(GraysTouch( i^i>>1, j^j>>1 )?"x":".") +
(GraysTouch( j^j>>1, i^i>>1 )?"X":".") + (j?"":"\n"));
How this works: ... will be explained and not the OP code because it is highly suspect (see Caveats commentary below).
A property of XOR
, aka the ^
operator, is that bits that match are 0
and bits that are different are 1
.
1^0 == 0^1 == 1
1^1 == 0^0 == 0
Also, for a bit, 0 XOR b
works as the identity function or simply b
and
1 XOR b
works as the complement (no compliments please) function or ~b
.
id(x) == x == x^0
opposite(x) == ~x == x^11111111 Why eight 1's? Are eight enough?
When comparing two bit strings with XOR
, bits that are different XOR
as 1
, otherwise the bits must match and the XOR
is 0
:
0101 0001111001100111000
XOR 0011 XOR 0001111001100000111
------ ---------------------
0110 0000000000000111111
This explains the x^y
part of the code above.
----------------------------------------------------------------------
An aside:
n^n>>1
does a quick conversion from base 2 binary to the Gray code binary numbers used here.
Also note how potent it is that f(a,b)=a^b^b=a
is idempotent for any b
!
An in place swap is then a=a^b; b=a^b; a=a^b;
.
Unrolled c=a^b; d=c^b; e=c^d;
ie. d=a^b^b=a; e=a^b^a=b;
----------------------------------------------------------------------
Now, by definition, for two Gray coded numbers to be adjacent or consecutive there must be one and only one bit that can change and be different.
Examples:
Johnson
Code
000 000 000 000
001 001 001 100
011 101 011 110
111 111 010 010
110 011 110 011
100 010 111 111
110 101 101
100 100 001
^^^
this Gray coding
is the one used here
Examine it carefully.
Case 1
When the lowest order bit of consecutive numbers, x
and y
, for any of the Gray codes, are different, the rest must be the same! This is the definition of a Gray code. This means x^y
must look like 0000...0001.
Remember complement, the ~
function aka 1^b
? To test the last bit x^y
is XOR
'd with 1
.
This explains the x^y ^ 1
.
-------------------------------------------
Case 2
The location of the different bit in the consecutive Gray code numbers x
and y
is not the lowest order bit. Look carefully at these Gray code consecutive numbers.
001 010 101 lower order bits all match
011 110 111
| | | <-- | mark location of lowest 1
010 100 010 <-- XOR's
Interestingly, in this Gray code, when the lowest order bits match in x
and y
, so too does the location of the lowest order 1
.
Even more interesting is that, for consecutive numbers, the bits are always different (for this Gray code) in the next higher order bit position!
So, x^y
looks like ???...?1000...0
where 1000...0
must have at least one 0, 10
(Why?) and ???...?
are the mystery bits that for consecutive Gray code numbers must be 000...0
. (Why? ie. to be consecutive x^y
must look like ... )
The observation is that
x^y looks like ???...?100...0 if and only if
x and y look like ???...?:10...0
| <-- remember? the 1 location !!
The |
location can be found by either x&-x
or y&-y
. (Why? Why must the -
be done using a 2's complement machine?)
However, the :
location must be checked to see that it is 1
(Why?) and the ???...?
are 000...0
. (Why?)
So,
x^y looks like ???...?100...0 and
(y&-y)<<1 looks like 000...0100...0
and this explains the x^y ^ ((y&-y)<<1)
test.
-------------------------------------------------------------------
Why this works: ... is a consequence of the properties of the particular Gray code used here. An examination and explanation is too complicated to be given here as to why this Gray code should have these properties.
----------------------------------------------------------------------
Commentary on the inadequacies of previous answers due to OP code issues.
Caveat 1: Just to be explicit, the algorithm in the OP's question:
private static int graycode(byte term1, byte term2) {
byte x = (byte)(term1^term2); // why use XOR?
int count = 0;
while(x!=0)
{
x = (byte)(x &(x-1)); // why use bitwise operator?
count++; // what is count?
}
return count == 1;
}
has an interesting interpretation of consecutive Gray codes. It does report correctly when any two binary sequences differ in a single bit position.
If, by consecutive codes it is meant that the Gray codes are used to enumerate a monotonic ordering, there is a problem.
Specifically, the code will return true
for all these pairs:
000, 001 or 000, 010 or 000, 100
so an ordering might be 001, 000, 010
but then where can 100
go?
The algorithm reports (correctly) that the "consecutiveness" of 100
with either of 001 or 010
is false
.
Thus 100
must immediately precede or follow 000
in an enumeration but cannot immediately precede or follow 001
or 010
. DOH!!!
Caveat 2: Note x = (byte)(x & (x-1))
resets the lowest order 1 bit of x
to zero.
refs:
Gray code increment function
Deriving nth Gray code from the (n-1)th Gray Code
https://electronics.stackexchange.com/questions/26677/3bit-gray-counter-using-d-flip-flops-and-logic-gates
How do I find next bit to change in a Gray code in constant time?
How to find if two numbers are consecutive numbers in gray code sequence