1 //Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc. 2 3 //Distributed under the Boost Software License, Version 1.0. (See accompanying 4 //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #ifndef BOOST_QVM_E831FAD6B38F11DE8CECBF0D56D89593 7 #define BOOST_QVM_E831FAD6B38F11DE8CECBF0D56D89593 8 9 #include <boost/qvm/inline.hpp> 10 #include <boost/qvm/deduce_vec.hpp> 11 #include <boost/qvm/enable_if.hpp> 12 #include <boost/qvm/assert.hpp> 13 14 namespace 15 boost 16 { 17 namespace 18 qvm 19 { 20 namespace 21 qvm_detail 22 { 23 BOOST_QVM_INLINE_CRITICAL 24 void const * get_null()25 get_null() 26 { 27 static int const obj=0; 28 return &obj; 29 } 30 31 template <int A,class Next=void> struct swizzle_idx { static int const value=A; typedef Next next; }; 32 33 template <class V,int Idx> 34 struct 35 const_value 36 { 37 static 38 BOOST_QVM_INLINE_TRIVIAL 39 typename vec_traits<V>::scalar_type valueboost::qvm::qvm_detail::const_value40 value() 41 { 42 BOOST_QVM_ASSERT(0); 43 return typename vec_traits<V>::scalar_type(); 44 } 45 }; 46 47 template <class V> 48 struct 49 const_value<V,-1> 50 { 51 static 52 BOOST_QVM_INLINE_TRIVIAL 53 typename vec_traits<V>::scalar_type valueboost::qvm::qvm_detail::const_value54 value() 55 { 56 return scalar_traits<typename vec_traits<V>::scalar_type>::value(0); 57 } 58 }; 59 60 template <class V> 61 struct 62 const_value<V,-2> 63 { 64 static 65 BOOST_QVM_INLINE_TRIVIAL 66 typename vec_traits<V>::scalar_type valueboost::qvm::qvm_detail::const_value67 value() 68 { 69 return scalar_traits<typename vec_traits<V>::scalar_type>::value(1); 70 } 71 }; 72 73 template <int Index,bool Neg=(Index<0)> 74 struct neg_zero; 75 76 template <int Index> 77 struct 78 neg_zero<Index,true> 79 { 80 static int const value=0; 81 }; 82 83 template <int Index> 84 struct 85 neg_zero<Index,false> 86 { 87 static int const value=Index; 88 }; 89 90 template <class SwizzleList,int Index,int C=0> 91 struct 92 swizzle 93 { 94 static int const value=swizzle<typename SwizzleList::next,Index,C+1>::value; 95 }; 96 97 template <class SwizzleList,int Match> 98 struct 99 swizzle<SwizzleList,Match,Match> 100 { 101 static int const value=SwizzleList::value; 102 }; 103 104 template <int Index,int C> 105 struct swizzle<void,Index,C>; 106 107 template <class SwizzleList,int C=0> 108 struct 109 swizzle_list_length 110 { 111 static int const value=swizzle_list_length<typename SwizzleList::next,C+1>::value; 112 }; 113 114 template <int C> 115 struct 116 swizzle_list_length<void,C> 117 { 118 static int const value=C; 119 }; 120 121 template <class SwizzleList,int D> 122 struct 123 validate_swizzle_list 124 { 125 static bool const value = 126 ((SwizzleList::value)<D) && //don't touch extra (), MSVC parsing bug. 127 validate_swizzle_list<typename SwizzleList::next,D>::value; 128 }; 129 130 template <int D> 131 struct 132 validate_swizzle_list<void,D> 133 { 134 static bool const value=true; 135 }; 136 137 template <class OriginalType,class SwizzleList> 138 class 139 sw_ 140 { 141 sw_( sw_ const & ); 142 sw_ & operator=( sw_ const & ); 143 ~sw_(); 144 145 BOOST_QVM_STATIC_ASSERT((validate_swizzle_list<SwizzleList,vec_traits<OriginalType>::dim>::value)); 146 147 public: 148 149 template <class T> 150 BOOST_QVM_INLINE_TRIVIAL 151 sw_ & operator =(T const & x)152 operator=( T const & x ) 153 { 154 assign(*this,x); 155 return *this; 156 } 157 158 template <class R> 159 BOOST_QVM_INLINE_TRIVIAL operator R() const160 operator R() const 161 { 162 R r; 163 assign(r,*this); 164 return r; 165 } 166 }; 167 168 template <class SwizzleList> 169 class 170 sw01_ 171 { 172 sw01_( sw01_ const & ); 173 sw01_ & operator=( sw01_ const & ); 174 ~sw01_(); 175 176 public: 177 178 template <class R> 179 BOOST_QVM_INLINE_TRIVIAL operator R() const180 operator R() const 181 { 182 R r; 183 assign(r,*this); 184 return r; 185 } 186 }; 187 188 template <class OriginalType,class SwizzleList> 189 class 190 sws_ 191 { 192 sws_( sws_ const & ); 193 sws_ & operator=( sws_ const & ); 194 ~sws_(); 195 196 BOOST_QVM_STATIC_ASSERT((validate_swizzle_list<SwizzleList,1>::value)); 197 198 public: 199 200 template <class R> 201 BOOST_QVM_INLINE_TRIVIAL operator R() const202 operator R() const 203 { 204 R r; 205 assign(r,*this); 206 return r; 207 } 208 }; 209 } 210 211 template <class OriginalVector,class SwizzleList> 212 struct 213 vec_traits<qvm_detail::sw_<OriginalVector,SwizzleList> > 214 { 215 typedef qvm_detail::sw_<OriginalVector,SwizzleList> this_vector; 216 typedef typename vec_traits<OriginalVector>::scalar_type scalar_type; 217 static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value; 218 219 template <int I> 220 static 221 BOOST_QVM_INLINE_CRITICAL 222 scalar_type read_elementboost::qvm::vec_traits223 read_element( this_vector const & x ) 224 { 225 BOOST_QVM_STATIC_ASSERT(I>=0); 226 BOOST_QVM_STATIC_ASSERT(I<dim); 227 int const idx=qvm_detail::swizzle<SwizzleList,I>::value; 228 BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim); 229 return idx>=0? 230 vec_traits<OriginalVector>::template read_element<qvm_detail::neg_zero<idx>::value>(reinterpret_cast<OriginalVector const &>(x)) : 231 qvm_detail::const_value<this_vector,idx>::value(); 232 } 233 234 template <int I> 235 static 236 BOOST_QVM_INLINE_CRITICAL 237 scalar_type & write_elementboost::qvm::vec_traits238 write_element( this_vector & x ) 239 { 240 BOOST_QVM_STATIC_ASSERT(I>=0); 241 BOOST_QVM_STATIC_ASSERT(I<dim); 242 int const idx=qvm_detail::swizzle<SwizzleList,I>::value; 243 BOOST_QVM_STATIC_ASSERT(idx>=0); 244 BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim); 245 return vec_traits<OriginalVector>::template write_element<idx>(reinterpret_cast<OriginalVector &>(x)); 246 } 247 }; 248 249 template <class SwizzleList> 250 struct 251 vec_traits<qvm_detail::sw01_<SwizzleList> > 252 { 253 typedef qvm_detail::sw01_<SwizzleList> this_vector; 254 typedef int scalar_type; 255 static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value; 256 257 template <int I> 258 static 259 BOOST_QVM_INLINE_CRITICAL 260 scalar_type read_elementboost::qvm::vec_traits261 read_element( this_vector const & ) 262 { 263 BOOST_QVM_STATIC_ASSERT(I>=0); 264 BOOST_QVM_STATIC_ASSERT(I<dim); 265 int const idx=qvm_detail::swizzle<SwizzleList,I>::value; 266 BOOST_QVM_STATIC_ASSERT(idx<0); 267 return qvm_detail::const_value<this_vector,idx>::value(); 268 } 269 }; 270 271 template <class OriginalScalar,class SwizzleList> 272 struct 273 vec_traits<qvm_detail::sws_<OriginalScalar,SwizzleList> > 274 { 275 typedef qvm_detail::sws_<OriginalScalar,SwizzleList> this_vector; 276 typedef OriginalScalar scalar_type; 277 static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value; 278 279 template <int I> 280 static 281 BOOST_QVM_INLINE_CRITICAL 282 scalar_type read_elementboost::qvm::vec_traits283 read_element( this_vector const & x ) 284 { 285 BOOST_QVM_STATIC_ASSERT(I>=0); 286 BOOST_QVM_STATIC_ASSERT(I<dim); 287 int const idx=qvm_detail::swizzle<SwizzleList,I>::value; 288 BOOST_QVM_STATIC_ASSERT(idx<1); 289 return idx==0? 290 reinterpret_cast<OriginalScalar const &>(x) : 291 qvm_detail::const_value<this_vector,idx>::value(); 292 } 293 294 template <int I> 295 static 296 BOOST_QVM_INLINE_CRITICAL 297 scalar_type & write_elementboost::qvm::vec_traits298 write_element( this_vector & x ) 299 { 300 BOOST_QVM_STATIC_ASSERT(I>=0); 301 BOOST_QVM_STATIC_ASSERT(I<dim); 302 int const idx=qvm_detail::swizzle<SwizzleList,I>::value; 303 BOOST_QVM_STATIC_ASSERT(idx==0); 304 return reinterpret_cast<OriginalScalar &>(x); 305 } 306 }; 307 308 template <class OriginalVector,class SwizzleList,int D> 309 struct 310 deduce_vec<qvm_detail::sw_<OriginalVector,SwizzleList>,D> 311 { 312 typedef vec<typename vec_traits<OriginalVector>::scalar_type,D> type; 313 }; 314 315 template <class OriginalVector,class SwizzleList,int D> 316 struct 317 deduce_vec2<qvm_detail::sw_<OriginalVector,SwizzleList>,qvm_detail::sw_<OriginalVector,SwizzleList>,D> 318 { 319 typedef vec<typename vec_traits<OriginalVector>::scalar_type,D> type; 320 }; 321 322 template <class Scalar,class SwizzleList,int D> 323 struct 324 deduce_vec<qvm_detail::sws_<Scalar,SwizzleList>,D> 325 { 326 typedef vec<Scalar,D> type; 327 }; 328 329 template <class Scalar,class SwizzleList,int D> 330 struct 331 deduce_vec2<qvm_detail::sws_<Scalar,SwizzleList>,qvm_detail::sws_<Scalar,SwizzleList>,D> 332 { 333 typedef vec<Scalar,D> type; 334 }; 335 } 336 } 337 338 #endif 339