How to multiply two arrays element by element

I need to multiply the array by another array element by element, just like the product of the Hadamard vectors in mathematics. For instance:

A = [1,2,3,4] B = [2,3,4,5] C = A*B = [2,6,12,20] 

I can’t even understand the code, I tried to do it bit by bit, but it seems to me that this is too dirty a solution, have any ideas?

+10
source share
5 answers

Slowing down two arrays gives a sequence of tuples (a_i, b_i) which can then be multiplied by type:

 let A = [1,2,3,4] let B = [2,3,4,5] let C = zip(A, B).map { $0 * $1 } print(C) // [2, 6, 12, 20] 

(If arrays have different lengths, then zip silently ignores additional elements of a longer array.)

As @appzYourLife correctly said, you can also pass the multiplication operator directly as a map argument instead of a closure expression:

 let C = zip(A, B).map(*) 
+21
source

Multiple instructions with multiple instructions

If your vectors have exactly 4 components, you can use the superfast simd (Single Instruction Multiple Data) commands provided by iOS.

It uses a CPU to perform parallel computing.

Given 2 vectors 4 components from Int32

 import simd let a = int4(1, 2, 3, 4) let b = int4(2, 3, 4, 5) 

you can multiply each component

 let res = a &* b // int4(2, 6, 12, 20) 

As noted by Martin R, an array of float(s) or double(s) also provided by the simd module.

+6
source

Frame acceleration

For the vector multiplication theme, another alternative (in addition to the neat simd that @appzYourLife's answer applies to ) uses Speed ​​up frames . In this case, in particular, the vDSP methods vDSP_vmul and vDSP_vmuld ,

 func vDSP_vmul(UnsafePointer<Float>, vDSP_Stride, UnsafePointer<Float>, vDSP_Stride, UnsafeMutablePointer<Float>, vDSP_Stride, vDSP_Length) func vDSP_vmulD(UnsafePointer<Double>, vDSP_Stride, UnsafePointer<Double>, vDSP_Stride, UnsafeMutablePointer<Double>, vDSP_Stride, vDSP_Length) 

For example, the latter is used to multiply one element from two vectors of Double values:

 import Accelerate let a = [1.5, 2.5, 16.5, 7.5, 3.0] let b = [3.0, 4.5, 0.25, 3.5, 6.25] var result = [Double](repeating: 0.0, count: a.count) if a.count == b.count { vDSP_vmulD(a, 1, b, 1, &result, 1, vDSP_Length(a.count)) print(result) // [4.5, 11.25, 4.125, 26.25, 18.75] } 

Please note that using Accelerate is not as convenient and safe as alternative methods, since the vDSP_vmuld vector arguments vDSP_vmuld fixed as unsafe pointers ( UnsafePointer<Double> ) and it is our responsibility to ensure that the input vectors are the same length as well as the vector A result that is properly allocated before vector multiplication by vDSP_vmuld .

+5
source

With Swift 5, you can use one of the following methods to solve your problem.


# 1. Using SIMD vector types

The following Playground code example shows elementwise multiplication using SIMD4 :

 let vector1 = SIMD4(1, 2, 3, 4) let vector2 = SIMD4(2, 3, 4, 5) let vector3 = vector1 &* vector2 print(vector3) // prints: SIMD4<Int>(2, 6, 12, 20) 

Note that the SIMD protocol conforms to ExpressibleByArrayLiteral . This way you can initialize your vector using an array literal:

 var vector1: SIMD4 = [1, 2, 3, 4] let vector2: SIMD4 = [2, 3, 4, 5] vector1 &*= vector2 print(vector1) // prints: SIMD4<Int>(2, 6, 12, 20) 

# 2. Using a custom type that conforms to the Numeric and ExpressibleByArrayLiteral protocols

You can create your own type corresponding to Numeric and ExpressibleByArrayLiteral . The following Playground code example shows how to implement and use it:

 struct Vector { let x, y: Int init(_ x: Int, _ y: Int) { self.x = x self.y = y } } 
 extension Vector: AdditiveArithmetic { static var zero: Vector { return Vector(0, 0) } static func +(lhs: Vector, rhs: Vector) -> Vector { return Vector(lhs.x + rhs.x, lhs.y + rhs.y) } static func +=(lhs: inout Vector, rhs: Vector) { lhs = lhs + rhs } static func -(lhs: Vector, rhs: Vector) -> Vector { return Vector(lhs.x - rhs.x, lhs.y - rhs.y) } static func -=(lhs: inout Vector, rhs: Vector) { lhs = lhs - rhs } } 
 extension Vector: ExpressibleByIntegerLiteral { init(integerLiteral value: Int) { x = value y = value } } 
 import Darwin extension Vector: Numeric { var magnitude: Int { // Implement according to your needs return Int(Darwin.sqrt(Double(x * x + y * y))) } init?<T>(exactly source: T) where T : BinaryInteger { guard let source = source as? Int else { return nil } x = source y = source } static func *(lhs: Vector, rhs: Vector) -> Vector { return Vector(lhs.x * rhs.y, lhs.y * rhs.x) } static func *=(lhs: inout Vector, rhs: Vector) { lhs = lhs * rhs } } 
 extension Vector: ExpressibleByArrayLiteral { init(arrayLiteral elements: Int...) { assert(elements.count == 2, "arrayLiteral should have exactly 2 elements") self.x = elements[0] self.y = elements[1] } } 

Using:

 let vector1 = Vector(1, 2) let vector2 = Vector(2, 3) let vector3 = vector1 * vector2 print(vector3) // prints: Vector(x: 3, y: 4) 
 let vector1: Vector = [1, 2] let vector2: Vector = [2, 3] let vector3 = vector1 * vector2 print(vector3) // prints: Vector(x: 3, y: 4) 
+1
source
  let A = [1,2,3,4] let B = [2,3,4,5] var C = [Int]() A.enumerated().forEach{ index, value in return C.append(value * B[index]) } 
0
source

All Articles