I have a function in swift, as below. There is a loop with a reference to variables existing within an instance of this class. (fftfilterbankReal is an array in the class). However after one pass, I get an error with 'index out of range' at the code line 'for i in 0..
In the debugger it seems that on the 2nd iteration of this loop, there are no variables under the 'self' drop down.
If I comment out the line 'vDSP_zvmul(&kernel!, 1, &fft1Input, 1, &result, 1, vDSP_Length(r.count), 1)' then the loop runs and I can debug at any time and visually see the self variables in the debugger.
What am I missing that seems to make these variables disappear? I have read into memory allocation and such, and my class variables are declared using 'var' and nothing more, as that should default to strong in swift.
func convolveInput(realsamples:[Float], imagsamples:[Float]) -> [Float]{
realResult = Array(repeating: [], count: filterbankReal.count)
imagResult = Array(repeating: [], count: filterbankReal.count)
let x = realsamples
let y = imagsamples
var N = x.count
var logN = 16
var fft1Setup = vDSP_create_fftsetup(UInt(logN), FFTRadix(FFT_RADIX2))!
var paddedLength = x.count + filterbankReal.count - 1
var halfPaddedLength = paddedLength/2
var halfKernelLength = kernelLength/2
//setup Complex Buffer 1
var reals = [Float]()
var imags = [Float]()
for i in 0..<x.count{
reals.append(x[i])
imags.append(y[i])
}
var complexBuffer1 = DSPSplitComplex(realp: UnsafeMutablePointer(mutating: reals), imagp: UnsafeMutablePointer(mutating: imags))
//Perform FFT on incoming samples
var re = [Float](repeating:0.0, count: N)
var im = [Float](repeating:0.0, count: N)
var fft1Input = DSPSplitComplex(realp: UnsafeMutablePointer(mutating: re), imagp: UnsafeMutablePointer(mutating: im))
var fftlength = 10
vDSP_fft_zop(fft1Setup, &(complexBuffer1), 1, &fft1Input, 1, UInt(fftlength), Int32(FFT_FORWARD))
//Remove DC from FFT Signal
re.remove(at: 0)
im.remove(at: 0)
for i in 0..<self.fftfilterbankReal.count {
var r:[Float] = self.fftfilterbankReal[i]
var im:[Float] = self.fftfilterbankImag[i]
var kernel:DSPSplitComplex? = DSPSplitComplex(realp: &r, imagp: &im)
var res:Float = 0
var ims:Float = 0
var result:DSPSplitComplex = DSPSplitComplex(realp: &res, imagp: &ims)
vDSP_zvmul(&kernel!, 1, &fft1Input, 1, &result, 1, vDSP_Length(r.count), 1)
self.realResult[i].append(res)
self.imagResult[i].append(ims)
}
Your code is sort of a showcase of bad usages when working with Arrays and pointers.
For example:
var complexBuffer1 = DSPSplitComplex(realp: UnsafeMutablePointer(mutating: reals), imagp: UnsafeMutablePointer(mutating: imags))
or:
var kernel:DSPSplitComplex? = DSPSplitComplex(realp: &r, imagp: &im)
DSPSplitComplex holds two pointers for real part and imaginary part separately and does not copy the contents. You should not pass Swift Arrays for such parameters.
And the most critical part in your code is...
var res:Float = 0
var ims:Float = 0
var result:DSPSplitComplex = DSPSplitComplex(realp: &res, imagp: &ims)
vDSP_zvmul(&kernel!, 1, &fft1Input, 1, &result, 1, vDSP_Length(r.count), 1)
vDSP_zvmul generates N (in your code N = vDSP_Length(r.count)) complex numbers, so you need to prepare a region which can hold N elements.
Once you call vDSP_zvmul with your current code, you break whole stack contents which causes what you have experienced:
In the debugger it seems that on the 2nd iteration of this loop, there
are no variables under the 'self' drop down.
You are hiding many parts of your code, so it is very hard to guess what you really want to do, but if I re-write your code in safer manner, it would be something like this:
func convolveInput(realsamples:[Float], imagsamples:[Float]) -> [Float]{
realResult = Array(repeating: [], count: filterbankReal.count)
imagResult = Array(repeating: [], count: filterbankReal.count)
let x = realsamples
let y = imagsamples
var N = x.count
var logN = 16
var fft1Setup = vDSP_create_fftsetup(UInt(logN), FFTRadix(FFT_RADIX2))!
var paddedLength = x.count + filterbankReal.count - 1
var halfPaddedLength = paddedLength/2
var halfKernelLength = kernelLength/2
//setup Complex Buffer 1
var reals = UnsafeMutableBufferPointer<Float>.allocate(capacity: x.count)
defer {reals.deallocate()}
var imags = UnsafeMutableBufferPointer<Float>.allocate(capacity: y.count)
defer {imags.deallocate()}
_ = reals.initialize(from: x)
_ = imags.initialize(from: y)
var complexBuffer1 = DSPSplitComplex(realp: reals.baseAddress!, imagp: imags.baseAddress!)
//Perform FFT on incoming samples
var re = UnsafeMutableBufferPointer<Float>.allocate(capacity: N)
defer {re.deallocate()}
var im = UnsafeMutableBufferPointer<Float>.allocate(capacity: N)
defer {im.deallocate()}
var fft1Input = DSPSplitComplex(realp: re.baseAddress!, imagp: im.baseAddress!)
let fftlength = 10
vDSP_fft_zop(fft1Setup, &complexBuffer1, 1, &fft1Input, 1, UInt(fftlength), Int32(FFT_FORWARD))
//Remove DC from FFT Signal
fft1Input = DSPSplitComplex(realp: re.baseAddress!+1, imagp: im.baseAddress!+1)
for i in 0..<self.fftfilterbankReal.count {
self.fftfilterbankReal[i].withUnsafeMutableBufferPointer {rBuf in
self.fftfilterbankImag[i].withUnsafeMutableBufferPointer {imBuf in
var kernel = DSPSplitComplex(realp: rBuf.baseAddress!, imagp: imBuf.baseAddress!)
var res = UnsafeMutableBufferPointer<Float>.allocate(capacity: rBuf.count)
defer {res.deallocate()}
var ims = UnsafeMutableBufferPointer<Float>.allocate(capacity: rBuf.count)
defer {ims.deallocate()}
var result:DSPSplitComplex = DSPSplitComplex(realp: res.baseAddress!, imagp: ims.baseAddress!)
vDSP_zvmul(&kernel, 1, &fft1Input, 1, &result, 1, vDSP_Length(rBuf.count), 1)
//vDSP_zvmul generates `N` complex numbers,
// I do not understand what you really want to do...
self.realResult[i].append(res[0])
self.imagResult[i].append(ims[0])
}
}
}
//...
}
There may be other parts to fix, but anyway, please try and see what you get.
Foreword: Boy, sifting through all this took me almost 2 hours, and it's still not even perfect, but boy is this much nicer. I hope it helps!
Your code is suffer massively because the Accelerate APIs are C APIs that are not adapted to take advantage of Swift features. You will have much more readable code if you make yourself some nice wrappers for the Accelerate API, which lets you tuck all the "Ugly stuff" away into a corner you seldom have to see or edit.
I did this by creating a new type, ComplexFloatArray, which is similar to DSPSplitComplex, but actually encapsulates and owns its buffers. This prevents the dangling buffers that DSPSplitComplex is susceptible to.
After dining the ComplexFloatArray types, it's time to define some wrappers for the the Accelerate functions you used. In this case, vDSP_zvmul and vDSP_fft_zop. Since C doesn't have tuples, returning multiple values from a C function usually requires that you use out-parameters, which are used pervasively in the Accelerate framework. We can re-design these as Swift functions with regular return types. These APIs are very naturally expressed as instance methods that operate on ComplexFloatArray, so we'll put them there.
Additionally, your code is made much more complex by its dependance on external state. Convolution is a function, there's no reason why it does anything besides taking in input (via parameters, and not via instance variables) and returns the result (via return value, and not via instance variables).
import Accelerate
class ComplexFloatArray {
var reals: [Float]
var imaginaries: [Float]
init(reals: [Float], imaginaries: [Float]) {
self.reals = reals
self.imaginaries = imaginaries
}
}
extension ComplexFloatArray { // Core features
var count: Int {
assert(reals.count == imaginaries.count)
return reals.count
}
static let stride = 1
func append(real: Float, imaginary: Float) {
self.reals.append(real)
self.imaginaries.append(imaginary)
}
func useAsDSPSplitComplex<R>(_ closure: (inout DSPSplitComplex) -> R) -> R {
return reals.withUnsafeMutableBufferPointer { realBufferPointer in
return imaginaries.withUnsafeMutableBufferPointer { imaginaryBufferPointer in
var dspSplitComplex = DSPSplitComplex(realp: realBufferPointer.baseAddress!, imagp: imaginaryBufferPointer.baseAddress!)
return closure(&dspSplitComplex)
}
}
}
}
extension ComplexFloatArray { // Convenience utilities
convenience init() {
self.init(reals: [], imaginaries: [])
}
static func zeros(count: Int) -> ComplexFloatArray {
return ComplexFloatArray(reals: Array(repeating: 0, count: count), imaginaries:Array(repeating: 0, count: count))
}
}
extension ComplexFloatArray { // Vector multiplciation extensions
enum ComplexMultiplicationType: Int32 { case normal = 1, conjugate = -1 }
func complexMultiply(
with other: ComplexFloatArray,
multiplicationType: ComplexMultiplicationType = .normal
) -> ComplexFloatArray {
assert(self.count == other.count, "Multiplied vectors must have the same size!")
let result = ComplexFloatArray.zeros(count: self.count)
self.useAsDSPSplitComplex { selfPointer in
other.useAsDSPSplitComplex { otherPointer in
result.useAsDSPSplitComplex { resultPointer in
vDSP_zvmul(
&selfPointer, ComplexFloatArray.stride,
&otherPointer, ComplexFloatArray.stride,
&resultPointer, ComplexFloatArray.stride, vDSP_Length(result.count),
multiplicationType.rawValue)
}
}
}
return result
}
}
extension ComplexFloatArray { // FFT extensions
enum FourierTransformDirection: Int32 { case forward = 1, inverse = -1 }
//TODO: name log2n label better
func outOfPlaceComplexFourierTransform(
setup: FFTSetup,
resultSize: Int,
log2n: UInt,
direction: FourierTransformDirection
) -> ComplexFloatArray {
let result = ComplexFloatArray.zeros(count: resultSize)
self.useAsDSPSplitComplex { selfPointer in
result.useAsDSPSplitComplex{ resultPointer in
vDSP_fft_zop(
setup,
&selfPointer, ComplexFloatArray.stride,
&resultPointer, ComplexFloatArray.stride,
log2n,
direction.rawValue
)
}
}
return result
}
}
extension FFTSetup {
enum FourierTransformRadix: Int32 {
case radix2 = 0, radix3 = 1, radix5 = 2
// Static let constants are only initialized once
// This function's intent to to make sure this enum stays in sync with the raw constants the Accelerate framework uses
static let assertRawValuesAreCorrect: Void = {
func assertRawValue(for actual: FourierTransformRadix, isEqualTo expected: Int) {
assert(actual.rawValue == expected, "\(actual) has a rawValue of \(actual.rawValue), but expected \(expected).")
}
assertRawValue(for: .radix2, isEqualTo: kFFTRadix2)
assertRawValue(for: .radix3, isEqualTo: kFFTRadix3)
assertRawValue(for: .radix5, isEqualTo: kFFTRadix5)
}()
}
init(log2n: Int, _ radix: FourierTransformRadix) {
_ = FourierTransformRadix.assertRawValuesAreCorrect
guard let setup = vDSP_create_fftsetup(vDSP_Length(log2n), FFTRadix(radix.rawValue)) else {
fatalError("vDSP_create_fftsetup(\(log2n), \(radix)) returned nil")
}
self = setup
}
}
struct NameMe {
// I don't know what this is, but if it can somehow be removed,
// the whole convolveInput method could be moved into an extension on ComplexFloatArray.
var fftFilterBank: [ComplexFloatArray]
func convolve(samples: ComplexFloatArray) -> [ComplexFloatArray] {
// TODO: rework reimplement this code to remove the DC from samples, and add it back in
// //Remove DC from FFT Signal
// re.remove(at: 0)
// im.remove(at: 0)
let fftlength: UInt = 10 // Todo: what is this, exactly?
let fft1Input = samples.outOfPlaceComplexFourierTransform( // Rename me to something better
setup: FFTSetup(log2n: 16, .radix2),
resultSize: samples.count,
log2n: fftlength,
direction: .forward
)
return self.fftFilterBank.map { kernel in kernel.complexMultiply(with: fft1Input) }
}
// Stub for compatibility with the old API. Deprecate it and move to the
// `convolve(samples: ComplexFloatArray) -> [ComplexFloatArray]` as soon as possible.
func convolveInput(realsamples: [Float], imagsamples: [Float]) -> [ComplexFloatArray] {
return self.convolve(samples: ComplexFloatArray(reals: realsamples, imaginaries: imagsamples))
}
}
I have some notes along the way
This function is WAAAAAAAAAAAY too long. If you have a function that's over 10 lines long, there's a fairly strong indicator that it's growing too large, does to many things, and could benefit from being broken down into simpler steps.
You have lots of redundant variables. You don't need more than 1 copy of any given immutable value. You have all these different names, referring to the same thing, which just complicates things. There might be an argument to be made that this can be useful if the new names have significance, but names like x, y, re, im are near-useless in their communicative ability, and should almost-always be avoided entirely.
Arrays are value types with Copy-on-Write. You can make copies of them by simply assigning to them to a new variable, so code like:
var reals = [Float]()
var imags = [Float]()
for i in 0..<x.count{
reals.append(x[i])
imags.append(y[i])
}
Is both slow, and visually cumbersome. This could be simply: let (reals, imags) = (x, y). But again, these copies are unnecessary (as are x and y). Remove them, and just use realsamples and imagsamples directly.
When you find yourself frequently passing multiple pieces of data together, that's a very strong indication that you should define a new aggregate type to wrap them. For example, if you're passing two Array<Float> to represent complex vectors, you should define a ComplexVector type. This can let you enforce invariants (e.g. there are always as many real values as imaginary values), and add convenient operations (e.g. a func append(real: Float, imaginary: Float), which operates on both simultaneously, ensuring you can never forget to append to one of the arrays).
In closing,
There's a lot going on here, so I can't possible pre-empt every question and explain it ahead of time. I encourage you to take some time, read through this, and feel free to ask me any follow up questions.
I suspect I've made mistakes during my refactor (because I had no test cases to work with), but the code is modular enough that it should be very simple to isolate and fix and bugs.
Related
I'm working on a project where I need to work with large arrays, and by using UnsafeMutablePointers, I get a threefold speed increase over using the regular array methods. However, I believe the copy on write behavior is causing me to change instances that I do not want to be affected. For example, in the following code, I want to update the values in copyArray, but leave the original values in anArray.
import Foundation
func increaseWithPointers(_ arr: inout [Int]) {
let count = arr.count
let ptr = UnsafeMutablePointer(mutating: &arr)
for i in 0..<count {
ptr[i] = ptr[i] + 1
}
}
var anArray = [1,2,3,4,5]
var copyArray = anArray
increaseWithPointers(©Array)
print(anArray)
Executing this code prints [2,3,4,5,6].
I can get around this by declaring copyArray as follows:
var copyArray = [Int](repeating: 0, count: 5)
for i in 0..<5 {
copyArray[i] = anArray[i]
}
However, this requires writing each value twice: to zero, then to the intended value. Is there a way to efficiently guarantee a copy of an array?
I can reproduce your problem using Xcode 9 beta 3, but not using Xcode 8.3.3. I suggest you file a Swift bug report.
This fixes the problem:
import Foundation
func increaseWithPointers(_ arr: inout [Int]) {
arr.withUnsafeMutableBufferPointer { (buffer) in
for i in buffer.indices {
buffer[i] += 1
}
}
}
var anArray = [1,2,3,4,5]
var copyArray = anArray
increaseWithPointers(©Array)
print(anArray)
I'm doing a bunch of BLE in iOS, which means lots of tight packed C structures being encoded/decoded as byte packets. The following playground snippets illustrate what I'm trying to do generically.
import Foundation
// THE PROBLEM
struct Thing {
var a:UInt8 = 0
var b:UInt32 = 0
var c:UInt8 = 0
}
sizeof(Thing) // --> 9 :(
var thing = Thing(a: 0x42, b: 0xDEADBEAF, c: 0x13)
var data = NSData(bytes: &thing, length: sizeof(Thing)) // --> <42000000 afbeadde 13> :(
So given a series of fields of varying size, we don't get the "tightest" packing of bytes. Pretty well known and accepted. Given my simple structs, I'd like to be able to arbitrarily encode the fields back to back with no padding or alignment stuff. Relatively easy actually:
// ARBITRARY PACKING
var mirror = Mirror(reflecting: thing)
var output:[UInt8] = []
mirror.children.forEach { (label, child) in
switch child {
case let value as UInt32:
(0...3).forEach { output.append(UInt8((value >> ($0 * 8)) & 0xFF)) }
case let value as UInt8:
output.append(value)
default:
print("Don't know how to serialize \(child.dynamicType) (field \(label))")
}
}
output.count // --> 6 :)
data = NSData(bytes: &output, length: output.count) // --> <42afbead de13> :)
Huzzah! Works as expected. Could probably add a Class around it, or maybe a Protocol extension and have a nice utility. The problem I'm up against is the reverse process:
// ARBITRARY DEPACKING
var input = output.generate()
var thing2 = Thing()
"\(thing2.a), \(thing2.b), \(thing2.c)" // --> "0, 0, 0"
mirror = Mirror(reflecting:thing2)
mirror.children.forEach { (label, child) in
switch child {
case let oldValue as UInt8:
let newValue = input.next()!
print("new value for \(label!) would be \(newValue)")
// *(&child) = newValue // HOW TO DO THIS IN SWIFT??
case let oldValue as UInt32: // do little endian
var newValue:UInt32 = 0
(0...3).forEach {
newValue |= UInt32(input.next()!) << UInt32($0 * 8)
}
print("new value for \(label!) would be \(newValue)")
// *(&child) = newValue // HOW TO DO THIS IN SWIFT??
default:
print("skipping field \(label) of type \(child.dynamicType)")
}
}
Given an unpopulated struct value, I can decode the byte stream appropriately, figure out what the new value would be for each field. What I don't know how to do is to actually update the target struct with the new value. In my example above, I show how I might do it with C, get the pointer to the original child, and then update its value with the new value. I could do it easily in Python/Smalltalk/Ruby. But I don't know how one can do that in Swift.
UPDATE
As suggested in comments, I could do something like the following:
// SPECIFIC DEPACKING
extension GeneratorType where Element == UInt8 {
mutating func _UInt8() -> UInt8 {
return self.next()!
}
mutating func _UInt32() -> UInt32 {
var result:UInt32 = 0
(0...3).forEach {
result |= UInt32(self.next()!) << UInt32($0 * 8)
}
return result
}
}
extension Thing {
init(inout input:IndexingGenerator<[UInt8]>) {
self.init(a: input._UInt8(), b: input._UInt32(), c: input._UInt8())
}
}
input = output.generate()
let thing3 = Thing(input: &input)
"\(thing3.a), \(thing3.b), \(thing3.c)" // --> "66, 3735928495, 19"
Basically, I move the various stream decoding methods to byte stream (i.e. GeneratorType where Element == UInt8), and then I just have to write an initializer that strings those off in the same order and type the struct is defined as. I guess that part, which is essentially "copying" the structure definition itself (and therefore error prone), is what I had hoped to use some sort of introspection to handle. Mirrors are the only real Swift introspection I'm aware of, and it seems pretty limited.
As discussed in the comments, I suspect this is over-clever. Swift includes a lot of types not friendly to this approach. I would focus instead on how to make the boilerplate as easy as possible, without worrying about eliminating it. For example, this is very sloppy, but is in the direction I would probably go:
Start with some helper packer/unpacker functions:
func pack(values: Any...) -> [UInt8]{
var output:[UInt8] = []
for value in values {
switch value {
case let i as UInt32:
(0...3).forEach { output.append(UInt8((i >> ($0 * 8)) & 0xFF)) }
case let i as UInt8:
output.append(i)
default:
assertionFailure("Don't know how to serialize \(value.dynamicType)")
}
}
return output
}
func unpack<T>(bytes: AnyGenerator<UInt8>, inout target: T) throws {
switch target {
case is UInt32:
var newValue: UInt32 = 0
(0...3).forEach {
newValue |= UInt32(bytes.next()!) << UInt32($0 * 8)
}
target = newValue as! T
case is UInt8:
target = bytes.next()! as! T
default:
// Should throw an error here probably
assertionFailure("Don't know how to deserialize \(target.dynamicType)")
}
}
Then just call them:
struct Thing {
var a:UInt8 = 0
var b:UInt32 = 0
var c:UInt8 = 0
func encode() -> [UInt8] {
return pack(a, b, c)
}
static func decode(bytes: [UInt8]) throws -> Thing {
var thing = Thing()
let g = anyGenerator(bytes.generate())
try unpack(g, target: &thing.a)
try unpack(g, target: &thing.b)
try unpack(g, target: &thing.c)
return thing
}
}
A little more thought might be able to make the decode method a little less repetitive, but this is still probably the way I would go, explicitly listing the fields you want to encode rather than trying to introspect them. As you note, Swift introspection is very limited, and it may be that way for a long time. It's mostly used for debugging and logging, not logic.
I have tagged Rob's answer is the official answer. But I'd thought I'd share what I ended up doing as well, inspired by the comments and answers.
First, I fleshed out my "Problem" a little to include a nested structure:
struct Inner {
var ai:UInt16 = 0
var bi:UInt8 = 0
}
struct Thing {
var a:UInt8 = 0
var b:UInt32 = 0
var inner = Inner()
var c:UInt8 = 0
}
sizeof(Thing) // --> 12 :(
var thing = Thing(a: 0x42, b: 0xDEADBEAF, inner: Inner(ai: 0x1122, bi: 0xDD), c: 0x13)
var data = NSData(bytes: &thing, length: sizeof(Thing)) // --> <42000000 afbeadde 2211dd13> :(
For Arbitrary Packing, I stuck with the same generic approach:
protocol Packable {
func packed() -> [UInt8]
}
extension UInt8:Packable {
func packed() -> [UInt8] {
return [self]
}
}
extension UInt16:Packable {
func packed() -> [UInt8] {
return [(UInt8((self >> 0) & 0xFF)), (UInt8((self >> 8) & 0xFF))]
}
}
extension UInt32:Packable {
func packed() -> [UInt8] {
return [(UInt8((self >> 0) & 0xFF)), (UInt8((self >> 8) & 0xFF)), (UInt8((self >> 16) & 0xFF)), (UInt8((self >> 24) & 0xFF))]
}
}
extension Packable {
func packed() -> [UInt8] {
let mirror = Mirror(reflecting:self)
var bytes:[UInt8] = []
mirror.children.forEach { (label, child) in
switch child {
case let value as Packable:
bytes += value.packed()
default:
print("Don't know how to serialize \(child.dynamicType) (field \(label))")
}
}
return bytes
}
}
Being able to "pack" things is as easy adding them to the Packable protocol and telling them to pack themselves. For my cases above, I only need 3 different types of signed integers, but one could add lots more. For example, in my own code, I have some Enums derived from UInt8 which I added the packed method to.
extension Thing:Packable { }
extension Inner:Packable { }
var output = thing.packed()
output.count // --> 9 :)
data = NSData(bytes: &output, length: output.count) // --> <42afbead de2211dd 13> :)
To be able to unpack stuff, I came up with a little bit of support:
protocol UnpackablePrimitive {
static func unpack(inout input:IndexingGenerator<[UInt8]>) -> Self
}
extension UInt8:UnpackablePrimitive {
static func unpack(inout input:IndexingGenerator<[UInt8]>) -> UInt8 {
return input.next()!
}
}
extension UInt16:UnpackablePrimitive {
static func unpack(inout input:IndexingGenerator<[UInt8]>) -> UInt16 {
return UInt16(input.next()!) | (UInt16(input.next()!) << 8)
}
}
extension UInt32:UnpackablePrimitive {
static func unpack(inout input:IndexingGenerator<[UInt8]>) -> UInt32 {
return UInt32(input.next()!) | (UInt32(input.next()!) << 8) | (UInt32(input.next()!) << 16) | (UInt32(input.next()!) << 24)
}
}
With this, I can then add initializers to my high level structures, e.g.
extension Inner:Unpackable {
init(inout packed bytes:IndexingGenerator<[UInt8]>) {
self.init(ai: UInt16.unpack(&bytes), bi: UInt8.unpack(&bytes))
}
}
extension Thing:Unpackable {
init(inout packed bytes:IndexingGenerator<[UInt8]>) {
self.init(a: UInt8.unpack(&bytes), b: UInt32.unpack(&bytes), inner: Inner(packed:&bytes), c: UInt8.unpack(&bytes))
}
}
What I liked about this is that these initializers call the default initializer in the same order and types as the structure is defined. So if the structure changes in type or order, I have to revisit the (packed:) initializer. The kids a bit long, but not too.
What I didn't like about this, was having to pass the inout everywhere. I'm honestly not sure what the value is of value based generators, since passing them around you almost always want to share state. Kind of the whole point of reifying an object that captures the position of a stream of data, is to be able to share it. I also don't like having to specify IndexingGenerator directly, but I imagine there's some fu magic that would make that less specific and still work, but I'm not there yet.
I did play with something more pythonic, where I return a tuple of the type and the remainder of a passed array (rather than a stream/generator), but that wasn't nearly as easy to use at the top level init level.
I also tried putting the static methods as extensions on byte based generators, but you have to use a function (would rather have used a computed var with side effects) there whose name doesn't match a type, so you end up with something like
self.init(a: bytes._UInt8(), b: bytes._UInt32(), inner: Inner(packed:&bytes), c: bytes._UInt8())
This is shorter, but doesn't put the type like functions next to the argument names. And would require all kinds of application specific method names to be added as well as one extended the set of UnpackablePrimitives.
I am using the vDSP_meanD function to determine the average of a data set (consecutive diferences from an array)
The code I am using is below
func F(dataAllFrames:[Double],std:Double,medida:String)->Double{
let nframes=dataAllFrames.count
var diferencas_consecutivas_media = [Double](count: dataAllFrames.count-1, repeatedValue:0.0)
var mediaDifConseq:Double = 0
for(var i:Int=1; i<dataAllFrames.count; i++){
diferencas_consecutivas_media[i-1]=dataAllFrames[i]-dataAllFrames[i-1]
}
var meanConseqDif = [Double](count: 1, repeatedValue:0.0)
var meanConseqDifPtr = UnsafeMutablePointer<Double>(meanConseqDif)
vDSP_meanvD(diferencas_consecutivas_media,1,meanConseqDifPtr,UInt(nframes))
print( meanConseqDif[0])
}
The function F is called within a thread block
let group = dispatch_group_create()
let queue = dispatch_queue_create("myqueue.data.processor", DISPATCH_QUEUE_CONCURRENT)
dispatch_group_async(group, queue) {
F(measureData,std: std, medida: medida)
}
The F function is called in multiple dispatch block with different variables instances every now and then i get different values for the value returned from vDSP_meanD is there any context where this may happen ?
May the thread call have some influence on that?
Any "lights" would be greatly appreciated
I wouldn't expect this code to work. This shouldn't be correct:
var meanConseqDif = [Double](count: 1, repeatedValue:0.0)
var meanConseqDifPtr = UnsafeMutablePointer<Double>(meanConseqDif)
vDSP_meanvD(diferencas_consecutivas_media,1,meanConseqDifPtr,UInt(nframes))
I believe this is pointing directly at the Array struct, so you're probably blowing away the metadata rather than updating the value you meant. But I would expect that you don't get the right answers at all in that case. Have you validated that your results are correct usually?
I think the code you mean is like this:
func F(dataAllFrames: [Double], std: Double, medida: String) -> Double {
let nframes = UInt(dataAllFrames.count)
var diferencas_consecutivas_media = [Double](count: dataAllFrames.count-1, repeatedValue:0.0)
for(var i = 1; i < dataAllFrames.count; i += 1) {
diferencas_consecutivas_media[i-1] = dataAllFrames[i] - dataAllFrames[i-1]
}
var mediaDifConseq = 0.0
vDSP_meanvD(diferencas_consecutivas_media, 1, &mediaDifConseq, nframes)
return mediaDifConseq
}
You don't need an output array to collect a single result. You can just use a Double directly, and use & to take an unsafe pointer to it.
Unrelated point, but you can get rid of all of the difference-generating code with a single zip and map:
let diferencasConsecutivasMedia = zip(dataAllFrames, dataAllFrames.dropFirst())
.map { $1 - $0 }
I haven't profiled these two approaches, though. It's possible that your approach is faster. I find the zip and map much clearer and less error-prone, but others may feel differently.
I need to generate a random number.
It appears the arc4random function no longer exists as well as the arc4random_uniform function.
The options I have are arc4random_stir(), arc4random_buf(UnsafeMutablePointer<Void>, Int), and arc4random_addrandom(UnsafeMutablePointer<UInt8>, Int32).
I can't find any docs on the functions and no comments in the header files give hints.
let randomIntFrom0To10 = Int.random(in: 1..<10)
let randomFloat = Float.random(in: 0..<1)
// if you want to get a random element in an array
let greetings = ["hey", "hi", "hello", "hola"]
greetings.randomElement()
You could try as well:
let diceRoll = Int(arc4random_uniform(UInt32(6)))
I had to add "UInt32" to make it work.
Just call this function and provide minimum and maximum range of number and you will get a random number.
eg.like randomNumber(MIN: 0, MAX: 10) and You will get number between 0 to 9.
func randomNumber(MIN: Int, MAX: Int)-> Int{
return Int(arc4random_uniform(UInt32(MAX-MIN)) + UInt32(MIN));
}
Note:- You will always get output an Integer number.
After some investigation I wrote this:
import Foundation
struct Math {
private static var seeded = false
static func randomFractional() -> CGFloat {
if !Math.seeded {
let time = Int(NSDate().timeIntervalSinceReferenceDate)
srand48(time)
Math.seeded = true
}
return CGFloat(drand48())
}
}
Now you can just do Math.randomFraction() to get random numbers [0..1[ without having to remember seeding first. Hope this helps someone :o)
Update with swift 4.2 :
let randomInt = Int.random(in: 1..<5)
let randomFloat = Float.random(in: 1..<10)
let randomDouble = Double.random(in: 1...100)
let randomCGFloat = CGFloat.random(in: 1...1000)
Another option is to use the xorshift128plus algorithm:
func xorshift128plus(seed0 : UInt64, _ seed1 : UInt64) -> () -> UInt64 {
var state0 : UInt64 = seed0
var state1 : UInt64 = seed1
if state0 == 0 && state1 == 0 {
state0 = 1 // both state variables cannot be 0
}
func rand() -> UInt64 {
var s1 : UInt64 = state0
let s0 : UInt64 = state1
state0 = s0
s1 ^= s1 << 23
s1 ^= s1 >> 17
s1 ^= s0
s1 ^= s0 >> 26
state1 = s1
return UInt64.addWithOverflow(state0, state1).0
}
return rand
}
This algorithm has a period of 2^128 - 1 and passes all the tests of the BigCrush test suite. Note that while this is a high-quality pseudo-random number generator with a long period, it is not a cryptographically secure random number generator.
You could seed it from the current time or any other random source of entropy. For example, if you had a function called urand64() that read a UInt64 from /dev/urandom, you could use it like this:
let rand = xorshift128plus(urand64(), urand64())
for _ in 1...10 {
print(rand())
}
let MAX : UInt32 = 9
let MIN : UInt32 = 1
func randomNumber()
{
var random_number = Int(arc4random_uniform(MAX) + MIN)
print ("random = ", random_number);
}
In Swift 3 :
It will generate random number between 0 to limit
let limit : UInt32 = 6
print("Random Number : \(arc4random_uniform(limit))")
My implementation as an Int extension. Will generate random numbers in range from..<to
public extension Int {
static func random(from: Int, to: Int) -> Int {
guard to > from else {
assertionFailure("Can not generate negative random numbers")
return 0
}
return Int(arc4random_uniform(UInt32(to - from)) + UInt32(from))
}
}
This is how I get a random number between 2 int's!
func randomNumber(MIN: Int, MAX: Int)-> Int{
var list : [Int] = []
for i in MIN...MAX {
list.append(i)
}
return list[Int(arc4random_uniform(UInt32(list.count)))]
}
usage:
print("My Random Number is: \(randomNumber(MIN:-10,MAX:10))")
Another option is to use GKMersenneTwisterRandomSource from GameKit. The docs say:
A deterministic pseudo-random source that generates random numbers
based on a mersenne twister algorithm. This is a deterministic random
source suitable for creating reliable gameplay mechanics. It is
slightly slower than an Arc4 source, but more random, in that it has a
longer period until repeating sequences. While deterministic, this is
not a cryptographic random source. It is however suitable for
obfuscation of gameplay data.
import GameKit
let minValue = 0
let maxValue = 100
var randomDistribution: GKRandomDistribution?
let randomSource = GKMersenneTwisterRandomSource()
randomDistribution = GKRandomDistribution(randomSource: randomSource, lowestValue: minValue, highestValue: maxValue)
let number = randomDistribution?.nextInt() ?? 0
print(number)
Example taken from Apple's sample code: https://github.com/carekit-apple/CareKit/blob/master/CareKitPrototypingTool/OCKPrototyper/CareKitPatient/RandomNumberGeneratorHelper.swift
I'm late to the party 🤩🎉
Using a function that allows you to change the size of the array and the range selection on the fly is the most versatile method. You can also use map so it's very concise. I use it in all of my performance testing/bench marking.
elements is the number of items in the array
only including numbers from 0...max
func randArr(_ elements: Int, _ max: Int) -> [Int] {
return (0..<elements).map{ _ in Int.random(in: 0...max) }
}
Code Sense / Placeholders look like this.
randArr(elements: Int, max: Int)
10 elements in my array ranging from 0 to 1000.
randArr(10, 1000) // [554, 8, 54, 87, 10, 33, 349, 888, 2, 77]
you can use this in specific rate:
let die = [1, 2, 3, 4, 5, 6]
let firstRoll = die[Int(arc4random_uniform(UInt32(die.count)))]
let secondRoll = die[Int(arc4random_uniform(UInt32(die.count)))]
Lets Code with Swift for the random number or random string :)
let quotes: NSArray = ["R", "A", "N", "D", "O", "M"]
let randomNumber = arc4random_uniform(UInt32(quotes.count))
let quoteString = quotes[Int(randomNumber)]
print(quoteString)
it will give you output randomly.
Don't forget that some numbers will repeat! so you need to do something like....
my totalQuestions was 47.
func getRandomNumbers(totalQuestions:Int) -> NSMutableArray
{
var arrayOfRandomQuestions: [Int] = []
print("arraySizeRequired = 40")
print("totalQuestions = \(totalQuestions)")
//This will output a 40 random numbers between 0 and totalQuestions (47)
while arrayOfRandomQuestions.count < 40
{
let limit: UInt32 = UInt32(totalQuestions)
let theRandomNumber = (Int(arc4random_uniform(limit)))
if arrayOfRandomQuestions.contains(theRandomNumber)
{
print("ping")
}
else
{
//item not found
arrayOfRandomQuestions.append(theRandomNumber)
}
}
print("Random Number set = \(arrayOfRandomQuestions)")
print("arrayOutputCount = \(arrayOfRandomQuestions.count)")
return arrayOfRandomQuestions as! NSMutableArray
}
look, i had the same problem but i insert
the function as a global variable
as
var RNumber = Int(arc4random_uniform(9)+1)
func GetCase(){
your code
}
obviously this is not efficent, so then i just copy and paste the code into the function so it could be reusable, then xcode suggest me to set the var as constant so my code were
func GetCase() {
let RNumber = Int(arc4random_uniform(9)+1)
if categoria == 1 {
}
}
well thats a part of my code so xcode tell me something of inmutable and initialization but, it build the app anyway and that advice simply dissapear
hope it helps
struct MapVector {
var distance: Double
var bearing: Double
}
func distanceAndBearing() -> [MapVector] {
var points = self.mapPoints
var currPoint:CLLocation = points.first!
points.removeAtIndex(0)
var result: [MapVector] = []
for point: CLLocation in points {
let calc = PointCalculator(initialPoint: currPoint, nextPoint: point)
let v = MapVector(distance: calc.pointDistance, bearing: calc.bearing)
result.append(v)
currPoint = point
}
return result
}
I am working in Swift on an application using map coordinates. I have a an array of CLLocations from which I would like to create an array of distances and bearings. The above code (its slightly simplified for readability, so may not be 100% correct) achieves that but I'd like to do it in a neater way. Is this something that can be done with map or filter? Still trying to get my head around the FP way of doing things.
Here is a simplified example for the same problem except the calculations:
let numbers = [3, 7, 2, 8, 3, 7, 5]
let result = numbers.isEmpty ? [] :
map(zip(numbers, numbers[1..<numbers.count])) {
(x, y) in
return (diff: x - y, mult: x * y)
}
result[0].diff // -4
result[0].mult // 21
Here I compute the differences and the multiplications of the numbers.
Note this will work only for Swift 1.2
In case you need it for earlier version, you should explore the use of Zip2.
For reference here are alternative solutions I came up with:-
func distanceAndBearing2() -> [MapVector]
{
// make the removeAtIndex(0) part safe
if (self.mapPoints.count == 0) {
return []
}
var t2 = self.mapPoints
t2.removeAtIndex(0)
let t3 = zip(self.mapPoints, t2)
return Array(t3).map({
(p1, p2) in
return PointCalculator(initialPoint: p1, nextPoint: p2).toMapVector()
})
}
This uses the new zip method from Xcode 6.3 Beta 2, and I moved the conversion to MapVector into the PointCalculator struct
func distanceAndBearing3() -> [MapVector] {
// make the shift part safe
if (self.mapPoints.count == 0) {
return []
}
var points = self.mapPoints
var currPoint = points.shift()!
return points.map {
point in
let initialPoint = currPoint
currPoint = point
return LocationPair(initialPoint: initialPoint,
nextPoint: point).toMapVector()
}
}
And this version uses the same toMapVector method on the PointCalculator struct, but uses a variable outside the map function which is updated by the map function; this feels like its not "correct"