/******************************************************************************* * * Copyright (c) 2019 Gnarly Narwhal * * ----------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files(the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * *******************************************************************************/ #include "../../GenoInts.h" #ifndef GNARLY_GENOME_VECTOR_FORWARD #define GNARLY_GENOME_VECTOR_FORWARD template class GenoVector; #endif // GNARLY_GENOME_VECTOR_FORWARD #ifndef GNARLY_GENOME_VECTOR3_FORWARD #define GNARLY_GENOME_VECTOR3_FORWARD template class GenoVector<3, T>; #endif // GNARLY_GENOME_VECTOR3_FORWARD #ifndef GNARLY_GENOME_VECTOR4_FORWARD #define GNARLY_GENOME_VECTOR4_FORWARD template class GenoVector<4, T>; #endif // GNARLY_GENOME_VECTOR4_FORWARD #ifndef GNARLY_GENOME_VECTOR2 #define GNARLY_GENOME_VECTOR2 #include #include #include "GenoVector.h" #include "GenoVector3.h" #include "GenoVector4.h" #include "GenoVectorDimensions.h" namespace GenoVectorDimensions { extern GenoVectorDimension<0> x; extern GenoVectorDimension<1> y; } template class GenoVector<2, T> { private: bool owner = true; void clean() { if (owner) delete [] v; } public: static GenoVector<2, T> * newArray(uint32 length) { T * v = new T[2 * length]; GenoVector<2, T> * ret = new GenoVector<2, T>[length]; ret[0] = GenoVector<2, T>(v); for (uint32 i = 1; i < length; ++i) ret[i] = GenoVector<2, T>(v + i * 2, false); return ret; } T * v; GenoVector() : v(new T[2]()) {} GenoVector(T * v, bool owner = true) noexcept : owner(owner), v(v) {} explicit GenoVector(T value) : v(new T[2] { value, value }) {} GenoVector(T x, T y) : v(new T[2] { x, y }) {} template GenoVector(const GenoVector<2, T2> & vector) : v(new T[2] { (T) vector.v[0], (T) vector.v[1] }) {} GenoVector(const GenoVector<2, T> & vector) : v(new T[2] { vector.v[0], vector.v[1] }) {} GenoVector(GenoVector<2, T> && vector) noexcept : owner(vector.owner), v(vector.v) { vector.owner = false; } GenoVector<2, T> & operator=(const GenoVector<2, T> & vector) { v[0] = vector.v[0]; v[1] = vector.v[1]; return *this; } GenoVector<2, T> & operator=(GenoVector<2, T> && vector) noexcept { if (owner) { clean(); owner = vector.owner; v = vector.v; vector.owner = false; } else { v[0] = vector.v[0]; v[1] = vector.v[1]; } return *this; } GenoVector<2, T> & operator+=(const GenoVector<2, T> & vector) { v[0] += vector.v[0]; v[1] += vector.v[1]; return *this; } GenoVector<2, T> & operator-=(const GenoVector<2, T> & vector) { v[0] -= vector.v[0]; v[1] -= vector.v[1]; return *this; } GenoVector<2, T> & operator*=(T scalar) { v[0] *= scalar; v[1] *= scalar; return *this; } GenoVector<2, T> & operator*=(const GenoVector<2, T> & vector) { v[0] *= vector.v[0]; v[1] *= vector.v[1]; return *this; } GenoVector<2, T> & operator/=(T scalar) { v[0] /= scalar; v[1] /= scalar; return *this; } GenoVector<2, T> & operator/=(const GenoVector<2, T> & vector) { v[0] /= vector.v[0]; v[1] /= vector.v[1]; return *this; } T & operator[](uint32 index) noexcept { return v[index]; } const T & operator[](uint32 index) const noexcept { return v[index]; } template T & operator[](const GenoVectorDimensions::GenoVectorDimension & dimension) noexcept { static_assert(GenoVectorDimensions::GenoVectorDimension::dimension != 2, "GenoVector<2, T> has no dimension z!"); static_assert(GenoVectorDimensions::GenoVectorDimension::dimension != 3, "GenoVector<2, T> has no dimension w!"); static_assert(GenoVectorDimensions::GenoVectorDimension::dimension < 4, "GenoVector<2, T> has no dimension beyond y!"); return v[GenoVectorDimensions::GenoVectorDimension::dimension]; } template const T & operator[](const GenoVectorDimensions::GenoVectorDimension & dimension) const noexcept { static_assert(GenoVectorDimensions::GenoVectorDimension::dimension != 2, "GenoVector<2, T> has no dimension z!"); static_assert(GenoVectorDimensions::GenoVectorDimension::dimension != 3, "GenoVector<2, T> has no dimension w!"); static_assert(GenoVectorDimensions::GenoVectorDimension::dimension < 4, "GenoVector<2, T> has no dimension beyond y!"); return v[GenoVectorDimensions::GenoVectorDimension::dimension]; } T & x() noexcept { return v[0]; } const T & x() const noexcept { return v[0]; } T & y() noexcept { return v[1]; } const T & y() const noexcept { return v[1]; } T getLength() const { return sqrt( v[0] * v[0] + v[1] * v[1] ); } T getLengthSquared() const { return ( v[0] * v[0] + v[1] * v[1] ); } GenoVector<2, T> & setLength(T length) { auto scalar = length / getLength(); v[0] *= scalar; v[1] *= scalar; return *this; } GenoVector<2, T> & normalize() { auto scalar = 1 / getLength(); v[0] *= scalar; v[1] *= scalar; return *this; } T getAngle() const { return atan2(v[1], v[0]); } GenoVector<2, T> & setAngle(T angle) { auto length = getLength(); v[0] = cos(angle) * length; v[1] = sin(angle) * length; return *this; } GenoVector<2, T> & rotate(T angle) { auto sine = sin(angle); auto cosine = cos(angle); auto x = v[0]; v[0] = v[0] * cosine - v[1] * sine; v[1] = x * sine - v[1] * cosine; return *this; } GenoVector<2, T> & negate() { v[0] = -v[0]; v[1] = -v[1]; return *this; } GenoVector<2, T> & project(const GenoVector<2, T> & projection) { auto scalar = dot(*this, projection) / projection.getLengthSquared(); v[0] /= scalar; v[1] /= scalar; return *this; } GenoVector<2, T> & shear(T axisAngle, T shearAngle) { auto sinAxis = sin(axisAngle); auto cosAxis = cos(axisAngle); auto scalar = v[0] * sinAxis - v[1] * cosAxis; scalar *= tan(shearAngle); v[0] += scalar * cosAxis; v[1] += scalar * sinAxis; return *this; } GenoVector<2, T> & shear(const GenoVector<2, T> & axis, T shearAngle) { auto unitAxis = normalize(axis); auto scalar = v[0] * unitAxis.v[1] - v[1] * unitAxis.v[0]; scalar *= tan(shearAngle); v[0] += scalar * unitAxis.v[0]; v[1] += scalar * unitAxis.v[1]; return *this; } GenoVector<2, T> & shear(T axisAngle, const GenoVector<2, T> & shear) { auto sinAxis = sin(axisAngle); auto cosAxis = cos(axisAngle); auto scalar = v[0] * sinAxis - v[1] * cosAxis; scalar *= shear.v[1] / shear.v[0]; v[0] += scalar * cosAxis; v[1] += scalar * sinAxis; return *this; } GenoVector<2, T> & shear(const GenoVector<2, T> & axis, const GenoVector<2, T> & shear) { auto unitAxis = normalize(axis); auto scalar = v[0] * unitAxis.v[1] - v[1] * unitAxis.v[0]; scalar *= shear.v[1] / shear.v[0]; v[0] += scalar * unitAxis.v[0]; v[1] += scalar * unitAxis.v[1]; return *this; } GenoVector<2, T> & shearX(T angle) { v[0] -= v[1] * tan(angle); return *this; } GenoVector<2, T> & shearX(const GenoVector<2, T> & shear) { v[0] -= v[1] * shear.v[1] / shear.v[0]; return *this; } GenoVector<2, T> & shearY(T angle) { v[1] += v[0] * tan(angle); return *this; } GenoVector<2, T> & shearY(const GenoVector<2, T> & shear) { v[1] += v[0] * shear.v[1] / shear.v[0]; return *this; } GenoVector<2, T> & set(const GenoVector<2, T> & set) { v[0] = set.v[0]; v[1] = set.v[1]; return *this; } GenoVector<2, T> & translate(const GenoVector<2, T> & translate) { v[0] += translate.v[0]; v[1] += translate.v[1]; return *this; } GenoVector<2, T> & scale(T scale) { v[0] *= scale; v[1] *= scale; return *this; } GenoVector<2, T> & scale(const GenoVector<2, T> & scale) { v[0] *= scale.v[0]; v[1] *= scale.v[1]; return *this; } GenoVector<2, T> & setX(T x) { v[0] = x; return *this; } GenoVector<2, T> & setY(T y) { v[1] = y; return *this; } GenoVector<2, T> & setXY(T x, T y) { v[0] = x; v[1] = y; return *this; } GenoVector<2, T> & setXY(const GenoVector<2, T> & set) { v[0] = set.v[0]; v[1] = set.v[1]; return *this; } GenoVector<2, T> & setYX(const GenoVector<2, T> & set) { v[1] = set.v[0]; v[0] = set.v[1]; return *this; } GenoVector<2, T> & translateX(T translateX) { v[0] += translateX; } GenoVector<2, T> & translateY(T translateY) { v[1] += translateY; } GenoVector<2, T> & translateXY(T translateX, T translateY) { v[0] += translateX; v[1] += translateY; } GenoVector<2, T> & translateXY(const GenoVector<2, T> & translate) { v[0] += translate.v[0]; v[1] += translate.v[1]; } GenoVector<2, T> & translateYX(const GenoVector<2, T> & translate) { v[1] += translate.v[0]; v[0] += translate.v[1]; } GenoVector<2, T> & scaleX(T scaleX) { v[0] *= scaleX; } GenoVector<2, T> & scaleY(T scaleY) { v[1] *= scaleY; } GenoVector<2, T> & scaleXY(T scale) { v[0] *= scale; v[1] *= scale; } GenoVector<2, T> & scaleXY(T scaleX, T scaleY) { v[0] *= scaleX; v[1] *= scaleY; } GenoVector<2, T> & scaleXY(const GenoVector<2, T> & scale) { v[0] *= scale.v[0]; v[1] *= scale.v[1]; } GenoVector<2, T> & scaleYX(const GenoVector<2, T> & scale) { v[1] *= scale.v[0]; v[0] *= scale.v[1]; } T getX() const { return v[0]; } T getY() const { return v[1]; } GenoVector<2, T> getXX() const { return { v[0], v[0] }; } GenoVector<2, T> getXY() const { return { v[0], v[1] }; } GenoVector<2, T> getYX() const { return { v[1], v[0] }; } GenoVector<2, T> getYY() const { return { v[1], v[1] }; } GenoVector<3, T> getXXX() const { return { v[0], v[0], v[0] }; } GenoVector<3, T> getXXY() const { return { v[0], v[0], v[1] }; } GenoVector<3, T> getXYX() const { return { v[0], v[1], v[0] }; } GenoVector<3, T> getXYY() const { return { v[0], v[1], v[1] }; } GenoVector<3, T> getYXX() const { return { v[1], v[0], v[0] }; } GenoVector<3, T> getYXY() const { return { v[1], v[0], v[1] }; } GenoVector<3, T> getYYX() const { return { v[1], v[1], v[0] }; } GenoVector<3, T> getYYY() const { return { v[1], v[1], v[1] }; } GenoVector<4, T> getXXXX() const { return { v[0], v[0], v[0], v[0] }; } GenoVector<4, T> getXXXY() const { return { v[0], v[0], v[0], v[1] }; } GenoVector<4, T> getXXYX() const { return { v[0], v[0], v[1], v[0] }; } GenoVector<4, T> getXXYY() const { return { v[0], v[0], v[1], v[1] }; } GenoVector<4, T> getXYXX() const { return { v[0], v[1], v[0], v[0] }; } GenoVector<4, T> getXYXY() const { return { v[0], v[1], v[0], v[1] }; } GenoVector<4, T> getXYYX() const { return { v[0], v[1], v[1], v[0] }; } GenoVector<4, T> getXYYY() const { return { v[0], v[1], v[1], v[1] }; } GenoVector<4, T> getYXXX() const { return { v[1], v[0], v[0], v[0] }; } GenoVector<4, T> getYXXY() const { return { v[1], v[0], v[0], v[1] }; } GenoVector<4, T> getYXYX() const { return { v[1], v[0], v[1], v[0] }; } GenoVector<4, T> getYXYY() const { return { v[1], v[0], v[1], v[1] }; } GenoVector<4, T> getYYXX() const { return { v[1], v[1], v[0], v[0] }; } GenoVector<4, T> getYYXY() const { return { v[1], v[1], v[0], v[1] }; } GenoVector<4, T> getYYYX() const { return { v[1], v[1], v[1], v[0] }; } GenoVector<4, T> getYYYY() const { return { v[1], v[1], v[1], v[1] }; } virtual ~GenoVector() noexcept { clean(); } }; template GenoVector<2, T> operator-(const GenoVector<2, T> & vector) { return { -vector.v[0], -vector.v[1] }; } template GenoVector<2, T> operator+(const GenoVector<2, T> & left, const GenoVector<2, T> & right) { return { left.v[0] + right.v[0], left.v[1] + right.v[1] }; } template GenoVector<2, T> operator-(const GenoVector<2, T> & left, const GenoVector<2, T> & right) { return { left.v[0] - right.v[0], left.v[1] - right.v[1] }; } template GenoVector<2, T> operator*(T left, const GenoVector<2, T> & right) { return { left * right.v[0], left * right.v[1] }; } template GenoVector<2, T> operator*(const GenoVector<2, T> & left, T right) { return { left.v[0] * right, left.v[1] * right }; } template GenoVector<2, T> operator*(const GenoVector<2, T> & left, const GenoVector<2, T> & right) { return { left.v[0] * right.v[0], left.v[1] * right.v[1] }; } template GenoVector<2, T> operator/(const GenoVector<2, T> & left, T right) { return { left.v[0] / right, left.v[1] / right }; } template GenoVector<2, T> operator/(const GenoVector<2, T> & left, const GenoVector<2, T> & right) { return { left.v[0] / right.v[0], left.v[1] / right.v[1] }; } template GenoVector<3, T> operator|(T left, const GenoVector<2, T> & right) { return { left, right.v[0], right.v[1] }; } template GenoVector<3, T> operator|(const GenoVector<2, T> & left, T right) { return { left.v[0], left.v[1], right }; } template GenoVector<4, T> operator|(const GenoVector<2, T> & left, const GenoVector<2, T> & right) { return { left.v[0], left.v[1], right.v[0], right.v[1] }; } template GenoVector<2, T> setLength(const GenoVector<2, T> & vector, T length) { auto scalar = length / vector.getLength(); return { vector.v[0] * scalar, vector.v[1] * scalar }; } template GenoVector<2, T> & setLength(const GenoVector<2, T> & vector, T length, GenoVector<2, T> & target) { auto scalar = length / vector.getLength(); target.v[0] = vector.v[0] * scalar; target.v[1] = vector.v[1] * scalar; return target; } template GenoVector<2, T> normalize(const GenoVector<2, T> & vector) { auto scalar = 1 / vector.getLength(); return { vector.v[0] * scalar, vector.v[1] * scalar }; } template GenoVector<2, T> & normalize(const GenoVector<2, T> & vector, GenoVector<2, T> & target) { auto scalar = 1 / vector.getLength(); target.v[0] = vector.v[0] * scalar; target.v[1] = vector.v[1] * scalar; return target; } template GenoVector<2, T> setAngle(const GenoVector<2, T> & vector, T angle) { auto length = vector.getLength(); return { cos(angle) * length, sin(angle) * length }; } template GenoVector<2, T> & setAngle(const GenoVector<2, T> & vector, T angle, GenoVector<2, T> & target) { auto length = vector.getLength(); target.v[0] = cos(angle) * length; target.v[1] = sin(angle) * length; return target; } template GenoVector<2, T> & rotate(const GenoVector<2, T> & vector, T angle) { auto sine = sin(angle); auto cosine = cos(angle); return { vector.v[0] * cosine - vector.v[1] * sine, vector.v[0] * sine + vector.v[1] * cosine }; } template GenoVector<2, T> & rotate(const GenoVector<2, T> & vector, T angle, GenoVector<2, T> & target) { auto sine = sin(angle); auto cosine = cos(angle); target.v[0] = vector.v[0] * cosine - vector.v[1] * sine; target.v[1] = vector.v[0] * sine + vector.v[1] * cosine; return target; } template GenoVector<2, T> negate(const GenoVector<2, T> & vector) { return { -vector.v[0], -vector.v[1] }; } template GenoVector<2, T> & negate(const GenoVector<2, T> & vector, GenoVector<2, T> & target) { target.v[0] = -vector.v[0]; target.v[1] = -vector.v[1]; return target; } template T dot(const GenoVector<2, T> & left, const GenoVector<2, T> & right) { return ( left.v[0] * right.v[0] + left.v[1] * right.v[1] ); } template GenoVector<2, T> project(const GenoVector<2, T> & vector, const GenoVector<2, T> & projection) { auto scalar = dot(vector, projection) / projection.getLengthSquared(); return { scalar * projection.v[0], scalar * projection.v[1] }; } template GenoVector<2, T> & project(const GenoVector<2, T> & vector, const GenoVector<2, T> & projection, GenoVector<2, T> & target) { auto scalar = dot(vector, projection) / projection.getLengthSquared(); target.v[0] = scalar * projection.v[0]; target.v[1] = scalar * projection.v[1]; return target; } template GenoVector<2, T> shear(const GenoVector<2, T> & vector, T axisAngle, T shearAngle) { auto sinAxis = sin(axisAngle); auto cosAxis = cos(axisAngle); auto scalar = vector.v[0] * sinAxis - vector.v[1] * cosAxis; scalar *= tan(shearAngle); return { vector.v[0] + scalar * cosAxis, vector.v[1] + scalar * sinAxis, }; } template GenoVector<2, T> & shear(const GenoVector<2, T> & vector, T axisAngle, T shearAngle, GenoVector<2, T> & target) { auto sinAxis = sin(axisAngle); auto cosAxis = cos(axisAngle); auto scalar = vector.v[0] * sinAxis - vector.v[1] * cosAxis; scalar *= tan(shearAngle); target.v[0] = vector.v[0] + scalar * cosAxis; target.v[1] = vector.v[1] + scalar * sinAxis; return target; } template GenoVector<2, T> shearX(const GenoVector<2, T> & vector, T angle) { return { vector.v[0] - vector.v[1] * tan(angle), vector.v[1] }; } template GenoVector<2, T> & shearX(const GenoVector<2, T> & vector, T angle, GenoVector<2, T> & target) { target.v[0] = vector.v[0] - vector.v[1] * tan(angle); target.v[1] = vector.v[1]; return target; } template GenoVector<2, T> shearY(const GenoVector<2, T> & vector, T angle) { return { vector.v[0], vector.v[1] + vector.v[0] * tan(angle) }; } template GenoVector<2, T> & shearY(const GenoVector<2, T> & vector, T angle, GenoVector<2, T> & target) { target.v[0] = vector.v[0]; target.v[1] = vector.v[1] + vector.v[0] * tan(angle); return target; } template GenoVector<2, T> translate(const GenoVector<2, T> & vector, const GenoVector<2, T> & translate) { return { vector.v[0] + translate.v[0], vector.v[1] + translate.v[1] }; } template GenoVector<2, T> & translate(const GenoVector<2, T> & vector, const GenoVector<2, T> & translate, GenoVector<2, T> & target) { target.v[0] = vector.v[0] + translate.v[0]; target.v[1] = vector.v[1] + translate.v[1]; return target; } template GenoVector<2, T> scale(const GenoVector<2, T> & vector, T scale) { return { vector.v[0] * scale, vector.v[1] * scale }; } template GenoVector<2, T> & scale(const GenoVector<2, T> & vector, T scale, GenoVector<2, T> & target) { target.v[0] = vector.v[0] * scale; target.v[1] = vector.v[1] * scale; return target; } template GenoVector<2, T> scale(const GenoVector<2, T> & vector, const GenoVector<2, T> & scale) { return { vector.v[0] * scale.v[0], vector.v[1] * scale.v[1] }; } template GenoVector<2, T> & scale(const GenoVector<2, T> & vector, const GenoVector<2, T> & scale, GenoVector<2, T> & target) { target.v[0] = vector.v[0] * scale.v[0]; target.v[1] = vector.v[1] * scale.v[1]; return target; } template GenoVector<2, T> setX(const GenoVector<2, T> & vector, T x) { return { x, vector.v[1] }; } template GenoVector<2, T> setY(const GenoVector<2, T> & vector, T y) { return { vector.v[0], y }; } template GenoVector<2, T> setX(const GenoVector<2, T> & vector, T x, GenoVector<2, T> & target) { target.v[0] = x; target.v[1] = vector.v[1]; return target; } template GenoVector<2, T> setY(const GenoVector<2, T> & vector, T y, GenoVector<2, T> & target) { target.v[0] = vector.v[0]; target.v[1] = y; return target; } template GenoVector<2, T> translateX(const GenoVector<2, T> & vector, T translateX) { return { vector.v[0] + translateX, vector.v[1] }; } template GenoVector<2, T> translateY(const GenoVector<2, T> & vector, T translateY) { return { vector.v[0], vector.v[1] + translateY }; } template GenoVector<2, T> translateXY(const GenoVector<2, T> & vector, T translateX, T translateY) { return { vector.v[0] + translateX, vector.v[1] + translateY }; } template GenoVector<2, T> translateXY(const GenoVector<2, T> & vector, const GenoVector<2, T> & translate) { return { vector.v[0] + translate.v[0], vector.v[1] + translate.v[1] }; } template GenoVector<2, T> translateYX(const GenoVector<2, T> & vector, const GenoVector<2, T> & translate) { return { vector.v[0] + translate.v[1], vector.v[1] + translate.v[0] }; } template GenoVector<2, T> translateX(const GenoVector<2, T> & vector, T translateX, GenoVector<2, T> & target) { target.v[0] = vector.v[0] + translateX; target.v[1] = vector.v[1]; return target; } template GenoVector<2, T> translateY(const GenoVector<2, T> & vector, T translateY, GenoVector<2, T> & target) { target.v[0] = vector.v[0]; target.v[1] = vector.v[1] + translateY; return target; } template GenoVector<2, T> translateXY(const GenoVector<2, T> & vector, T translateX, T translateY, GenoVector<2, T> & target) { target.v[0] = vector.v[0] + translateX; target.v[1] = vector.v[1] + translateY; return target; } template GenoVector<2, T> translateXY(const GenoVector<2, T> & vector, const GenoVector<2, T> & translate, GenoVector<2, T> & target) { target.v[0] = vector.v[0] + translate.v[0]; target.v[1] = vector.v[1] + translate.v[1]; return target; } template GenoVector<2, T> translateYX(const GenoVector<2, T> & vector, const GenoVector<2, T> & translate, GenoVector<2, T> & target) { target.v[0] = vector.v[0] + translate.v[1]; target.v[1] = vector.v[1] + translate.v[0]; return target; } template GenoVector<2, T> scaleX(const GenoVector<2, T> & vector, T scaleX) { return { vector.v[0] * scaleX, vector.v[1] }; } template GenoVector<2, T> scaleY(const GenoVector<2, T> & vector, T scaleY) { return { vector.v[0], vector.v[1] * scaleY }; } template GenoVector<2, T> scaleXY(const GenoVector<2, T> & vector, T scale) { return { vector.v[0] * scale, vector.v[1] * scale }; } template GenoVector<2, T> scaleXY(const GenoVector<2, T> & vector, T scaleX, T scaleY) { return { vector.v[0] * scaleX, vector.v[1] * scaleY }; } template GenoVector<2, T> scaleXY(const GenoVector<2, T> & vector, const GenoVector<2, T> & scale) { return { vector.v[0] * scale.v[0], vector.v[1] * scale.v[1] }; } template GenoVector<2, T> scaleYX(const GenoVector<2, T> & vector, const GenoVector<2, T> & scale) { return { vector.v[0] * scale.v[1], vector.v[1] * scale.v[0] }; } template GenoVector<2, T> scaleX(const GenoVector<2, T> & vector, T scaleX, const GenoVector<2, T> & target) { target.v[0] = vector.v[0] * scaleX; target.v[1] = vector.v[1]; return target; } template GenoVector<2, T> scaleY(const GenoVector<2, T> & vector, T scaleY, const GenoVector<2, T> & target) { target.v[0] = vector.v[0]; target.v[1] = vector.v[1] * scaleY; return target; } template GenoVector<2, T> scaleXY(const GenoVector<2, T> & vector, T scale, GenoVector<2, T> & target) { target.v[0] = vector.v[0] * scale; target.v[1] = vector.v[1] * scale; return target; } template GenoVector<2, T> scaleXY(const GenoVector<2, T> & vector, T scaleX, T scaleY, const GenoVector<2, T> & target) { target.v[0] = vector.v[0] * scaleX; target.v[1] = vector.v[1] * scaleY; return target; } template GenoVector<2, T> scaleXY(const GenoVector<2, T> & vector, const GenoVector<2, T> & scale, GenoVector<2, T> & target) { target.v[0] = vector.v[0] * scale.v[0]; target.v[1] = vector.v[1] * scale.v[1]; return target; } template GenoVector<2, T> scaleYX(const GenoVector<2, T> & vector, const GenoVector<2, T> & scale, GenoVector<2, T> & target) { target.v[0] = vector.v[0] * scale.v[1]; target.v[1] = vector.v[1] * scale.v[0]; return target; } template std::ostream & operator<<(std::ostream & stream, const GenoVector<2, T> & vector) { return stream << '<' << vector.v[0] << ", " << vector.v[1] << '>'; } template using GenoVector2 = GenoVector<2, T>; using GenoVector2b = GenoVector2< int8 >; using GenoVector2ub = GenoVector2; using GenoVector2s = GenoVector2< int16>; using GenoVector2us = GenoVector2; using GenoVector2i = GenoVector2< int32>; using GenoVector2ui = GenoVector2; using GenoVector2l = GenoVector2< int64>; using GenoVector2ul = GenoVector2; using GenoVector2f = GenoVector2; using GenoVector2d = GenoVector2; #define GNARLY_GENOME_VECTOR2_FORWARD #endif // GNARLY_GENOME_VECTOR2