File indexing completed on 2025-09-17 08:49:23
0001 #ifndef BOOST_QVM_DETAIL_SWIZZLE_TRAITS_HPP_INCLUDED
0002 #define BOOST_QVM_DETAIL_SWIZZLE_TRAITS_HPP_INCLUDED
0003
0004
0005
0006
0007
0008 #include <boost/qvm/config.hpp>
0009 #include <boost/qvm/deduce_vec.hpp>
0010 #include <boost/qvm/enable_if.hpp>
0011 #include <boost/qvm/assert.hpp>
0012
0013 namespace boost { namespace qvm {
0014
0015 namespace
0016 qvm_detail
0017 {
0018 BOOST_QVM_INLINE_CRITICAL
0019 void const *
0020 get_null()
0021 {
0022 static int const obj=0;
0023 return &obj;
0024 }
0025
0026 template <int A,class Next=void> struct swizzle_idx { static int const value=A; typedef Next next; };
0027
0028 template <class V,int Idx>
0029 struct
0030 const_value
0031 {
0032 static
0033 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
0034 typename vec_traits<V>::scalar_type
0035 value()
0036 {
0037 BOOST_QVM_ASSERT(0);
0038 return typename vec_traits<V>::scalar_type();
0039 }
0040 };
0041
0042 template <class V>
0043 struct
0044 const_value<V,-1>
0045 {
0046 static
0047 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
0048 typename vec_traits<V>::scalar_type
0049 value()
0050 {
0051 return scalar_traits<typename vec_traits<V>::scalar_type>::value(0);
0052 }
0053 };
0054
0055 template <class V>
0056 struct
0057 const_value<V,-2>
0058 {
0059 static
0060 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
0061 typename vec_traits<V>::scalar_type
0062 value()
0063 {
0064 return scalar_traits<typename vec_traits<V>::scalar_type>::value(1);
0065 }
0066 };
0067
0068 template <int Index,bool Neg=(Index<0)>
0069 struct neg_zero;
0070
0071 template <int Index>
0072 struct
0073 neg_zero<Index,true>
0074 {
0075 static int const value=0;
0076 };
0077
0078 template <int Index>
0079 struct
0080 neg_zero<Index,false>
0081 {
0082 static int const value=Index;
0083 };
0084
0085 template <class SwizzleList,int Index,int C=0>
0086 struct
0087 swizzle
0088 {
0089 static int const value=swizzle<typename SwizzleList::next,Index,C+1>::value;
0090 };
0091
0092 template <class SwizzleList,int Match>
0093 struct
0094 swizzle<SwizzleList,Match,Match>
0095 {
0096 static int const value=SwizzleList::value;
0097 };
0098
0099 template <int Index,int C>
0100 struct swizzle<void,Index,C>;
0101
0102 template <class SwizzleList,int C=0>
0103 struct
0104 swizzle_list_length
0105 {
0106 static int const value=swizzle_list_length<typename SwizzleList::next,C+1>::value;
0107 };
0108
0109 template <int C>
0110 struct
0111 swizzle_list_length<void,C>
0112 {
0113 static int const value=C;
0114 };
0115
0116 template <class SwizzleList,int D>
0117 struct
0118 validate_swizzle_list
0119 {
0120 static bool const value =
0121 ((SwizzleList::value)<D) &&
0122 validate_swizzle_list<typename SwizzleList::next,D>::value;
0123 };
0124
0125 template <int D>
0126 struct
0127 validate_swizzle_list<void,D>
0128 {
0129 static bool const value=true;
0130 };
0131
0132 template <class OriginalType,class SwizzleList>
0133 class
0134 sw_
0135 {
0136 sw_( sw_ const & );
0137 sw_ & operator=( sw_ const & );
0138 ~sw_();
0139
0140 BOOST_QVM_STATIC_ASSERT((validate_swizzle_list<SwizzleList,vec_traits<OriginalType>::dim>::value));
0141
0142 public:
0143
0144 template <class T>
0145 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
0146 sw_ &
0147 operator=( T const & x )
0148 {
0149 assign(*this,x);
0150 return *this;
0151 }
0152
0153 template <class R
0154 #if __cplusplus >= 201103L
0155 , class = typename enable_if<is_vec<R> >::type
0156 #endif
0157 >
0158 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
0159 operator R() const
0160 {
0161 R r;
0162 assign(r,*this);
0163 return r;
0164 }
0165 };
0166
0167 template <class OriginalVector,class SwizzleList,bool WriteElementRef=vec_write_element_ref<OriginalVector>::value>
0168 struct sw_write_traits;
0169
0170 template <class OriginalVector,class SwizzleList>
0171 struct
0172 sw_write_traits<OriginalVector,SwizzleList,true>
0173 {
0174 typedef qvm_detail::sw_<OriginalVector,SwizzleList> this_vector;
0175 typedef typename vec_traits<OriginalVector>::scalar_type scalar_type;
0176 static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
0177
0178 template <int I>
0179 static
0180 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
0181 scalar_type &
0182 write_element( this_vector & x )
0183 {
0184 BOOST_QVM_STATIC_ASSERT(I>=0);
0185 BOOST_QVM_STATIC_ASSERT(I<dim);
0186 int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
0187 BOOST_QVM_STATIC_ASSERT(idx>=0);
0188 BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim);
0189 return vec_traits<OriginalVector>::template write_element<idx>(reinterpret_cast<OriginalVector &>(x));
0190 }
0191 };
0192
0193 template <class OriginalVector,class SwizzleList>
0194 struct
0195 sw_write_traits<OriginalVector,SwizzleList,false>
0196 {
0197 typedef qvm_detail::sw_<OriginalVector,SwizzleList> this_vector;
0198 typedef typename vec_traits<OriginalVector>::scalar_type scalar_type;
0199 static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
0200
0201 template <int I>
0202 static
0203 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
0204 void
0205 write_element( this_vector & x, scalar_type s )
0206 {
0207 BOOST_QVM_STATIC_ASSERT(I>=0);
0208 BOOST_QVM_STATIC_ASSERT(I<dim);
0209 int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
0210 BOOST_QVM_STATIC_ASSERT(idx>=0);
0211 BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim);
0212 vec_traits<OriginalVector>::template write_element<idx>(reinterpret_cast<OriginalVector &>(x), s);
0213 }
0214 };
0215
0216 template <class SwizzleList>
0217 class
0218 sw01_
0219 {
0220 sw01_( sw01_ const & );
0221 sw01_ & operator=( sw01_ const & );
0222 ~sw01_();
0223
0224 public:
0225
0226 template <class R
0227 #if __cplusplus >= 201103L
0228 , class = typename enable_if<is_vec<R> >::type
0229 #endif
0230 >
0231 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
0232 operator R() const
0233 {
0234 R r;
0235 assign(r,*this);
0236 return r;
0237 }
0238 };
0239
0240 template <class OriginalType,class SwizzleList>
0241 class
0242 sws_
0243 {
0244 sws_( sws_ const & );
0245 sws_ & operator=( sws_ const & );
0246 ~sws_();
0247
0248 BOOST_QVM_STATIC_ASSERT((validate_swizzle_list<SwizzleList,1>::value));
0249
0250 public:
0251
0252 template <class R
0253 #if __cplusplus >= 201103L
0254 , class = typename enable_if<is_vec<R> >::type
0255 #endif
0256 >
0257 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
0258 operator R() const
0259 {
0260 R r;
0261 assign(r,*this);
0262 return r;
0263 }
0264 };
0265 }
0266
0267 template <class OriginalVector,class SwizzleList>
0268 struct
0269 vec_traits<qvm_detail::sw_<OriginalVector,SwizzleList> >:
0270 qvm_detail::sw_write_traits<OriginalVector,SwizzleList>
0271 {
0272 typedef qvm_detail::sw_<OriginalVector,SwizzleList> this_vector;
0273 typedef typename vec_traits<OriginalVector>::scalar_type scalar_type;
0274 static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
0275
0276 template <int I>
0277 static
0278 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
0279 scalar_type
0280 read_element( this_vector const & x )
0281 {
0282 BOOST_QVM_STATIC_ASSERT(I>=0);
0283 BOOST_QVM_STATIC_ASSERT(I<dim);
0284 int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
0285 BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim);
0286 return idx>=0?
0287 vec_traits<OriginalVector>::template read_element<qvm_detail::neg_zero<idx>::value>(reinterpret_cast<OriginalVector const &>(x)) :
0288 qvm_detail::const_value<this_vector,idx>::value();
0289 }
0290 };
0291
0292 template <class SwizzleList>
0293 struct
0294 vec_traits<qvm_detail::sw01_<SwizzleList> >
0295 {
0296 typedef qvm_detail::sw01_<SwizzleList> this_vector;
0297 typedef int scalar_type;
0298 static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
0299
0300 template <int I>
0301 static
0302 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
0303 scalar_type
0304 read_element( this_vector const & )
0305 {
0306 BOOST_QVM_STATIC_ASSERT(I>=0);
0307 BOOST_QVM_STATIC_ASSERT(I<dim);
0308 int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
0309 BOOST_QVM_STATIC_ASSERT(idx<0);
0310 return qvm_detail::const_value<this_vector,idx>::value();
0311 }
0312 };
0313
0314 template <class OriginalScalar,class SwizzleList>
0315 struct
0316 vec_traits<qvm_detail::sws_<OriginalScalar,SwizzleList> >
0317 {
0318 typedef qvm_detail::sws_<OriginalScalar,SwizzleList> this_vector;
0319 typedef OriginalScalar scalar_type;
0320 static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
0321
0322 template <int I>
0323 static
0324 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
0325 scalar_type
0326 read_element( this_vector const & x )
0327 {
0328 BOOST_QVM_STATIC_ASSERT(I>=0);
0329 BOOST_QVM_STATIC_ASSERT(I<dim);
0330 int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
0331 BOOST_QVM_STATIC_ASSERT(idx<1);
0332 return idx==0?
0333 reinterpret_cast<OriginalScalar const &>(x) :
0334 qvm_detail::const_value<this_vector,idx>::value();
0335 }
0336
0337 template <int I>
0338 static
0339 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
0340 scalar_type &
0341 write_element( this_vector & x )
0342 {
0343 BOOST_QVM_STATIC_ASSERT(I>=0);
0344 BOOST_QVM_STATIC_ASSERT(I<dim);
0345 int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
0346 BOOST_QVM_STATIC_ASSERT(idx<1);
0347 return reinterpret_cast<OriginalScalar &>(x);
0348 }
0349 };
0350
0351 template <class OriginalVector,class SwizzleList,int D>
0352 struct
0353 deduce_vec<qvm_detail::sw_<OriginalVector,SwizzleList>,D>
0354 {
0355 typedef vec<typename vec_traits<OriginalVector>::scalar_type,D> type;
0356 };
0357
0358 template <class OriginalVector,class SwizzleList,int D>
0359 struct
0360 deduce_vec2<qvm_detail::sw_<OriginalVector,SwizzleList>,qvm_detail::sw_<OriginalVector,SwizzleList>,D>
0361 {
0362 typedef vec<typename vec_traits<OriginalVector>::scalar_type,D> type;
0363 };
0364
0365 template <class Scalar,class SwizzleList,int D>
0366 struct
0367 deduce_vec<qvm_detail::sws_<Scalar,SwizzleList>,D>
0368 {
0369 typedef vec<Scalar,D> type;
0370 };
0371
0372 template <class Scalar,class SwizzleList,int D>
0373 struct
0374 deduce_vec2<qvm_detail::sws_<Scalar,SwizzleList>,qvm_detail::sws_<Scalar,SwizzleList>,D>
0375 {
0376 typedef vec<Scalar,D> type;
0377 };
0378
0379 } }
0380
0381 #endif