vec.h revision 3301542828febc768e1df42892cfac4992c35474
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 V, 212 typename TYPE, 213 size_t SIZE 214> 215V<TYPE, SIZE> PURE normalize(const V<TYPE, SIZE>& v) { 216 return v * (1/length(v)); 217} 218 219template < 220 template<typename T, size_t S> class VLHS, 221 template<typename T, size_t S> class VRHS, 222 typename TYPE 223> 224VLHS<TYPE, 3> PURE cross_product( 225 const VLHS<TYPE, 3>& u, 226 const VRHS<TYPE, 3>& v) { 227 VLHS<TYPE, 3> r; 228 r.x = u.y*v.z - u.z*v.y; 229 r.y = u.z*v.x - u.x*v.z; 230 r.z = u.x*v.y - u.y*v.x; 231 return r; 232} 233 234 235template <typename TYPE, size_t SIZE> 236vec<TYPE, SIZE> PURE operator - (const vec<TYPE, SIZE>& lhs) { 237 vec<TYPE, SIZE> r; 238 for (size_t i=0 ; i<SIZE ; i++) 239 r[i] = -lhs[i]; 240 return r; 241} 242 243// ----------------------------------------------------------------------- 244 245// This our basic vector type, it just implements the data storage 246// and accessors. 247 248template <typename TYPE, size_t SIZE> 249struct vbase { 250 TYPE v[SIZE]; 251 inline const TYPE& operator[](size_t i) const { return v[i]; } 252 inline TYPE& operator[](size_t i) { return v[i]; } 253}; 254template<> struct vbase<float, 2> { 255 union { 256 float v[2]; 257 struct { float x, y; }; 258 struct { float s, t; }; 259 }; 260 inline const float& operator[](size_t i) const { return v[i]; } 261 inline float& operator[](size_t i) { return v[i]; } 262}; 263template<> struct vbase<float, 3> { 264 union { 265 float v[3]; 266 struct { float x, y, z; }; 267 struct { float s, t, r; }; 268 vbase<float, 2> xy; 269 vbase<float, 2> st; 270 }; 271 inline const float& operator[](size_t i) const { return v[i]; } 272 inline float& operator[](size_t i) { return v[i]; } 273}; 274template<> struct vbase<float, 4> { 275 union { 276 float v[4]; 277 struct { float x, y, z, w; }; 278 struct { float s, t, r, q; }; 279 vbase<float, 3> xyz; 280 vbase<float, 3> str; 281 vbase<float, 2> xy; 282 vbase<float, 2> st; 283 }; 284 inline const float& operator[](size_t i) const { return v[i]; } 285 inline float& operator[](size_t i) { return v[i]; } 286}; 287 288// ----------------------------------------------------------------------- 289 290template <typename TYPE, size_t SIZE> 291class vec : public vbase<TYPE, SIZE> 292{ 293 typedef typename TypeTraits<TYPE>::ParameterType pTYPE; 294 typedef vbase<TYPE, SIZE> base; 295 296public: 297 // STL-like interface. 298 typedef TYPE value_type; 299 typedef TYPE& reference; 300 typedef TYPE const& const_reference; 301 typedef size_t size_type; 302 303 typedef TYPE* iterator; 304 typedef TYPE const* const_iterator; 305 iterator begin() { return base::v; } 306 iterator end() { return base::v + SIZE; } 307 const_iterator begin() const { return base::v; } 308 const_iterator end() const { return base::v + SIZE; } 309 size_type size() const { return SIZE; } 310 311 // ----------------------------------------------------------------------- 312 // default constructors 313 314 vec() { } 315 vec(const vec& rhs) : base(rhs) { } 316 vec(const base& rhs) : base(rhs) { } 317 318 // ----------------------------------------------------------------------- 319 // conversion constructors 320 321 vec(pTYPE rhs) { 322 for (size_t i=0 ; i<SIZE ; i++) 323 base::operator[](i) = rhs; 324 } 325 326 template < template<typename T, size_t S> class VEC, size_t S> 327 explicit vec(const VEC<TYPE, S>& rhs) { 328 helpers::doAssign(*this, rhs); 329 } 330 331 explicit vec(TYPE const* array) { 332 for (size_t i=0 ; i<SIZE ; i++) 333 base::operator[](i) = array[i]; 334 } 335 336 // ----------------------------------------------------------------------- 337 // Assignment 338 339 vec& operator = (const vec& rhs) { 340 base::operator=(rhs); 341 return *this; 342 } 343 344 vec& operator = (const base& rhs) { 345 base::operator=(rhs); 346 return *this; 347 } 348 349 vec& operator = (pTYPE rhs) { 350 for (size_t i=0 ; i<SIZE ; i++) 351 base::operator[](i) = rhs; 352 return *this; 353 } 354 355 template < template<typename T, size_t S> class VEC, size_t S> 356 vec& operator = (const VEC<TYPE, S>& rhs) { 357 return helpers::doAssign(*this, rhs); 358 } 359 360 // ----------------------------------------------------------------------- 361 // operation-assignment 362 363 vec& operator += (const vec& rhs); 364 vec& operator -= (const vec& rhs); 365 vec& operator *= (pTYPE rhs); 366 367 // ----------------------------------------------------------------------- 368 // non-member function declaration and definition 369 // NOTE: we declare the non-member function as friend inside the class 370 // so that they are known to the compiler when the class is instantiated. 371 // This helps the compiler doing template argument deduction when the 372 // passed types are not identical. Essentially this helps with 373 // type conversion so that you can multiply a vec<float> by an scalar int 374 // (for instance). 375 376 friend inline vec PURE operator + (const vec& lhs, const vec& rhs) { 377 return helpers::doAdd(lhs, rhs); 378 } 379 friend inline vec PURE operator - (const vec& lhs, const vec& rhs) { 380 return helpers::doSub(lhs, rhs); 381 } 382 friend inline vec PURE operator * (const vec& lhs, pTYPE v) { 383 return helpers::doMulScalar(lhs, v); 384 } 385 friend inline vec PURE operator * (pTYPE v, const vec& rhs) { 386 return helpers::doScalarMul(v, rhs); 387 } 388 friend inline TYPE PURE dot_product(const vec& lhs, const vec& rhs) { 389 return android::dot_product(lhs, rhs); 390 } 391}; 392 393// ----------------------------------------------------------------------- 394 395template <typename TYPE, size_t SIZE> 396vec<TYPE, SIZE>& vec<TYPE, SIZE>::operator += (const vec<TYPE, SIZE>& rhs) { 397 vec<TYPE, SIZE>& lhs(*this); 398 for (size_t i=0 ; i<SIZE ; i++) 399 lhs[i] += rhs[i]; 400 return lhs; 401} 402 403template <typename TYPE, size_t SIZE> 404vec<TYPE, SIZE>& vec<TYPE, SIZE>::operator -= (const vec<TYPE, SIZE>& rhs) { 405 vec<TYPE, SIZE>& lhs(*this); 406 for (size_t i=0 ; i<SIZE ; i++) 407 lhs[i] -= rhs[i]; 408 return lhs; 409} 410 411template <typename TYPE, size_t SIZE> 412vec<TYPE, SIZE>& vec<TYPE, SIZE>::operator *= (vec<TYPE, SIZE>::pTYPE rhs) { 413 vec<TYPE, SIZE>& lhs(*this); 414 for (size_t i=0 ; i<SIZE ; i++) 415 lhs[i] *= rhs; 416 return lhs; 417} 418 419// ----------------------------------------------------------------------- 420 421typedef vec<float, 2> vec2_t; 422typedef vec<float, 3> vec3_t; 423typedef vec<float, 4> vec4_t; 424 425// ----------------------------------------------------------------------- 426 427}; // namespace android 428 429#endif /* ANDROID_VEC_H */ 430