/** Copyright (c) 2014-present, Facebook, Inc. All rights reserved. This source code is licensed under the BSD-style license found in the LICENSE file in the root directory of this source tree. An additional grant of patent rights can be found in the PATENTS file in the same directory. */ #ifndef __POP__FBVector__ #define __POP__FBVector__ #include #include #import #import #if TARGET_OS_IPHONE #import #endif #import "POPMath.h" #import "POPDefines.h" namespace POP { /** Fixed two-size vector class */ template struct Vector2 { private: typedef T Vector2::* const _data[2]; static const _data _v; public: T x; T y; // Zero vector static const Vector2 Zero() { return Vector2(0); } // Constructors Vector2() {} explicit Vector2(T v) { x = v; y = v; }; explicit Vector2(T x0, T y0) : x(x0), y(y0) {}; explicit Vector2(const CGPoint &p) : x(p.x), y (p.y) {} explicit Vector2(const CGSize &s) : x(s.width), y (s.height) {} // Copy constructor template explicit Vector2(const Vector2 &v) : x(v.x), y(v.y) {} // Index operators const T& operator[](size_t i) const { return this->*_v[i]; } T& operator[](size_t i) { return this->*_v[i]; } const T& operator()(size_t i) const { return this->*_v[i]; } T& operator()(size_t i) { return this->*_v[i]; } // Backing data T * data() { return &(this->*_v[0]); } const T * data() const { return &(this->*_v[0]); } // Size inline size_t size() const { return 2; } // Assignment Vector2 &operator= (T v) { x = v; y = v; return *this;} template Vector2 &operator= (const Vector2 &v) { x = v.x; y = v.y; return *this;} // Negation Vector2 operator- (void) const { return Vector2(-x, -y); } // Equality bool operator== (T v) const { return (x == v && y == v); } bool operator== (const Vector2 &v) const { return (x == v.x && y == v.y); } // Inequality bool operator!= (T v) const {return (x != v || y != v); } bool operator!= (const Vector2 &v) const { return (x != v.x || y != v.y); } // Scalar Math Vector2 operator+ (T v) const { return Vector2(x + v, y + v); } Vector2 operator- (T v) const { return Vector2(x - v, y - v); } Vector2 operator* (T v) const { return Vector2(x * v, y * v); } Vector2 operator/ (T v) const { return Vector2(x / v, y / v); } Vector2 &operator+= (T v) { x += v; y += v; return *this; }; Vector2 &operator-= (T v) { x -= v; y -= v; return *this; }; Vector2 &operator*= (T v) { x *= v; y *= v; return *this; }; Vector2 &operator/= (T v) { x /= v; y /= v; return *this; }; // Vector Math Vector2 operator+ (const Vector2 &v) const { return Vector2(x + v.x, y + v.y); } Vector2 operator- (const Vector2 &v) const { return Vector2(x - v.x, y - v.y); } Vector2 &operator+= (const Vector2 &v) { x += v.x; y += v.y; return *this; }; Vector2 &operator-= (const Vector2 &v) { x -= v.x; y -= v.y; return *this; }; // Norms CGFloat norm() const { return sqrtr(squaredNorm()); } CGFloat squaredNorm() const { return x * x + y * y; } // Cast template Vector2 cast() const { return Vector2(x, y); } CGPoint cg_point() const { return CGPointMake(x, y); }; }; template const typename Vector2::_data Vector2::_v = { &Vector2::x, &Vector2::y }; /** Fixed three-size vector class */ template struct Vector3 { private: typedef T Vector3::* const _data[3]; static const _data _v; public: T x; T y; T z; // Zero vector static const Vector3 Zero() { return Vector3(0); }; // Constructors Vector3() {} explicit Vector3(T v) : x(v), y(v), z(v) {}; explicit Vector3(T x0, T y0, T z0) : x(x0), y(y0), z(z0) {}; // Copy constructor template explicit Vector3(const Vector3 &v) : x(v.x), y(v.y), z(v.z) {} // Index operators const T& operator[](size_t i) const { return this->*_v[i]; } T& operator[](size_t i) { return this->*_v[i]; } const T& operator()(size_t i) const { return this->*_v[i]; } T& operator()(size_t i) { return this->*_v[i]; } // Backing data T * data() { return &(this->*_v[0]); } const T * data() const { return &(this->*_v[0]); } // Size inline size_t size() const { return 3; } // Assignment Vector3 &operator= (T v) { x = v; y = v; z = v; return *this;} template Vector3 &operator= (const Vector3 &v) { x = v.x; y = v.y; z = v.z; return *this;} // Negation Vector3 operator- (void) const { return Vector3(-x, -y, -z); } // Equality bool operator== (T v) const { return (x == v && y == v && z = v); } bool operator== (const Vector3 &v) const { return (x == v.x && y == v.y && z == v.z); } // Inequality bool operator!= (T v) const {return (x != v || y != v || z != v); } bool operator!= (const Vector3 &v) const { return (x != v.x || y != v.y || z != v.z); } // Scalar Math Vector3 operator+ (T v) const { return Vector3(x + v, y + v, z + v); } Vector3 operator- (T v) const { return Vector3(x - v, y - v, z - v); } Vector3 operator* (T v) const { return Vector3(x * v, y * v, z * v); } Vector3 operator/ (T v) const { return Vector3(x / v, y / v, z / v); } Vector3 &operator+= (T v) { x += v; y += v; z += v; return *this; }; Vector3 &operator-= (T v) { x -= v; y -= v; z -= v; return *this; }; Vector3 &operator*= (T v) { x *= v; y *= v; z *= v; return *this; }; Vector3 &operator/= (T v) { x /= v; y /= v; z /= v; return *this; }; // Vector Math Vector3 operator+ (const Vector3 &v) const { return Vector3(x + v.x, y + v.y, z + v.z); } Vector3 operator- (const Vector3 &v) const { return Vector3(x - v.x, y - v.y, z - v.z); } Vector3 &operator+= (const Vector3 &v) { x += v.x; y += v.y; z += v.z; return *this; }; Vector3 &operator-= (const Vector3 &v) { x -= v.x; y -= v.y; z -= v.z; return *this; }; // Norms CGFloat norm() const { return sqrtr(squaredNorm()); } CGFloat squaredNorm() const { return x * x + y * y + z * z; } // Cast template Vector3 cast() const { return Vector3(x, y, z); } }; template const typename Vector3::_data Vector3::_v = { &Vector3::x, &Vector3::y, &Vector3::z }; /** Fixed four-size vector class */ template struct Vector4 { private: typedef T Vector4::* const _data[4]; static const _data _v; public: T x; T y; T z; T w; // Zero vector static const Vector4 Zero() { return Vector4(0); }; // Constructors Vector4() {} explicit Vector4(T v) : x(v), y(v), z(v), w(v) {}; explicit Vector4(T x0, T y0, T z0, T w0) : x(x0), y(y0), z(z0), w(w0) {}; // Copy constructor template explicit Vector4(const Vector4 &v) : x(v.x), y(v.y), z(v.z), w(v.w) {} // Index operators const T& operator[](size_t i) const { return this->*_v[i]; } T& operator[](size_t i) { return this->*_v[i]; } const T& operator()(size_t i) const { return this->*_v[i]; } T& operator()(size_t i) { return this->*_v[i]; } // Backing data T * data() { return &(this->*_v[0]); } const T * data() const { return &(this->*_v[0]); } // Size inline size_t size() const { return 4; } // Assignment Vector4 &operator= (T v) { x = v; y = v; z = v; w = v; return *this;} template Vector4 &operator= (const Vector4 &v) { x = v.x; y = v.y; z = v.z; w = v.w; return *this;} // Negation Vector4 operator- (void) const { return Vector4(-x, -y, -z, -w); } // Equality bool operator== (T v) const { return (x == v && y == v && z = v, w = v); } bool operator== (const Vector4 &v) const { return (x == v.x && y == v.y && z == v.z && w == v.w); } // Inequality bool operator!= (T v) const {return (x != v || y != v || z != v || w != v); } bool operator!= (const Vector4 &v) const { return (x != v.x || y != v.y || z != v.z || w != v.w); } // Scalar Math Vector4 operator+ (T v) const { return Vector4(x + v, y + v, z + v, w + v); } Vector4 operator- (T v) const { return Vector4(x - v, y - v, z - v, w - v); } Vector4 operator* (T v) const { return Vector4(x * v, y * v, z * v, w * v); } Vector4 operator/ (T v) const { return Vector4(x / v, y / v, z / v, w / v); } Vector4 &operator+= (T v) { x += v; y += v; z += v; w += v; return *this; }; Vector4 &operator-= (T v) { x -= v; y -= v; z -= v; w -= v; return *this; }; Vector4 &operator*= (T v) { x *= v; y *= v; z *= v; w *= v; return *this; }; Vector4 &operator/= (T v) { x /= v; y /= v; z /= v; w /= v; return *this; }; // Vector Math Vector4 operator+ (const Vector4 &v) const { return Vector4(x + v.x, y + v.y, z + v.z, w + v.w); } Vector4 operator- (const Vector4 &v) const { return Vector4(x - v.x, y - v.y, z - v.z, w - v.w); } Vector4 &operator+= (const Vector4 &v) { x += v.x; y += v.y; z += v.z; w += v.w; return *this; }; Vector4 &operator-= (const Vector4 &v) { x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; }; // Norms CGFloat norm() const { return sqrtr(squaredNorm()); } CGFloat squaredNorm() const { return x * x + y * y + z * z + w * w; } // Cast template Vector4 cast() const { return Vector4(x, y, z, w); } }; template const typename Vector4::_data Vector4::_v = { &Vector4::x, &Vector4::y, &Vector4::z, &Vector4::w }; /** Convenience typedefs */ typedef Vector2 Vector2f; typedef Vector2 Vector2d; typedef Vector2 Vector2r; typedef Vector3 Vector3f; typedef Vector3 Vector3d; typedef Vector3 Vector3r; typedef Vector4 Vector4f; typedef Vector4 Vector4d; typedef Vector4 Vector4r; /** Variable-sized vector class */ class Vector { size_t _count; CGFloat *_values; private: Vector(size_t); Vector(const Vector& other); public: ~Vector(); // Creates a new vector instance of count with values. Initializing a vector of size 0 returns NULL. static Vector *new_vector(NSUInteger count, const CGFloat *values); // Creates a new vector given a pointer to another. Can return NULL. static Vector *new_vector(const Vector * const other); // Creates a variable size vector given a static vector and count. static Vector *new_vector(NSUInteger count, Vector4r vec); // Size of vector NSUInteger size() const { return _count; } // Returns array of values CGFloat *data () { return _values; } const CGFloat *data () const { return _values; }; // Vector2r support Vector2r vector2r() const; // Vector4r support Vector4r vector4r() const; // CGFloat support static Vector *new_cg_float(CGFloat f); // CGPoint support CGPoint cg_point() const; static Vector *new_cg_point(const CGPoint &p); // CGSize support CGSize cg_size() const; static Vector *new_cg_size(const CGSize &s); // CGRect support CGRect cg_rect() const; static Vector *new_cg_rect(const CGRect &r); #if TARGET_OS_IPHONE // UIEdgeInsets support UIEdgeInsets ui_edge_insets() const; static Vector *new_ui_edge_insets(const UIEdgeInsets &i); #endif // CGAffineTransform support CGAffineTransform cg_affine_transform() const; static Vector *new_cg_affine_transform(const CGAffineTransform &t); // CGColorRef support CGColorRef cg_color() const CF_RETURNS_RETAINED; static Vector *new_cg_color(CGColorRef color); // operator overloads CGFloat &operator[](size_t i) const { NSCAssert(size() > i, @"unexpected vector size:%lu", (unsigned long)size()); return _values[i]; } // Returns the mathematical length CGFloat norm() const; CGFloat squaredNorm() const; // Round to nearest sub void subRound(CGFloat sub); // Returns string description NSString * toString() const; // Operator overloads template Vector& operator= (const Vector4& other) { size_t count = MIN(_count, other.size()); for (size_t i = 0; i < count; i++) { _values[i] = other[i]; } return *this; } Vector& operator= (const Vector& other); void swap(Vector &first, Vector &second); bool operator==(const Vector &other) const; bool operator!=(const Vector &other) const; }; /** Convenience typedefs */ typedef std::shared_ptr VectorRef; typedef std::shared_ptr VectorConstRef; } #endif /* defined(__POP__FBVector__) */