Bit Shifting Right Help

and isnt what I gave him :slight_smile:

[quote=473519:@Garry Pettet]Since you seem well informed, I am assuming my method for an unsigned shift:

Public Function RShiftU32(v As Int32, shift As Integer) As Int32
Return Bitwise.ShiftRight(value, shift, 32)
End Function

Is good for both Int64 and Int32 data types?[/quote]

Nope. You can see clearly that you are trying to handle 32 bit only (and not the safest way for unsigneds), not 64 bit ready.

Public Function RShift(v As Uint64, shift As Integer) As Uint64 Return Bitwise.ShiftRight(v, shift) End Function

^-- Not tested. Just edited here. Check.

You could just go Xojo native here: Bitwise.ShiftRight(v, shift)

or write one version that takes each of the sized numeric types (int8, unit8, int16, uint16) and returns something of the same size and you’d get the right one used all the time rather than try to write one that you have to pass all kinds of control parameters to (like bitwise does)

Public Function RShift(v As Uint8, shift As Integer) As Uint8
  Return Bitwise.ShiftRight(v, shift)
End Function

Public Function RShift(v As Uint16, shift As Integer) As Uint16
  Return Bitwise.ShiftRight(v, shift)
End Function

Public Function RShift(v As Uint32, shift As Integer) As Uint32
  Return Bitwise.ShiftRight(v, shift)
End Function

etc

just dont write one with INTEGER since integer turns into either an int32 or int64 depending on whether you compile for 32 or 64 bit

Be careful with your translations.

is Signed, >>> is Unsigned.

[quote=473539:@Rick Araujo]Be careful with your translations.

is Signed, >>> is Unsigned.[/quote]
You’re correct. I edited the post in question.

Perhaps I’m making a mountain out of a molehill here.

I’ve been concerned about Int32 and Int64 because the maths library I’m porting uses >>> and >> on various combinations of int (Int32) and long (Int64). Am I right in thinking that just manipulating a UInt64 and casting to the appropriate data type will work?

Mostly yes. As when moving an int of larger size, to a smaller one, it’ll just truncate high order bits off that we must suppose won’t be in use for such use cases.

[quote=473537:@Norman Palardy]or write one version that takes each of the sized numeric types (int8, unit8, int16, uint16) and returns something of the same size and you’d get the right one used all the time rather than try to write one that you have to pass all kinds of control parameters to (like bitwise does)

Public Function RShift(v As Uint8, shift As Integer) As Uint8
  Return Bitwise.ShiftRight(v, shift)
End Function

Public Function RShift(v As Uint16, shift As Integer) As Uint16
  Return Bitwise.ShiftRight(v, shift)
End Function

Public Function RShift(v As Uint32, shift As Integer) As Uint32
  Return Bitwise.ShiftRight(v, shift)
End Function

etc

just dont write one with INTEGER since integer turns into either an int32 or int64 depending on whether you compile for 32 or 64 bit[/quote]
The issue I found with those type of overrides is when passing in number literals. I think they are automatically assumed to be Int64’s.

As far as I know this is the case
But you can force them to be a specific sized numeric type by using CType

I’m about to give up. I’m sick of this. The unsigned (>>>) operator port doesn’t work either.

This Java code:

long a = -2 >>> 1; // 2147483647 long b = 0 >>> 1; // 0 long c = -1 >>> 1; // 2147483647 long d = 1 >>> 1; // 0 long e = 100 >>> 1; // 50 long f = -2147483648 >>> 1; // 1073741824 long g = 2147483647 >>> 1; // 1073741823

Which is shifting right (unsigned) various integers (the Java interpreter assumes number literals to be Int32 int types) and putting the result in a Java long (Int64).

Using this Xojo code:

Var a As Int64 = Return Bitwise.ShiftRight(-2, 1) // 9223372036854775807 Var b As Int64 = Return Bitwise.ShiftRight(-2, 1) // 0 Var c As Int64 = Return Bitwise.ShiftRight(-2, 1) // 9223372036854775807 Var d As Int64 = Return Bitwise.ShiftRight(-2, 1) // 0 Var e As Int64 = Return Bitwise.ShiftRight(-2, 1) // 50 Var f As Int64 = Return Bitwise.ShiftRight(-2, 1) // 9223372035781033984 Var g As Int64 = Return Bitwise.ShiftRight(-2, 1) // 1073741823

Gives the results you see in the comments. I don’t get it. I just don’t get it but I can’t progress this port if the maths is off :frowning:

Can anyone help out? I appreciate the offerings so far, I really do. Is there some way to do this with a MemoryBlock that I’m not seeing?

just about done writing a module that does this

It looks like Java is treating the numeric literals as 32-bit. Try

Var a As Int64 = Return Bitwise.ShiftRight(ctype(-2, Int32), 1)

OMG! I think I’ve cracked it. Tim has hit is spot on the head (I suspected this a little bit before he posted which gave me a chance to tweak some code).

The issue is that Java assumes that all numeric literals are Int32 unless specifically stipulated by suffixing the literal with L. since Xojo infers that numeric literals are Int64 by default, we begin to see the issue.

The solution is that we need 3 methods. One to replicate Java’s >> signed right shift operator:

[code]Function RightShift(v As Int64, s As Integer) as Int64
If v >= 0 Then
Return Bitwise.ShiftRight(v, s)
Else
If s = 1 Then
Return Bitwise.BitOr(&h8000000000000000, Bitwise.ShiftRight(v, s))
End
Return Bitwise.BitOr(Bitwise.ShiftLeft(-1, 64 - s), Bitwise.ShiftRight(v, s))
End

End Function[/code]

And we need two methods to handle Java’s >>> unsigned right shift operator because how Java handles them depends on whether the left hand operand is an int (Int32) or a long (Int64).

To pass an Int32:

Function RightShiftU32(v As Int32, s As Integer) as Int32 Return Bitwise.ShiftRight(v, s, 32) End Function

To pass an Int64:

Function RightShiftU64(value As Int64, shift As Integer) as Int64 Return Bitwise.ShiftRight(value, shift, 64) End Function

Int4 >> x Proof:

[code]// Values that fit into an Int32.
Var a As Int64 = MathsKit.RightShift(-2, 1)
Var b As Int64 = MathsKit.RightShift(0, 1)
Var c As Int64 = MathsKit.RightShift(-1, 1)
Var d As Int64 = MathsKit.RightShift(1, 1)
Var e As Int64 = MathsKit.RightShift(100, 1)
Var f As Int64 = MathsKit.RightShift(-2147483648, 1)
Var g As Int64 = MathsKit.RightShift(2147483647, 1)
Var h As Int64 = MathsKit.RightShift(2147483647, 5)
Var i As Int64 = MathsKit.RightShift(-1, 30)

Assert.AreEqual(-1, a)
Assert.AreEqual(0, b)
Assert.AreEqual(-1, c)
Assert.AreEqual(0, d)
Assert.AreEqual(50, e)
Assert.AreEqual(-1073741824, f)
Assert.AreEqual(1073741823, g)
Assert.AreEqual(67108863, h)
Assert.AreEqual(-1, i)

// Use values that would only fit in an Int64.
Var j As Int64 = MathsKit.RightShift(2147483999, 1)
Var k As Int64 = MathsKit.RightShift(-2147483999, 30)

Assert.AreEqual(1073741999, j)
Assert.AreEqual(-3, k)[/code]

Int32 >>> x Proof

[code]Var a As Int64 = MathsKit.RightShiftU32(-2, 1) ’ -2 >>> 1
Var b As Int64 = MathsKit.RightShiftU32(0, 1) ’ 0 >>> 1
Var c As Int64 = MathsKit.RightShiftU32(-1, 1) ’ -1 >>> 1
Var d As Int64 = MathsKit.RightShiftU32(1, 1) ’ 1 >>> 1
Var e As Int64 = MathsKit.RightShiftU32(100, 1) ’ 100 >>> 1
Var f As Int64 = MathsKit.RightShiftU32(-2147483648, 1) ’ -2147483648, >>> 1
Var g As Int64 = MathsKit.RightShiftU32(2147483647, 1) ’ 2147483647 >>> 1

Assert.AreEqual(2147483647, a)
Assert.AreEqual(0, b)
Assert.AreEqual(2147483647, c)
Assert.AreEqual(0, d)
Assert.AreEqual(50, e)
Assert.AreEqual(1073741824, f)
Assert.AreEqual(1073741823, g)[/code]

Int64 >>> x Proof:

Var a As Int64 = MathsKit.RightShiftU64(-2, 1) ’ -2 >>> 1
Var b As Int64 = MathsKit.RightShiftU64(0, 1) ’ 0 >>> 1
Var c As Int64 = MathsKit.RightShiftU64(-1, 1) ’ -1 >>> 1
Var d As Int64 = MathsKit.RightShiftU64(1, 1) ’ 1 >>> 1
Var e As Int64 = MathsKit.RightShiftU64(100, 1) ’ 100 >>> 1
Var f As Int64 = MathsKit.RightShiftU64(-2147483648, 1) ’ -2147483648, >>> 1
Var g As Int64 = MathsKit.RightShiftU64(2147483647, 1) ’ 2147483647 >>> 1
Var h As Int64 = MathsKit.RightShiftU64(2147483999, 1) ’ 2147483999 >>> 1

Assert.AreEqual(9223372036854775807, a)
Assert.AreEqual(0, b)
Assert.AreEqual(9223372036854775807, c)
Assert.AreEqual(0, d)
Assert.AreEqual(50, e)
Assert.AreEqual(9223372035781033984, f)
Assert.AreEqual(1073741823, g)
Assert.AreEqual(1073741999, h)

This is when Norman finds a bug and posts a more elegant solution in like 2 minutes time :slight_smile: