1/**
2 **
3 ** Copyright 2010, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18#ifndef _PIXELFLINGER2_VECTOR4_H_
19#define _PIXELFLINGER2_VECTOR4_H_
20
21#ifdef __cplusplus
22
23template <typename Type> struct Vec4 {
24    union {
25        struct { Type x, y, z, w; };
26        struct { Type r, g, b, a; };
27        struct { Type S, T, R, Q; };
28#if !USE_FIXED_POINT
29        float f[4];
30		unsigned u[4];
31        int i[4];
32#endif
33#if defined(__ARM_HAVE_NEON) && USE_NEON
34        float32x4_t f4;
35#endif
36    };
37
38    //Vec4() : x(0), y(0), z(0), w(0) {}
39    Vec4() {}
40    Vec4(Type X, Type Y, Type Z, Type W) : x(X), y(Y), z(Z), w(W) {}
41    Vec4(Type X) : x(X), y(X), z(X), w(X) {}
42
43#define VECTOR4_OP_UNARY(op,rhs) { \
44x op rhs.x; \
45y op rhs.y; \
46z op rhs.z; \
47w op rhs.w; }
48
49#define VECTOR4_OP_UNARY_SCALAR(op,rhs) { \
50x op rhs; \
51y op rhs; \
52z op rhs; \
53w op rhs; }
54
55    inline void operator += (const Vec4<Type> & rhs) __attribute__((always_inline))
56    VECTOR4_OP_UNARY(+=,rhs)
57    inline void operator -= (const Vec4<Type> & rhs) __attribute__((always_inline))
58    VECTOR4_OP_UNARY(-=,rhs)
59    inline void operator *= (const Vec4<Type> & rhs) __attribute__((always_inline))
60    VECTOR4_OP_UNARY(*=,rhs)
61    inline void operator /= (const Vec4<Type> & rhs) __attribute__((always_inline))
62    VECTOR4_OP_UNARY(/=,rhs)
63    inline void operator *= (Type rhs) __attribute__((always_inline))
64    VECTOR4_OP_UNARY_SCALAR(*=,rhs)
65    inline void operator /= (Type rhs) __attribute__((always_inline))
66    VECTOR4_OP_UNARY_SCALAR(/=,rhs)
67
68    inline Vec4 operator+(const Vec4 & rhs) const
69    { Vec4 res = *this; res += rhs; return res; }
70
71#undef VECTOR4_OP_UNARY
72#undef VECTOR4_OP_UNARY_SCALAR
73
74    void CrossProduct3(const Vec4<Type> & lhs, const Vec4<Type> & rhs)
75    {
76        x = lhs.y * rhs.z - lhs.z * rhs.y;
77        y = lhs.z * rhs.x - lhs.x * rhs.z;
78        z = lhs.y * rhs.x - lhs.x * rhs.y;
79        w = 0;
80    }
81
82    void LShr(const unsigned shift) { u[0] >>= shift; u[1] >>= shift; u[2] >>= shift; u[3] >>= shift; }
83    void AShr(const unsigned shift) { i[0] >>= shift; i[1] >>= shift; i[2] >>= shift; i[3] >>= shift; }
84
85    bool operator==(const Vec4 & rhs) const { return u[0] == rhs.u[0] && u[1] == rhs.u[1] && u[2] == rhs.u[2] && u[3] == rhs.u[3]; }
86    bool operator!=(const Vec4 & rhs) const { return !(*this == rhs); }
87};
88
89#if defined(__ARM_HAVE_NEON) && USE_NEON
90template <> inline void Vec4<float>::operator += (const Vec4<float> & rhs) __attribute__((always_inline));
91template <> inline void Vec4<float>::operator += (const Vec4<float> & rhs)
92{ f4 = vaddq_f32(f4, rhs.f4); }
93template <> inline void Vec4<float>::operator -= (const Vec4<float> & rhs)  __attribute__((always_inline));
94template <> inline void Vec4<float>::operator -= (const Vec4<float> & rhs)
95{ f4 = vsubq_f32(f4, rhs.f4); }
96template <> inline void Vec4<float>::operator *= (float rhs) __attribute__((always_inline));
97template <> inline void Vec4<float>::operator *= (float rhs)
98{ f4 = vmulq_n_f32(f4, rhs); }
99template <> inline void Vec4<float>::operator /= (float rhs) __attribute__((always_inline));
100template <> inline void Vec4<float>::operator /= (float rhs)
101{ f4 = vmulq_n_f32(f4, 1 / rhs); }
102#endif // #if defined(__ARM_HAVE_NEON) && USE_NEON
103
104#if USE_FIXED_POINT
105deprecated, should be removed
106/*#define FIXED_POINT_ONE 0x10000
107#define FIXED_POINT_SHIFT 16
108struct FixedPoint
109{
110    int val;
111    //FixedPoint() {}
112    //explicit FixedPoint(int v) : val(v << FIXED_POINT_SHIFT) {}
113    //explicit FixedPoint(float v) : val(v * (2 << FIXED_POINT_SHIFT)) {}
114    //explicit FixedPoint(double v) : val(v * (2 << FIXED_POINT_SHIFT)) {}
115    static FixedPoint From(int v) { FixedPoint x; x.val = v << FIXED_POINT_SHIFT; return x; }
116    static FixedPoint From(unsigned v) { FixedPoint x; x.val = v << FIXED_POINT_SHIFT; return x; }
117    static FixedPoint From(float v) { FixedPoint x; x.val = v * (2 << FIXED_POINT_SHIFT); return x; }
118    static FixedPoint One() { FixedPoint x; x.val = FIXED_POINT_ONE; return x; }
119    static FixedPoint Zero() { FixedPoint x; x.val = 0; return x; }
120    FixedPoint operator-() const
121    {
122        FixedPoint res;
123        res.val = -val;
124        return res;
125    }
126    FixedPoint operator+(const FixedPoint & rhs) const
127    {
128        FixedPoint res;
129        res.val = val + rhs.val;
130        return res;
131    }
132    FixedPoint operator-(const FixedPoint & rhs) const
133    {
134        FixedPoint res;
135        res.val = val - rhs.val;
136        return res;
137    }
138    FixedPoint operator*(const FixedPoint & rhs) const
139    {
140        FixedPoint res;
141        res.val = (val >> 8) * (rhs.val >> 8);
142        return res;
143    }
144    FixedPoint operator/(const FixedPoint & rhs) const
145    {
146        FixedPoint res;
147
148        long long lh = (long long)val << 32, rh = rhs.val | 1;
149        lh /= rh;
150        rh = (lh >> 16) & 0xffffffffL;
151        res.val = rh;
152        return res;
153
154        //res.val = ((val << 2) / (rhs.val >> 6 | 1)) << 8;
155        //return res;
156    }
157    void operator+=(const FixedPoint & rhs) { val += rhs.val; }
158    void operator-=(const FixedPoint & rhs) { val += rhs.val; }
159    void operator*=(const FixedPoint & rhs) { *this = *this * rhs; }
160    void operator/=(const FixedPoint & rhs) { *this = *this / rhs; }
161
162    bool operator<(const FixedPoint & rhs) const { return val < rhs.val; }
163    bool operator>(const FixedPoint & rhs) const { return val > rhs.val; }
164    bool operator<=(const FixedPoint & rhs) const { return val <= rhs.val; }
165    bool operator>=(const FixedPoint & rhs) const { return val >= rhs.val; }
166    bool operator==(const FixedPoint & rhs) const { return val == rhs.val; }
167    bool operator!=(const FixedPoint & rhs) const { return val != rhs.val; }
168
169    operator int() const { return val >> FIXED_POINT_SHIFT; }
170    operator unsigned() const { return val >> FIXED_POINT_SHIFT; }
171    operator float() const { return (float)val / FIXED_POINT_ONE; }
172};
173
174typedef FixedPoint VectorComp_t;
175typedef Vec4<VectorComp_t> Vector4;
176#define Vector4_CTR(x,y,z,w) Vector4(FixedPoint::From(x), FixedPoint::From(y), \
177                                        FixedPoint::From(z), FixedPoint::From(w))
178#define VectorComp_t_CTR(x) FixedPoint::From(x)
179#define VectorComp_t_Zero FixedPoint::Zero()
180#define VectorComp_t_One FixedPoint::One()*/
181
182#else // if USE_FIXED_POINT
183
184typedef float VectorComp_t;
185typedef struct Vec4<VectorComp_t> Vector4;
186#define Vector4_CTR(x,y,z,w) Vector4(x,y,z,w)
187#define VectorComp_t_CTR(x) (float)(x)
188#define VectorComp_t_Zero 0
189#define VectorComp_t_One 1
190
191#endif // if USE_FIXED_POINT
192
193#else // #ifdef __cplusplus
194
195//typedef float Vector4 [4];
196typedef struct { float x, y, z, w; } Vector4;
197
198#define VECTOR4_OP_UNARY(v,op,s) \
199   v.x op s.x; \
200   v.y op s.y; \
201   v.z op s.z; \
202   v.w op s.w;
203
204#define VECTOR4_OP_UNARY_SCALAR(v,op,s) \
205   v.x op s; \
206   v.y op s; \
207   v.z op s; \
208   v.w op s;
209
210#define VECTOR4_CTR(x,y,z,w) \
211   ((Vector4){x,y,z,w})
212
213#endif // #ifdef __cplusplus
214
215#endif // #ifndef _PIXELFLINGER2_VECTOR4_H_