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))
Related
I am refactoring some older Java code over to Kotlin. There is a function that returns the index of the minimum value held by an element in a Kotlin IntArray within the range [a, b]. The range values default to 0 and the size of the array - 1.
I would like to do something along the lines of...
return data.minOf().indexOf()
...but while only iterating between the a and b indices of data.
Here is the function:
// data is the IntArray property that I'm looping through.
fun absMinIndex(a: Int = 0, b: Int = (data.size - 1)) : Int {
var minVal = data[a]
var minIndex = 0
for (i in (a + 1)..b) {
val e = data[i]
if (e < minVal) {
minVal = e
minIndex = i
}
}
return maxIndex
}
This [for loop] solves the issue nicely by never visiting indices out of range, and by not generating a copied array/sub-array. I'm wondering if it could be done 'prettier'.
Question
Is there a more idiomatic Kotlin approach to iterating through an array within a range that would not negatively impact the performance of my current solution?
Edited some code for clarity.
I believe this approach would be more idiomatic:
Use IntRange as an input parameter
Define extension method for IntArray providing custom iterator to traverse the list in the desired range wrapping values into IndexedValue:
fun IntArray.withIndexInRange(range: IntRange = 0..lastIndex) = Iterable {
require(range.first >= 0 && range.last <= lastIndex)
object : Iterator<IndexedValue<Int>> {
private var index = range.first
override fun hasNext() = index <= range.last
override fun next() = IndexedValue(index, this#withIndexInRange[index++])
}
}
Use minByOrNull method from stdlib to find minimal value or wrap it into another extension method for convenience:
fun <T : Comparable<T>> Iterable<IndexedValue<T>>.indexOfMinOrNull() = minByOrNull { it.value }?.index
Usage:
data.withIndexInRange(a..b).indexOfMinOrNull()
Note, that this will have some performance penalties (creation and GC of N extra objects), but as Donald Knuth says:
Premature optimization is the root of all evil
So, I believe better readability worth it.
As Tenfour04 suggested, not much you can do without loosing performance. But as per your idea with changing the way you call it, you can make it an extension function.
fun IntArray.findIndexOfMinInRange(a: Int = 0, b: Int = this.size - 1): Int {
var maxVal = get(a)
var maxIndex = 0
for (i in (a + 1)..b) {
if (get(i) < maxVal) {
maxVal = get(i)
maxIndex = i
}
}
return maxIndex
}
//and call it like this:
data.findIndexOfMinInRange(0, 15) //or without anything in the parentheses for the default values
One thing that I would change is the variable names inside the function, we are searching for the minimum value, not max, and also for the index of the minimum, not the maximum index. Also maybe (big maybe) creating a val of data[it] instead of accessing it twice might be better (honestly not sure, we would be trading a .get for a few bytes of memory).
So all in all, I'd probably leave it at this:
fun IntArray.findIndexOfMinInRange(fromIndex: Int = 0, toIndex: Int = this.size - 1): Int {
var min = get(fromIndex)
var indexOfMin = fromIndex
for(i in (fromIndex + 1)..toIndex){
val current = get(i)
if (current < min) {
min = current
indexOfMin = i
}
}
return indexOfMin
}
//would be called in the same way the one above
Also, a note of caution, if you create an IntArray of a certain size, and do not populate it in full, the default values it will hold for the non populated ones is 0. If you do:
val data = IntArray(6)
data[0] = 10
data[1] = 11
data[2] = 100
data[3] = 9
data[4] = 50
Then the actual array is [10, 11, 100, 9, 50, 0].
My current code is like:
double[][][] result = new double[1000][][];
for (int i = 0; i < result.length; i++){
result[i] = somemethod();
}
Now I want to use stream to do the same thing. I did a lot of research, but cannot find an answer to fill the first dimension with the return value of another method.
For your task, the 3D nature of the array is irrelevant. You can replace double[][] with X in your mind and follow the same generic steps, you would do when producing the array X[]:
X[] array = IntStream.range(0, size).mapToObj(i -> somemethod()).toArray(X[]::new);
Using double[][] for X and 1000 for size yields:
double[][][] result
= IntStream.range(0, 1000).mapToObj(i -> somemethod()).toArray(double[][][]::new);
If somemethod() is expensive, but has no interference (so multiple concurrent calls are safe), you can use .parallel() with the stream. You could also use
double[][][] result = new double[1000][][];
Arrays.parallelSetAll(args, i -> somemethod());
in that case.
Is there a way to skip array initialization in ES6 ? I have to enumerate below R twice, first to initialize counters, then to do actual count of A elements. I would rather do one enumeration
var A = ['red',1,'blue','red',1]; // test data
var R = []; //associative array keeping count of A values
A.map((item)=> R[item]=0); //initialize R with A elements as R indexes
A.map((item)=> R[item]++); //count repeated A elelemnts in R
So many ways to approach this differently... Here's one:
R = A.reduce(function (R, item) {
R[item] = (R[item] || 0) + 1;
return R;
}, {});
You don't need to initialise, you could do something like this:
A.forEach((val) => {
if (R[val]) {
R[val] += 1
} else {
R[val] = 1
}
});
Is there a way to skip array initialization in ES6 ?
No, there isn't. You always need to declare and initialize a variable in javascript. There are no differences between es and esnext (outside from strict-mode you can skip the declaration, but isn't a good practice).
I didn't understand what you're trying to do...
It seems that you are counting each instance of a given element in a collection.
If you want to do that, you should use an associative array instead of an indexeed array:
var collection = [1, 2, 3, 4, 'me', 'you', 'she', 'me', 'you', 1];
var count = {};
collection.forEach(item => (count[item] = 1 + (count[item] || 0)));
You should keep in mind that associative arrays are indexed by string, so, you cannot have 'complex types' in your collection (eg: arrays), even, I think, number are converted to string. In ES6 you should use Map to work around this issue.
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]
I want to improve on a closure I wrote using Swift's Array.map function
I'm basically taking an Array and remapping all of its elements using a closure.
// Here's the array:
var numbersArray = [1, 2, 3, 4, 5]
// Here's the closure - it takes whatever number is passed into it and
// multiplies it by 2.0
var multiplier = { (currentNum: Int) -> Double in
let result = Double(currentNum) * 2.0
return result
}
// And here's how I'm calling it:
var newArray = numbersArray.map(multiplier)
And this works perfectly.
But what if I want to multiply everything by 2.1? or 3.5? or any value? In other words, what if I want to make the amount I multiply by also be a variable? And have it be passed into the closure as a second argument?
I tried adding it to the argument list like this:
var multiplier = { (currentNum: Int, factor: Double) -> Double in
let result = Double(currentNum) * factor
return result
}
and then changing my call to this:
var newArray = numbersArray.map(multiplier, 3.5)
but I'm getting all sorts of errors (and I tried all sorts of variations on this of course.)
What am I doing wrong?
Edit: Note: This language feature was removed in Swift 2.
A swift-er way than connor's answer (but along the same lines), is to use a curried function. From The Swift Programming Language->Language Reference->Declarations->Curried Functions and Methods:
A function declared this way is understood as a function whose return
type is another function.
So you can simplify this:
func multiplier(factor: Double) -> (Int)->Double
{
return { (currentNum: Int) -> Double in
let result = Double(currentNum) * factor
return result
}
}
to this:
func multiplier(factor: Double)(currentNum: Int) -> Double {
return Double(currentNum) * factor
}
and use it exactly the same way:
let numbersArray = [1, 2, 3, 4, 5]
let multipliedArray = numbersArray.map(multiplier(3.5))
You can use a higher order function to produce a custom function that you can then use with the array's map function. Like this:
var numbersArray = [1, 2, 3, 4, 5]
func multiplier(factor: Double) -> (Int)->Double
{
return { (currentNum: Int) -> Double in
let result = Double(currentNum) * factor
return result
}
}
var newArray = numbersArray.map(multiplier(2.5))