-
Notifications
You must be signed in to change notification settings - Fork 2
Open
Description
Hello.
I was using the Rsh method and came across an unexpected behavior. I think this code might reproduce the problem.
I am comparing it with uint256.
valueU256 := uint256.MustFromDecimal("6276865796315986613307619852238232712866172378830163935232")
fmt.Println("Result uint256:", valueU256.Rsh(valueU256, 128).Dec())
valueI256 := int256.MustFromDec("6276865796315986613307619852238232712866172378830163935232")
fmt.Println("Result int256:", valueI256.Rsh(valueI256, 128).Dec())
The code produce this result:
Result uint256: 18446050711097703530
Result int256: 0
A Rsh operation where z and x are same have that error, but if we use a new receiver as below it does not happen.
valueU256 := uint256.MustFromDecimal("6276865796315986613307619852238232712866172378830163935232")
fmt.Println("Result uint256:", valueU256.Rsh(valueU256, 128).Dec())
valueI256 := int256.MustFromDec("6276865796315986613307619852238232712866172378830163935232")
fmt.Println("Result int256:", new(int256.Int).Rsh(valueI256, 128).Dec())
The result is the same as uint256.
Result uint256: 18446050711097703530
Result int256: 18446050711097703530
I think it has to do with the order some things are done here:
func (z *Int) rsh(x *Int, n uint) *Int {
if n >= 255 {
return z.Clear()
}
switch {
case n >= 192:
n -= 192
z[3], z[2], z[1], z[0] = 0, 0, 0, x[3]>>n
case n >= 128:
n -= 128
z[3], z[2] = 0, 0// If z and x are the same reference, then this will change x[3] and x[2] as well
z[1] = x[3] >> n // causing this to be z[1] = 0 >> n.
z[0] = (x[3] << (64 - n)) | (x[2] >> n) // and this to be (0 << (64 - n)) | (0 >> n).
case n >= 64:
// I think this case have the same problem as the previous one.
n -= 64
z[3] = 0
z[2] = x[3] >> n
z[1] = (x[3] << (64 - n)) | (x[2] >> n)
z[0] = (x[2] << (64 - n)) | (x[1] >> n)
default:
z[3] = x[3] >> n
z[2] = (x[3] << (64 - n)) | (x[2] >> n)
z[1] = (x[2] << (64 - n)) | (x[1] >> n)
z[0] = (x[1] << (64 - n)) | (x[0] >> n)
}
return `z`
}
It worked when I changed to:
func (z *Int) rsh(x *Int, n uint) *Int {
if n >= 255 {
return z.Clear()
}
switch {
case n >= 192:
n -= 192
z[3], z[2], z[1], z[0] = 0, 0, 0, x[3]>>n
case n >= 128:
n -= 128
z[0] = (x[3] << (64 - n)) | (x[2] >> n)
z[1] = x[3] >> n
z[3], z[2] = 0, 0
case n >= 64:
n -= 64
z[0] = (x[2] << (64 - n)) | (x[1] >> n)
z[1] = (x[3] << (64 - n)) | (x[2] >> n)
z[2] = x[3] >> n
z[3] = 0
default:
z[0] = (x[1] << (64 - n)) | (x[0] >> n)
z[1] = (x[2] << (64 - n)) | (x[1] >> n)
z[2] = (x[3] << (64 - n)) | (x[2] >> n)
z[3] = x[3] >> n
}
return z
}
I hope this can help somehow.
DONOVA28 and vuquang23
Metadata
Metadata
Assignees
Labels
No labels