Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions Sources/PropertyBased/Gen+SIMD.swift
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,35 @@ extension Gen<SIMD4<Double>> {
}
}

#if !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64))
@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
extension Gen<SIMD2<Float16>> {
/// A generator of vectors with length 1.
public static var unitVector: Generator<SIMD2<Float16>, Shrink.None<(Float16, Float16)>> {
let gen = Gen<Float16>.float16(in: 0...1)
return gen.simd2.map { normalize($0) }.filter { $0.x.isFinite }.withoutShrink()
}
}

@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
extension Gen<SIMD3<Float16>> {
/// A generator of vectors with length 1.
public static var unitVector: Generator<SIMD3<Float16>, Shrink.None<(Float16, Float16, Float16)>> {
let gen = Gen<Float16>.float16(in: 0...1)
return gen.simd3.map { normalize($0) }.filter { $0.x.isFinite }.withoutShrink()
}
}

@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
extension Gen<SIMD4<Float16>> {
/// A generator of vectors with length 1.
public static var unitVector: Generator<SIMD4<Float16>, Shrink.None<(Float16, Float16, Float16, Float16)>> {
let gen = Gen<Float16>.float16(in: 0...1)
return gen.simd4.map { normalize($0) }.filter { $0.x.isFinite }.withoutShrink()
}
}
#endif

#if canImport(simd)
extension Gen where Value == simd_quatf {
/// A generator of rotation quaternions with length 1 and a random angle.
Expand All @@ -121,6 +150,19 @@ extension Gen where Value == simd_quatd {
return zip(angle, vector).map { t in simd.simd_quatd(angle: t.0, axis: t.1) }
}
}

#if !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64))
@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
extension Gen where Value == simd_quath {
/// A generator of rotation quaternions with length 1 and a random angle.
public static var simd_quath: Generator<simd_quath, Shrink.Tuple<(Float, (Float, Float, Float))>> {
return Gen<simd_quatf>.simd_quatf.map { q in
simd.simd_quath(vector: simd_half4(q.vector))
}
}
}
#endif

#endif

@_disfavoredOverload
Expand Down
29 changes: 28 additions & 1 deletion Tests/PropertyBasedTests/GenTests+SIMD.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,21 @@ import simd
await unitVectorCheck(Gen<SIMD4<Double>>.unitVector)
}

#if !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64))
@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
@Test func testUnitVectorHalf2() async {
await unitVectorCheck(Gen<SIMD2<Float16>>.unitVector)
}
@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
@Test func testUnitVectorHalf3() async {
await unitVectorCheck(Gen<SIMD3<Float16>>.unitVector)
}
@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
@Test func testUnitVectorHalf4() async {
await unitVectorCheck(Gen<SIMD4<Float16>>.unitVector)
}
#endif

@Test func testVectorLength() {
#expect(!length([2, 0] as SIMD2<Float>).isApproximately(1))
#expect(length([3, 0] as SIMD2<Float>).isApproximately(3))
Expand All @@ -96,11 +111,23 @@ import simd
#expect(quat.length.isApproximately(1))
}
}

#if !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64))
@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
@Test func testQuatH() async {
await testGen(Gen.simd_quath.map(\.vector))
await propertyCheck(input: Gen.simd_quath) { quat in
let cast = simd_quatf(vector: .init(quat.vector))
#expect(cast.length.isApproximately(1))
}
}
#endif

#endif
}

extension FloatingPoint where Self: ExpressibleByFloatLiteral {
func isApproximately(_ other: Self, tolerance: Self = 0.001) -> Bool {
func isApproximately(_ other: Self, tolerance: Self = 0.01) -> Bool {
return abs(self - other) < tolerance
}
}