Got a suggestion that lerp() could be optimized to be one arithmetic
operation less. While valid in certain cases, it would break in case the
endpoints have wildly different magnitudes. Unfortunately that was only
my personal knowledge, not backed by regression tests. Now it is.
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.
Despite what the standard tries to say. I bet a large portion of
<type_traits> is impossible to implement without it, which is why all
STL implementations define it there already.
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.
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.
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.
It was implemented only for the Half type and not the others, and I just
felt like using it on a vector now, 12 years after the Vector class got
first added.
Because it somewhat confusingly may have implied that it's really
composed of 8-bit bools, and not bits. The same reasoning was used to
pick the name for Corrade's Containers::BitArray.
Backwards compatibility aliases are in place as usual, however the
internal BoolVectorConverter is now BitVectorConverter and there
unfortunately cannot be any backwards compatibility. This breaks only
GLM and Eigen integration in the magnum-integration repo, which I'm
fixing immediately. I don't expect any user code to use this internal
helper. For regular vectors maybe, for this one definitely not.
This makes it possible to conveniently do things like
Containers::StridedArrayView1D<Float> array = …;
Vector4 vector{NoInit};
Utility::copy(array, vector); // or the other way around
which is especially useful together with the new JSON classes. In some
cases this means the function is no longer constexpr, but those weren't
constexpr because it was useful for anything, they were only because it
was possible. So this breakage shouldn't do any harm I think.
These shouldn't be needed (the newer classes such as Half or
CubicHermite don't have them and work fine), moreover Clang 12 is now
emitting the following warning for them:
Definition of implicit copy assignment operator for 'Foo' is
deprecated because it has a user-declared copy constructor
[-Wdeprecated-copy]
The old one is deprecated, and will be removed in a future release.
Unfortunately, to avoid deprecation warnings, all use of NoInit in the
Math library temporarily have to be Magnum::NoInit This will be cleaned
up when the deprecated alias is removed.
Should make new things more discoverable, avoid confusion when a
documented API isn't there and reduce the need for maintaining multiple
separate versions of the docs.