Skip to content

Commit 58ee2c5

Browse files
authored
Ensure length of flattened_data is same as end of cumulative_length (#211)
* Ensure length of flattened_data is same as end of cumulative_length
1 parent f6fb8ef commit 58ee2c5

File tree

2 files changed

+24
-18
lines changed

2 files changed

+24
-18
lines changed

src/lgdo/types/vectorofvectors.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,11 @@ def __init__(
243243
)
244244
elif self.flattened_data is None:
245245
self.flattened_data = flattened_data
246+
expected_fd_size = self.cumulative_length[-1] if len(self) > 0 else 0
247+
if len(flattened_data) != expected_fd_size:
248+
msg = "provided flattened_data array has different size than indicated by cumulative_length. Resizing..."
249+
log.warning(msg)
250+
self.flattened_data.resize(expected_fd_size)
246251

247252
super().__init__(attrs)
248253

@@ -474,8 +479,8 @@ def _set_vector_unsafe(
474479
`vec` in ``self.flattened_data[j:sum(lens)]``. Finally updates
475480
``self.cumulative_length[i]`` with the new flattened data array length.
476481
477-
Vectors stored after index `i` can be overridden, producing unintended
478-
behavior. This method is typically used for fast sequential fill of a
482+
Vectors stored after index `i` are removed and the VectorOfVectors is
483+
resized. This method is typically used for fast sequential fill of a
479484
pre-allocated vector of vectors.
480485
481486
If i`vec` is 1D array and `lens` is ``None``, set using full array. If
@@ -484,8 +489,9 @@ def _set_vector_unsafe(
484489
485490
Danger
486491
------
487-
This method can lead to undefined behavior or vector invalidation if
488-
used improperly. Use it only if you know what you are doing.
492+
This method resizes the array, removes subsequent vectors, and can lead
493+
to undefined behavior or vector-view invalidation if used improperly.
494+
Use it only if you know what you are doing.
489495
490496
See Also
491497
--------
@@ -518,6 +524,9 @@ def _set_vector_unsafe(
518524
nan_val = np.nan
519525
from .vovutils import _nb_fill # noqa: PLC0415
520526

527+
self.flattened_data.resize(cum_lens[-1])
528+
self.cumulative_length.resize(i + len(lens))
529+
521530
_nb_fill(
522531
vec,
523532
lens,

tests/types/test_vectorofvectors.py

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -460,23 +460,20 @@ def test_set_vector_unsafe(testvov):
460460
== np.nan_to_num(exp_entry_w_overflow, nan=0)
461461
)
462462

463-
# test vectorized filling when len is longer than array
464-
fourth_vov = lgdo.VectorOfVectors(
463+
# test vectorized filling with fewer elements than are in initial array
464+
fifth_vov = lgdo.VectorOfVectors(
465465
shape_guess=(5, 5), dtype=current_testvov.dtype
466466
)
467-
desired_lens[3] = 10
468-
fourth_vov._set_vector_unsafe(0, desired_aoa, desired_lens)
469-
if current_testvov.dtype in ["int32", "int64", "uint16", "uint32"]:
470-
exp_entry_w_overflow = np.concatenate(
471-
[desired[3], np.array([np.iinfo(current_testvov.dtype).min] * 6)]
472-
)
473-
else:
474-
exp_entry_w_overflow = np.concatenate([desired[3], np.array([np.nan] * 6)])
475-
476-
assert np.all(
477-
np.nan_to_num(fourth_vov[3], nan=0)
478-
== np.nan_to_num(exp_entry_w_overflow, nan=0)
467+
current_testvov = VectorOfVectors(
468+
flattened_data=current_testvov.flattened_data.nda[
469+
: current_testvov.cumulative_length[2]
470+
],
471+
cumulative_length=current_testvov.cumulative_length[:3],
479472
)
473+
fifth_vov._set_vector_unsafe(0, desired_aoa[:3, ...], desired_lens[:3])
474+
assert len(fifth_vov) == 3
475+
assert len(fifth_vov.flattened_data) == len(current_testvov.flattened_data)
476+
assert current_testvov == fifth_vov
480477

481478

482479
def test_iter(testvov):

0 commit comments

Comments
 (0)