* Add Storage::forget
* Adjust implementations of Reallocator to use Storage::forget
* Fix formatting
* Rename forget to forget_elements and add safety comments
* Update comments in Reallocator implementations
---------
Co-authored-by: Nick Mertin <nickmertin@gmail.com>
* Add macro for concatenating matrices
* Replace DimUnify with DimEq::representative
* Add some simple cat macro output generation tests
* Fix formatting in cat macro code
* Add random prefix to cat macro output
* Add simple quote_spanned for cat macro
* Use `generic_view_mut` in cat macro
* Fix clippy lints in cat macro
* Clean up documentation for cat macro
* Remove identity literal from cat macro
* Allow references in input to cat macro
* Rename cat macro to stack
* Add more stack macro tests
* Add comment to explain reason for prefix in stack! macro
* Refactor matrix!, stack! macros into separate modules
* Take all blocks by reference in stack! macro
* Make empty stack![] invocation well-defined
* Fix stack! macro incorrect reference to data
* More extensive tests for stack! macro
* Move nalgebra-macros tests to nalgebra tests
By testing matrix!, stack! macros etc. in nalgebra, we ensure that
these macros are used in the same way that users will be using them.
* Fix stack! code generation tests
* Add back nalgebra as dev-dependency of nalgebra-macros
* Fix accidental wrong matrix! macro references in docs
* Rewrite stack! documentation for clarity
* Formatting
* Skip formatting of macro, rustfmt messes it up
* Rewrite stack! impl for improved clarity, Span behavior
This improves error messages upon dimension mismatch, among other
things. I've also tried to make the implementation easier to understand,
adding some comments to help the reader understand the individual steps.
* Use SameNumberOfRows/Columns instead of DimEq in stack! macro
This gives more accurate compiler errors if matrix dimensions
are mismatched.
* Check that stack! panics at runtime for basic dimension mismatch
* Add suggested edge cases from initial PR to tests
* stack! impl: use fixed prefix everywhere
This ensures that the expected generated code in tests
is the actual generated code when used in the wild.
* nalgebra-macros: Remove clippy pedantic, fix clippy complaints
pedantic seems to be mostly intent on wasting the programmer's time
* Add stack! sanity tests for built-ins and Complex
* Fix formatting in test
* Improve readability of format_ident! calls in stack! impl
* fix trybuild tests
* chore: run tests with a specific rust version
* More trybuild fixes
---------
Co-authored-by: Birk Tjelmeland <git@birktj.no>
Co-authored-by: Sébastien Crozet <sebcrozet@dimforge.com>
The existing implementation compares each component to zero with
an epsilon; effectively `glm::all(glm::is_comp_null(v, epsilon))`.
This probably isn't the desired semantics when calling `glm::is_null`;
rather, we want to determine if the magnitude of the vector is within
`epsilon` units of zero. It's the question of circle versus square.
This behavior matches that of OpenGL Mathematics.
In the documentation of RawStorage::stride it was falsely claimed that
the storage of the matrix happens in a row-major fashion. In fact it is
column-major.
* fix: Normalize the column once more
The column may not be normalized if the `factor` is on a scale of 1e-40.
Possibly, f32 just runs out of precision.
There is likely a better solution to the problem.
* chore: Add test that fails before fix
* chore: add comment providing details on the householder fix.
* chore: rename regression test
---------
Co-authored-by: Sébastien Crozet <sebcrozet@dimforge.com>
The existing comparison bound of $\epsilon^2$ is improperly scaled for
testing an epsilon of the squared vector magnitude. Let $\epsilon$ be
our specified epsilon and $\delta$ be the permissible delta of the
squared magnitude. Thus, for a nearly-normalized vector, we have
$$\begin{align}
\sqrt{1 + \delta} &= 1 + \epsilon \\
\delta &= (1 + \epsilon)^2 - 1 \\
\delta &= \epsilon^2 + 2\epsilon
\text{ .}\end{align}$$
Since we only care about small epsilon, we can assume
that $\epsilon^2$ is small and just use $\delta = 2\epsilon$. And in
fact, [this is the bound used by GLM][GLM#isNormalized] (MIT license)
... except they're using `length` and not `length2` for some reason.
[GLM#isNormalized]: b06b775c1c/glm/gtx/vector_query.inl (L102)
If we stick an epsilon of `1.0e-6` into the current implementation,
this gives us a computed delta of `1.0e-12`: smaller than the `f32`
machine epsilon, and thus no different than direct float comparison
without epsilon. This also gives an effetive epsilon of `5.0e-13`;
*much* less than the intended `1.0e-6` of intended permitted slack!
By doing a bit more algebra, we can find the effective epsilon is
$\sqrt{\texttt{epsilon}^2 + 1} - 1$. This patch makes the effective
epsilon $\sqrt{2\times\texttt{epsilon} + 1} - 1$ which still isn't
*perfect*, but it's effectively linear in the domain we care about,
only really making a practical difference above an epsilon of 10%.
TL;DR: the existing `is_normalized` considers a vector normalized if
the squared magnitude is within `epsilon*epsilon` of `1`. This is wrong
and it should be testing if it's within `2*epsilon`. This PR fixes it.
For absence of doubt, a comparison epsilon of $\texttt{epsilon}^2$ is
correct when comparing squared magnitude against zero, such as when
testing if a displacement vector is nearly zero.