|
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