vec.h revision 984826cc158193e61e3a00359ef4f6699c7d748a
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef ANDROID_VEC_H 18#define ANDROID_VEC_H 19 20#include <math.h> 21 22#include <stdint.h> 23#include <stddef.h> 24 25#include "traits.h" 26 27// ----------------------------------------------------------------------- 28 29#define PURE __attribute__((pure)) 30 31namespace android { 32 33// ----------------------------------------------------------------------- 34// non-inline helpers 35 36template <typename TYPE, size_t SIZE> 37class vec; 38 39template <typename TYPE, size_t SIZE> 40class vbase; 41 42namespace helpers { 43 44template <typename T> inline T min(T a, T b) { return a<b ? a : b; } 45template <typename T> inline T max(T a, T b) { return a>b ? a : b; } 46 47template < template<typename T, size_t S> class VEC, 48 typename TYPE, size_t SIZE, size_t S> 49vec<TYPE, SIZE>& doAssign( 50 vec<TYPE, SIZE>& lhs, const VEC<TYPE, S>& rhs) { 51 const size_t minSize = min(SIZE, S); 52 const size_t maxSize = max(SIZE, S); 53 for (size_t i=0 ; i<minSize ; i++) 54 lhs[i] = rhs[i]; 55 for (size_t i=minSize ; i<maxSize ; i++) 56 lhs[i] = 0; 57 return lhs; 58} 59 60 61template < 62 template<typename T, size_t S> class VLHS, 63 template<typename T, size_t S> class VRHS, 64 typename TYPE, 65 size_t SIZE 66> 67VLHS<TYPE, SIZE> PURE doAdd( 68 const VLHS<TYPE, SIZE>& lhs, 69 const VRHS<TYPE, SIZE>& rhs) { 70 VLHS<TYPE, SIZE> r; 71 for (size_t i=0 ; i<SIZE ; i++) 72 r[i] = lhs[i] + rhs[i]; 73 return r; 74} 75 76template < 77 template<typename T, size_t S> class VLHS, 78 template<typename T, size_t S> class VRHS, 79 typename TYPE, 80 size_t SIZE 81> 82VLHS<TYPE, SIZE> PURE doSub( 83 const VLHS<TYPE, SIZE>& lhs, 84 const VRHS<TYPE, SIZE>& rhs) { 85 VLHS<TYPE, SIZE> r; 86 for (size_t i=0 ; i<SIZE ; i++) 87 r[i] = lhs[i] - rhs[i]; 88 return r; 89} 90 91template < 92 template<typename T, size_t S> class VEC, 93 typename TYPE, 94 size_t SIZE 95> 96VEC<TYPE, SIZE> PURE doMulScalar( 97 const VEC<TYPE, SIZE>& lhs, 98 typename TypeTraits<TYPE>::ParameterType rhs) { 99 VEC<TYPE, SIZE> r; 100 for (size_t i=0 ; i<SIZE ; i++) 101 r[i] = lhs[i] * rhs; 102 return r; 103} 104 105template < 106 template<typename T, size_t S> class VEC, 107 typename TYPE, 108 size_t SIZE 109> 110VEC<TYPE, SIZE> PURE doScalarMul( 111 typename TypeTraits<TYPE>::ParameterType lhs, 112 const VEC<TYPE, SIZE>& rhs) { 113 VEC<TYPE, SIZE> r; 114 for (size_t i=0 ; i<SIZE ; i++) 115 r[i] = lhs * rhs[i]; 116 return r; 117} 118 119}; // namespace helpers 120 121// ----------------------------------------------------------------------- 122// Below we define the mathematical operators for vectors. 123// We use template template arguments so we can generically 124// handle the case where the right-hand-size and left-hand-side are 125// different vector types (but with same value_type and size). 126// This is needed for performance when using ".xy{z}" element access 127// on vec<>. Without this, an extra conversion to vec<> would be needed. 128// 129// example: 130// vec4_t a; 131// vec3_t b; 132// vec3_t c = a.xyz + b; 133// 134// "a.xyz + b" is a mixed-operation between a vbase<> and a vec<>, requiring 135// a conversion of vbase<> to vec<>. The template gunk below avoids this, 136// by allowing the addition on these different vector types directly 137// 138 139template < 140 template<typename T, size_t S> class VLHS, 141 template<typename T, size_t S> class VRHS, 142 typename TYPE, 143 size_t SIZE 144> 145inline VLHS<TYPE, SIZE> PURE operator + ( 146 const VLHS<TYPE, SIZE>& lhs, 147 const VRHS<TYPE, SIZE>& rhs) { 148 return helpers::doAdd(lhs, rhs); 149} 150 151template < 152 template<typename T, size_t S> class VLHS, 153 template<typename T, size_t S> class VRHS, 154 typename TYPE, 155 size_t SIZE 156> 157inline VLHS<TYPE, SIZE> PURE operator - ( 158 const VLHS<TYPE, SIZE>& lhs, 159 const VRHS<TYPE, SIZE>& rhs) { 160 return helpers::doSub(lhs, rhs); 161} 162 163template < 164 template<typename T, size_t S> class VEC, 165 typename TYPE, 166 size_t SIZE 167> 168inline VEC<TYPE, SIZE> PURE operator * ( 169 const VEC<TYPE, SIZE>& lhs, 170 typename TypeTraits<TYPE>::ParameterType rhs) { 171 return helpers::doMulScalar(lhs, rhs); 172} 173 174template < 175 template<typename T, size_t S> class VEC, 176 typename TYPE, 177 size_t SIZE 178> 179inline VEC<TYPE, SIZE> PURE operator * ( 180 typename TypeTraits<TYPE>::ParameterType lhs, 181 const VEC<TYPE, SIZE>& rhs) { 182 return helpers::doScalarMul(lhs, rhs); 183} 184 185 186template < 187 template<typename T, size_t S> class VLHS, 188 template<typename T, size_t S> class VRHS, 189 typename TYPE, 190 size_t SIZE 191> 192TYPE PURE dot_product( 193 const VLHS<TYPE, SIZE>& lhs, 194 const VRHS<TYPE, SIZE>& rhs) { 195 TYPE r(0); 196 for (size_t i=0 ; i<SIZE ; i++) 197 r += lhs[i] * rhs[i]; 198 return r; 199} 200 201template < 202 template<typename T, size_t S> class V, 203 typename TYPE, 204 size_t SIZE 205> 206TYPE PURE length(const V<TYPE, SIZE>& v) { 207 return sqrt(dot_product(v, v)); 208} 209 210template < 211 template<typename T, size_t S> class VLHS, 212 template<typename T, size_t S> class VRHS, 213 typename TYPE 214> 215VLHS<TYPE, 3> PURE cross_product( 216 const VLHS<TYPE, 3>& u, 217 const VRHS<TYPE, 3>& v) { 218 VLHS<TYPE, 3> r; 219 r.x = u.y*v.z - u.z*v.y; 220 r.y = u.z*v.x - u.x*v.z; 221 r.z = u.x*v.y - u.y*v.x; 222 return r; 223} 224 225 226template <typename TYPE, size_t SIZE> 227vec<TYPE, SIZE> PURE operator - (const vec<TYPE, SIZE>& lhs) { 228 vec<TYPE, SIZE> r; 229 for (size_t i=0 ; i<SIZE ; i++) 230 r[i] = -lhs[i]; 231 return r; 232} 233 234// ----------------------------------------------------------------------- 235 236// This our basic vector type, it just implements the data storage 237// and accessors. 238 239template <typename TYPE, size_t SIZE> 240struct vbase { 241 TYPE v[SIZE]; 242 inline const TYPE& operator[](size_t i) const { return v[i]; } 243 inline TYPE& operator[](size_t i) { return v[i]; } 244}; 245template<> struct vbase<float, 2> { 246 union { 247 float v[2]; 248 struct { float x, y; }; 249 struct { float s, t; }; 250 }; 251 inline const float& operator[](size_t i) const { return v[i]; } 252 inline float& operator[](size_t i) { return v[i]; } 253}; 254template<> struct vbase<float, 3> { 255 union { 256 float v[3]; 257 struct { float x, y, z; }; 258 struct { float s, t, r; }; 259 vbase<float, 2> xy; 260 vbase<float, 2> st; 261 }; 262 inline const float& operator[](size_t i) const { return v[i]; } 263 inline float& operator[](size_t i) { return v[i]; } 264}; 265template<> struct vbase<float, 4> { 266 union { 267 float v[4]; 268 struct { float x, y, z, w; }; 269 struct { float s, t, r, q; }; 270 vbase<float, 3> xyz; 271 vbase<float, 3> str; 272 vbase<float, 2> xy; 273 vbase<float, 2> st; 274 }; 275 inline const float& operator[](size_t i) const { return v[i]; } 276 inline float& operator[](size_t i) { return v[i]; } 277}; 278 279// ----------------------------------------------------------------------- 280 281template <typename TYPE, size_t SIZE> 282class vec : public vbase<TYPE, SIZE> 283{ 284 typedef typename TypeTraits<TYPE>::ParameterType pTYPE; 285 typedef vbase<TYPE, SIZE> base; 286 287public: 288 // STL-like interface. 289 typedef TYPE value_type; 290 typedef TYPE& reference; 291 typedef TYPE const& const_reference; 292 typedef size_t size_type; 293 294 typedef TYPE* iterator; 295 typedef TYPE const* const_iterator; 296 iterator begin() { return base::v; } 297 iterator end() { return base::v + SIZE; } 298 const_iterator begin() const { return base::v; } 299 const_iterator end() const { return base::v + SIZE; } 300 size_type size() const { return SIZE; } 301 302 // ----------------------------------------------------------------------- 303 // default constructors 304 305 vec() { } 306 vec(const vec& rhs) : base(rhs) { } 307 vec(const base& rhs) : base(rhs) { } 308 309 // ----------------------------------------------------------------------- 310 // conversion constructors 311 312 vec(pTYPE rhs) { 313 for (size_t i=0 ; i<SIZE ; i++) 314 base::operator[](i) = rhs; 315 } 316 317 template < template<typename T, size_t S> class VEC, size_t S> 318 explicit vec(const VEC<TYPE, S>& rhs) { 319 helpers::doAssign(*this, rhs); 320 } 321 322 explicit vec(TYPE const* array) { 323 for (size_t i=0 ; i<SIZE ; i++) 324 base::operator[](i) = array[i]; 325 } 326 327 // ----------------------------------------------------------------------- 328 // Assignment 329 330 vec& operator = (const vec& rhs) { 331 base::operator=(rhs); 332 return *this; 333 } 334 335 vec& operator = (const base& rhs) { 336 base::operator=(rhs); 337 return *this; 338 } 339 340 vec& operator = (pTYPE rhs) { 341 for (size_t i=0 ; i<SIZE ; i++) 342 base::operator[](i) = rhs; 343 return *this; 344 } 345 346 template < template<typename T, size_t S> class VEC, size_t S> 347 vec& operator = (const VEC<TYPE, S>& rhs) { 348 return helpers::doAssign(*this, rhs); 349 } 350 351 // ----------------------------------------------------------------------- 352 // operation-assignment 353 354 vec& operator += (const vec& rhs); 355 vec& operator -= (const vec& rhs); 356 vec& operator *= (pTYPE rhs); 357 358 // ----------------------------------------------------------------------- 359 // non-member function declaration and definition 360 // NOTE: we declare the non-member function as friend inside the class 361 // so that they are known to the compiler when the class is instantiated. 362 // This helps the compiler doing template argument deduction when the 363 // passed types are not identical. Essentially this helps with 364 // type conversion so that you can multiply a vec<float> by an scalar int 365 // (for instance). 366 367 friend inline vec PURE operator + (const vec& lhs, const vec& rhs) { 368 return helpers::doAdd(lhs, rhs); 369 } 370 friend inline vec PURE operator - (const vec& lhs, const vec& rhs) { 371 return helpers::doSub(lhs, rhs); 372 } 373 friend inline vec PURE operator * (const vec& lhs, pTYPE v) { 374 return helpers::doMulScalar(lhs, v); 375 } 376 friend inline vec PURE operator * (pTYPE v, const vec& rhs) { 377 return helpers::doScalarMul(v, rhs); 378 } 379 friend inline TYPE PURE dot_product(const vec& lhs, const vec& rhs) { 380 return android::dot_product(lhs, rhs); 381 } 382}; 383 384// ----------------------------------------------------------------------- 385 386template <typename TYPE, size_t SIZE> 387vec<TYPE, SIZE>& vec<TYPE, SIZE>::operator += (const vec<TYPE, SIZE>& rhs) { 388 vec<TYPE, SIZE>& lhs(*this); 389 for (size_t i=0 ; i<SIZE ; i++) 390 lhs[i] += rhs[i]; 391 return lhs; 392} 393 394template <typename TYPE, size_t SIZE> 395vec<TYPE, SIZE>& vec<TYPE, SIZE>::operator -= (const vec<TYPE, SIZE>& rhs) { 396 vec<TYPE, SIZE>& lhs(*this); 397 for (size_t i=0 ; i<SIZE ; i++) 398 lhs[i] -= rhs[i]; 399 return lhs; 400} 401 402template <typename TYPE, size_t SIZE> 403vec<TYPE, SIZE>& vec<TYPE, SIZE>::operator *= (vec<TYPE, SIZE>::pTYPE rhs) { 404 vec<TYPE, SIZE>& lhs(*this); 405 for (size_t i=0 ; i<SIZE ; i++) 406 lhs[i] *= rhs; 407 return lhs; 408} 409 410// ----------------------------------------------------------------------- 411 412typedef vec<float, 2> vec2_t; 413typedef vec<float, 3> vec3_t; 414typedef vec<float, 4> vec4_t; 415 416// ----------------------------------------------------------------------- 417 418}; // namespace android 419 420#endif /* ANDROID_VEC_H */ 421