I am using Apple's Accelerate framework with swift. I am working with DSPSplitComplex numbers to work with complex vectors.
I would like to create a filter bank (An array of filters). To do this, I iterate through a loop, and add the result to my array using the following code:
func makeSine(freq:Float, N:Int) -> DSPSplitComplex {
var sreal:[Float] = Array(repeating: 0, count: N)
var simag:[Float] = Array(repeating: 0, count: N)
var compSine = DSPSplitComplex(realp: UnsafeMutablePointer(mutating:sreal), imagp: UnsafeMutablePointer(mutating:simag))
for i in 0..<t.count{
var x = 2 * Float.pi * freq * t[i]
sreal[i] = cos(x)
simag[i] = sin(x)
}
return compSine
}
the function above makes a complex sine wave. I call the function with:
var s = makeSine(freq:400.0, N:2048)
My issue is using DSPSplitComplex I am creating pointers to the arrays initialised in the function. I cannot inspect the variable s directly in the debug area in Xcode, however I achieve this using the following code:
var inspect:[Float]=[]
for i in 0..<t.count {
inspect.append(s.realp[I])
}
t.count being the length of the filter. Comparing the values of this array with the values printed out whilst inside the makeSine function, they are both very different. Because this is just a pointer, I believe it is not passing the actual values and these arrays are being deallocated.
My problem is that I am looking at iterating through the makeSine (and other functions) a few hundred times, resulting in hundreds of realp and imagp arrays. How do I handle these programatically?
Okay, I actually found a way around this earlier than I thought and posting to help others.
At the top of my class I initialise the separate arrays for the real and imaginary parts:
var realSines:[[Float]]=[]
var imagSines:[[Float]]=[]
then the rewritten makeSine function is:
func makeSine(freq:Float, N:Int, iteration:Int) -> DSPSplitComplex {
var sreal:[Float] = Array(repeating: 0, count: N)
var simag:[Float] = Array(repeating: 0, count: N)
var compSine = DSPSplitComplex(realp: UnsafeMutablePointer(mutating:sreal), imagp: UnsafeMutablePointer(mutating:simag))
for i in 0..<t.count{
var x = 2 * Float.pi * freq * t[i]
sreal[i] = cos(x)
simag[i] = sin(x)
}
realSines.append(sreal)
imagSines.append(simag)
}
then whenever I want to use a DSPSplitComplex I declare it with:
var tempSineReal = realSines[iteration]
var tempSineImag = imagSines[iteration]
var tempSine = DSPSplitComplex(realp: UnsafeMutablePointer(mutating:tempSineReal), imagp: UnsafeMutablePointer(mutating: tempSineImag))
Is there any way to have an n dimensional array in swift? I would like to be able to make a function that creates an array with n dimensions but I cannot figure out how.
Basically something like this:
func ndarray <T> (dimensions: Int...) -> [[T]] { // What do I tell it I return?
var out
for d in dimensions {
out = Array<T>(repeating: out, count: d)
}
return out
}
The above code does not work for obvios reasons but, I think it points out the main problems I am having:
How do I define a return type
How do I actually create the array
Once created how do I traverse and populate the array
Here is the implementation of an N-Dimensional Array. It uses a normal array internally for storage and converts the multi-dimensional indices into a single index for the internal array.
struct NDimArray<T> {
let dimensions: [Int]
var data: [T]
init(dimensions: Int..., initialValue: T) {
self.dimensions = dimensions
data = Array(repeating: initialValue, count: dimensions.reduce(1, *))
}
init(dimensions: Int..., initUsing initializer: () -> T) {
self.dimensions = dimensions
data = (0 ..< dimensions.reduce(1, *)).map { _ in initializer() }
}
// Compute index into data from indices
private func computeIndex(_ indices: [Int]) -> Int {
guard indices.count == dimensions.count else { fatalError("Wrong number of indices: got \(indices.count), expected \(dimensions.count)") }
zip(dimensions, indices).forEach { dim, idx in
guard (0 ..< dim) ~= idx else { fatalError("Index out of range") }
}
var idx = indices
var dims = dimensions
var product = 1
var total = idx.removeLast()
while !idx.isEmpty {
product *= dims.removeLast()
total += (idx.removeLast() * product)
}
return total
}
subscript(_ indices: Int...) -> T {
get {
return data[computeIndex(indices)]
}
set {
data[computeIndex(indices)] = newValue
}
}
}
Example:
// Create a 3 x 4 x 5 array of String with initial value ""
var arr = NDimArray<String>(dimensions: 3, 4, 5, initialValue: "")
for x in 0 ..< 3 {
for y in 0 ..< 4 {
for z in 0 ..< 5 {
// Encode indices in the string
arr[x, y, z] = "(\(x),\(y),\(z))"
}
}
}
// Show internal storage of data
print(arr.data)
["(0,0,0)", "(0,0,1)", "(0,0,2)", "(0,0,3)", "(0,0,4)", "(0,1,0)", "(0,1,1)", "(0,1,2)", "(0,1,3)", "(0,1,4)", "(0,2,0)", "(0,2,1)", "(0,2,2)", "(0,2,3)", "(0,2,4)", "(0,3,0)", "(0,3,1)", "(0,3,2)", "(0,3,3)", "(0,3,4)", "(1,0,0)", "(1,0,1)", "(1,0,2)", "(1,0,3)", "(1,0,4)", "(1,1,0)", "(1,1,1)", "(1,1,2)", "(1,1,3)", "(1,1,4)", "(1,2,0)", "(1,2,1)", "(1,2,2)", "(1,2,3)", "(1,2,4)", "(1,3,0)", "(1,3,1)", "(1,3,2)", "(1,3,3)", "(1,3,4)", "(2,0,0)", "(2,0,1)", "(2,0,2)", "(2,0,3)", "(2,0,4)", "(2,1,0)", "(2,1,1)", "(2,1,2)", "(2,1,3)", "(2,1,4)", "(2,2,0)", "(2,2,1)", "(2,2,2)", "(2,2,3)", "(2,2,4)", "(2,3,0)", "(2,3,1)", "(2,3,2)", "(2,3,3)", "(2,3,4)"]
print(arr[2, 2, 2]) // "(2,2,2)"
print(arr[3, 0, 0]) // Fatal error: Index out of range
print(arr[0, 4, 0]) // Fatal error: Index out of range
print(arr[2]) // Fatal error: Wrong number of indices: got 1, expected 3
Initializing an Array with a Reference Type
As #DuncanC noted in the comments, you have to be careful when initializing an array with a value which is a reference type, because the array will be filled with references to the object and modifying the object at any index will modify all of them.
To solve this, I added a second initializer:
init(dimensions: Int..., initUsing initializer: () -> T)
which takes a closure () -> T which can be used to create a new object for each element of the array.
For example:
class Person {
var name = ""
}
// Pass a closure which creates a `Person` instance to fill the array
// with 25 person objects
let arr = NDimArray(dimensions: 5, 5, initUsing: { Person() })
arr[3, 3].name = "Fred"
arr[2, 2].name = "Wilma"
print(arr[3, 3].name, arr[2, 2].name)
Fred Wilma
Nope, it's not possible. Array dimensions is something that needs to be determined at compile time, while the argument you want to pass to the initializer will not be known until runtime. If you really want to achieve something like this, then you'll need to move the array indexing from compile time to runtime, e.g. by accessing the array via an array of indexes. Still you don't have compile validation, since the array length can at runtime to not match the dimensions of the array.
This problem is similar to the one that attempts to convert a tuple to an array.
I made a function that returns multiple values
let interestingNumbers = [ // String:Array<Int>
"Prime": [2, 3, 5, 7, 11, 23],
"Fibonacci": [1, 1, 2, 3, 5, 80],
"Square": [1, 4, 9, 16, 25],
]
func largestNum(objDictionary:[String:Array<Int>]) -> (Int,String) {
var largest = 0
var ki:String? = nil
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
ki=kind
}
}
}
return (largest , ki!)
}
print(largestNum(interestingNumbers)) //calling fuction and print
/*var ar2:[Int,String] = largestNum(interestingNumbers))
print(ar2)*/' this code have an error`
How can I store the returned values from the function in the array
Update:
If you want both values in a single array with ar[0] being the Int and ar[1] being the String, then you'll need to declare ar2 to be [Any] and unpack the tuple when initializing ar2:
let largest = largestNum(interestingNumbers)
var ar2:[Any] = [largest.0, largest.1]
print(ar2) // [80, "Fibonacci"]
If you just assign the return to ar2 and leave it as a tuple, you can access the values with ar2.0 and ar2.1:
var ar2 = largestNum(interestingNumbers)
print(ar2.0) // 80
print(ar2.1) // "Fibonacci"
Or if you change your largestNum to return a named tuple:
func largestNum(objDictionary:[String:Array<Int>]) -> (number: Int, kind: String) {
}
var ar2 = largestNum(interestingNumbers)
print(ar2.number) // 80
print(ar2.kind) // "Fibonacci"
Original Answer:
Declare your array ar2 to hold tuples pairs of Int and String, and then wrap your return value in [] to create an array:
var ar2:[(Int,String)] = [largestNum(interestingNumbers)]
print(ar2) // [(80, "Fibonacci")]
Because tuples are really meant for temporary values, it is better style to store values in an array using a struct:
Change your function to return an InterestingNumber:
struct InterestingNumber {
let kind: String
let number: Int
}
func largestNum(objDictionary:[String:Array<Int>]) -> InterestingNumber {
// contents omitted for brevity
return InterestingNumber(kind: ki!, number: largest)
}
let largest = largestNum(interestingNumbers)
// Define your array to hold `InterestingNumber`s:
var ar2:[InterestingNumber] = [largest]
print(ar2) // [InterestingNumber(kind: "Fibonacci", number: 80)]
If you meant for ar2 to just hold a single value, then simply do:
var ar2 = largestNum(interestingNumbers)
and Swift will infer the type (which is a tuple in your original code or an InterestingNumber when using the struct.
your code runs fine in xcode 7.3.1 playground
okay, now i get your question:
let z: (Int, String) = largestNum(interestingNumbers)
The part after the arrow in your function definition is the type (i think called tupel), you can use it for a variable.
I've got an array of unsigned integers and I'd like to get a product of certain subsets.
For example, if my array was [2,2,1,5], I'd like the product of every two numbers (2 * 2 = 4 and 1 * 5 = 5).
So far, I've got:
var myArray:[UInt8] = [2,2,1,5]
var mySlice: Array<UInt8>
for (index,i) in enumerate(myArray) {
if (index % 2 == 1) {
mySlice = Array(myArray[(index - 1)...index])
println(mySlice.reduce(1,*))
mySlice.removeAll()
}
}
This seems like it would work (though ugly) but I get Execution was interrupted, reason: EXC_BAD_INSTRUCTION.
What's the best way to walk linearly down an array returning products (or computations) at certain intervals?
Thanks.
It looks like the problem is clearing out the slice while iterating the bigger array.
You should be able to work through this by adding the items to a separate array as you go, like this:
let myArray:[UInt8] = [2,2,1,5]
var result:[UInt8] = []
for (index,i) in enumerate(myArray) {
if (index % 2 == 1) {
let mySlice = Array(myArray[(index - 1)...index])
let tmp = mySlice.reduce(1,*)
result.append(tmp)
println(tmp)
}
}
println(result)
If you would like to put the results back into myArray, you can assign it after the loop.
Demo.
There are a few changes you can make that will make this much easier (and have much better performance) than your current attempt. First, use the global stride(from:to:interval:) function, which builds a sequence of indexes like the one you want -- no need to loop through all and skip the odd ones!
for i in stride(from: 0, to: myArray.count, by: 2) {
// ...
}
Second, you can use a slice's reduce method, so you don't have to convert a Slice back to an Array (doing so is unnecessary and inefficient):
let r = myArray[i ... i + 1].reduce(1, *)
So to bring it all together, your code could be:
var myArray: [UInt8] = [2, 2, 1, 5]
var result: [UInt8] = []
for i in stride(from: 0, to: myArray.count, by: 2) {
result.append( myArray[i...i + 1].reduce(1, *) )
}
// result is [4, 5]