How to Shift Bits Using Swift

How do I perform a circular shift in Swift?

You can achieve this with two bit shift operators and a bitwise OR:

func circularRightShift(_ input: UInt8, _ amount: UInt8) -> UInt8 {
let amount = amount % 8 // Reduce to the range 0...7
return (input >> amount) | (input << (8 - amount))
}

Example (amount=5):

abcdefgh    <- bits of input

00000abc <- bits of input >> amount
defgh000 <- bits of input << (8 - amount)
defghabc <- bits of result

Shifting behavior for variable bits in Swift

those are the overloaded operators in Swift basically for operator >>, as you see there is no such operator overloading which works on UInt32 with Int:

>> operators


you can overload this operator anytime for your wish, like

func >>(lhs: UInt32, rhs: Int) -> UInt32 {
return lhs >> UInt32(rhs);
}

and your second code snippet will work without any issue in the future:

let shiftMe: UInt32 = 0xFF0000
let shiftValue: Int = 16
let shiftedConst = shiftMe >> shiftValue

you will find more information about custom operators in Swift here.


in Xcode6 beta, beta2, beta3

What does shift left () actually do in Swift?

That's the bitwise left shift operator

Basically it's doing this

// moves 0 bits to left for 00000001
let birdCategory: UInt32 = 1 << 0

// moves 1 bits to left for 00000001 then you have 00000010
let worldCategory: UInt32 = 1 << 1

// moves 2 bits to left for 00000001 then you have 00000100
let pipeCategory: UInt32 = 1 << 2

// moves 3 bits to left for 00000001 then you have 00001000
let scoreCategory: UInt32 = 1 << 3

You end up having

birdCategory = 1
worldCategory = 2
pipeCategory = 4
scoreCategory= 8

Zero fill right shift in swift

If you use the truncatingBitPattern initializer of integer types
to extract a byte then you don't have to mask the value and it does not matter if the shift operator fills with zeros or ones (which depends on whether the source
type is unsigned or signed).

Choose Int8 or UInt8 depending
on whether the byte should be interpreted as a signed or
unsigned number.

let value = 0xABCD

let signedByte = Int8(truncatingBitPattern: value >> 8)
print(signedByte) // -85

let unsignedByte = UInt8(truncatingBitPattern: value >> 8)
print(unsignedByte) // 171

Unsigned right shift operator '' in Swift

One sure way to do it is using the unsigned shift operation of unsigned integer type:

infix operator >>> : BitwiseShiftPrecedence

func >>> (lhs: Int64, rhs: Int64) -> Int64 {
return Int64(bitPattern: UInt64(bitPattern: lhs) >> UInt64(rhs))
}

print(-7 >>> 16) //->281474976710655

(Using -7 for testing with bit count 16 does not seem to be a good example, it loses all significant bits with 16-bit right shift.)

If you want to do it in your way, the bitwise-ORed missing sign bit cannot be a constant 0x4000000000000000. It needs to be 0x8000_0000_0000_0000 (this constant overflows in Swift Int64) when bit count == 0, and needs to be logically shifted with the same bits.

So, you need to write something like this:

infix operator >>>> : BitwiseShiftPrecedence

func >>>> (lhs: Int64, rhs: Int64) -> Int64 {
if lhs >= 0 {
return lhs >> rhs
} else {
return (Int64.max + lhs + 1) >> rhs | (1 << (63-rhs))
}
}

print(-7 >>>> 16) //->281474976710655

It seems far easier to work with unsigned integer types when you need unsigned shift operation.

How to break up expressions involve bitwise shift operators? Swift

hashValue is already an Int, so the Int(...) constructors are not
needed. This compiles in Xcode 9:

let value = topLeft.hashValue | (topRight.hashValue << 1) | (bottomLeft.hashValue << 2) | (bottomRight.hashValue << 3)

But that is a bad idea! It relies on the hash value of booleans having specific values:

false.hashValue == 0
true.hashValue == 1

which is nowhere guaranteed. (The only guarantee is that identical elements have the same hash value. One must not even assume that hash
values are equal across different executions of your program,
see Hashable).

A better solution would be

let value = (topLeft ? 1 : 0) + (topRight ? 2 : 0) + (bottomLeft ? 4 : 0) + (bottomRight ? 8 : 0)

Alternatively, use a switch-statement. Example:

switch (topLeft, topRight, bottomLeft, bottomRight) {
case (false, false, false, false):
// ... all false ...
case (false, true, true, false):
// ... topRight and bottomLeft are true ...
case (true, false, false, true):
// ... topLeft and bottomRight are true ...
default:
// ... all other cases ...
}

Bit shifting in swift generic function

I have a blog post on this topic that goes into more detail, but essentially there are three steps:

  1. Create a new protocol with the bitshift operators and a constructor from UInt8:

    protocol BitshiftOperationsType {
    func <<(lhs: Self, rhs: Self) -> Self
    func >>(lhs: Self, rhs: Self) -> Self
    init(_ val: UInt8)
    }
  2. Declare conformance with an extension on each of the integer types - easy since they already implement everything in BitshiftOperationsType:

    extension Int    : BitshiftOperationsType {}
    extension Int8 : BitshiftOperationsType {}
    extension Int16 : BitshiftOperationsType {}
    extension Int32 : BitshiftOperationsType {}
    extension Int64 : BitshiftOperationsType {}
    extension UInt : BitshiftOperationsType {}
    extension UInt8 : BitshiftOperationsType {}
    extension UInt16 : BitshiftOperationsType {}
    extension UInt32 : BitshiftOperationsType {}
    extension UInt64 : BitshiftOperationsType {}
  3. Add a generic constraint so T conforms to your new protocol:

    func testBytes<T: IntegerType where T: BitshiftOperationsType>(bytesIn: [UInt8], inout dataOut: T){
    let outputSize = sizeof(T)
    var temp: T = 0
    dataOut = 0
    temp = T(bytesIn[0])
    temp = temp << 1
    }

Thanks to Martin R. for the fix for the gross bit I had here before!



Related Topics



Leave a reply



Submit