blob: 21ea74ea5ddb544a780c86cf36a6f3423a2e37d0 [file] [log] [blame]
/*
* Copyright 2014 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MATHFU_VECTOR_2_SIMD_H_
#define MATHFU_VECTOR_2_SIMD_H_
#include "mathfu/internal/vector_2.h"
#include "mathfu/utilities.h"
#include <math.h>
/// @file mathfu/internal/vector_2_simd.h MathFu Vector<T, 2> Specialization
/// @brief 2-dimensional specialization of mathfu::Vector for SIMD optimized
/// builds.
/// @see mathfu::Vector
#if !defined(MATHFU_COMPILE_WITHOUT_SIMD_SUPPORT) && defined(__ARM_NEON__)
#include <vectorial/simd2f.h>
#endif
namespace mathfu {
#if !defined(MATHFU_COMPILE_WITHOUT_SIMD_SUPPORT) && defined(__ARM_NEON__)
/// @cond MATHFU_INTERNAL
template <>
class Vector<float, 2> {
public:
typedef float Scalar;
inline Vector() {}
inline Vector(const Vector<float, 2>& v) { simd = v.simd; }
explicit inline Vector(const Vector<int, 2>& v) {
data_[0] = static_cast<float>(v[0]);
data_[1] = static_cast<float>(v[1]);
}
explicit inline Vector(const simd2f& v) { simd = v; }
explicit inline Vector(const float& s) { simd = simd2f_create(s, s); }
inline Vector(const float& s1, const float& s2) {
simd = simd2f_create(s1, s2);
}
explicit inline Vector(const float* v) { simd = simd2f_uload2(v); }
explicit inline Vector(const VectorPacked<float, 2>& vector) {
simd = simd2f_uload2(vector.data);
}
inline float& operator()(const int i) { return data_[i]; }
inline const float& operator()(const int i) const { return data_[i]; }
inline float& operator[](const int i) { return data_[i]; }
inline const float& operator[](const int i) const { return data_[i]; }
inline void Pack(VectorPacked<float, 2>* const vector) const {
simd2f_ustore2(simd, vector->data);
}
inline Vector<float, 2> operator-() const {
return Vector<float, 2>(simd2f_sub(simd2f_zero(), simd));
}
inline Vector<float, 2> operator*(const Vector<float, 2>& v) const {
return Vector<float, 2>(simd2f_mul(simd, v.simd));
}
inline Vector<float, 2> operator/(const Vector<float, 2>& v) const {
return Vector<float, 2>(simd2f_div(simd, v.simd));
}
inline Vector<float, 2> operator+(const Vector<float, 2>& v) const {
return Vector<float, 2>(simd2f_add(simd, v.simd));
}
inline Vector<float, 2> operator-(const Vector<float, 2>& v) const {
return Vector<float, 2>(simd2f_sub(simd, v.simd));
}
inline Vector<float, 2> operator*(const float& s) const {
return Vector<float, 2>(simd2f_mul(simd, simd2f_splat(s)));
}
inline Vector<float, 2> operator/(const float& s) const {
return Vector<float, 2>(simd2f_div(simd, simd2f_splat(s)));
}
inline Vector<float, 2> operator+(const float& s) const {
return Vector<float, 2>(simd2f_add(simd, simd2f_splat(s)));
}
inline Vector<float, 2> operator-(const float& s) const {
return Vector<float, 2>(simd2f_sub(simd, simd2f_splat(s)));
}
inline Vector<float, 2>& operator*=(const Vector<float, 2>& v) {
simd = simd2f_mul(simd, v.simd);
return *this;
}
inline Vector<float, 2>& operator/=(const Vector<float, 2>& v) {
simd = simd2f_div(simd, v.simd);
return *this;
}
inline Vector<float, 2>& operator+=(const Vector<float, 2>& v) {
simd = simd2f_add(simd, v.simd);
return *this;
}
inline Vector<float, 2>& operator-=(const Vector<float, 2>& v) {
simd = simd2f_sub(simd, v.simd);
return *this;
}
inline Vector<float, 2>& operator*=(const float& s) {
simd = simd2f_mul(simd, simd2f_splat(s));
return *this;
}
inline Vector<float, 2>& operator/=(const float& s) {
simd = simd2f_div(simd, simd2f_splat(s));
return *this;
}
inline Vector<float, 2>& operator+=(const float& s) {
simd = simd2f_add(simd, simd2f_splat(s));
return *this;
}
inline Vector<float, 2>& operator-=(const float& s) {
simd = simd2f_sub(simd, simd2f_splat(s));
return *this;
}
inline bool operator==(const Vector<float, 2>& v) const {
for (int i = 0; i < 2; ++i) {
if ((*this)[i] != v[i]) return false;
}
return true;
}
inline bool operator!=(const Vector<float, 2>& v) const {
return !operator==(v);
}
inline float LengthSquared() const {
return simd2f_get_x(simd2f_dot2(simd, simd));
}
inline float Length() const { return simd2f_get_x(simd2f_length2(simd)); }
inline float Normalize() {
const float length = Length();
simd = simd2f_mul(simd, simd2f_splat(1 / length));
return length;
}
inline Vector<float, 2> Normalized() const {
return Vector<float, 2>(simd2f_normalize2(simd));
}
template <typename CompatibleT>
static inline Vector<float, 2> FromType(const CompatibleT& compatible) {
return FromTypeHelper<float, 2, CompatibleT>(compatible);
}
template <typename CompatibleT>
static inline CompatibleT ToType(const Vector<float, 2>& v) {
return ToTypeHelper<float, 2, CompatibleT>(v);
}
static inline float DotProduct(const Vector<float, 2>& v1,
const Vector<float, 2>& v2) {
return simd2f_get_x(simd2f_dot2(v1.simd, v2.simd));
}
static inline Vector<float, 2> HadamardProduct(const Vector<float, 2>& v1,
const Vector<float, 2>& v2) {
return Vector<float, 2>(simd2f_mul(v1.simd, v2.simd));
}
static inline Vector<float, 2> Lerp(const Vector<float, 2>& v1,
const Vector<float, 2>& v2,
float percent) {
const Vector<float, 2> percentv(percent);
const Vector<float, 2> one_minus_percent(
simd2f_sub(simd2f_splat(1.0f), percentv.simd));
return Vector<float, 2>(
simd2f_add(simd2f_mul(one_minus_percent.simd, v1.simd),
simd2f_mul(percentv.simd, v2.simd)));
}
/// Generates a random vector, where the range for each component is
/// bounded by min and max.
static inline Vector<float, 2> RandomInRange(const Vector<float, 2>& min,
const Vector<float, 2>& max) {
return Vector<float, 2>(mathfu::RandomInRange<float>(min[0], max[0]),
mathfu::RandomInRange<float>(min[1], max[1]));
}
static inline Vector<float, 2> Max(const Vector<float, 2>& v1,
const Vector<float, 2>& v2) {
return Vector<float, 2>(std::max(v1[0], v2[0]), std::max(v1[1], v2[1]));
}
static inline Vector<float, 2> Min(const Vector<float, 2>& v1,
const Vector<float, 2>& v2) {
return Vector<float, 2>(std::min(v1[0], v2[0]), std::min(v1[1], v2[1]));
}
MATHFU_DEFINE_CLASS_SIMD_AWARE_NEW_DELETE
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpedantic"
#endif // defined(__clang__)
union {
simd2f simd;
float data_[2];
struct {
float x;
float y;
};
};
#if defined(__clang__)
#pragma clang diagnostic pop
#endif // defined(__clang__)
};
/// @endcond
#endif // !defined(MATHFU_COMPILE_WITHOUT_SIMD_SUPPORT) &&
// defined(__ARM_NEON__)
} // namespace mathfu
#endif // MATHFU_VECTOR_2_SIMD_H_