@@ -137,17 +137,19 @@ using rel_t = typename std::conditional<
137
137
138
138
// Special type indicating that SwizzleOp should just read value from vector -
139
139
// not trying to perform any operations. Should not be called.
140
- template <typename DataT > class GetOp {
140
+ template <typename T > class GetOp {
141
141
public:
142
+ using DataT = T;
142
143
DataT getValue (size_t Index) const ;
143
144
DataT operator ()(DataT LHS, DataT Rhs);
144
145
};
145
146
146
147
// Special type for working SwizzleOp with scalars, stores a scalar and gives
147
148
// the scalar at any index. Provides interface is compatible with SwizzleOp
148
149
// operations
149
- template <typename DataT > class GetScalarOp {
150
+ template <typename T > class GetScalarOp {
150
151
public:
152
+ using DataT = T;
151
153
GetScalarOp (DataT Data) : m_Data(Data) {}
152
154
DataT getValue (size_t Index) const { return m_Data; }
153
155
@@ -230,7 +232,9 @@ T convertHelper(const T &Opnd) {
230
232
231
233
} // namespace detail
232
234
233
- template <typename DataT, int NumElements> class vec {
235
+ template <typename Type, int NumElements> class vec {
236
+ using DataT = Type;
237
+
234
238
// This represent type of underlying value. There should be only one field
235
239
// in the class, so vec<float, 16> should be equal to float16 in memory.
236
240
using DataType =
@@ -806,6 +810,9 @@ template <typename VecT, typename OperationLeftT, typename OperationRightT,
806
810
template <typename > class OperationCurrentT , int ... Indexes>
807
811
class SwizzleOp {
808
812
using DataT = typename VecT::element_type;
813
+ using CommonDataT =
814
+ typename std::common_type<typename OperationLeftT::DataT,
815
+ typename OperationRightT::DataT>::type;
809
816
using rel_t = detail::rel_t <DataT>;
810
817
static constexpr int getNumElements () { return sizeof ...(Indexes); }
811
818
@@ -830,15 +837,13 @@ class SwizzleOp {
830
837
OperationCurrentT, Indexes...>,
831
838
OperationCurrentT_, Idx_...>;
832
839
833
- template <int IdxNum>
834
- using EnableIfOneIndex =
835
- typename std::enable_if<1 == IdxNum &&
836
- SwizzleOp::getNumElements () == IdxNum>::type;
840
+ template <int IdxNum, typename T = void >
841
+ using EnableIfOneIndex = typename std::enable_if<
842
+ 1 == IdxNum && SwizzleOp::getNumElements() == IdxNum, T>::type;
837
843
838
- template <int IdxNum>
839
- using EnableIfMultipleIndexes =
840
- typename std::enable_if<1 != IdxNum &&
841
- SwizzleOp::getNumElements () == IdxNum>::type;
844
+ template <int IdxNum, typename T = void >
845
+ using EnableIfMultipleIndexes = typename std::enable_if<
846
+ 1 != IdxNum && SwizzleOp::getNumElements() == IdxNum, T>::type;
842
847
843
848
template <typename T>
844
849
using EnableIfScalarType =
@@ -1308,8 +1313,22 @@ class SwizzleOp {
1308
1313
m_RightOperation(std::move(Rhs.m_RightOperation)) {}
1309
1314
1310
1315
// Either performing CurrentOperation on results of left and right operands
1311
- // or reading values from actual vector.
1312
- DataT getValue (size_t Index) const {
1316
+ // or reading values from actual vector. Perform implicit type conversion when
1317
+ // the number of elements == 1
1318
+
1319
+ template <int IdxNum = getNumElements()>
1320
+ CommonDataT getValue (EnableIfOneIndex<IdxNum, size_t > Index) const {
1321
+ if (std::is_same<OperationCurrentT<DataT>, GetOp<DataT>>::value) {
1322
+ std::array<int , getNumElements ()> Idxs{Indexes...};
1323
+ return m_Vector->getValue (Idxs[Index]);
1324
+ }
1325
+ auto Op = OperationCurrentT<CommonDataT>();
1326
+ return Op (m_LeftOperation.getValue (Index),
1327
+ m_RightOperation.getValue (Index));
1328
+ }
1329
+
1330
+ template <int IdxNum = getNumElements()>
1331
+ DataT getValue (EnableIfMultipleIndexes<IdxNum, size_t > Index) const {
1313
1332
if (std::is_same<OperationCurrentT<DataT>, GetOp<DataT>>::value) {
1314
1333
std::array<int , getNumElements ()> Idxs{Indexes...};
1315
1334
return m_Vector->getValue (Idxs[Index]);
0 commit comments