Skip to content

fix(mv): wrap norm() in Abs for even-grade multivectors#554

Merged
utensil merged 3 commits intopygae:masterfrom
utiberious:fix/issue-522-norm-abs-bar
Mar 31, 2026
Merged

fix(mv): wrap norm() in Abs for even-grade multivectors#554
utensil merged 3 commits intopygae:masterfrom
utiberious:fix/issue-522-norm-abs-bar

Conversation

@utiberious
Copy link
Copy Markdown
Contributor

Summary

Fixes norm() to always return a nonnegative value by wrapping the result in Abs when the multivector has even-grade components (where the norm-squared can be negative, e.g. for timelike vectors in Minkowski space).

Previously, norm() could return expressions with no absolute value bars for even grades, which is mathematically incorrect since the norm should always be nonnegative.

Fixes #522

Changes

  • galgebra/mv.py: Wrap norm() result in Abs() when the squared norm may be negative
  • test/test_mv.py: Add test verifying norm() returns nonneg for even-grade multivectors
  • examples/ipython/test_gsg_undual_etc.ipynb: Update notebook outputs for norm/abs changes

Test plan

  • Unit tests pass
  • Full CI with nbval notebooks passes

The norm method could return expressions like s instead of Abs(s) for
scalar and even-grade multivectors. Now norm checks whether the result
from square_root_of_expr is guaranteed nonneg, and wraps it in Abs
when it is not.

Fixes #6
The norm/abs/bar fix (issue pygae#522) changes how these operations are
printed in LaTeX. Update saved notebook outputs to match.
@review-notebook-app
Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@utensil
Copy link
Copy Markdown
Member

utensil commented Mar 31, 2026

Thanks for addressing this.

Two requests:

1. Dead code. The if result.is_number: return Abs(result) branch is identical to the final fallback — both return Abs(result). Remove it.

2. Test coverage. The test only covers Euclidean G3. Issue #522 (and PR #510) specifically call out non-Euclidean metrics as the hard case. Please add:

# non-Euclidean: symbolic vector where norm may not be provably nonneg
g2mn = Ga('e', g=[1, -1], coords=symbols('x t', real=True))
v = g2mn.mv('v', 'vector')
assert v.norm(hint='+').is_nonnegative

@utiberious
Copy link
Copy Markdown
Contributor Author

Addressed both:

  1. Removed the dead if result.is_number: return Abs(result) branch (identical to the fallback).
  2. Added non-Euclidean test: Ga('e', g=[1, -1]) with symbolic vector, asserts v.norm(hint='+').is_nonnegative.

Pushed in a16d314.

@utensil utensil added bug component: core Ga, Mv, Metric, etc labels Mar 31, 2026
@utensil utensil merged commit b03f781 into pygae:master Mar 31, 2026
6 checks passed
@utensil utensil added this to the 0.6.0 milestone Mar 31, 2026
utiberious added a commit to utiberious/galgebra that referenced this pull request Apr 1, 2026
Groups new entries by: features, bug fixes, examples/docs, tests/maintenance.

Features: Cl() kingdon interface (pygae#550, closes pygae#524), Mv.__rtruediv__
(pygae#543, closes pygae#512), shirokov_inverse/hitzer_inverse (pygae#530).

Bugs: interop dual mode contamination (pygae#556, closes pygae#555), norm() Abs
wrapping (pygae#554, closes pygae#522), is_versor() improvement (pygae#536, closes pygae#533).

Examples/docs: sundial + cheatsheet tests (pygae#549+pygae#557, closes pygae#506),
coords tutorial (pygae#551), README ops (pygae#548, closes pygae#523).

Tests/maintenance: lt.matrix() regression tests (pygae#558, closes pygae#461),
extra-cdot regression test (pygae#545), er_blade + ReciprocalFrame refactors
(pygae#552+pygae#553), CI fix (pygae#535).
utensil pushed a commit that referenced this pull request Apr 1, 2026
* docs: add 0.6.0 changelog entries

Groups new entries by: features, bug fixes, examples/docs, tests/maintenance.

Features: Cl() kingdon interface (#550, closes #524), Mv.__rtruediv__
(#543, closes #512), shirokov_inverse/hitzer_inverse (#530).

Bugs: interop dual mode contamination (#556, closes #555), norm() Abs
wrapping (#554, closes #522), is_versor() improvement (#536, closes #533).

Examples/docs: sundial + cheatsheet tests (#549+#557, closes #506),
coords tutorial (#551), README ops (#548, closes #523).

Tests/maintenance: lt.matrix() regression tests (#558, closes #461),
extra-cdot regression test (#545), er_blade + ReciprocalFrame refactors
(#552+#553), CI fix (#535).

* docs: add missing issue link for #551 entry

* docs: add changelog entry for #560 (Lt callable zero fix)

* docs: move Lt zero fix into bug group, use issue #540 as reference
utiberious added a commit to utiberious/galgebra that referenced this pull request Apr 2, 2026
* Fix norm to always return nonneg value for even grades

The norm method could return expressions like s instead of Abs(s) for
scalar and even-grade multivectors. Now norm checks whether the result
from square_root_of_expr is guaranteed nonneg, and wraps it in Abs
when it is not.

Fixes #6

* Update test_gsg_undual_etc notebook output for norm/abs/bar changes

The norm/abs/bar fix (issue pygae#522) changes how these operations are
printed in LaTeX. Update saved notebook outputs to match.

* Remove dead code branch, add non-Euclidean norm test
utiberious added a commit to utiberious/galgebra that referenced this pull request Apr 2, 2026
* docs: add 0.6.0 changelog entries

Groups new entries by: features, bug fixes, examples/docs, tests/maintenance.

Features: Cl() kingdon interface (pygae#550, closes pygae#524), Mv.__rtruediv__
(pygae#543, closes pygae#512), shirokov_inverse/hitzer_inverse (pygae#530).

Bugs: interop dual mode contamination (pygae#556, closes pygae#555), norm() Abs
wrapping (pygae#554, closes pygae#522), is_versor() improvement (pygae#536, closes pygae#533).

Examples/docs: sundial + cheatsheet tests (pygae#549+pygae#557, closes pygae#506),
coords tutorial (pygae#551), README ops (pygae#548, closes pygae#523).

Tests/maintenance: lt.matrix() regression tests (pygae#558, closes pygae#461),
extra-cdot regression test (pygae#545), er_blade + ReciprocalFrame refactors
(pygae#552+pygae#553), CI fix (pygae#535).

* docs: add missing issue link for pygae#551 entry

* docs: add changelog entry for pygae#560 (Lt callable zero fix)

* docs: move Lt zero fix into bug group, use issue pygae#540 as reference
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug component: core Ga, Mv, Metric, etc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

norm has no abs bar for even grades

2 participants