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