@@ -859,6 +859,61 @@ where D: Dimension
859859
860860        Ok ( ( ) ) 
861861    } 
862+ 
863+     /// Shrink Array allocation capacity to be as small as it can be. 
864+      pub  fn  shrink_to_fit ( & mut  self ) 
865+     { 
866+         // Example: 
867+         //                        (1)         (2)                 (3)              .- len 
868+         // Vector:     [ x x x x x V x V x V x V x V x V x V x V x V x x x x x x x ]       .- capacity 
869+         // Allocation: [ m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m ] 
870+         // 
871+         // x: valid data in OwnedRepr but outside current array slicing 
872+         // V: valid data in OwnedRepr and visible in current array slicing 
873+         // m: allocated memory 
874+         // (1): Lowest address element 
875+         // (2): Logical pointer (Element at index zero; normally (1) == (2) but can be 
876+         // located anywhere (1) <= (2) <= (3)) 
877+         // (3): Highest address element 
878+         // 
879+         // Span: From (1) to (3). 
880+         // 
881+         // Algorithm: Compute 1, 2, 3. 
882+         // Move data so that unused areas before (1) and after (3) are removed from the storage/vector. 
883+         // Then shrink the vector's allocation to fit the valid elements. 
884+         // 
885+         // After: 
886+         //              (1)         (2)                 (3).- len == capacity 
887+         // Vector:     [ V x V x V x V x V x V x V x V x V ] 
888+         // Allocation: [ m m m m m m m m m m m m m m m m m ] 
889+         // 
890+ 
891+         if  mem:: size_of :: < A > ( )  == 0  { 
892+             return ; 
893+         } 
894+ 
895+         let  data_ptr = self . data . as_ptr ( ) ; 
896+         let  logical_ptr = self . as_ptr ( ) ; 
897+         let  offset_to_logical = dimension:: offset_from_low_addr_ptr_to_logical_ptr ( & self . dim ,  & self . strides ) ; 
898+         let  offset_to_high = dimension:: offset_from_logical_ptr_to_high_addr_ptr ( & self . dim ,  & self . strides ) ; 
899+ 
900+         let  span = offset_to_logical + offset_to_high + 1 ; 
901+         debug_assert ! ( span >= self . len( ) ) ; 
902+ 
903+         // We are in a panic critical section because: Array/OwnedRepr's destructors rely on 
904+         // dimension, strides, and self.ptr to deallocate correctly. 
905+         // We could panic here because custom user code is running when removing elements 
906+         // (destructors running). 
907+         let  guard = AbortIfPanic ( & "shrink_to_fit: owned repr not in consistent state" ) ; 
908+         unsafe  { 
909+             let  front_slop = logical_ptr. offset_from ( data_ptr)  as  usize  - offset_to_logical; 
910+             let  new_low_ptr = self 
911+                 . data 
912+                 . preserve_range_and_shrink ( front_slop..( front_slop + span) ) ; 
913+             self . ptr  = new_low_ptr. add ( offset_to_logical) ; 
914+         } 
915+         guard. defuse ( ) ; 
916+     } 
862917} 
863918
864919/// This drops all "unreachable" elements in `self_` given the data pointer and data length. 
@@ -1016,3 +1071,70 @@ where D: Dimension
10161071        } 
10171072    } 
10181073} 
1074+ 
1075+ #[ cfg( test) ]  
1076+ mod  tests
1077+ { 
1078+     use  crate :: Array ; 
1079+     use  crate :: Array2 ; 
1080+     use  crate :: Slice ; 
1081+     use  core:: fmt:: Debug ; 
1082+     use  core:: mem:: size_of; 
1083+ 
1084+     #[ test]  
1085+     fn  test_shrink_to_fit ( ) 
1086+     { 
1087+         fn  assert_shrink_before_after < T > ( mut  a :  Array2 < T > ,  s1 :  Slice ,  s2 :  Slice ,  new_capacity :  usize ) 
1088+         where  T :  Debug  + Clone  + Eq 
1089+         { 
1090+             let  initial_len = a. len ( ) ; 
1091+             if  size_of :: < T > ( )  > 0  { 
1092+                 assert_eq ! ( a. data. capacity( ) ,  initial_len) ; 
1093+             } 
1094+             a = a. slice_move ( s ! [ s1,  s2] ) ; 
1095+             let  before_value = a. clone ( ) ; 
1096+             let  before_strides = a. strides ( ) . to_vec ( ) ; 
1097+             #[ cfg( feature = "std" ) ]  
1098+             println ! ( "{:?}, {}, {:?}" ,  a,  a. len( ) ,  a. data) ; 
1099+             a. shrink_to_fit ( ) ; 
1100+             #[ cfg( feature = "std" ) ]  
1101+             println ! ( "{:?}, {}, {:?}" ,  a,  a. len( ) ,  a. data) ; 
1102+ 
1103+             assert_eq ! ( before_value,  a) ; 
1104+             assert_eq ! ( before_strides,  a. strides( ) ) ; 
1105+ 
1106+             if  size_of :: < T > ( )  > 0  { 
1107+                 assert ! ( a. data. capacity( )  < initial_len) ; 
1108+                 assert ! ( a. data. capacity( )  >= a. len( ) ) ; 
1109+             } 
1110+             assert_eq ! ( a. data. capacity( ) ,  new_capacity) ; 
1111+         } 
1112+ 
1113+         let  a = Array :: from_iter ( 0 ..56 ) 
1114+             . into_shape_with_order ( ( 8 ,  7 ) ) 
1115+             . unwrap ( ) ; 
1116+         assert_shrink_before_after ( a,  Slice :: new ( 1 ,  Some ( -1 ) ,  1 ) ,  Slice :: new ( 0 ,  None ,  2 ) ,  42 ) ; 
1117+ 
1118+         let  a = Array :: from_iter ( 0 ..56 ) 
1119+             . into_shape_with_order ( ( 8 ,  7 ) ) 
1120+             . unwrap ( ) ; 
1121+         assert_shrink_before_after ( a,  Slice :: new ( 1 ,  Some ( -1 ) ,  -1 ) ,  Slice :: new ( 0 ,  None ,  -1 ) ,  42 ) ; 
1122+ 
1123+         let  a = Array :: from_iter ( 0 ..56 ) 
1124+             . into_shape_with_order ( ( 8 ,  7 ) ) 
1125+             . unwrap ( ) ; 
1126+         assert_shrink_before_after ( a,  Slice :: new ( 1 ,  Some ( 3 ) ,  1 ) ,  Slice :: new ( 1 ,  None ,  -2 ) ,  12 ) ; 
1127+ 
1128+         // empty but still has some allocation to allow offsetting along each stride 
1129+         let  a = Array :: from_iter ( 0 ..56 ) 
1130+             . into_shape_with_order ( ( 8 ,  7 ) ) 
1131+             . unwrap ( ) ; 
1132+         assert_shrink_before_after ( a,  Slice :: new ( 1 ,  Some ( 1 ) ,  1 ) ,  Slice :: new ( 1 ,  None ,  1 ) ,  6 ) ; 
1133+ 
1134+         // Test ZST 
1135+         let  a = Array :: from_iter ( ( 0 ..56 ) . map ( |_| ( ) ) ) 
1136+             . into_shape_with_order ( ( 8 ,  7 ) ) 
1137+             . unwrap ( ) ; 
1138+         assert_shrink_before_after ( a,  Slice :: new ( 1 ,  Some ( 3 ) ,  1 ) ,  Slice :: new ( 1 ,  None ,  -2 ) ,  usize:: MAX ) ; 
1139+     } 
1140+ } 
0 commit comments