Bitwise shift Data in Swift - swift

I have a data object, containing multiple bytes of information. For an algorithm I need this Data to be shifted left or right by one bit. Is there any efficient way to do this?
I tired implementing it something like this, but I believe this is highly ineffective solution:
fileprivate let LSBofByte: UInt8 = 0x01 // 0000 0001
fileprivate let MSBofByte: UInt8 = 0x80 // 1000 0000
extension Data {
mutating func leftShiftByteArray() {
self[0] <<= 1 // Shift first byte
for i in 1...self.count-1 {
if (self[i] & MSBofByte) == MSBofByte {
self[i-1] |= LSBofByte // Carry the leading 1 from current byte to previous
}
self[i] <<= 1 // Shift other bytes
}
}
}

Related

How to get the binary inverse of a number in Swift?

If we have a given number, say 9 (binary representation is 1001). How can we most efficiently get it's inverse 6 (binary representation is 0110)? i.e replacing 0 with 1 and 1 with 0.
I have written a code of order O(1) complexity? But can there be a better way? Does Swift provide an elegant way of handling this?
Note negate function ~9 results in -10. This is not what I am seeking.
func inverse(of givenNumber: Int) -> Int // eg. 9
{
let binaryRepresentation = String(givenNumber, radix: 2) // "1001"
let binaryRepresentationLength = binaryRepresentation.count // 4
let maxValueInLength = (1 << binaryRepresentationLength) - 1 // 15, i.e., 1111
let answer = givenNumber ^ maxValueInLength // 6, i.e., 0110
return answer
}
Edit 1: givenNumber > 0
For positive numbers you can use the following:
func intInverse<T: FixedWidthInteger>(of givenNumber: T) -> T
{
assert(!T.isSigned || givenNumber & (T(1) << (givenNumber.bitWidth - 1)) == 0)
let binaryRepresentationLength = givenNumber.bitWidth - givenNumber.leadingZeroBitCount
let maxValueInLength = givenNumber.leadingZeroBitCount > 0 ? (~(~T(0) << binaryRepresentationLength)) : ~0
let answer = givenNumber ^ maxValueInLength
return answer
}
Which is identical to your algorithm but doesn't require stringifying the number. It doesn't work for negative numbers, but then neither does your algorithm because your algorithm sticks a - on the front of the number.
Probably the easiest way to extend this to cover negative numbers is to invert all the bits to get the binaryRepresentationLength
EDIT
I changed the way the exclusive or mask is created because the old one crashed for unsigned values with the top bit set and for signed values with the second highest bit set.
The code becomes much simpler using the property binade of a floating-point value.
func inverse(of givenNumber: Int) -> Int // eg. 9
{
let maxValueInLength = Int((Double(givenNumber).binade * 2) - 1) // 15, i.e., 1111
let answer = givenNumber ^ maxValueInLength // 6, i.e., 0110
return answer
}

Reading Data into a Struct in Swift

I'm trying to read bare Data into a Swift 4 struct using the withUnsafeBytes method. The problem
The network UDP packet has this format:
data: 0102 0A00 0000 0B00 0000
01 : 1 byte : majorVersion (decimal 01)
02 : 1 byte : minorVersion (decimal 02)
0A00 0000 : 4 bytes: applicationHostId (decimal 10)
0B00 0000 : 4 bytes: versionNumber (decimal 11)
Then I have an extension on Data that takes a start and the length of bytes to read
extension Data {
func scanValue<T>(start: Int, length: Int) -> T {
return self.subdata(in: start..<start+length).withUnsafeBytes { $0.pointee }
}
}
This works correctly when reading the values one by one:
// correctly read as decimal "1"
let majorVersion: UInt8 = data.scanValue(start: 0, length: 1)
// correctly read as decimal "2"
let minorVersion: UInt8 = data.scanValue(start: 1, length: 1)
// correctly read as decimal "10"
let applicationHostId: UInt32 = data.scanValue(start: 2, length: 4)
// correctly read as decimal "11"
let versionNumber: UInt32 = data.scanValue(start: 6, length: 4)
Then I created a struct that represents the entire packet as follows
struct XPLBeacon {
var majorVersion: UInt8 // 1 Byte
var minorVersion: UInt8 // 1 Byte
var applicationHostId: UInt32 // 4 Bytes
var versionNumber: UInt32 // 4 Bytes
}
But when I read the data directly into the structure I have some issues:
var beacon: XPLBeacon = data.scanValue(start: 0, length: data.count)
// correctly read as decimal "1"
beacon.majorVersion
// correctly read as decimal "2"
beacon.minorVersion
// not correctly read
beacon.applicationHostId
// not correctly read
beacon.versionNumber
I it supposed to work to parse an entire struct like this?
Reading the entire structure from the data does not work because
the struct members are padded to their natural boundary. The
memory layout of struct XPLBeacon is
A B x x C C C C D D D D
where
offset member
0 A - majorVersion (UInt8)
1 B - minorVersion (UInt8)
2 x x - padding
4 C C C C - applicationHostId (UInt32)
8 D D D D - versionNumber (UInt32)
and the padding is inserted so that the UInt32 members are
aligned to memory addresses which are a multiple of their size. This is
also confirmed by
print(MemoryLayout<XPLBeacon>.size) // 12
(For more information about alignment in Swift, see
Type Layout).
If you read the entire data into the struct then the bytes are assigned
as follows
01 02 0A 00 00 00 0B 00 00 00
A B x x C C C C D D D D
which explains why major/minorVersion are correct, but applicationHostId and versionNumber
are wrong. Reading all members separately from the data is the correct solution.
Since Swift 3 Data conforms to RandomAccessCollection, MutableCollection, RangeReplaceableCollection. So you can simply create a custom initializer to initialise your struct properties as follow:
struct XPLBeacon {
let majorVersion, minorVersion: UInt8 // 1 + 1 = 2 Bytes
let applicationHostId, versionNumber: UInt32 // 4 + 4 = 8 Bytes
init(data: Data) {
self.majorVersion = data[0]
self.minorVersion = data[1]
self.applicationHostId = data
.subdata(in: 2..<6)
.withUnsafeBytes { $0.load(as: UInt32.self) }
self.versionNumber = data
.subdata(in: 6..<10)
.withUnsafeBytes { $0.load(as: UInt32.self) }
}
}
var data = Data([0x01,0x02, 0x0A, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00,0x00])
print(data as NSData) // "{length = 10, bytes = 0x01020a0000000b000000}\n" <01020a00 00000b00 0000>
let beacon = XPLBeacon(data: data)
beacon.majorVersion // 1
beacon.minorVersion // 2
beacon.applicationHostId // 10
beacon.versionNumber // 11
Following on Leo Dabus answer, I created a slightly more readable constructor:
extension Data {
func object<T>(at index: Index) -> T {
subdata(in: index ..< index.advanced(by: MemoryLayout<T>.size))
.withUnsafeBytes { $0.load(as: T.self) }
}
}
struct XPLBeacon {
var majorVersion: UInt8
var minorVersion: UInt8
var applicationHostId: UInt32
var versionNumber: UInt32
init(data: Data) {
var index = data.startIndex
majorVersion = data.object(at: index)
index += MemoryLayout.size(ofValue: majorVersion)
minorVersion = data.object(at: index)
index += MemoryLayout.size(ofValue: minorVersion)
applicationHostId = data.object(at: index)
index += MemoryLayout.size(ofValue: applicationHostId)
versionNumber = data.object(at: index)
}
}
What is not part of this is of course the checking for the correctness of the data. As other mentioned in comments, this could be done either by having a failable init method or by throwing an Error.

Two Ways To Get 4 Bytes of (Swift3) Data Into a UInt32

So, I have a stream of well-formed data coming from some hardware. The stream consists of a bunch of chunks of 8-bit data, some of which are meant to form into 32-bit integers. That's all good. The data moves along and now I want to parcel the sequence up.
The data is actually a block of contiguous bytes, with segments of it mapped to useful data. So, for example, the first byte is a confirmation code, the following four bytes represent a UInt32 of some application-specific meaning, followed by two bytes representing a UInt16, and so on for a couple dozen bytes.
I found two different ways to do that, both of which seem a bit..overwrought. It may just what happens when you get close to the metal.
But — are these two code idioms generally what one should expect to do? Or am I missing something more compact?
// data : Data exists before this code, and has what we're transforming into UInt32
// One Way to get 4 bytes from Data into a UInt32
var y : [UInt8] = [UInt8](repeating:UInt8(0x0), count: 4)
data.copyBytes(to: &y, from: Range(uncheckedBounds: (2,6)))
let u32result = UnsafePointer(y).withMemoryRebound(to: UInt32.self, capacity: 1, {
$0.pointee
})
// u32result contains the 4 bytes from data
// Another Way to get 4 bytes from Data into a UInt32 via NSData
var result : UInt32 = 0
let resultAsNSData : NSData = data.subdata(in: Range(uncheckedBounds: (2,6))) as NSData
resultAsNSData.getBytes(&result, range: NSRange(location: 0, length: 4))
// result contains the 4 bytes from data
Creating UInt32 array from well-formed data object.
Swift 3
// Create sample data
let data = "foo".data(using: .utf8)!
// Using pointers style constructor
let array = data.withUnsafeBytes {
[UInt32](UnsafeBufferPointer(start: $0, count: data.count))
}
Swift 2
// Create sample data
let data = "foo".dataUsingEncoding(NSUTF8StringEncoding)!
// Using pointers style constructor
let array = Array(UnsafeBufferPointer(start: UnsafePointer<UInt32>(data.bytes), count: data.length))
I found two other ways of doing this which is leading me to believe that there are plenty of ways to do it, which is good, I suppose.
Two additional ways are described in some fashion over on Ray Wenderlich
This code dropped into your Xcode playground will reveal these two other idioms.
do {
let count = 1 // number of UInt32s
let stride = MemoryLayout<UInt32>.stride
let alignment = MemoryLayout<UInt32>.alignment
let byteCount = count * stride
var bytes : [UInt8] = [0x0D, 0x0C, 0x0B, 0x0A] // little-endian LSB -> MSB
var data : Data = Data.init(bytes: bytes) // In my situtation, I actually start with an instance of Data, so the [UInt8] above is a conceit.
print("---------------- 1 ------------------")
let placeholder = UnsafeMutableRawPointer.allocate(bytes: byteCount, alignedTo:alignment)
withUnsafeBytes(of: &data, { (bytes) in
for (index, byte) in data.enumerated() {
print("byte[\(index)]->\(String(format: "0x%02x",byte)) data[\(index)]->\(String(format: "0x%02x", data[index])) addr: \(bytes.baseAddress!+index)")
placeholder.storeBytes(of: byte, toByteOffset: index, as: UInt8.self)
}
})
let typedPointer1 = placeholder.bindMemory(to: UInt32.self, capacity: count)
print("u32: \(String(format: "0x%08x", typedPointer1.pointee))")
print("---------------- 2 ------------------")
for (index, byte) in bytes.enumerated() {
placeholder.storeBytes(of: byte, toByteOffset: index, as: UInt8.self)
// print("byte \(index): \(byte)")
print("byte[\(index)]->\(String(format: "0x%02x",byte))")
}
let typedPointer = placeholder.bindMemory(to: UInt32.self, capacity: count)
print(typedPointer.pointee)
let result : UInt32 = typedPointer.pointee
print("u32: \(String(format: "0x%08x", typedPointer.pointee))")
}
With output:
---------------- 1 ------------------
byte[0]->0x0d data[0]->0x0d addr: 0x00007fff57243f68
byte[1]->0x0c data[1]->0x0c addr: 0x00007fff57243f69
byte[2]->0x0b data[2]->0x0b addr: 0x00007fff57243f6a
byte[3]->0x0a data[3]->0x0a addr: 0x00007fff57243f6b
u32: 0x0a0b0c0d
---------------- 2 ------------------
byte[0]->0x0d
byte[1]->0x0c
byte[2]->0x0b
byte[3]->0x0a
168496141
u32: 0x0a0b0c0d
Here's a Gist.
let a = [ 0x00, 0x00, 0x00, 0x0e ]
let b = a[0] << 24 + a[1] << 16 + a[2] << 8 + a[3]
print(b) // will print 14.
Should I describe this operation ?

Bitwise and arithmetic operations in swift

Honestly speaking, porting to swift3(from obj-c) is going hard. The easiest but the swiftiest question.
public func readByte() -> UInt8
{
// ...
}
public func readShortInteger() -> Int16
{
return (self.readByte() << 8) + self.readByte();
}
Getting error message from compiler: "Binary operator + cannot be applied to two UInt8 operands."
What is wrong?
ps. What a shame ;)
readByte returns a UInt8 so:
You cannot shift a UInt8 left by 8 bits, you'll lose all its bits.
The type of the expression is UInt8 which cannot fit the Int16 value it is computing.
The type of the expression is UInt8 which is not the annotated return type Int16.
d
func readShortInteger() -> Int16
{
let highByte = self.readByte()
let lowByte = self.readByte()
return Int16(highByte) << 8 | Int16(lowByte)
}
While Swift have a strictly left-right evaluation order of the operands, I refactored the code to make it explicit which byte is read first and which is read second.
Also an OR operator is more self-documenting and semantic.
Apple has some great Swift documentation on this, here:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html
let shiftBits: UInt8 = 4 // 00000100 in binary
shiftBits << 1 // 00001000
shiftBits << 2 // 00010000
shiftBits << 5 // 10000000
shiftBits << 6 // 00000000
shiftBits >> 2 // 00000001

Convert half precision float (bytes) to float in Swift

I would like to be able to read in half floats from a binary file and convert them to a float in Swift. I've looked at several conversions from other languages such as Java and C#, however I have not been able to get the correct value corresponding to the half float. If anyone could help me with an implementation I would appreciate it. A conversion from Float to Half Float would also be extremely helpful. Here's an implementation I attempted to convert from this Java implementation.
static func toFloat(value: UInt16) -> Float {
let value = Int32(value)
var mantissa = Int32(value) & 0x03ff
var exp: Int32 = Int32(value) & 0x7c00
if(exp == 0x7c00) {
exp = 0x3fc00
} else if exp != 0 {
exp += 0x1c000
if(mantissa == 0 && exp > 0x1c400) {
return Float((value & 0x8000) << 16 | exp << 13 | 0x3ff)
}
} else if mantissa != 0 {
exp = 0x1c400
repeat {
mantissa << 1
exp -= 0x400
} while ((mantissa & 0x400) == 0)
mantissa &= 0x3ff
}
return Float((value & 0x80000) << 16 | (exp | mantissa) << 13)
}
If you have an array of half-precision data, you can convert all of it to float at once using vImageConvert_Planar16FtoPlanarF, which is provided by Accelerate.framework:
import Accelerate
let n = 2
var input: [UInt16] = [ 0x3c00, 0xbc00 ]
var output = [Float](count: n, repeatedValue: 0)
var src = vImage_Buffer(data:&input, height:1, width:UInt(n), rowBytes:2*n)
var dst = vImage_Buffer(data:&output, height:1, width:UInt(n), rowBytes:4*n)
vImageConvert_Planar16FtoPlanarF(&src, &dst, 0)
// output now contains [1.0, -1.0]
You can also use this method to convert individual values, but it's fairly heavyweight if that's all that you're doing; on the other hand it's extremely efficient if you have large buffers of values to convert.
If you need to convert isolated values, you might put something like the following C function in your bridging header and use it from Swift:
#include <stdint.h>
static inline float loadFromF16(const uint16_t *pointer) { return *(const __fp16 *)pointer; }
This will use hardware conversion instructions when you're compiling for targets that have them (armv7s, arm64, x86_64h), and call a reasonably good software conversion routine when compiling for targets that don't have hardware support.
addendum: going the other way
You can convert float to half-precision in pretty much the same way:
static inline storeAsF16(float value, uint16_t *pointer) { *(const __fp16 *)pointer = value; }
Or use the function vImageConvert_PlanarFtoPlanar16F.