Skip to content

Commit 8371d67

Browse files
committed
Add vDSP_vmulD and vvpow
1 parent b7e0792 commit 8371d67

File tree

3 files changed

+96
-8
lines changed

3 files changed

+96
-8
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ The package is structured as follows:
5252
- [x] `vDSP_minvD` - Find the minimum value in a vector
5353
- [x] `vDSP_vaddD` - Add two vectors
5454
- [x] `vDSP_vsubD` - Subtract two vectors
55-
- [ ] `vDSP_vmulD` - Multiply two vectors
56-
- [ ] `vvpow` - Raise a vector to a power
55+
- [x] `vDSP_vmulD` - Multiply two vectors
56+
- [x] `vvpow` - Raise a vector to a power
5757
- [ ] `vDSP_vclrD` - Clear a vector
5858
- [ ] `vDSP_vfillD` - Fill a vector with a value
5959
- [ ] `vDSP_vabsD` - Absolute value of a vector

Sources/AccelerateLinux/VectorOps/VectorBasicOps.swift

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#if canImport(Accelerate)
22
@_exported import Accelerate
33
#else
4+
import FoundationEssentials
45

56
/// Calculates the double-precision maximum value of a vector.
67
/// - Parameters:
@@ -93,4 +94,61 @@ public func vDSP_vsubD(
9394
i += 1
9495
}
9596
}
97+
98+
/// Calculates the double-precision element-wise product of two vectors, using the specified stride.
99+
/// - Parameters:
100+
/// - __A: The first input vector, A.
101+
/// - __IA: The distance between the elements in the first input vector.
102+
/// - __B: The second input vector, B.
103+
/// - __IB: The distance between the elements in the second input vector.
104+
/// - __C: The output vector, C.
105+
/// - __IC: The distance between the elements in the output vector.
106+
/// - __N: The number of elements that the function processes.
107+
public func vDSP_vmulD(
108+
_ __A: UnsafePointer<Double>,
109+
_ __IA: vDSP_Stride,
110+
_ __B: UnsafePointer<Double>,
111+
_ __IB: vDSP_Stride,
112+
_ __C: UnsafeMutablePointer<Double>,
113+
_ __IC: vDSP_Stride,
114+
_ __N: vDSP_Length
115+
) {
116+
var i = 0
117+
while i < __N {
118+
__C[Int(i) * __IC] = __A[Int(i) * __IA] * __B[Int(i) * __IB]
119+
i += 1
120+
}
121+
}
122+
123+
/// Raises each element in an array to the power of the corresponding element in a second array of double-precision values.
124+
/// - Parameters:
125+
/// - _: The output array, z.
126+
/// - _: The exponent input array, y.
127+
/// - _: The base input array, x.
128+
/// - _: The number of elements in the arrays.
129+
public func vvpow(
130+
_ z: UnsafeMutablePointer<Double>,
131+
_ y: UnsafePointer<Double>,
132+
_ x: UnsafePointer<Double>,
133+
_ n: UnsafePointer<Int32>
134+
) {
135+
// Exponentiation by squaring
136+
func expBySquaring(_ b: Double, elevatedTo n: Double) -> Double {
137+
func aux(_ y: Double, _ b: Double, _ n: Double) -> Double {
138+
switch n {
139+
case let x where x < 0: aux(y, 1 / b, -n)
140+
case 0: y
141+
case let x where x.truncatingRemainder(dividingBy: 2) == 0: aux(y, b * b, n / 2)
142+
default: aux(b * y, b * b, (n - 1) / 2)
143+
}
144+
}
145+
return aux(1, b, n)
146+
}
147+
148+
var i = 0
149+
while i < n.pointee {
150+
z[i] = expBySquaring(x[i], elevatedTo: y[i])
151+
i += 1
152+
}
153+
}
96154
#endif

Tests/AccelerateLinuxTests/VectorTests/VectorBasicOpsTests.swift

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,9 @@ struct VectorBasicOpsTests {
8686
buffer, initializedCount in
8787

8888
vDSP_vsubD(
89-
b,
90-
stride,
91-
a,
92-
stride,
93-
buffer.baseAddress!,
94-
stride,
89+
b, stride,
90+
a, stride,
91+
buffer.baseAddress!, stride,
9592
vDSP_Length(count)
9693
)
9794

@@ -100,4 +97,37 @@ struct VectorBasicOpsTests {
10097

10198
#expect(c == [9.0, 18.0, 27.0, 36.0, 45.0])
10299
}
100+
101+
// https://developer.apple.com/documentation/accelerate/1450138-vdsp_vmuld
102+
@Test("vmulD")
103+
func vDSP_vmulDTest() {
104+
let stride = 1
105+
let count = 5
106+
107+
let a: [Double] = [1, 2, 3, 4, 5]
108+
let b: [Double] = [10, 20, 30, 40, 50]
109+
110+
let c = [Double](unsafeUninitializedCapacity: count) { buffer, initializedCount in
111+
vDSP_vmulD(
112+
a, stride,
113+
b, stride,
114+
buffer.baseAddress!, stride,
115+
vDSP_Length(count)
116+
)
117+
initializedCount = count
118+
}
119+
120+
#expect(c == [10.0, 40.0, 90.0, 160.0, 250.0])
121+
}
122+
123+
@Test("vvpow")
124+
func vvpowTest() {
125+
var x: [Double] = [3, 2, 10, 6]
126+
var y: [Double] = [2, 4, 3, 2]
127+
var z = [Double](repeating: 0, count: x.count)
128+
var n = Int32(x.count)
129+
130+
vvpow(&z, &y, &x, &n)
131+
#expect(z == [9.0, 16.0, 1000.0, 36.0])
132+
}
103133
}

0 commit comments

Comments
 (0)