173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian/*
273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian * Copyright (C) 2011 The Android Open Source Project
373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian *
473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian * Licensed under the Apache License, Version 2.0 (the "License");
573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian * you may not use this file except in compliance with the License.
673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian * You may obtain a copy of the License at
773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian *
873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian *      http://www.apache.org/licenses/LICENSE-2.0
973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian *
1073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian * Unless required by applicable law or agreed to in writing, software
1173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian * distributed under the License is distributed on an "AS IS" BASIS,
1273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian * See the License for the specific language governing permissions and
1473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian * limitations under the License.
1573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian */
1673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
1773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian#ifndef ANDROID_VEC_H
1873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian#define ANDROID_VEC_H
1973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
2073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian#include <math.h>
2173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
2273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian#include <stdint.h>
2373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian#include <stddef.h>
2473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
2573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian#include "traits.h"
2673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
2773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// -----------------------------------------------------------------------
2873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
2973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian#define PURE __attribute__((pure))
3073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
3173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiannamespace android {
3273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
3373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// -----------------------------------------------------------------------
3473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// non-inline helpers
3573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
3673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <typename TYPE, size_t SIZE>
3773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopianclass vec;
3873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
3973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <typename TYPE, size_t SIZE>
4073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopianclass vbase;
4173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
4273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiannamespace helpers {
4373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
4473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <typename T> inline T min(T a, T b) { return a<b ? a : b; }
4573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <typename T> inline T max(T a, T b) { return a>b ? a : b; }
4673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
4773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate < template<typename T, size_t S> class VEC,
4873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typename TYPE, size_t SIZE, size_t S>
4973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopianvec<TYPE, SIZE>& doAssign(
5073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        vec<TYPE, SIZE>& lhs, const VEC<TYPE, S>& rhs) {
5173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    const size_t minSize = min(SIZE, S);
5273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    const size_t maxSize = max(SIZE, S);
5373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    for (size_t i=0 ; i<minSize ; i++)
5473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        lhs[i] = rhs[i];
5573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    for (size_t i=minSize ; i<maxSize ; i++)
5673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        lhs[i] = 0;
5773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    return lhs;
5873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}
5973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
6073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
6173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <
6273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template<typename T, size_t S> class VLHS,
6373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template<typename T, size_t S> class VRHS,
6473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typename TYPE,
6573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    size_t SIZE
6673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian>
6773e0bc805a143d8cc2202fccb73230459edc6869Mathias AgopianVLHS<TYPE, SIZE> PURE doAdd(
6873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        const VLHS<TYPE, SIZE>& lhs,
6973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        const VRHS<TYPE, SIZE>& rhs) {
7073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    VLHS<TYPE, SIZE> r;
7173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    for (size_t i=0 ; i<SIZE ; i++)
7273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        r[i] = lhs[i] + rhs[i];
7373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    return r;
7473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}
7573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
7673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <
7773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template<typename T, size_t S> class VLHS,
7873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template<typename T, size_t S> class VRHS,
7973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typename TYPE,
8073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    size_t SIZE
8173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian>
8273e0bc805a143d8cc2202fccb73230459edc6869Mathias AgopianVLHS<TYPE, SIZE> PURE doSub(
8373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        const VLHS<TYPE, SIZE>& lhs,
8473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        const VRHS<TYPE, SIZE>& rhs) {
8573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    VLHS<TYPE, SIZE> r;
8673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    for (size_t i=0 ; i<SIZE ; i++)
8773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        r[i] = lhs[i] - rhs[i];
8873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    return r;
8973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}
9073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
9173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <
9273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template<typename T, size_t S> class VEC,
9373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typename TYPE,
9473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    size_t SIZE
9573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian>
9673e0bc805a143d8cc2202fccb73230459edc6869Mathias AgopianVEC<TYPE, SIZE> PURE doMulScalar(
9773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        const VEC<TYPE, SIZE>& lhs,
9873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        typename TypeTraits<TYPE>::ParameterType rhs) {
9973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    VEC<TYPE, SIZE> r;
10073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    for (size_t i=0 ; i<SIZE ; i++)
10173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        r[i] = lhs[i] * rhs;
10273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    return r;
10373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}
10473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
10573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <
10673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template<typename T, size_t S> class VEC,
10773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typename TYPE,
10873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    size_t SIZE
10973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian>
11073e0bc805a143d8cc2202fccb73230459edc6869Mathias AgopianVEC<TYPE, SIZE> PURE doScalarMul(
11173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        typename TypeTraits<TYPE>::ParameterType lhs,
11273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        const VEC<TYPE, SIZE>& rhs) {
11373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    VEC<TYPE, SIZE> r;
11473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    for (size_t i=0 ; i<SIZE ; i++)
11573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        r[i] = lhs * rhs[i];
11673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    return r;
11773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}
11873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
11973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}; // namespace helpers
12073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
12173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// -----------------------------------------------------------------------
12273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// Below we define the mathematical operators for vectors.
12373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// We use template template arguments so we can generically
12473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// handle the case where the right-hand-size and left-hand-side are
12573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// different vector types (but with same value_type and size).
12673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// This is needed for performance when using ".xy{z}" element access
12773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// on vec<>. Without this, an extra conversion to vec<> would be needed.
12873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian//
12973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// example:
13073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian//      vec4_t a;
13173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian//      vec3_t b;
13273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian//      vec3_t c = a.xyz + b;
13373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian//
13473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian//  "a.xyz + b" is a mixed-operation between a vbase<> and a vec<>, requiring
13573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian//  a conversion of vbase<> to vec<>. The template gunk below avoids this,
13673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// by allowing the addition on these different vector types directly
13773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian//
13873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
13973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <
14073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template<typename T, size_t S> class VLHS,
14173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template<typename T, size_t S> class VRHS,
14273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typename TYPE,
14373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    size_t SIZE
14473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian>
14573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopianinline VLHS<TYPE, SIZE> PURE operator + (
14673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        const VLHS<TYPE, SIZE>& lhs,
14773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        const VRHS<TYPE, SIZE>& rhs) {
14873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    return helpers::doAdd(lhs, rhs);
14973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}
15073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
15173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <
15273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template<typename T, size_t S> class VLHS,
15373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template<typename T, size_t S> class VRHS,
15473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typename TYPE,
15573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    size_t SIZE
15673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian>
15773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopianinline VLHS<TYPE, SIZE> PURE operator - (
15873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        const VLHS<TYPE, SIZE>& lhs,
15973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        const VRHS<TYPE, SIZE>& rhs) {
16073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    return helpers::doSub(lhs, rhs);
16173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}
16273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
16373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <
16473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template<typename T, size_t S> class VEC,
16573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typename TYPE,
16673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    size_t SIZE
16773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian>
16873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopianinline VEC<TYPE, SIZE> PURE operator * (
16973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        const VEC<TYPE, SIZE>& lhs,
17073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        typename TypeTraits<TYPE>::ParameterType rhs) {
17173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    return helpers::doMulScalar(lhs, rhs);
17273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}
17373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
17473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <
17573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template<typename T, size_t S> class VEC,
17673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typename TYPE,
17773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    size_t SIZE
17873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian>
17973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopianinline VEC<TYPE, SIZE> PURE operator * (
18073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        typename TypeTraits<TYPE>::ParameterType lhs,
18173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        const VEC<TYPE, SIZE>& rhs) {
18273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    return helpers::doScalarMul(lhs, rhs);
18373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}
18473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
18573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
18673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <
18773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template<typename T, size_t S> class VLHS,
18873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template<typename T, size_t S> class VRHS,
18973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typename TYPE,
19073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    size_t SIZE
19173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian>
19273e0bc805a143d8cc2202fccb73230459edc6869Mathias AgopianTYPE PURE dot_product(
19373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        const VLHS<TYPE, SIZE>& lhs,
19473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        const VRHS<TYPE, SIZE>& rhs) {
19573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    TYPE r(0);
19673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    for (size_t i=0 ; i<SIZE ; i++)
19773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        r += lhs[i] * rhs[i];
19873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    return r;
19973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}
20073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
20173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <
20273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template<typename T, size_t S> class V,
20373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typename TYPE,
20473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    size_t SIZE
20573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian>
20673e0bc805a143d8cc2202fccb73230459edc6869Mathias AgopianTYPE PURE length(const V<TYPE, SIZE>& v) {
20773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    return sqrt(dot_product(v, v));
20873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}
20973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
21073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <
2116043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian    template<typename T, size_t S> class V,
2126043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian    typename TYPE,
2136043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian    size_t SIZE
2146043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian>
215f5cfea78b0454a31571693ee86c321adcb965410Michael JohnsonTYPE PURE length_squared(const V<TYPE, SIZE>& v) {
216f5cfea78b0454a31571693ee86c321adcb965410Michael Johnson    return dot_product(v, v);
217f5cfea78b0454a31571693ee86c321adcb965410Michael Johnson}
218f5cfea78b0454a31571693ee86c321adcb965410Michael Johnson
219f5cfea78b0454a31571693ee86c321adcb965410Michael Johnsontemplate <
220f5cfea78b0454a31571693ee86c321adcb965410Michael Johnson    template<typename T, size_t S> class V,
221f5cfea78b0454a31571693ee86c321adcb965410Michael Johnson    typename TYPE,
222f5cfea78b0454a31571693ee86c321adcb965410Michael Johnson    size_t SIZE
223f5cfea78b0454a31571693ee86c321adcb965410Michael Johnson>
2246043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias AgopianV<TYPE, SIZE> PURE normalize(const V<TYPE, SIZE>& v) {
2256043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian    return v * (1/length(v));
2266043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian}
2276043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian
2286043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopiantemplate <
22973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template<typename T, size_t S> class VLHS,
23073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template<typename T, size_t S> class VRHS,
23173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typename TYPE
23273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian>
23373e0bc805a143d8cc2202fccb73230459edc6869Mathias AgopianVLHS<TYPE, 3> PURE cross_product(
23473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        const VLHS<TYPE, 3>& u,
23573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        const VRHS<TYPE, 3>& v) {
23673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    VLHS<TYPE, 3> r;
23773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    r.x = u.y*v.z - u.z*v.y;
23873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    r.y = u.z*v.x - u.x*v.z;
23973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    r.z = u.x*v.y - u.y*v.x;
24073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    return r;
24173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}
24273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
24373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
24473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <typename TYPE, size_t SIZE>
24573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopianvec<TYPE, SIZE> PURE operator - (const vec<TYPE, SIZE>& lhs) {
24673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    vec<TYPE, SIZE> r;
24773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    for (size_t i=0 ; i<SIZE ; i++)
24873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        r[i] = -lhs[i];
24973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    return r;
25073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}
25173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
25273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// -----------------------------------------------------------------------
25373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
25473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// This our basic vector type, it just implements the data storage
25573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// and accessors.
25673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
25773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <typename TYPE, size_t SIZE>
25873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopianstruct vbase {
25973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    TYPE v[SIZE];
26073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    inline const TYPE& operator[](size_t i) const { return v[i]; }
26173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    inline       TYPE& operator[](size_t i)       { return v[i]; }
26273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian};
26373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate<> struct vbase<float, 2> {
26473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    union {
26573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        float v[2];
26673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        struct { float x, y; };
26773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        struct { float s, t; };
26873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    };
26973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    inline const float& operator[](size_t i) const { return v[i]; }
27073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    inline       float& operator[](size_t i)       { return v[i]; }
27173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian};
27273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate<> struct vbase<float, 3> {
27373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    union {
27473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        float v[3];
27573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        struct { float x, y, z; };
27673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        struct { float s, t, r; };
27773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        vbase<float, 2> xy;
27873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        vbase<float, 2> st;
27973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    };
28073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    inline const float& operator[](size_t i) const { return v[i]; }
28173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    inline       float& operator[](size_t i)       { return v[i]; }
28273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian};
28373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate<> struct vbase<float, 4> {
28473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    union {
28573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        float v[4];
28673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        struct { float x, y, z, w; };
28773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        struct { float s, t, r, q; };
28873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        vbase<float, 3> xyz;
28973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        vbase<float, 3> str;
29073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        vbase<float, 2> xy;
29173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        vbase<float, 2> st;
29273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    };
29373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    inline const float& operator[](size_t i) const { return v[i]; }
29473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    inline       float& operator[](size_t i)       { return v[i]; }
29573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian};
29673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
29773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// -----------------------------------------------------------------------
29873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
29973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <typename TYPE, size_t SIZE>
30073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopianclass vec : public vbase<TYPE, SIZE>
30173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian{
30273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typedef typename TypeTraits<TYPE>::ParameterType pTYPE;
30373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typedef vbase<TYPE, SIZE> base;
30473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
30573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopianpublic:
30673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    // STL-like interface.
30773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typedef TYPE value_type;
30873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typedef TYPE& reference;
30973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typedef TYPE const& const_reference;
31073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typedef size_t size_type;
31173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
31273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typedef TYPE* iterator;
31373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    typedef TYPE const* const_iterator;
31473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    iterator begin() { return base::v; }
31573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    iterator end() { return base::v + SIZE; }
31673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    const_iterator begin() const { return base::v; }
31773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    const_iterator end() const { return base::v + SIZE; }
31873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    size_type size() const { return SIZE; }
31973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
32073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    // -----------------------------------------------------------------------
32173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    // default constructors
32273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
32373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    vec() { }
32473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    vec(const vec& rhs)  : base(rhs) { }
32573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    vec(const base& rhs) : base(rhs) { }
32673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
32773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    // -----------------------------------------------------------------------
32873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    // conversion constructors
32973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
33073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    vec(pTYPE rhs) {
33173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        for (size_t i=0 ; i<SIZE ; i++)
33273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian            base::operator[](i) = rhs;
33373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    }
33473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
33573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template < template<typename T, size_t S> class VEC, size_t S>
33673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    explicit vec(const VEC<TYPE, S>& rhs) {
33773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        helpers::doAssign(*this, rhs);
33873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    }
33973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
34073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    explicit vec(TYPE const* array) {
34173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        for (size_t i=0 ; i<SIZE ; i++)
34273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian            base::operator[](i) = array[i];
34373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    }
34473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
34573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    // -----------------------------------------------------------------------
34673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    // Assignment
34773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
34873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    vec& operator = (const vec& rhs) {
34973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        base::operator=(rhs);
35073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        return *this;
35173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    }
35273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
35373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    vec& operator = (const base& rhs) {
35473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        base::operator=(rhs);
35573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        return *this;
35673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    }
35773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
35873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    vec& operator = (pTYPE rhs) {
35973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        for (size_t i=0 ; i<SIZE ; i++)
36073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian            base::operator[](i) = rhs;
36173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        return *this;
36273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    }
36373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
36473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    template < template<typename T, size_t S> class VEC, size_t S>
36573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    vec& operator = (const VEC<TYPE, S>& rhs) {
36673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        return helpers::doAssign(*this, rhs);
36773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    }
36873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
36973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    // -----------------------------------------------------------------------
37073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    // operation-assignment
37173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
37273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    vec& operator += (const vec& rhs);
37373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    vec& operator -= (const vec& rhs);
37473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    vec& operator *= (pTYPE rhs);
37573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
37673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    // -----------------------------------------------------------------------
37773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    // non-member function declaration and definition
37873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    // NOTE: we declare the non-member function as friend inside the class
37973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    // so that they are known to the compiler when the class is instantiated.
38073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    // This helps the compiler doing template argument deduction when the
38173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    // passed types are not identical. Essentially this helps with
38273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    // type conversion so that you can multiply a vec<float> by an scalar int
38373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    // (for instance).
38473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
38573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    friend inline vec PURE operator + (const vec& lhs, const vec& rhs) {
38673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        return helpers::doAdd(lhs, rhs);
38773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    }
38873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    friend inline vec PURE operator - (const vec& lhs, const vec& rhs) {
38973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        return helpers::doSub(lhs, rhs);
39073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    }
39173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    friend inline vec PURE operator * (const vec& lhs, pTYPE v) {
39273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        return helpers::doMulScalar(lhs, v);
39373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    }
39473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    friend inline vec PURE operator * (pTYPE v, const vec& rhs) {
39573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        return helpers::doScalarMul(v, rhs);
39673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    }
39773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    friend inline TYPE PURE dot_product(const vec& lhs, const vec& rhs) {
39873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        return android::dot_product(lhs, rhs);
39973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    }
40073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian};
40173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
40273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// -----------------------------------------------------------------------
40373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
40473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <typename TYPE, size_t SIZE>
40573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopianvec<TYPE, SIZE>& vec<TYPE, SIZE>::operator += (const vec<TYPE, SIZE>& rhs) {
40673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    vec<TYPE, SIZE>& lhs(*this);
40773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    for (size_t i=0 ; i<SIZE ; i++)
40873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        lhs[i] += rhs[i];
40973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    return lhs;
41073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}
41173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
41273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <typename TYPE, size_t SIZE>
41373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopianvec<TYPE, SIZE>& vec<TYPE, SIZE>::operator -= (const vec<TYPE, SIZE>& rhs) {
41473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    vec<TYPE, SIZE>& lhs(*this);
41573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    for (size_t i=0 ; i<SIZE ; i++)
41673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        lhs[i] -= rhs[i];
41773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    return lhs;
41873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}
41973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
42073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantemplate <typename TYPE, size_t SIZE>
42173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopianvec<TYPE, SIZE>& vec<TYPE, SIZE>::operator *= (vec<TYPE, SIZE>::pTYPE rhs) {
42273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    vec<TYPE, SIZE>& lhs(*this);
42373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    for (size_t i=0 ; i<SIZE ; i++)
42473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        lhs[i] *= rhs;
42573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian    return lhs;
42673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}
42773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
42873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// -----------------------------------------------------------------------
42973e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
43073e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantypedef vec<float, 2> vec2_t;
43173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantypedef vec<float, 3> vec3_t;
43273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopiantypedef vec<float, 4> vec4_t;
43373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
43473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian// -----------------------------------------------------------------------
43573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
43673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian}; // namespace android
43773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian
43873e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian#endif /* ANDROID_VEC_H */
439