bastie
(Sebastian Ritter)
1
Hello,
what is an elegant way to transform low int values into a simple bit representation to store on disc and load it back. At best without external libraries.
I have exact 8 times pos integer values with max value of 31. This 8 times are so 2^5 different values. I looking for an elegant way to store it in 6 bytes (aka UInt8) and take the other 4 bits to store/load similar data with max 15.
For nibbles (right and left as UInt8) I use simple functions like
let storage : UInt8 = (left << 4) + right
let right : UInt8 = (storage << 4) >> 4
let left : UInt8 = (container >> 4)
Is it elegant to take an [UInt8] to store my 8 values or is it better to use UInt64 and what is a very fast way to store and read this values?
Thanks
Sebastian
tera
2
UInt64 + the ops similar to what you have above would be the fastest. Nowhere near as elegant as C-s bit fields (which Swift can handle), but those were never truly portable nor appropriate for serialising to / from disk / network.
2 Likes
scanon
(Steve Canon)
3
You can do something along the lines of:
struct BitField<T: FixedWidthInteger> {
var value: T
subscript<Other: FixedWidthInteger>(range: Range<Int>) -> Other {
get {
let width = range.upperBound - range.lowerBound
let mask: T = 1 << width &- 1
return Other(truncatingIfNeeded: value >> range.lowerBound & mask)
}
set {
let width = range.upperBound - range.lowerBound
let mask: T = 1 << width &- 1
value &= ~(mask << range.lowerBound)
value |= (T(truncatingIfNeeded: newValue) & mask) << range.lowerBound
}
}
}
extension FixedWidthInteger {
var bitField: BitField<Self> {
get { BitField(value: self) }
set { self = newValue.value }
}
}
func pack(fiveBits: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8),
nibbles: (UInt8, UInt8, UInt8, UInt8)) -> UInt64 {
var packed: UInt64 = 0
packed.bitField[ 0 ..< 5] = fiveBits.0
packed.bitField[ 5 ..< 10] = fiveBits.1
packed.bitField[10 ..< 15] = fiveBits.2
packed.bitField[15 ..< 20] = fiveBits.3
packed.bitField[20 ..< 25] = fiveBits.4
packed.bitField[25 ..< 30] = fiveBits.5
packed.bitField[30 ..< 35] = fiveBits.6
packed.bitField[35 ..< 40] = fiveBits.7
packed.bitField[48 ..< 52] = nibbles.0
packed.bitField[52 ..< 56] = nibbles.1
packed.bitField[56 ..< 60] = nibbles.2
packed.bitField[60 ..< 64] = nibbles.3
return packed
}
(I'm sketching this in a browser window, so apologies for any errors. I also didn't include any checking, which you would probably want to add.)
3 Likes