Binary Coding To Gray Coding and viceversa

Share your advanced PureBasic knowledge/code with the community.
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

Demivec wrote:Your original code could not be used on values equal to zero. It caused a wrap to occur and you had to wait for the value to count down from 2147483647 to 0 before it exited. Try it and see, I used this statement for the time test: GrayCodingToBinaryCoding(0). That's how I came to the precise speed increase of a gazillion times.
Tested before to post it. And also now.
Please take a closer look because you are very wrong this time.
Demivec wrote:One more comment, the "Until d<2 or s=something" is used to determine when shifting any more would be useless. Either it has run out of bits to shift (d<2 which affects shifts to the right) or it has run into a maximum value (s=something, which affects shifts to the left). The shift to the left value is equal to the size of the variable with all bits on except the sign bit (or high bit). For example in my code it equals $4000000000000000.
Again wrong.
For your example code $40 is enough. There is a nonsense more than $40 when dealing with quads. And there is a nonsense more than $20 for longs.

Here it is a nice version:

Code: Select all

;Albert (Psychophanta) February 2008:
;with GrayCodingToBinaryCoding() by Demivec
;improved GrayCodingToBinaryCoding() by Pupil
Procedure.l BinaryCodingToGrayCoding(n.l)
  ProcedureReturn n!(n>>1)
EndProcedure
Procedure.l GrayCodingToBinaryCoding(n.l)
  Protected s.l=1,d.l
  Repeat
    d=n>>s
    n!d
    s<<1
  Until d<2 Or s=32; <- s=64 if quads (.q) are used instead of longs (.l)
  ProcedureReturn n
EndProcedure
;Test it:
For t.l=1 To 1000
  a.l=Random(3000000)
  If a<>BinaryCodingToGrayCoding(GrayCodingToBinaryCoding(a))
    Debug "wrong!"
  EndIf
Next
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
User avatar
Demivec
Addict
Addict
Posts: 4270
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

Psychophanta wrote:
Demivec wrote:Your original code could not be used on values equal to zero. It caused a wrap to occur and you had to wait for the value to count down from 2147483647 to 0 before it exited. Try it and see, I used this statement for the time test: GrayCodingToBinaryCoding(0). That's how I came to the precise speed increase of a gazillion times.
Tested before to post it. And also now.
Please take a closer look because you are very wrong this time.
Demivec wrote:One more comment, the "Until d<2 or s=something" is used to determine when shifting any more would be useless. Either it has run out of bits to shift (d<2 which affects shifts to the right) or it has run into a maximum value (s=something, which affects shifts to the left). The shift to the left value is equal to the size of the variable with all bits on except the sign bit (or high bit). For example in my code it equals $4000000000000000.
Again wrong.
For your example code $40 is enough. There is a nonsense more than $40 when dealing with quads. And there is a nonsense more than $20 for longs.

Here it is a nice version:

Code: Select all

;Albert (Psychophanta) February 2008:
;with GrayCodingToBinaryCoding() by Demivec
;improved GrayCodingToBinaryCoding() by Pupil
Procedure.l BinaryCodingToGrayCoding(n.l)
  ProcedureReturn n!(n>>1)
EndProcedure
Procedure.l GrayCodingToBinaryCoding(n.l)
  Protected s.l=1,d.l
  Repeat
    d=n>>s
    n!d
    s<<1
  Until d<2 Or s=32; <- s=64 if quads (.q) are used instead of longs (.l)
  ProcedureReturn n
EndProcedure
;Test it:
For t.l=1 To 1000
  a.l=Random(3000000)
  If a<>BinaryCodingToGrayCoding(GrayCodingToBinaryCoding(a))
    Debug "wrong!"
  EndIf
Next
@Psychophanta: now it's my turn to appologize. To make up for it, I made an improvement and eliminated the check with the variable "s". Your logic made me see the error of my ways, it was a redundant check because I had used the wrong value in it and my version still worked. I also added an error check as well if an illegal value is supplied. Should be faster yet (no, i didn't time it :wink:)

Code: Select all

Procedure.q GrayCodingToBinaryCoding(n.q) ;largest integer that is handled is 9223372035781775807
  Protected s.l = 1,d.q
  
  If n<0
    ProcedureReturn -1 ;bad parameter value, can't be negative
  EndIf
  Repeat
    d = n >> s
    n ! d
    If d < 2
      ProcedureReturn n
    EndIf 
    s << 1
  ForEver
EndProcedure
@Edit: Updated code to change "s.q" to "s.l"
Last edited by Demivec on Tue Feb 19, 2008 11:55 pm, edited 1 time in total.
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

Apologies accepted of course.
Made your written algorithm in asm, but for longs only (quads is another history, could be made a nice one using SSE or so):

Code: Select all

Procedure.l GrayCodingToBinaryCodingASM(n.l)
  !mov cl,1
  !mov eax,dword[p.v_n]
  !@@:mov ebx,eax
  !shr ebx,cl
  !xor eax,ebx
  !shl cl,1
  !cmp cl,32
  !jnz @r
  ProcedureReturn
EndProcedure
EDIT: Final optimized codes at first post.
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
Post Reply