Skip to content

Commit 5afe404

Browse files
Concrete simd mask operations (swiftlang#36571)
* Replace lhs/rhs with a/b for clarity of documentation and to match concrete ops. * Concretize additional SIMDMask operations: .&=, .|=, .^=, .==, .!= Also reflect documentation changes back to generic implementations.
1 parent 5e9f8c0 commit 5afe404

File tree

3 files changed

+572
-256
lines changed

3 files changed

+572
-256
lines changed

stdlib/public/core/SIMDConcreteOperations.swift.gyb

Lines changed: 138 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,38 +38,172 @@ extension SIMDMask where Storage == ${Vector} {
3838
return zero .== zero
3939
}
4040

41-
/// A vector mask that is the boolean negation of the input.
41+
/// A vector mask that is the pointwise logical negation of the input.
42+
///
43+
/// Equivalent to:
44+
/// ```
45+
/// var result = SIMDMask<${Vector}>()
46+
/// for i in result.indices {
47+
/// result[i] = !a[i]
48+
/// }
49+
/// ```
4250
@_alwaysEmitIntoClient
4351
public static prefix func .!(a: Self) -> Self {
4452
a .^ .allTrue
4553
}
4654

47-
/// A vector mask that is the boolean conjunction of the inputs.
55+
/// A vector mask that is the pointwise logical conjunction of the inputs.
56+
///
57+
/// Equivalent to:
58+
/// ```
59+
/// var result = SIMDMask<${Vector}>()
60+
/// for i in result.indices {
61+
/// result[i] = a[i] && b[i]
62+
/// }
63+
/// ```
64+
///
65+
/// Note that unlike the scalar `&&` operator, the SIMD `.&` operator
66+
/// always fully evaluates both arguments.
4867
@_alwaysEmitIntoClient
4968
public static func .&(a: Self, b: Self) -> Self {
5069
Self(${Vector}(Builtin.and_${Builtin}(
5170
a._storage._storage._value,
5271
b._storage._storage._value
5372
)))
5473
}
74+
75+
/// Replaces `a` with the pointwise logical conjuction of `a` and `b`.
76+
///
77+
/// Equivalent to:
78+
/// ```
79+
/// for i in a.indices {
80+
/// a[i] = a[i] && b[i]
81+
/// }
82+
/// ```
83+
@_alwaysEmitIntoClient
84+
public static func .&=(a: inout Self, b: Self) {
85+
a = a .& b
86+
}
5587

56-
/// A vector mask that is the exclusive or of the inputs.
88+
/// A vector mask that is the pointwise exclusive or of the inputs.
89+
///
90+
/// Equivalent to:
91+
/// ```
92+
/// var result = SIMDMask<${Vector}>()
93+
/// for i in result.indices {
94+
/// result[i] = a[i] != b[i]
95+
/// }
96+
/// ```
5797
@_alwaysEmitIntoClient
5898
public static func .^(a: Self, b: Self) -> Self {
5999
Self(${Vector}(Builtin.xor_${Builtin}(
60100
a._storage._storage._value,
61101
b._storage._storage._value
62102
)))
63103
}
104+
105+
/// Replaces `a` with the pointwise exclusive or of `a` and `b`.
106+
///
107+
/// Equivalent to:
108+
/// ```
109+
/// for i in a.indices {
110+
/// a[i] = a[i] != b[i]
111+
/// }
112+
/// ```
113+
@_alwaysEmitIntoClient
114+
public static func .^=(a: inout Self, b: Self) {
115+
a = a .^ b
116+
}
64117

65-
/// A vector mask that is the boolean disjunction of the inputs.
118+
/// A vector mask that is the pointwise logical disjunction of the inputs.
119+
///
120+
/// Equivalent to:
121+
/// ```
122+
/// var result = SIMDMask<${Vector}>()
123+
/// for i in result.indices {
124+
/// result[i] = a[i] || b[i]
125+
/// }
126+
/// ```
127+
///
128+
/// Note that unlike the scalar `||` operator, the SIMD `.|` operator
129+
/// always fully evaluates both arguments.
66130
@_alwaysEmitIntoClient
67131
public static func .|(a: Self, b: Self) -> Self {
68132
Self(${Vector}(Builtin.or_${Builtin}(
69133
a._storage._storage._value,
70134
b._storage._storage._value
71135
)))
72136
}
137+
138+
/// Replaces `a` with the pointwise logical disjunction of `a` and `b`.
139+
///
140+
/// Equivalent to:
141+
/// ```
142+
/// for i in a.indices {
143+
/// a[i] = a[i] || b[i]
144+
/// }
145+
/// ```
146+
@_alwaysEmitIntoClient
147+
public static func .|=(a: inout Self, b: Self) {
148+
a = a .| b
149+
}
150+
151+
/// A vector mask with the result of a pointwise equality comparison.
152+
///
153+
/// Equivalent to:
154+
/// ```
155+
/// var result = SIMDMask<${Vector}>()
156+
/// for i in result.indices {
157+
/// result[i] = a[i] == b[i]
158+
/// }
159+
/// ```
160+
@_alwaysEmitIntoClient
161+
public static func .==(a: Self, b: Self) -> Self {
162+
.!(a .^ b)
163+
}
164+
165+
/// A vector mask with the result of a pointwise inequality comparison.
166+
///
167+
/// Equivalent to:
168+
/// ```
169+
/// var result = SIMDMask<${Vector}>()
170+
/// for i in result.indices {
171+
/// result[i] = a[i] != b[i]
172+
/// }
173+
/// ```
174+
@_alwaysEmitIntoClient
175+
public static func .!=(a: Self, b: Self) -> Self {
176+
a .^ b
177+
}
178+
179+
/// Replaces elements of this vector with elements of `other` in the lanes
180+
/// where `mask` is `true`.
181+
///
182+
/// Equivalent to:
183+
/// ```
184+
/// for i in indices {
185+
/// if mask[i] { self[i] = other[i] }
186+
/// }
187+
/// ```
188+
@_alwaysEmitIntoClient
189+
public mutating func replace(with other: Self, where mask: Self) {
190+
self = replacing(with: other, where: mask)
191+
}
192+
193+
/// Returns a copy of this vector, with elements replaced by elements of
194+
/// `other` in the lanes where `mask` is `true`.
195+
///
196+
/// Equivalent to:
197+
/// ```
198+
/// var result = Self()
199+
/// for i in indices {
200+
/// result[i] = mask[i] ? other[i] : self[i]
201+
/// }
202+
/// ```
203+
@_alwaysEmitIntoClient
204+
public func replacing(with other: Self, where mask: Self) -> Self {
205+
(self .& .!mask) .| (other .& mask)
206+
}
73207
}
74208

75209
% end

0 commit comments

Comments
 (0)