refactored vector classes to avoid reinterpret_cast
[xonotic/netradiant.git] / libs / generic / vector.h
1
2 #if !defined(INCLUDED_VECTOR_H)
3 #define INCLUDED_VECTOR_H
4
5 #include <cstddef>
6
7 template <typename Element>
8 class BasicVector2
9 {
10   Element m_elements[2];
11 public:
12   BasicVector2()
13   {
14   }
15   BasicVector2(const Element& x_, const Element& y_)
16   {
17     x() = x_;
18     y() = y_;
19   }
20
21   Element& x()
22   {
23     return m_elements[0];
24   }
25   const Element& x() const
26   {
27     return m_elements[0];
28   }
29   Element& y()
30   {
31     return m_elements[1];
32   }
33   const Element& y() const
34   {
35     return m_elements[1];
36   }
37
38   const Element& operator[](std::size_t i) const
39   {
40     return m_elements[i];
41   }
42   Element& operator[](std::size_t i)
43   {
44     return m_elements[i];
45   }
46
47   Element* data()
48   {
49     return m_elements;
50   }
51   const Element* data() const
52   {
53     return m_elements;
54   }
55 };
56
57 /// \brief A 3-element vector.
58 template<typename Element>
59 class BasicVector3
60 {
61   Element m_elements[3];
62 public:
63
64   BasicVector3()
65   {
66   }
67   template<typename OtherElement>
68   BasicVector3(const BasicVector3<OtherElement>& other)
69   {
70     x() = static_cast<Element>(other.x());
71     y() = static_cast<Element>(other.y());
72     z() = static_cast<Element>(other.z());
73   }
74   BasicVector3(const Element& x_, const Element& y_, const Element& z_)
75   {
76     x() = x_;
77     y() = y_;
78     z() = z_;
79   }
80
81   Element& x()
82   {
83     return m_elements[0];
84   }
85   const Element& x() const
86   {
87     return m_elements[0];
88   }
89   Element& y()
90   {
91     return m_elements[1];
92   }
93   const Element& y() const
94   {
95     return m_elements[1];
96   }
97   Element& z()
98   {
99     return m_elements[2];
100   }
101   const Element& z() const
102   {
103     return m_elements[2];
104   }
105
106   const Element& operator[](std::size_t i) const
107   {
108     return m_elements[i];
109   }
110   Element& operator[](std::size_t i)
111   {
112     return m_elements[i];
113   }
114
115   Element* data()
116   {
117     return m_elements;
118   }
119   const Element* data() const
120   {
121     return m_elements;
122   }
123 };
124
125 /// \brief A 4-element vector.
126 template<typename Element>
127 class BasicVector4
128 {
129   Element m_elements[4];
130 public:
131
132   BasicVector4()
133   {
134   }
135   BasicVector4(Element x_, Element y_, Element z_, Element w_)
136   {
137     x() = x_;
138     y() = y_;
139     z() = z_;
140     w() = w_;
141   }
142   BasicVector4(const BasicVector3<Element>& self, Element w_)
143   {
144     x() = self.x();
145     y() = self.y();
146     z() = self.z();
147     w() = w_;
148   }
149
150   Element& x()
151   {
152     return m_elements[0];
153   }
154   const Element& x() const
155   {
156     return m_elements[0];
157   }
158   Element& y()
159   {
160     return m_elements[1];
161   }
162   const Element& y() const
163   {
164     return m_elements[1];
165   }
166   Element& z()
167   {
168     return m_elements[2];
169   }
170   const Element& z() const
171   {
172     return m_elements[2];
173   }
174   Element& w()
175   {
176     return m_elements[3];
177   }
178   const Element& w() const
179   {
180     return m_elements[3];
181   }
182
183   Element index(std::size_t i) const
184   {
185     return m_elements[i];
186   }
187   Element& index(std::size_t i)
188   {
189     return m_elements[i];
190   }
191   Element operator[](std::size_t i) const
192   {
193     return m_elements[i];
194   }
195   Element& operator[](std::size_t i)
196   {
197     return m_elements[i];
198   }
199
200   Element* data()
201   {
202     return m_elements;
203   }
204   const Element* data() const
205   {
206     return m_elements;
207   }
208 };
209
210 template<typename Element>
211 inline BasicVector3<Element> vector3_from_array(const Element* array)
212 {
213   return BasicVector3<Element>(array[0], array[1], array[2]);
214 }
215
216 template<typename Element>
217 inline Element* vector3_to_array(BasicVector3<Element>& self)
218 {
219   return self.data();
220 }
221 template<typename Element>
222 inline const Element* vector3_to_array(const BasicVector3<Element>& self)
223 {
224   return self.data();
225 }
226
227 template<typename Element>
228 inline Element* vector4_to_array(BasicVector4<Element>& self)
229 {
230   return self.data();
231 }
232 template<typename Element>
233 inline const Element* vector4_to_array(const BasicVector4<Element>& self)
234 {
235   return self.data();
236 }
237
238 template<typename Element>
239 inline BasicVector3<Element>& vector4_to_vector3(BasicVector4<Element>& self)
240 {
241   return *reinterpret_cast<BasicVector3<Element>*>(vector4_to_array(self));
242 }
243 template<typename Element>
244 inline const BasicVector3<Element>& vector4_to_vector3(const BasicVector4<Element>& self)
245 {
246   return *reinterpret_cast<const BasicVector3<Element>*>(vector4_to_array(self));
247 }
248
249 /// \brief A 2-element vector stored in single-precision floating-point.
250 typedef BasicVector2<float> Vector2;
251
252 /// \brief A 3-element vector stored in single-precision floating-point.
253 typedef BasicVector3<float> Vector3;
254
255 /// \brief A 4-element vector stored in single-precision floating-point.
256 typedef BasicVector4<float> Vector4;
257
258
259 #endif