Skip to content

Commit 211c86f

Browse files
authored
reduce amount of array allocations (#99)
1 parent 985f830 commit 211c86f

File tree

2 files changed

+18
-13
lines changed

2 files changed

+18
-13
lines changed

pylinalg/matrix.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,9 @@ def quat_from_mat(matrix, /, *, out=None, dtype=None) -> np.ndarray:
285285
w = (m[1, 0] - m[0, 1]) / s
286286

287287
if out is None:
288-
out = np.empty((4,), dtype=dtype)
289-
out[:] = np.array([x, y, z, w])
288+
out = np.array([x, y, z, w], dtype=dtype)
289+
else:
290+
out[:] = [x, y, z, w]
290291
return out
291292

292293

@@ -422,7 +423,7 @@ def mat_decompose(
422423

423424
rotation = out[1] if out is not None else None
424425

425-
rotation_matrix = matrix[:-1, :-1].copy().astype(float)
426+
rotation_matrix = matrix[:-1, :-1].astype(float, copy=True)
426427
mask = scaling != 0
427428
rotation_matrix[:, mask] /= scaling[mask][None, :]
428429
rotation_matrix[:, ~mask] = 0.0

pylinalg/vector.py

+14-10
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def vec_normalize(vectors, /, *, out=None, dtype=None) -> np.ndarray:
2626
ndarray, [..., 3]
2727
array of normalized vectors.
2828
"""
29-
vectors = np.asarray(vectors, dtype=np.float64)
29+
vectors = np.asarray(vectors, dtype=float)
3030
if out is None:
3131
out = np.empty_like(vectors, dtype=dtype)
3232

@@ -102,14 +102,15 @@ def vec_transform(vectors, matrix, /, *, w=1, out=None, dtype=None) -> np.ndarra
102102
vectors = np.asarray(vectors, dtype=float)
103103
matrix = np.asarray(matrix, dtype=float)
104104

105-
if out is None:
106-
out_shape = np.broadcast_shapes(vectors.shape[:-1], matrix.shape[:-2])
107-
out = np.empty((*out_shape, 3), dtype=dtype)
108-
109105
vectors = vec_homogeneous(vectors, w=w)
110106
result = matrix @ vectors[..., None]
111107
result /= result[..., -1, :][..., None, :]
112-
out[:] = result[..., :-1, 0]
108+
result = result[..., :-1, 0]
109+
110+
if out is not None:
111+
out[:] = result
112+
else:
113+
out = result.astype(dtype, copy=False)
113114

114115
return out
115116

@@ -482,7 +483,9 @@ def vec_spherical_safe(vector, /, *, out=None, dtype=None) -> np.ndarray:
482483
return out
483484

484485

485-
def quat_to_euler(quaternion, /, *, order="xyz", out=None, dtype=None) -> np.ndarray:
486+
def quat_to_euler(
487+
quaternion, /, *, order="xyz", epsilon=1e-7, out=None, dtype=None
488+
) -> np.ndarray:
486489
"""Convert quaternions to Euler angles with specified rotation order.
487490
488491
Parameters
@@ -493,6 +496,8 @@ def quat_to_euler(quaternion, /, *, order="xyz", out=None, dtype=None) -> np.nda
493496
The rotation order as a string. Can include 'X', 'Y', 'Z' for intrinsic
494497
rotation (uppercase) or 'x', 'y', 'z' for extrinsic rotation (lowercase).
495498
Default is "xyz".
499+
epsilon : float, optional
500+
The floating point error margin. Default is 1e-7.
496501
out : ndarray, optional
497502
A location into which the result is stored. If provided, it
498503
must have a shape that the inputs broadcast to. If not provided or
@@ -538,7 +543,6 @@ def quat_to_euler(quaternion, /, *, order="xyz", out=None, dtype=None) -> np.nda
538543
# Check if permutation is even (+1) or odd (-1)
539544
sign = int((i - j) * (j - k) * (k - i) / 2)
540545

541-
eps = 1e-7
542546
for ind in range(num_rotations):
543547
if num_rotations == 1 and out.ndim == 1:
544548
_angles = out
@@ -564,8 +568,8 @@ def quat_to_euler(quaternion, /, *, order="xyz", out=None, dtype=None) -> np.nda
564568
_angles[1] = np.arccos(2 * (a**2 + b**2) / n2 - 1)
565569

566570
# ... and check if it is equal to 0 or pi, causing a singularity
567-
safe1 = np.abs(_angles[1]) >= eps
568-
safe2 = np.abs(_angles[1] - np.pi) >= eps
571+
safe1 = np.abs(_angles[1]) >= epsilon
572+
safe2 = np.abs(_angles[1] - np.pi) >= epsilon
569573
safe = safe1 and safe2
570574

571575
# Step 4

0 commit comments

Comments
 (0)