|
1 | 1 | use indexmap::IndexMap;
|
2 | 2 | use ndarray::prelude::*;
|
3 | 3 | use ndarray::{Data, DataMut, Slice};
|
| 4 | +use stacker::maybe_grow; |
| 5 | + |
| 6 | +/// Guaranteed stack size per recursion step of 1 MiB. |
| 7 | +const RED_ZONE: usize = 1_024 * 1_024; |
| 8 | +/// New stack space of 8 MiB to allocate if within [`RED_ZONE`]. |
| 9 | +const STACK_SIZE: usize = 8 * RED_ZONE; |
4 | 10 |
|
5 | 11 | /// Methods for sorting and partitioning 1-D arrays.
|
6 | 12 | pub trait Sort1dExt<A, S>
|
@@ -357,7 +363,9 @@ where
|
357 | 363 | // Since `!indexes.is_empty()` and indexes must be in-bounds, `array` must
|
358 | 364 | // be non-empty.
|
359 | 365 | let mut values = vec![array[0].clone(); indexes.len()];
|
360 |
| - _get_many_from_sorted_mut_unchecked(array.view_mut(), &mut indexes.to_owned(), &mut values); |
| 366 | + maybe_grow(RED_ZONE, STACK_SIZE, || { |
| 367 | + _get_many_from_sorted_mut_unchecked(array.view_mut(), &mut indexes.to_owned(), &mut values); |
| 368 | + }); |
361 | 369 |
|
362 | 370 | // We convert the vector to a more search-friendly `IndexMap`.
|
363 | 371 | indexes.iter().cloned().zip(values.into_iter()).collect()
|
@@ -451,21 +459,25 @@ fn _get_many_from_sorted_mut_unchecked<A>(
|
451 | 459 |
|
452 | 460 | // We search recursively for the values corresponding to indexes strictly less than
|
453 | 461 | // `pivot_index` in the lower partition.
|
454 |
| - _get_many_from_sorted_mut_unchecked( |
455 |
| - array.slice_axis_mut(Axis(0), Slice::from(..pivot_index)), |
456 |
| - lower_indexes, |
457 |
| - lower_values, |
458 |
| - ); |
| 462 | + maybe_grow(RED_ZONE, STACK_SIZE, || { |
| 463 | + _get_many_from_sorted_mut_unchecked( |
| 464 | + array.slice_axis_mut(Axis(0), Slice::from(..pivot_index)), |
| 465 | + lower_indexes, |
| 466 | + lower_values, |
| 467 | + ); |
| 468 | + }); |
459 | 469 |
|
460 | 470 | // We search recursively for the values corresponding to indexes greater than or equal
|
461 | 471 | // `pivot_index` in the upper partition. Since only the upper partition of the array is
|
462 | 472 | // passed in, the indexes need to be shifted by length of the lower partition.
|
463 | 473 | upper_indexes.iter_mut().for_each(|x| *x -= pivot_index + 1);
|
464 |
| - _get_many_from_sorted_mut_unchecked( |
465 |
| - array.slice_axis_mut(Axis(0), Slice::from(pivot_index + 1..)), |
466 |
| - upper_indexes, |
467 |
| - upper_values, |
468 |
| - ); |
| 474 | + maybe_grow(RED_ZONE, STACK_SIZE, || { |
| 475 | + _get_many_from_sorted_mut_unchecked( |
| 476 | + array.slice_axis_mut(Axis(0), Slice::from(pivot_index + 1..)), |
| 477 | + upper_indexes, |
| 478 | + upper_values, |
| 479 | + ); |
| 480 | + }); |
469 | 481 |
|
470 | 482 | return;
|
471 | 483 | }
|
@@ -519,32 +531,38 @@ fn _get_many_from_sorted_mut_unchecked<A>(
|
519 | 531 |
|
520 | 532 | // We search recursively for the values corresponding to indexes strictly less than
|
521 | 533 | // `lower_index` in the lower partition.
|
522 |
| - _get_many_from_sorted_mut_unchecked( |
523 |
| - array.slice_axis_mut(Axis(0), Slice::from(..lower_index)), |
524 |
| - lower_indexes, |
525 |
| - lower_values, |
526 |
| - ); |
| 534 | + maybe_grow(RED_ZONE, STACK_SIZE, || { |
| 535 | + _get_many_from_sorted_mut_unchecked( |
| 536 | + array.slice_axis_mut(Axis(0), Slice::from(..lower_index)), |
| 537 | + lower_indexes, |
| 538 | + lower_values, |
| 539 | + ); |
| 540 | + }); |
527 | 541 |
|
528 | 542 | // We search recursively for the values corresponding to indexes greater than or equal
|
529 | 543 | // `lower_index` in the inner partition, that is between the lower and upper partition. Since
|
530 | 544 | // only the inner partition of the array is passed in, the indexes need to be shifted by length
|
531 | 545 | // of the lower partition.
|
532 | 546 | inner_indexes.iter_mut().for_each(|x| *x -= lower_index + 1);
|
533 |
| - _get_many_from_sorted_mut_unchecked( |
534 |
| - array.slice_axis_mut(Axis(0), Slice::from(lower_index + 1..upper_index)), |
535 |
| - inner_indexes, |
536 |
| - inner_values, |
537 |
| - ); |
| 547 | + maybe_grow(RED_ZONE, STACK_SIZE, || { |
| 548 | + _get_many_from_sorted_mut_unchecked( |
| 549 | + array.slice_axis_mut(Axis(0), Slice::from(lower_index + 1..upper_index)), |
| 550 | + inner_indexes, |
| 551 | + inner_values, |
| 552 | + ); |
| 553 | + }); |
538 | 554 |
|
539 | 555 | // We search recursively for the values corresponding to indexes greater than or equal
|
540 | 556 | // `upper_index` in the upper partition. Since only the upper partition of the array is passed
|
541 | 557 | // in, the indexes need to be shifted by the combined length of the lower and inner partition.
|
542 | 558 | upper_indexes.iter_mut().for_each(|x| *x -= upper_index + 1);
|
543 |
| - _get_many_from_sorted_mut_unchecked( |
544 |
| - array.slice_axis_mut(Axis(0), Slice::from(upper_index + 1..)), |
545 |
| - upper_indexes, |
546 |
| - upper_values, |
547 |
| - ); |
| 559 | + maybe_grow(RED_ZONE, STACK_SIZE, || { |
| 560 | + _get_many_from_sorted_mut_unchecked( |
| 561 | + array.slice_axis_mut(Axis(0), Slice::from(upper_index + 1..)), |
| 562 | + upper_indexes, |
| 563 | + upper_values, |
| 564 | + ); |
| 565 | + }); |
548 | 566 | }
|
549 | 567 |
|
550 | 568 | /// Equally space `sample` indexes around the center of `array` and sort them by their values.
|
|
0 commit comments