Like the Deg / Rad classes, these are for strongly-typed representation
of time. Because the current way, either with untyped and imprecise
Float, or the insanely-hard-to-use and bloated std::chrono::nanoseconds,
was just too crappy.
This is just the types alone, corresponding typedefs in the root
namespace, and conversion from std::chrono. Using these in the Animation
library, in Timeline, in DebugTools::FrameProfiler, GL::TimeQuery etc.,
will eventually and gradually follow.
Breaking change, but the new behavior makes a lot more sense. Hopefully
not that significant breakage -- I don't assume people regularly worked
with angles this way.
Basically what Vector has already, need this for integer representation
of time, i.e. that
1.0_sec*1.25
gives back 1.25_sec, where the internal representation is a 64-bit
nanosecond value.
Just in case the codegen was a bit different between the two. Also this
makes it more likely that the actually tested lines are shown in code
coverage.
Need to make a constexpr style data for the UI library and it involves
various multiplications and such, so took that as an opportunity to
enable constexpr on all operators. No other functions such as max() so
far, as I don't really need those yet.
After a few abandoned iterations that involved adding constexpr
overloads only to the Vector2, Vector3 and Vector4 subclasses I ended up
with a rather minimal solution that makes the base Vector constexpr
already, and just about 50 extra lines in total.
In the original code from 2010, to avoid redundant code, the const
operations were delegating to compound assignment operations, i.e.
operator*() being implemented by making a copy of itself and then
delegating to operator*=(). Thus, as far as a Debug build is concerned,
one extra indirection for each. The new solution is *also* one
indirection (which is needed in order to expand the variadic sequence)
so it's not worse in Debug in any way, however it's one indirection less
in the Vector2, Vector3 and Vector4 subclasses as there it delegates
directly to the internal implementation instead of the base class
operator. On GCC at least, there's no measurable impact on build times
either -- the whole project builds in ~2:22 both before and after this
change.
The way the change is done also allows the new code to be compiled out
if C++14 constexpr is enabled, where the functions would simply delegate
to the compound assignments. I'm not planning to touch that any time
soon either.
This complier is making my hair gray. Fortunately the out-of-class
operator doesn't conflict with the in-class one, so it's purely an
additive workaround. Adding extra checks to all subclasses to be sure
this works correctly in all cases and not just in the base class.
Except for a vector and a row matrix multiplication operator, which
doesn't make sense to be a member. These are all now significantly
shorter thanks to not having to repeat that many template parameters,
and they can make use of direct access into the _data array for better
debug perf.
In particular verify also the compound assignment operators and that
they correctly return a reference to self. And make sure the
non-mutating operators can be called on const instances.
The tests were mostly written back in 2010 and it shows. It survived all
that time because I didn't need any larger refactor of the math library
until now, but I'm going to make some changes and it'll be embarrassing
to introduce nasty regressions because the test coverage was lacking.
For some reason a lot of these got forgotten in
b2c353bf21. Also adding a comment
explaining the difference, because it's likely to stop being obvious few
months from now.
Also adjusting two tests which were calling rotation() on matrices that
actually didn't have a correct rotation part, and it only slipped
through because of the bug in isOrthogonal().
Co-authored-by: John Turner <7strbass@gmail.com>
Need them for the UI. Will eventually need the sRGB literals too, not
sure what to do there yet, std::pow() is only constexpr in C++26. I'll
be probably long retired when *that* version becomes the min spec for
Magnum.
Using Containers::Pair allows me to make certain Range APIs constexpr
that weren't possible in C++11 before. Compared to std::pair it's also
trivially copyable, which is a nice property when storing it in various
growable containers.
As usual, the <Corrade/Containers/PairStl.h> include is in place to help
people with porting, although in many cases this change will be
breaking. I had to do it at some point anyway, so the earlier it is the
better.
Instead of defining the same types and vaguely risking little
differences. Typedefs that don't exist in Magnum.h (such as integer
quaternions) and typedefs that differ from Magnum.h (such as
using Vector<4, T> instead of Vector4<T>) stay as typedefs, to make it
clear what *deliberately* differs and what not.
Typedefs that didn't conflict with the template types in Math (such as
Vector3us) are removed entirely, as the typedef from Magnum.h can be
used directly in that case, without any `using`.
I did this back in 2010 because it "felt like the right thing to do",
given that all of Magnum depended on Math and not vice versa. But,
strictly speaking, Math already uses typedefs from Magnum/Types.h so why
it couldn't also bring in the Corrade namespace, and the
Debug/Warning/Error names too. Having to type out Corrade:: in all these
was really just a waste of time, weird inconsistency in docs and an
extra roadblock for whoever might want to contribute anything there.
Partially needed to avoid build breakages because Corrade itself
switched as well, partially because a cleanup is always good. Done
except for (STL-heavy) code that's deprecated or SceneGraph-related APIs
that are still quite full of STL as well.
It should be returning twice the value, this is the half-angle. Sad that
this went unnoticed for so long, extra bad points for me to have a
complicated test but not actually verifying that the returned value
makes sense, sigh.
A *nasty* option would be to just fix it, but -- even though there's a
chance nonbody ever used it since nobody ever complained -- it would
introduce breakages to any code that fixed it and that's something to
definitely not do in a trusted codebase. So it's instead deprecated,
firing an annoying warning to whoever might have called it, and there's
a (temporary) replacement called halfAngle() that does exactly the same
but is named appropriately.
Then, once the deprecated angle() is removed (the usual deprecation
period, so a year or the span of two releases, whichever takes longer)
and enough time passes (so another year at least), I'll reintroduce it
with a correct return value.
Most of the testing scaffolding here is a preparation for the actually
complex formats like BC6/7 or ASTC. Also, it's great to be able to use
Magnum from Python to prepare data for testing the C++ Magnum APIs.
The perf cost is just too great for these to be enabled always. The only
place where the assertions are kept always is in the batch APIs -- there
it's assumed the function is called on large enough data to offset this
overhead, plus since it's often dealing with large blocks of data the
memory safety is more important than various FP drifts which were the
usual case why other assertions were firing.
The article this API was originally based on assumes a scenario which
just *isn't* matching usual practices here, giving wrong results. Too
bad I didn't spend more time questioning the proof there and just
blindly assumed it's correct because everyone said so.
Won't be typing all that reasoning again in the commit message, see the
changelog entry and the comment in the test for details.
For generic code, which would otherwise have to invent some SFINAE
"use castInto() if the types are different and Utility::copy()
otherwise" nastiness in every such case, and that's just annoying.