Explicitly instantiate float vector members in cpp

This commit is contained in:
Vittorio Romeo 2022-06-24 01:33:33 +02:00 committed by Lukas Dürrenberger
parent a3dd3e02aa
commit 8a2aa6397f
10 changed files with 231 additions and 147 deletions

View File

@ -26,9 +26,8 @@
#define SFML_VECTOR2_HPP
#include <SFML/System/Angle.hpp>
#include <SFML/System/Export.hpp>
#include <cassert>
#include <cmath>
#include <type_traits>
namespace sf
@ -75,7 +74,7 @@ public:
constexpr explicit Vector2(const Vector2<U>& vector);
////////////////////////////////////////////////////////////
/// \brief Construct the vector from polar coordinates
/// \brief Construct the vector from polar coordinates <i><b>(floating-point)</b></i>
///
/// \param r Length of vector (can be negative)
/// \param phi Angle from X axis
@ -88,19 +87,19 @@ public:
/// * Vector2(r, phi) == Vector2(r, phi + n * 360_deg)
///
////////////////////////////////////////////////////////////
Vector2(T r, Angle phi);
SFML_SYSTEM_API Vector2(T r, Angle phi);
////////////////////////////////////////////////////////////
/// \brief Length of the vector <i><b>(floating-point)</b></i>.
///
/// If you are not interested in the actual length, but only in comparisons, consider using lengthSq().
///
////////////////////////////////////////////////////////////
T length() const;
SFML_SYSTEM_API T length() const;
////////////////////////////////////////////////////////////
/// \brief Square of vector's length.
///
///
/// Suitable for comparisons, more efficient than length().
///
////////////////////////////////////////////////////////////
@ -108,57 +107,57 @@ public:
////////////////////////////////////////////////////////////
/// \brief Vector with same direction but length 1 <i><b>(floating-point)</b></i>.
///
///
/// \pre \c *this is no zero vector.
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2 normalized() const;
[[nodiscard]] SFML_SYSTEM_API Vector2 normalized() const;
////////////////////////////////////////////////////////////
/// \brief Signed angle from \c *this to \c rhs <i><b>(floating-point)</b></i>.
///
///
/// \return The smallest angle which rotates \c *this in positive
/// or negative direction, until it has the same direction as \c rhs.
/// The result has a sign and lies in the range [-180, 180) degrees.
/// \pre Neither \c *this nor \c rhs is a zero vector.
///
////////////////////////////////////////////////////////////
Angle angleTo(const Vector2& rhs) const;
SFML_SYSTEM_API Angle angleTo(const Vector2& rhs) const;
////////////////////////////////////////////////////////////
/// \brief Signed angle from +X or (1,0) vector <i><b>(floating-point)</b></i>.
///
///
/// For example, the vector (1,0) corresponds to 0 degrees, (0,1) corresponds to 90 degrees.
///
///
/// \return Angle in the range [-180, 180) degrees.
/// \pre This vector is no zero vector.
///
////////////////////////////////////////////////////////////
Angle angle() const;
SFML_SYSTEM_API Angle angle() const;
////////////////////////////////////////////////////////////
/// \brief Rotate by angle \c phi <i><b>(floating-point)</b></i>.
///
///
/// Returns a vector with same length but different direction.
///
/// In SFML's default coordinate system with +X right and +Y down,
/// this amounts to a clockwise rotation by \c phi.
///
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector2 rotatedBy(Angle phi) const;
[[nodiscard]] SFML_SYSTEM_API Vector2 rotatedBy(Angle phi) const;
////////////////////////////////////////////////////////////
/// \brief Projection of this vector onto \c axis <i><b>(floating-point)</b></i>.
///
///
/// \param axis Vector being projected onto. Need not be normalized.
/// \pre \c axis must not have length zero.
///
////////////////////////////////////////////////////////////
[[nodiscard]] constexpr Vector2 projectedOnto(const Vector2& axis) const;
[[nodiscard]] SFML_SYSTEM_API Vector2 projectedOnto(const Vector2& axis) const;
////////////////////////////////////////////////////////////
/// \brief Returns a perpendicular vector.
///
///
/// Returns \c *this rotated by +90 degrees; (x,y) becomes (-y,x).
/// For example, the vector (1,0) is transformed to (0,1).
///
@ -176,7 +175,7 @@ public:
////////////////////////////////////////////////////////////
/// \brief Z component of the cross product of two 2D vectors.
///
///
/// Treats the operands as 3D vectors, computes their cross product
/// and returns the result's Z component (X and Y components are always zero).
///
@ -187,7 +186,7 @@ public:
/// \brief Component-wise multiplication of \c *this and \c rhs.
///
/// Computes <tt>(lhs.x*rhs.x, lhs.y*rhs.y)</tt>.
///
///
/// Scaling is the most common use case for component-wise multiplication/division.
/// This operation is also known as the Hadamard or Schur product.
///
@ -196,11 +195,11 @@ public:
////////////////////////////////////////////////////////////
/// \brief Component-wise division of \c *this and \c rhs.
///
///
/// Computes <tt>(lhs.x/rhs.x, lhs.y/rhs.y)</tt>.
///
///
/// Scaling is the most common use case for component-wise multiplication/division.
///
///
/// \pre Neither component of \c rhs is zero.
///
////////////////////////////////////////////////////////////
@ -417,7 +416,7 @@ template <typename T>
/// The API provides basic arithmetic (addition, subtraction, scale), as
/// well as more advanced geometric operations, such as dot/cross products,
/// length and angle computations, projections, rotations, etc.
///
///
/// The template parameter T is the type of the coordinates. It
/// can be any type that supports arithmetic operations (+, -, /, *)
/// and comparisons (==, !=), for example int or float.
@ -425,7 +424,7 @@ template <typename T>
/// a floating point type (e.g. float or double), often because
/// results cannot be represented accurately with integers.
/// The method documentation mentions "(floating-point)" in those cases.
///
///
/// You generally don't have to care about the templated form (sf::Vector2<T>),
/// the most common specializations have special type aliases:
/// \li sf::Vector2<float> is sf::Vector2f

View File

@ -53,26 +53,6 @@ y(static_cast<T>(vector.y))
}
////////////////////////////////////////////////////////////
template <typename T>
Vector2<T>::Vector2(T r, Angle phi) :
x(r * static_cast<T>(std::cos(phi.asRadians()))),
y(r * static_cast<T>(std::sin(phi.asRadians())))
{
static_assert(std::is_floating_point_v<T>, "Vector2::Vector2(T, Angle) is only supported for floating point types");
}
////////////////////////////////////////////////////////////
template <typename T>
T Vector2<T>::length() const
{
static_assert(std::is_floating_point_v<T>, "Vector2::length() is only supported for floating point types");
return std::hypot(x, y);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr T Vector2<T>::lengthSq() const
@ -81,68 +61,6 @@ constexpr T Vector2<T>::lengthSq() const
}
////////////////////////////////////////////////////////////
template <typename T>
Vector2<T> Vector2<T>::normalized() const
{
static_assert(std::is_floating_point_v<T>, "Vector2::normalized() is only supported for floating point types");
assert(*this != Vector2<T>());
return (*this) / length();
}
////////////////////////////////////////////////////////////
template <typename T>
Angle Vector2<T>::angleTo(const Vector2<T>& rhs) const
{
static_assert(std::is_floating_point_v<T>, "Vector2::angleTo() is only supported for floating point types");
assert(*this != Vector2<T>());
assert(rhs != Vector2<T>());
return radians(std::atan2(cross(rhs), dot(rhs)));
}
////////////////////////////////////////////////////////////
template <typename T>
Angle Vector2<T>::angle() const
{
static_assert(std::is_floating_point_v<T>, "Vector2::angle() is only supported for floating point types");
assert(*this != Vector2<T>());
return radians(std::atan2(y, x));
}
////////////////////////////////////////////////////////////
template <typename T>
Vector2<T> Vector2<T>::rotatedBy(Angle angle) const
{
static_assert(std::is_floating_point_v<T>, "Vector2::rotatedBy() is only supported for floating point types");
// No zero vector assert, because rotating a zero vector is well-defined (yields always itself)
T cos = std::cos(angle.asRadians());
T sin = std::sin(angle.asRadians());
// Don't manipulate x and y separately, otherwise they're overwritten too early
return Vector2<T>(
cos * x - sin * y,
sin * x + cos * y);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T> Vector2<T>::projectedOnto(const Vector2<T>& axis) const
{
static_assert(std::is_floating_point_v<T>, "Vector2::projectedOnto() is only supported for floating point types");
assert(axis != Vector2<T>());
return dot(axis) / axis.lengthSq() * axis;
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr Vector2<T> Vector2<T>::perpendicular() const

View File

@ -25,9 +25,8 @@
#ifndef SFML_VECTOR3_HPP
#define SFML_VECTOR3_HPP
#include <SFML/System/Export.hpp>
#include <cassert>
#include <cmath>
#include <type_traits>
namespace sf
{
@ -79,11 +78,11 @@ public:
/// If you are not interested in the actual length, but only in comparisons, consider using lengthSq().
///
////////////////////////////////////////////////////////////
T length() const;
SFML_SYSTEM_API T length() const;
////////////////////////////////////////////////////////////
/// \brief Square of vector's length.
///
///
/// Suitable for comparisons, more efficient than length().
///
////////////////////////////////////////////////////////////
@ -91,11 +90,11 @@ public:
////////////////////////////////////////////////////////////
/// \brief Vector with same direction but length 1 <i><b>(floating-point)</b></i>.
///
///
/// \pre \c *this is no zero vector.
///
////////////////////////////////////////////////////////////
[[nodiscard]] Vector3 normalized() const;
[[nodiscard]] SFML_SYSTEM_API Vector3 normalized() const;
////////////////////////////////////////////////////////////
/// \brief Dot product of two 3D vectors.
@ -113,7 +112,7 @@ public:
/// \brief Component-wise multiplication of \c *this and \c rhs.
///
/// Computes <tt>(lhs.x*rhs.x, lhs.y*rhs.y, lhs.z*rhs.z)</tt>.
///
///
/// Scaling is the most common use case for component-wise multiplication/division.
/// This operation is also known as the Hadamard or Schur product.
///
@ -122,11 +121,11 @@ public:
////////////////////////////////////////////////////////////
/// \brief Component-wise division of \c *this and \c rhs.
///
///
/// Computes <tt>(lhs.x/rhs.x, lhs.y/rhs.y, lhs.z/rhs.z)</tt>.
///
///
/// Scaling is the most common use case for component-wise multiplication/division.
///
///
/// \pre Neither component of \c rhs is zero.
///
////////////////////////////////////////////////////////////
@ -360,7 +359,7 @@ using Vector3f = Vector3<float>;
///
/// float s = v.dot(w);
/// sf::Vector3f t = v.cross(w);
///
///
/// bool different = (v != u);
/// \endcode
///

View File

@ -56,15 +56,6 @@ z(static_cast<T>(vector.z))
}
////////////////////////////////////////////////////////////
template <typename T>
T Vector3<T>::length() const
{
static_assert(std::is_floating_point_v<T>, "Vector3::length() is only supported for floating point types");
return std::hypot(x, y, z);
}
////////////////////////////////////////////////////////////
template <typename T>
@ -74,17 +65,6 @@ constexpr T Vector3<T>::lengthSq() const
}
////////////////////////////////////////////////////////////
template <typename T>
Vector3<T> Vector3<T>::normalized() const
{
static_assert(std::is_floating_point_v<T>, "Vector3::normalized() is only supported for floating point types");
assert(*this != Vector3<T>());
return (*this) / length();
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr T Vector3<T>::dot(const Vector3<T>& rhs) const

View File

@ -22,8 +22,10 @@ set(SRC
${INCROOT}/Time.inl
${INCROOT}/Utf.hpp
${INCROOT}/Utf.inl
${SRCROOT}/Vector2.cpp
${INCROOT}/Vector2.hpp
${INCROOT}/Vector2.inl
${SRCROOT}/Vector3.cpp
${INCROOT}/Vector3.hpp
${INCROOT}/Vector3.inl
${SRCROOT}/FileInputStream.cpp

123
src/SFML/System/Vector2.cpp Normal file
View File

@ -0,0 +1,123 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2022 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#include <SFML/System/Vector2.hpp>
#include <type_traits>
#include <cassert>
#include <cmath>
namespace sf
{
////////////////////////////////////////////////////////////
template <typename T>
Vector2<T> Vector2<T>::normalized() const
{
static_assert(std::is_floating_point_v<T>, "Vector2::normalized() is only supported for floating point types");
assert(*this != Vector2<T>());
return (*this) / length();
}
////////////////////////////////////////////////////////////
template <typename T>
Angle Vector2<T>::angleTo(const Vector2<T>& rhs) const
{
static_assert(std::is_floating_point_v<T>, "Vector2::angleTo() is only supported for floating point types");
assert(*this != Vector2<T>());
assert(rhs != Vector2<T>());
return radians(static_cast<float>(std::atan2(cross(rhs), dot(rhs))));
}
////////////////////////////////////////////////////////////
template <typename T>
Angle Vector2<T>::angle() const
{
static_assert(std::is_floating_point_v<T>, "Vector2::angle() is only supported for floating point types");
assert(*this != Vector2<T>());
return radians(static_cast<float>(std::atan2(y, x)));
}
////////////////////////////////////////////////////////////
template <typename T>
Vector2<T> Vector2<T>::rotatedBy(Angle angle) const
{
static_assert(std::is_floating_point_v<T>, "Vector2::rotatedBy() is only supported for floating point types");
// No zero vector assert, because rotating a zero vector is well-defined (yields always itself)
T cos = std::cos(static_cast<T>(angle.asRadians()));
T sin = std::sin(static_cast<T>(angle.asRadians()));
// Don't manipulate x and y separately, otherwise they're overwritten too early
return Vector2<T>(
cos * x - sin * y,
sin * x + cos * y);
}
////////////////////////////////////////////////////////////
template <typename T>
Vector2<T> Vector2<T>::projectedOnto(const Vector2<T>& axis) const
{
static_assert(std::is_floating_point_v<T>, "Vector2::projectedOnto() is only supported for floating point types");
assert(axis != Vector2<T>());
return dot(axis) / axis.lengthSq() * axis;
}
////////////////////////////////////////////////////////////
template <typename T>
Vector2<T>::Vector2(T r, Angle phi) :
x(r * static_cast<T>(std::cos(phi.asRadians()))),
y(r * static_cast<T>(std::sin(phi.asRadians())))
{
static_assert(std::is_floating_point_v<T>, "Vector2::Vector2(T, Angle) is only supported for floating point types");
}
////////////////////////////////////////////////////////////
template <typename T>
T Vector2<T>::length() const
{
static_assert(std::is_floating_point_v<T>, "Vector2::length() is only supported for floating point types");
return std::hypot(x, y);
}
}
////////////////////////////////////////////////////////////
// Explicit template instantiations
////////////////////////////////////////////////////////////
template class sf::Vector2<float>;
template class sf::Vector2<double>;
template class sf::Vector2<long double>;

View File

@ -0,0 +1,62 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2022 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#include <SFML/System/Vector3.hpp>
#include <type_traits>
#include <cassert>
#include <cmath>
namespace sf
{
////////////////////////////////////////////////////////////
template <typename T>
Vector3<T> Vector3<T>::normalized() const
{
static_assert(std::is_floating_point_v<T>, "Vector3::normalized() is only supported for floating point types");
assert(*this != Vector3<T>());
return (*this) / length();
}
////////////////////////////////////////////////////////////
template <typename T>
T Vector3<T>::length() const
{
static_assert(std::is_floating_point_v<T>, "Vector3::length() is only supported for floating point types");
return std::hypot(x, y, z);
}
}
////////////////////////////////////////////////////////////
// Explicit template instantiations
////////////////////////////////////////////////////////////
template class sf::Vector3<float>;
template class sf::Vector3<double>;
template class sf::Vector3<long double>;

View File

@ -27,7 +27,6 @@
////////////////////////////////////////////////////////////
#include <SFML/Window/Mouse.hpp>
#include <SFML/Window/InputImpl.hpp>
#include <SFML/Window/Window.hpp>
namespace sf

View File

@ -1,6 +1,7 @@
#include <SFML/System/Vector2.hpp>
#include "SystemUtil.hpp"
#include <type_traits>
#include <cmath>
#include <doctest.h>
@ -248,7 +249,7 @@ TEST_CASE("sf::Vector2 class template - [system]")
CHECK(v.normalized() == Approx(sf::Vector2f(0.624695f, 0.780869f)));
const sf::Vector2f w(-0.7f, -2.2f);
CHECK(w.length() == Approx(2.30868f));
CHECK(w.lengthSq() == Approx(5.3300033f));
CHECK(w.normalized() == Approx(sf::Vector2f(-0.303204f, -0.952926f)));
@ -257,7 +258,7 @@ TEST_CASE("sf::Vector2 class template - [system]")
SUBCASE("Rotations and angles")
{
const sf::Vector2f v(2.4f, 3.0f);
CHECK(v.angle() == Approx(51.3402_deg));
CHECK(sf::Vector2f::UnitX.angleTo(v) == Approx(51.3402_deg));
CHECK(sf::Vector2f::UnitY.angleTo(v) == Approx(-38.6598_deg));
@ -282,7 +283,7 @@ TEST_CASE("sf::Vector2 class template - [system]")
CHECK(v.rotatedBy(27.14_deg) == Approx(sf::Vector2f(0.767248f, 3.76448f)));
CHECK(v.rotatedBy(-36.11_deg) == Approx(sf::Vector2f(3.70694f, 1.00925f)));
}
SUBCASE("Products and quotients")
{
const sf::Vector2f v(2.4f, 3.0f);
@ -293,18 +294,18 @@ TEST_CASE("sf::Vector2 class template - [system]")
CHECK(v.cross(w) == Approx(-3.18f));
CHECK(w.cross(v) == Approx(+3.18f));
CHECK(v.cwiseMul(w) == Approx(sf::Vector2f(-1.68f, -6.6f)));
CHECK(w.cwiseMul(v) == Approx(sf::Vector2f(-1.68f, -6.6f)));
CHECK(v.cwiseDiv(w) == Approx(sf::Vector2f(-3.428571f, -1.363636f)));
CHECK(w.cwiseDiv(v) == Approx(sf::Vector2f(-0.291666f, -0.733333f)));
}
SUBCASE("Projection")
{
const sf::Vector2f v(2.4f, 3.0f);
const sf::Vector2f w(-0.7f, -2.2f);
CHECK(v.projectedOnto(w) == Approx(sf::Vector2f(1.087430f, 3.417636f)));
CHECK(v.projectedOnto(w) == Approx(sf::Vector2f(-1.55347f * w)));

View File

@ -10,6 +10,7 @@
#include <SFML/System/Vector3.hpp>
#include <iomanip>
#include <limits>
#include <ostream>
#include <sstream>
#include <string>