# Utils/Matrices

Rotation and decomposition operations for 2D and 3D matrices and vectors.

## Import and Use

```python
from gri_utils import matrices

rotated = matrices.rotate_ccw(matrix, angle_deg=45.0)
```

Or with a unique name:

```python
from gri_utils import matrices as gri_mat

rotated = gri_mat.rotate_ccw(matrix, angle_deg=45.0)
```

## Module Overview

| Symbol | Purpose |
| ------ | ------- |
| `rotate_ccw` | Rotate counter-clockwise by angle (optionally around an axis) |
| `rotate_cw` | Rotate clockwise by angle (optionally around an axis) |
| `decompose` | Eigendecomposition returning sorted eigenvalues and eigenvectors |
| `Decomposition` | NamedTuple: `vals` (eigenvalues), `uvecs` (unit eigenvectors) |

## Rotation

Rotate matrices or vectors by a given angle. For 2D inputs (2x2 matrix or length-2 vector), the rotation is in the plane. For 3D inputs (3x3 matrix or length-3 vector), specify an axis.

```python
import numpy as np
from gri_utils import matrices

# 2D rotation (no axis needed)
vec_2d = np.array([1.0, 0.0])
rotated = matrices.rotate_ccw(vec_2d, angle_deg=90.0)
# -> [0.0, 1.0]

# 3D rotation around z-axis
vec_3d = np.array([1.0, 0.0, 0.0])
rotated = matrices.rotate_ccw(vec_3d, angle_deg=90.0, axis="z")
# -> [0.0, 1.0, 0.0]

# Rotate a covariance matrix
cov = np.array([[100.0, 0.0], [0.0, 50.0]])
cov_rotated = matrices.rotate_ccw(cov, angle_deg=30.0)
```

The `axis` parameter accepts `"x"`, `"y"`, or `"z"` for 3D rotations.

## Decomposition

Eigendecomposition with eigenvalues sorted in descending order:

```python
import numpy as np
from gri_utils import matrices

cov = np.array([[100.0, 25.0], [25.0, 50.0]])
result = matrices.decompose(cov)

result.vals   # Eigenvalues (descending order)
result.uvecs  # Corresponding unit eigenvectors (columns)
```
