]> git.mxchange.org Git - simgear.git/blob - simgear/math/SGVec4.hxx
Mathias Froehlich: Add license information.
[simgear.git] / simgear / math / SGVec4.hxx
1 // Copyright (C) 2006  Mathias Froehlich - Mathias.Froehlich@web.de
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Library General Public License for more details.
12 //
13 // You should have received a copy of the GNU Library General Public
14 // License along with this library; if not, write to the
15 // Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 // Boston, MA  02111-1307, USA.
17 //
18
19 #ifndef SGVec4_H
20 #define SGVec4_H
21
22 /// 4D Vector Class
23 template<typename T>
24 class SGVec4 {
25 public:
26   typedef T value_type;
27
28   /// Default constructor. Does not initialize at all.
29   /// If you need them zero initialized, use SGVec4::zeros()
30   SGVec4(void)
31   {
32     /// Initialize with nans in the debug build, that will guarantee to have
33     /// a fast uninitialized default constructor in the release but shows up
34     /// uninitialized values in the debug build very fast ...
35 #ifndef NDEBUG
36     for (unsigned i = 0; i < 4; ++i)
37       _data[i] = SGLimits<T>::quiet_NaN();
38 #endif
39   }
40   /// Constructor. Initialize by the given values
41   SGVec4(T x, T y, T z, T w)
42   { _data[0] = x; _data[1] = y; _data[2] = z; _data[3] = w; }
43   /// Constructor. Initialize by the content of a plain array,
44   /// make sure it has at least 3 elements
45   explicit SGVec4(const T* d)
46   { _data[0] = d[0]; _data[1] = d[1]; _data[2] = d[2]; _data[3] = d[3]; }
47
48
49   /// Access by index, the index is unchecked
50   const T& operator()(unsigned i) const
51   { return _data[i]; }
52   /// Access by index, the index is unchecked
53   T& operator()(unsigned i)
54   { return _data[i]; }
55
56   /// Access raw data by index, the index is unchecked
57   const T& operator[](unsigned i) const
58   { return _data[i]; }
59   /// Access raw data by index, the index is unchecked
60   T& operator[](unsigned i)
61   { return _data[i]; }
62
63   /// Access the x component
64   const T& x(void) const
65   { return _data[0]; }
66   /// Access the x component
67   T& x(void)
68   { return _data[0]; }
69   /// Access the y component
70   const T& y(void) const
71   { return _data[1]; }
72   /// Access the y component
73   T& y(void)
74   { return _data[1]; }
75   /// Access the z component
76   const T& z(void) const
77   { return _data[2]; }
78   /// Access the z component
79   T& z(void)
80   { return _data[2]; }
81   /// Access the x component
82   const T& w(void) const
83   { return _data[3]; }
84   /// Access the x component
85   T& w(void)
86   { return _data[3]; }
87
88
89   /// Get the data pointer, usefull for interfacing with plib's sg*Vec
90   const T* data(void) const
91   { return _data; }
92   /// Get the data pointer, usefull for interfacing with plib's sg*Vec
93   T* data(void)
94   { return _data; }
95
96   /// Readonly interface function to ssg's sgVec3/sgdVec3
97   const T (&sg(void) const)[4]
98   { return _data; }
99   /// Interface function to ssg's sgVec3/sgdVec3
100   T (&sg(void))[4]
101   { return _data; }
102
103   /// Inplace addition
104   SGVec4& operator+=(const SGVec4& v)
105   { _data[0]+=v(0);_data[1]+=v(1);_data[2]+=v(2);_data[3]+=v(3);return *this; }
106   /// Inplace subtraction
107   SGVec4& operator-=(const SGVec4& v)
108   { _data[0]-=v(0);_data[1]-=v(1);_data[2]-=v(2);_data[3]-=v(3);return *this; }
109   /// Inplace scalar multiplication
110   template<typename S>
111   SGVec4& operator*=(S s)
112   { _data[0] *= s; _data[1] *= s; _data[2] *= s; _data[3] *= s; return *this; }
113   /// Inplace scalar multiplication by 1/s
114   template<typename S>
115   SGVec4& operator/=(S s)
116   { return operator*=(1/T(s)); }
117
118   /// Return an all zero vector
119   static SGVec4 zeros(void)
120   { return SGVec4(0, 0, 0, 0); }
121   /// Return unit vectors
122   static SGVec4 e1(void)
123   { return SGVec4(1, 0, 0, 0); }
124   static SGVec4 e2(void)
125   { return SGVec4(0, 1, 0, 0); }
126   static SGVec4 e3(void)
127   { return SGVec4(0, 0, 1, 0); }
128   static SGVec4 e4(void)
129   { return SGVec4(0, 0, 0, 1); }
130
131 private:
132   /// The actual data
133   T _data[4];
134 };
135
136 /// Unary +, do nothing ...
137 template<typename T>
138 inline
139 const SGVec4<T>&
140 operator+(const SGVec4<T>& v)
141 { return v; }
142
143 /// Unary -, do nearly nothing
144 template<typename T>
145 inline
146 SGVec4<T>
147 operator-(const SGVec4<T>& v)
148 { return SGVec4<T>(-v(0), -v(1), -v(2), -v(3)); }
149
150 /// Binary +
151 template<typename T>
152 inline
153 SGVec4<T>
154 operator+(const SGVec4<T>& v1, const SGVec4<T>& v2)
155 { return SGVec4<T>(v1(0)+v2(0), v1(1)+v2(1), v1(2)+v2(2), v1(3)+v2(3)); }
156
157 /// Binary -
158 template<typename T>
159 inline
160 SGVec4<T>
161 operator-(const SGVec4<T>& v1, const SGVec4<T>& v2)
162 { return SGVec4<T>(v1(0)-v2(0), v1(1)-v2(1), v1(2)-v2(2), v1(3)-v2(3)); }
163
164 /// Scalar multiplication
165 template<typename S, typename T>
166 inline
167 SGVec4<T>
168 operator*(S s, const SGVec4<T>& v)
169 { return SGVec4<T>(s*v(0), s*v(1), s*v(2), s*v(3)); }
170
171 /// Scalar multiplication
172 template<typename S, typename T>
173 inline
174 SGVec4<T>
175 operator*(const SGVec4<T>& v, S s)
176 { return SGVec4<T>(s*v(0), s*v(1), s*v(2), s*v(3)); }
177
178 /// Scalar dot product
179 template<typename T>
180 inline
181 T
182 dot(const SGVec4<T>& v1, const SGVec4<T>& v2)
183 { return v1(0)*v2(0) + v1(1)*v2(1) + v1(2)*v2(2) + v1(3)*v2(3); }
184
185 /// The euclidean norm of the vector, that is what most people call length
186 template<typename T>
187 inline
188 T
189 norm(const SGVec4<T>& v)
190 { return sqrt(dot(v, v)); }
191
192 /// The euclidean norm of the vector, that is what most people call length
193 template<typename T>
194 inline
195 T
196 length(const SGVec4<T>& v)
197 { return sqrt(dot(v, v)); }
198
199 /// The 1-norm of the vector, this one is the fastest length function we
200 /// can implement on modern cpu's
201 template<typename T>
202 inline
203 T
204 norm1(const SGVec4<T>& v)
205 { return fabs(v(0)) + fabs(v(1)) + fabs(v(2)) + fabs(v(3)); }
206
207 /// The euclidean norm of the vector, that is what most people call length
208 template<typename T>
209 inline
210 SGVec4<T>
211 normalize(const SGVec4<T>& v)
212 { return (1/norm(v))*v; }
213
214 /// Return true if exactly the same
215 template<typename T>
216 inline
217 bool
218 operator==(const SGVec4<T>& v1, const SGVec4<T>& v2)
219 { return v1(0)==v2(0) && v1(1)==v2(1) && v1(2)==v2(2) && v1(3)==v2(3); }
220
221 /// Return true if not exactly the same
222 template<typename T>
223 inline
224 bool
225 operator!=(const SGVec4<T>& v1, const SGVec4<T>& v2)
226 { return ! (v1 == v2); }
227
228 /// Return true if equal to the relative tolerance tol
229 template<typename T>
230 inline
231 bool
232 equivalent(const SGVec4<T>& v1, const SGVec4<T>& v2, T rtol, T atol)
233 { return norm1(v1 - v2) < rtol*(norm1(v1) + norm1(v2)) + atol; }
234
235 /// Return true if equal to the relative tolerance tol
236 template<typename T>
237 inline
238 bool
239 equivalent(const SGVec4<T>& v1, const SGVec4<T>& v2, T rtol)
240 { return norm1(v1 - v2) < rtol*(norm1(v1) + norm1(v2)); }
241
242 /// Return true if about equal to roundoff of the underlying type
243 template<typename T>
244 inline
245 bool
246 equivalent(const SGVec4<T>& v1, const SGVec4<T>& v2)
247 {
248   T tol = 100*SGLimits<T>::epsilon();
249   return equivalent(v1, v2, tol, tol);
250 }
251
252 #ifndef NDEBUG
253 template<typename T>
254 inline
255 bool
256 isNaN(const SGVec4<T>& v)
257 {
258   return SGMisc<T>::isNaN(v(0)) || SGMisc<T>::isNaN(v(1))
259     || SGMisc<T>::isNaN(v(2)) || SGMisc<T>::isNaN(v(3));
260 }
261 #endif
262
263 /// Output to an ostream
264 template<typename char_type, typename traits_type, typename T>
265 inline
266 std::basic_ostream<char_type, traits_type>&
267 operator<<(std::basic_ostream<char_type, traits_type>& s, const SGVec4<T>& v)
268 { return s << "[ " << v(0) << ", " << v(1) << ", " << v(2) << ", " << v(3) << " ]"; }
269
270 /// Two classes doing actually the same on different types
271 typedef SGVec4<float> SGVec4f;
272 typedef SGVec4<double> SGVec4d;
273
274 inline
275 SGVec4f
276 toVec4f(const SGVec4d& v)
277 { return SGVec4f((float)v(0), (float)v(1), (float)v(2), (float)v(3)); }
278
279 inline
280 SGVec4d
281 toVec4d(const SGVec4f& v)
282 { return SGVec4d(v(0), v(1), v(2), v(3)); }
283
284 #endif