libmath itself doesn't expose any stream operators anymore. However,
libutils is able to automatically print libmath types into its
io::ostream -- however matrices are not formatted nicely.
Added a new optional library, libmathio, that provides std::ostream
operators for all libmath types. libmathio does a better job at
formating matrices.
Also removed apply() and map() from libmath because there were not used
anywhere and they forced us to depend on <functional> in public headers.
the C++ standard says:
if T is a class type with a default constructor that is neither
user-provided nor deleted (that is, it may be a class with an
implicitly-defined or defaulted default constructor), the object
is zero-initialized and then it is default-initialized if it has a
non-trivial default constructor
Unfortunately, MSVC always calls the default constructor, even if it
is trivial, which breaks constexpr-ness.
To workaround this, we're always zero-initializing TVecN<>
Also removed constexpr from default constructors, since they never can
be constexpr as they're not initializing the vector.
We now follow the same rules than for basic types, when performing
mixed-precision operations, e.g.:
float3 + double3 -> double3
double3 + float3 -> double3
dot(float3, double3) -> double
In particular, e.g. swapping the arguments to arithmetic operations
now always yields to the same result type (before, float3 + double3
would not return the same type than double3 + float3).
This is nicer because this way the methods that don't match don't
even exist. Also make it better when editing code with a C++ aware
ide.
Also use the less verbose std::enable_if_t<>
It turns out that most of libmath couldn't be used in constexpr
expression due to our use of union{}. The C++ standard requires that
all accesses to a union{} in a constexpr expression be the same
element.
Also because libm and cmath are not constexpr some functions such
as length() or normalize() can't be constexpr. The same is true for
anything needing things like sqrt, cos, sin, ceil, floor.
This change mainly does the following:
- replace all accesses to vector elements by operator[]
(this ensure all of libmath uses the same union element)
- avoid use of std::min / std::max / std::abs
- avoid uninitialized variables, which can't be constexpr
- remove 'constexpr' keyword on functions that can never be
It is now possible to write things like:
constexpr mat4f I = inverse(
transpose(mat4f::translation(float3{ 1, 2, 3 })
* mat4f::scaling(4)));
We can now use for e.g. vec4<float> instead of float4, this is
useful for templated code. The existing solution was to reach
out to the math::detail::TVec<> class.