Different results on different systems

Report any Hollywood bugs here
Post Reply
User avatar
Allanon
Posts: 732
Joined: Sun Feb 14, 2010 7:53 pm
Location: Italy
Contact:

Different results on different systems

Post by Allanon »

Hello,
I've a strange behaviour with my sha library because it works on Windows but fails on Raspberry, digging in the code I've isolated the problem and seems that bit functions are giving different results, here is the test code:

Code: Select all

Function _ROL(x, y) Return(Rol(x, y)) EndFunction
Local v = 5140528219
DebugPrint(v, _ROL(v, 13), _ROL(v, 15), ROL(v, 10))
DebugPrompt("?")
I've remapped the function's name because of the original source code that I've ported, by the way the results returned on Windows are:

Code: Select all

5140528219 3347801676 506304819 2565958857
While on Raspberry Pi with latest OS 32 bit I have:

Code: Select all

5140528219 4294967295 4294967295 4294967295
Screenshot
Image

I'm getting old porting this library to hollywood :D
User avatar
airsoftsoftwair
Posts: 5433
Joined: Fri Feb 12, 2010 2:33 pm
Location: Germany
Contact:

Re: Different results on different systems

Post by airsoftsoftwair »

The problem is that Rol() and Ror() are currently limited to 32-bit integers but the number you're passing is bigger than that so what you get then is undefined behaviour. I agree that this is not nice and should be fixed to be consistent across platforms but strictly speaking, it's a bug in your code because Rol() and Ror() can't handle values larger than 32-bit at the moment ;)
User avatar
Allanon
Posts: 732
Joined: Sun Feb 14, 2010 7:53 pm
Location: Italy
Contact:

Re: Different results on different systems

Post by Allanon »

mmm... ok, I see... so if I split it into two 32bit numbers and do a manual ror/rol on them and then reassemble the "big" number it should work? I will try :)
User avatar
Allanon
Posts: 732
Joined: Sun Feb 14, 2010 7:53 pm
Location: Italy
Contact:

Re: Different results on different systems

Post by Allanon »

Hello,
seems that Cast() has the same problem on ARM machines, a >32bit number cannot be converted into a 32bit one.

Code: Select all

DebugPrint("CAST() TEST")
Local maxvalue = 2^32-1
Local overflow1 = maxvalue+1
Local overflow2 = maxvalue+2^33
DebugPrint("  1. max 32 bit: ", maxvalue)
DebugPrint("  2. max + 1   : ", overflow1)
DebugPrint("  3. max + 2^33: ", overflow2)
DebugPrint("CAST")
DebugPrint("  1. ", Cast(maxvalue, False, #INTEGER))
DebugPrint("  2. ", Cast(overflow1, False, #INTEGER))
DebugPrint("  3. ", Cast(overflow2, False, #INTEGER))
DebugPrompt("?")
Image

Right now I'm using a simple loop to subtract the overflow and reduce the number into a 32bit value but it is very very very (help me to say very) slowwwww :D
User avatar
Allanon
Posts: 732
Joined: Sun Feb 14, 2010 7:53 pm
Location: Italy
Contact:

Re: Different results on different systems

Post by Allanon »

Hello again,
I've found a relatively fast way to deal with this bug, for all people facing this problem and want to reduce a number to 32bit without using bitwise operators (which cause problems on ARM devices) here is my solution:

Code: Select all

Local max32bit = 4294967295
Local overflow  = max32bit + 1

Local mb = 0 ; useful to compute max bits used (see the commented line below)

Local cache    = {}
Local bitchecker = {}

; Init bitchecker array
For Local b = 32 To 63
  bitchecker[b] =  { _max = 2^b-1, overflow = 2^b }
Next

Local force32bit =
  Function(n)
    If HaveItem(cache, n) Then Return(cache[n])
    If n < overflow Then Return(n)
    
    DisableLinehook()
    Local i = n
    For Local b = 51 To 32 Step -1
      If n > bitchecker[b]._max
        While n > bitchecker[b]._max
          n = n-bitchecker[b].overflow
          ;If b>mb Then mb = b ; Stores max bit used for the handled numbers
        Wend
      EndIf
    Next
    cache[i] = n
    
    EnableLineHook()

    Return(n)
    
  EndFunction
Note that I'used a upper limit 51 bit since from my tests and my personal purposes I've never reached 49 bit numbers so you can adjust it as you wish.
jalih
Posts: 276
Joined: Fri Jun 18, 2010 8:08 pm
Location: Finland

Re: Different results on different systems

Post by jalih »

Allanon wrote: Thu Apr 14, 2022 9:37 am Hello again,
I've found a relatively fast way to deal with this bug, for all people facing this problem and want to reduce a number to 32bit without using bitwise operators (which cause problems on ARM devices) here is my solution:

Code: Select all

Local max32bit = 4294967295
Local overflow  = max32bit + 1

Local mb = 0 ; useful to compute max bits used (see the commented line below)

Local cache    = {}
Local bitchecker = {}

; Init bitchecker array
For Local b = 32 To 63
  bitchecker[b] =  { _max = 2^b-1, overflow = 2^b }
Next

Local force32bit =
  Function(n)
    If HaveItem(cache, n) Then Return(cache[n])
    If n < overflow Then Return(n)
    
    DisableLinehook()
    Local i = n
    For Local b = 51 To 32 Step -1
      If n > bitchecker[b]._max
        While n > bitchecker[b]._max
          n = n-bitchecker[b].overflow
          ;If b>mb Then mb = b ; Stores max bit used for the handled numbers
        Wend
      EndIf
    Next
    cache[i] = n
    
    EnableLineHook()

    Return(n)
    
  EndFunction
Note that I'used a upper limit 51 bit since from my tests and my personal purposes I've never reached 49 bit numbers so you can adjust it as you wish.
Hi Allanon,

I am not quite sure what you are trying to do but to me, you could replace all that code with:

Code: Select all

Mod(n, 4294967296)
You can calculate what is the MSB of the number n by simply:

Code: Select all

Int(Ln(n) / Ln(2))
User avatar
Allanon
Posts: 732
Joined: Sun Feb 14, 2010 7:53 pm
Location: Italy
Contact:

Re: Different results on different systems

Post by Allanon »

Hi jalih,
thank you for the suggestion, I'll try your code to see if it's faster than mine :)

What I was trying to do is to reduce a 64bit number to a 32bit one ignoring the bits 63-33 so I can use bitwise operators on Linux ARM which currently returns wrong results for number bigger than 32bit, while on Windows those excinding bits are simply ignored.
All of this to be able to use my libHash library I ported to Hollywood some time ago.
User avatar
airsoftsoftwair
Posts: 5433
Joined: Fri Feb 12, 2010 2:33 pm
Location: Germany
Contact:

Re: Different results on different systems

Post by airsoftsoftwair »

Well, the Cast() example finally convinced me to fix this so behaviour should be consistent across all platforms now even though Rol(), Ror() and Cast() are still limited to 32-bit for the moment.

Code: Select all

- Fix [Non-Windows]: Passing values greater than 32-bits to Hollywood functions which cannot deal with
  values greater than 32-bits led to the value getting clipped to $FFFFFFFF; on Windows, however, all bits
  higher than 31 were simply discarded; the Windows behaviour is now used on all other platforms as well
  because it is consistent with how Cast() behaves, i.e. when converting a value greater than the target
  type's range Cast() won't clip the value to the maximum acceptable by the type but it will simply kill
  all bits higher than the target type's range, e.g. Cast()ing 65537 to unsigned #SHORT will result in 1
  because Cast() will simply kill bit 16 in that case making bit 0 remain 
User avatar
Allanon
Posts: 732
Joined: Sun Feb 14, 2010 7:53 pm
Location: Italy
Contact:

Re: Different results on different systems

Post by Allanon »

Thank you Andreas for your efforts to fix this problem :)
32 bit precision is fine :D
Post Reply