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