1

I have a pointer to array of floats: arr = [a0, a1, a2, a3, ..., an]. I want the result to be: result = [a0+a1, a0+a1, a2+a3, a2+a3, a4+a5, a4+a5, ...]. Now I'm doing it with map() function:

let multiArrayValue: MLMultiArray = someMulityArray
let pointer = (multiArrayValue.dataPointer).bindMemory(to: Float.self, capacity: multiArrayValue.count)
let sums = (0..<multiArrayValue.count/2).map { (index) -> [Float] in
                let sum = pointer[index * 2] + pointer[index * 2 + 1]
                return [sum, sum]
            }.flatMap { $0 }

How to do it in an efficient way with Accelerate framework?

EDIT: I do manage to get res = [a0+a1, a2+a3, a4+a5, ..., an+an]:

let k = multiArrayValue.count/2
let n = vDSP_Length(k)
var res = [Float](repeating: 0, count: k)
vDSP_vadd(&pointer, vDSP_Stride(2),
          &pointer+1, vDSP_Stride(2),
          &res, vDSP_Stride(1),
          n)

So now the remained question is how, with Accelerate to get repeated values: [a1, a2, a3, ... an] => [a1, a1, a2, a2, ..., an, an]

Sanich
  • 1,739
  • 6
  • 25
  • 43
  • Do you really need the sums repeated in the result array? – Martin R Dec 16 '19 at 13:32
  • @MartinR I need it repeated for the next step in the calculation. – Sanich Dec 16 '19 at 13:33
  • @MartinR I just now managed to get `res = [a0+a1, a2+a3, a4+a5, a4+a5, ...]`. So it can be a separated question: how to: `[a1, a2, a3, ... an] => [a1, a1, a2, a2, ..., an, an]` – Sanich Dec 16 '19 at 13:58
  • 1
    Regarding your original question you could try `let sums = ptr.indices.map { ptr[$0 & ~1] + ptr[$0 | 1] }` because that avoids the creation of many temporary arrays. – Martin R Dec 16 '19 at 14:03
  • @Sanich how to: [a1, a2, a3, ... an] => [a1, a1, a2, a2, ..., an, an]: just enumerate original array , append(contentsOf: Array(repeating: element , count: 2)) – Amyth Dec 16 '19 at 14:05
  • @Sanich I'm not completely sure, but it may help you.. arraY.append(contentsOf: Array(repeating: ele + arr1[idx + 1], count: 2)) to get the solution. – Amyth Dec 16 '19 at 14:09
  • @Amyth I think your solutions involves loops which I'm trying to avoid – Sanich Dec 16 '19 at 14:23
  • @MartinR can you explain you comment which I've upvoted. Never saw such syntax – Sanich Dec 16 '19 at 14:28
  • 1
    As from Apple doc https://developer.apple.com/documentation/swift/sequence/2905332-flatmap. just use. let flatMapped = multiArrayValue.flatMap { Array(repeating: $0, count: 2) } – claude31 Dec 16 '19 at 14:35
  • @sanich So you’re just trying to create a duplicate of an element behind the original element? – Newbie Dec 16 '19 at 17:25

1 Answers1

0

The solution to this achieved in 2 steps. The key in both steps is to play with the strides. First just calculate the sums vector:

let k = multiArrayValue.count/2
let n = vDSP_Length(k)
var sums = [Float](repeating: 0, count: k)
vDSP_vadd(&pointer, vDSP_Stride(2),
          &pointer+1, vDSP_Stride(2),
          &sums, vDSP_Stride(1),
          n)

Second step is to get the repeated sums:

var resSparse = [Float](repeating: 0.0, count: k * 2)
vDSP_vmax(pointerOpt, 2, &sums + 1, 2, &resSparse, 2, k)
var res = [Float](repeating: 0.0, count: k * 2)
catlas_saxpby(k * 2 - 1, 1.0, &resSparse, 1, 1.0, &res + 1, 1)
catlas_saxpby(k * 2, 1.0, &resSparse, 1, 1.0, &res, 1)
Sanich
  • 1,739
  • 6
  • 25
  • 43