I am implementing, in go, a rolling version of the adler32 checksum.
This answer was helpful to double check my maths. However I am struggling at implementing it correctly in golang.
I wrote the following code:
func roll(adler, n, leave, enter uint32) uint32 {
a := adler & 0xffff
b := adler >> 16
a = (a + enter - leave) % MOD
b = (b - n*leave - 1 + a) % MOD
return b<<16 | a
}
It tested it on various inputs and it worked fine, until I decided to run it on random data. Here is a sample where it does not work (I found several of them).
What is baffling me is that the same code in python works perfectly on those inputs:
def roll(adler, n, leave, enter):
a = adler & 0xffff
b = adler >> 16
a = (a + enter - leave) % MOD
b = (b - n*leave - 1 + a) % MOD
return b<<16 | a
For good measure, I am including proof that this works in python. Note that the python checksum matches the non-rolling version of the go checksum (and that part is directly from the go core libraries).
I studied my results on all the other problematic samples, and found that I am never making a mistake on the least significant bits of the checksum (the "a" bits). Also, the error is consistently the same, equals to 0xe10000
. I suspect a peculiarity of how go handles modulo operations on uint32 integers to be the cause of this.
What is happening and how do I fix my code?