indxvec/lib.rs
1#![warn(missing_docs)]
2//! Vecs searching, indexing, ranking, sorting, merging, reversing, intersecting, printing, etc.
3
4/// Implementation of trait Indices for `&[usize]`
5pub mod indices;
6/// Implementation of trait Mutops for `&mut[T]`
7pub mod mutops;
8/// Utilities for serializing, writing and printing (optionally in colours) generic vectors.
9pub mod printing;
10/// Implementation of trait Search for Range<T>
11pub mod search;
12/// Implementation of trait Vecops for `&[T]`
13pub mod vecops;
14
15use core::{
16 cmp::{Ordering, Ordering::*, Reverse},
17 ops::Range
18};
19use printing::*;
20use std::{collections::BinaryHeap, fs::File, io, io::Write};
21
22/// Macro `here!("message")` gives `&str` with the `file:line path::function-name` of where it was invoked,
23/// followed by the passed "message" - useful for informative errors
24#[macro_export]
25macro_rules! here {
26 ($msg:expr) => {{
27 fn f() {}
28 fn type_name_of<T>(_: T) -> &'static str {
29 std::any::type_name::<T>()
30 }
31 let name = type_name_of(f);
32 format!(
33 "\n{}:{} {} - {}",
34 file!(),
35 line!(),
36 &name[..name.len() - 3],
37 $msg
38 )
39 }};
40}
41
42/// struct for minimum value, its index, maximum value, its index
43#[derive(Default)]
44pub struct MinMax<T> {
45 /// Minimum value
46 pub min: T,
47 /// Subscript (index) of the minimum
48 pub minindex: usize,
49 /// Maximum value
50 pub max: T,
51 /// Subscript (index) of the maximum
52 pub maxindex: usize,
53}
54
55/// Display implementation for MinMax struct
56impl<T> std::fmt::Display for MinMax<T>
57where
58 T: Clone + std::fmt::Display,
59{
60 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
61 write!(
62 f,
63 "min: {GR}{}{UN}, minindex: {YL}{}{UN}, max: {GR}{}{UN}, maxindex: {YL}{}{UN}",
64 self.min, self.minindex, self.max, self.maxindex
65 )
66 }
67}
68
69/// function to sort f64s
70pub fn qsortf64(v: &mut [f64]) {
71 v.sort_unstable_by(|a, b| a.total_cmp(b))
72}
73
74/// Trait to serialize tuples `&(T,T)` and `&(T,T,T)` and
75/// slices `&[T]`, `&[&[T]]`, `&[Vec<T>]`.
76/// Suitable for printing or writing to files pairs, triplets,
77/// all kinds of Vecs and slices and irregularly shaped 2D matrices.
78/// All are converted into Strings and optionally decorated and coloured.
79/// Included are methods and constants to render the resulting String
80/// in six primary bold ANSI terminal colours.
81pub trait Printing<T>
82where
83 Self: Sized,
84{
85 /// Printable in red
86 fn rd(self) -> String {
87 format!("{RD}{}{UN}", self.to_str())
88 }
89 /// Printable in green
90 fn gr(self) -> String {
91 format!("{GR}{}{UN}", self.to_str())
92 }
93 /// Printable in blue
94 fn bl(self) -> String {
95 format!("{BL}{}{UN}", self.to_str())
96 }
97 /// Printable in yellow
98 fn yl(self) -> String {
99 format!("{YL}{}{UN}", self.to_str())
100 }
101 /// Printable in magenta
102 fn mg(self) -> String {
103 format!("{MG}{}{UN}", self.to_str())
104 }
105 /// Printable in cyan
106 fn cy(self) -> String {
107 format!("{CY}{}{UN}", self.to_str())
108 }
109
110 /// Method to write vector(s) to file f (space separated, no brackets).
111 /// Passes up io errors
112 fn wvec(self, f: &mut File) -> Result<(), io::Error> {
113 Ok(write!(*f, "{} ", self.to_plainstr())?)
114 }
115
116 /// Method to print vector(s) to stdout (space separated, no brackets).
117 fn pvec(self) {
118 print!("{} ", self.to_plainstr())
119 }
120
121 /// Method to serialize.
122 /// Decorates Vecs with square brackets and tuples with round ones.
123 /// Implementation code is in `printing.rs`.
124 fn to_str(self) -> String;
125
126 /// Method to serialize in minimal form (space separated, no brackets)
127 /// Implementation code is in `printing.rs`.
128 fn to_plainstr(self) -> String;
129}
130
131/// Binary search algoritms implemented on RangeInclusive<T>.
132/// Using a closure `cmpr` to sample and compare data to captured target.
133pub trait Search<T> {
134 /// Unchecked first Ok(hit) or Err(insert order for a missing item).
135 fn binary_by(self, cmpr: impl FnMut(T) -> Ordering) -> Result<T, T>;
136 /// Unchecked first hit or insert order, and the final search range.
137 fn binary_any(&self, cmpr: impl FnMut(T) -> Ordering) -> (T, Range<T>);
138 /// General Binary Search, returns the range of all matching items
139 fn binary_all(&self, cmpr: impl FnMut(T) -> Ordering) -> Range<T>;
140}
141
142/// Methods to manipulate and apply indices of `Vec<usize>` type.
143pub trait Indices {
144 /// Indices::newindex(n) creates a new index without rePartialOrdering
145 fn newindex(n: usize) -> Vec<usize> {
146 Vec::from_iter(0..n)
147 }
148 /// Invert an index - turns a sort order into rank order and vice-versa
149 fn invindex(self) -> Vec<usize>;
150 /// complement of an index - reverses the ranking order
151 fn complindex(self) -> Vec<usize>;
152 /// Using a subspace index, projects `v`, into it.
153 fn select<T:Clone>(self, v: &[T]) -> Vec<T>;
154 /// Given a complete (sort) index, extracts indicated values from `v`
155 fn unindex<T:Clone>(self, v: &[T], ascending: bool) -> Vec<T>;
156 /// Correlation coefficient of two &[usize] slices.
157 /// Pearsons on raw data, Spearman's when applied to ranks.
158 fn ucorrelation(self, v: &[usize]) -> f64;
159 /// Potentially useful clone-recast of &[usize] to Vec<f64>
160 fn indx_to_f64(self) -> Vec<f64>;
161}
162
163/// Methods to manipulate generic Vecs and slices of type `&[T]`
164pub trait Vecops<'a, T> {
165 /// Builds Vec<T> from refs in Vec<&T> (inverse of ref_vec())
166 fn deref_vec(v: &[&T], rng: Range<usize>) -> Vec<T>
167 where
168 T: Clone,
169 {
170 v.iter()
171 .take(rng.end)
172 .skip(rng.start)
173 .map(|&x| x.clone())
174 .collect()
175 }
176 /// Constructs ref wrapped `Vec<&T>` from `&[T] in rng`
177 fn ref_vec(self, rng: Range<usize>) -> Vec<&'a T>;
178 /// Helper function to copy and cast entire &[T] to `Vec<f64>`.
179 fn tof64(self) -> Vec<f64>
180 where
181 T: Clone,
182 f64: From<T>;
183 /// Maximum value in self
184 fn maxt(self) -> T
185 where
186 T: PartialOrd + Clone;
187 /// Minimum value in self
188 fn mint(self) -> T
189 where
190 T: PartialOrd + Clone;
191 /// Minimum and maximum values in self
192 fn minmaxt(self) -> (T, T)
193 where
194 T: PartialOrd + Clone;
195 /// Returns MinMax{min, minindex, max, maxindex}
196 fn minmax(self) -> MinMax<T>
197 where
198 T: PartialOrd + Clone;
199 /// MinMax of n items starting at subscript i
200 fn minmax_slice(self, i: usize, n: usize) -> MinMax<T>
201 where
202 T: PartialOrd + Clone;
203 /// MinMax of a subset of self, defined by its idx subslice between i,i+n.
204 fn minmax_indexed(self, idx: &[usize], i: usize, n: usize) -> MinMax<T>
205 where
206 T: PartialOrd + Clone;
207 /// Reversed copy of self
208 fn revs(self) -> Vec<T>
209 where
210 T: Clone;
211 /// Repeated items removed
212 fn sansrepeat(self) -> Vec<T>
213 where
214 T: PartialEq + Clone;
215 /// Some(subscript) of the first occurence of m, or None
216 fn member(self, m: T, forward: bool) -> Option<usize>
217 where
218 T: PartialEq + Clone;
219 /// Counts partially equal occurrences of val by simple linear search of an unPartialOrdered set
220 fn occurs(self, val: T) -> usize
221 where
222 T: PartialOrd;
223 /// Unites (concatenates) two unsorted slices. For union of sorted slices, use `merge`
224 fn unite_unsorted(self, v: &[T]) -> Vec<T>
225 where
226 T: Clone;
227 /// Unites two ascending index-sorted slices.
228 fn unite_indexed(self, ix1: &[usize], v2: &[T], ix2: &[usize]) -> Vec<T>
229 where
230 T: PartialOrd + Clone;
231 /// Intersects two ascending explicitly sorted generic vectors.
232 fn intersect(self, v2: &[T]) -> Vec<T>
233 where
234 T: PartialOrd + Clone;
235 /// Intersects two ascending index sorted vectors.
236 fn intersect_indexed(self, ix1: &[usize], v2: &[T], ix2: &[usize]) -> Vec<T>
237 where
238 T: PartialOrd + Clone;
239 /// Removes items of sorted v2 from sorted self.
240 fn diff(self, v2: &[T]) -> Vec<T>
241 where
242 T: PartialOrd + Clone;
243 /// Removes items of v2 from self using their sort indices.
244 fn diff_indexed(self, ix1: &[usize], v2: &[T], ix2: &[usize]) -> Vec<T>
245 where
246 T: PartialOrd + Clone;
247 /// Divides an unordered set into three: items smaller than pivot, equal, and greater
248 fn partition(self, pivot: &T) -> (Vec<T>, Vec<T>, Vec<T>)
249 where
250 T: PartialOrd + Clone;
251 /// Divides an unordered set into three by the pivot. The results are subscripts to self
252 fn partition_indexed(self, pivot: &T) -> (Vec<usize>, Vec<usize>, Vec<usize>)
253 where
254 T: PartialOrd + Clone;
255 /// Binary Search. Automatic descending PartialOrder detection.
256 fn binsearch(self, target: &T) -> Range<usize>
257 where
258 T: PartialOrd + Copy;
259 /// Binary Search via index. Automatic descending PartialOrder detection
260 fn binsearch_indexed(self, idx: &[usize], target: &T) -> Range<usize>
261 where
262 T: PartialOrd + Copy;
263 /// Merges (unites) two sorted sets, result is also sorted
264 fn merge(self, v2: &[T]) -> Vec<T>
265 where
266 T: PartialOrd + Clone;
267 /// Merges (unites) two sets, using their sort indices, giving also the resulting sort index
268 fn merge_indexed(self, idx1: &[usize], v2: &[T], idx2: &[usize]) -> (Vec<T>, Vec<usize>)
269 where
270 T: PartialOrd + Clone;
271 /// Used by `merge_indexed`
272 fn merge_indices(self, idx1: &[usize], idx2: &[usize]) -> Vec<usize>
273 where
274 T: PartialOrd + Clone;
275 /// Stable Merge sort main method, giving sort index
276 fn mergesort_indexed(self) -> Vec<usize>
277 where
278 T: PartialOrd + Clone;
279 /// Utility used by mergesort_indexed
280 fn mergesortslice(self, i: usize, n: usize) -> Vec<usize>
281 where
282 T: PartialOrd + Clone;
283 /// Stable Merge sort, explicitly sorted result obtained via mergesort_indexed
284 fn sortm(self, ascending: bool) -> Vec<T>
285 where
286 T: PartialOrd + Clone;
287 /// Rank index obtained via mergesort_indexed
288 fn rank(self, ascending: bool) -> Vec<usize>
289 where
290 T: PartialOrd + Clone;
291 /// Utility, swaps any two items into ascending order
292 fn isorttwo(self, idx: &mut [usize], i0: usize, i1: usize)
293 where
294 T: PartialOrd;
295 /// Utility, sorts any three items into ascending order
296 fn isortthree(self, idx: &mut [usize], i0: usize, i1: usize, i2: usize)
297 where
298 T: PartialOrd;
299 /// Stable hash sort giving sort index
300 fn hashsort_indexed(self, quantify: impl Copy + Fn(&T) -> f64) -> Vec<usize>
301 where
302 T: PartialOrd + Clone;
303 /// Utility used by hashsort_indexed
304 fn hashsortslice(
305 self,
306 idx: &mut [usize],
307 i: usize,
308 n: usize,
309 min: f64,
310 max: f64,
311 quantify: impl Copy + Fn(&T) -> f64,
312 ) where
313 T: PartialOrd + Clone;
314 /// Stable hash sort. Returns new sorted data vector (ascending or descending)
315 fn sorth(self, quantify: impl Copy + Fn(&T) -> f64, ascending: bool) -> Vec<T>
316 where
317 T: PartialOrd + Clone;
318 /// Heap of k smallest items in no particular order, except the first one is maximum.
319 /// Best for finding just the one k-ranked item
320 fn smallest_k(&self, k: usize) -> BinaryHeap<&T>
321 where
322 T: Ord;
323 /// Heap of k biggest items in no particular order, except the first one is minimum
324 /// Best for finding just the one k complement ranked item (k-th from the end).
325 fn biggest_k(&self, k: usize) -> BinaryHeap<Reverse<&T>>
326 where
327 T: Ord;
328 /// Insert logsort, returns sort index. Reverse `c` for descending order
329 fn isort_indexed<F>(self, rng: Range<usize>, c: F) -> Vec<usize>
330 where
331 F: Fn(&T, &T) -> Ordering;
332 /// Insert logsort of refs (within range). Suitable for bulky end-types.
333 /// Faster than `isort_indexed`, as it does not construct an explicit index.
334 fn isort_refs<F>(self, rng: Range<usize>, c: F) -> Vec<&'a T>
335 where
336 F: Fn(&T, &T) -> Ordering;
337 /// First k sorted items from rng (ascending or descending, depending on `c`)
338 /// Faster than `smallest/biggest_k, followed by `.to_sorted_vec()`.
339 fn best_k<F>(self, k: usize, rng: Range<usize>, c: F) -> Vec<&'a T>
340 where
341 F: Fn(&T, &T) -> Ordering;
342 /// Sort index of the `best` k items in rng (ascending or descending, depending on `c`)
343 fn best_k_indexed<F>(self, k: usize, rng: Range<usize>, c: F) -> Vec<usize>
344 where
345 F: Fn(&T, &T) -> Ordering;
346 /// Unsorted index of the `best` k items in rng (ascending or descending, depending on `c`)
347 fn best_k_unsorted<F>(self, k: usize, rng: Range<usize>, c: F) -> Vec<usize>
348 where
349 F: Fn(&T, &T) -> Ordering;
350 /// Subspace index: sorted subscripts of only the sufficiently ranking values.
351 fn subspace<F>(self, rank:usize, c:F) -> Vec<usize>
352 where
353 F: Fn(&T, &T) -> Ordering;
354}
355
356/// Mutable Operators on `&mut[T]`
357pub trait Mutops<T> {
358 /// Associated method `part` partitions `s: &mut [&T]` within range `rng`, using comparator `c`.
359 /// Suitable pivot should be selected and placed in `s[rng.start]`.
360 /// Returns the boundaries of the rearranged partitions, (eqstart,gtstart), where
361 /// `rng.start..eqstart` (may be empty) contains references to items lesser than the pivot,
362 /// `gtstart-eqstart` is the number (>= 1) of items equal to the pivot (contains undefined references)
363 /// `gtstart..rng.end` (may be empty) contains references to items greater than the pivot.
364 fn part(
365 s: &mut [&T],
366 rng: &Range<usize>,
367 c: &mut impl FnMut(&T, &T) -> Ordering,
368 ) -> (usize, usize) {
369 // get pivot from the first location
370 let pivot = s[rng.start];
371 let mut eqstart = rng.start;
372 let mut gtstart = eqstart + 1;
373 for t in rng.start + 1..rng.end {
374 match c(s[t], pivot) {
375 Less => {
376 s[eqstart] = s[t];
377 eqstart += 1;
378 s[t] = s[gtstart];
379 gtstart += 1;
380 }
381 Equal => {
382 s[t] = s[gtstart];
383 gtstart += 1;
384 }
385 Greater => (),
386 }
387 }
388 (eqstart, gtstart)
389 }
390
391 /// partitions by bitmask
392 fn part_binary(self, rng: &Range<usize>, bitmask: u64) -> usize
393 where
394 T: Copy, u64: From<T>;
395 /// mutable reversal, general utility
396 fn mutrevs(self);
397 /// utility that mutably swaps two indexed items into ascending order
398 fn mutsorttwo(self, i0: usize, i1: usize) -> bool
399 where
400 T: PartialOrd;
401 /// utility that mutably bubble sorts three indexed items into ascending order
402 fn mutsortthree(self, i0: usize, i1: usize, i2: usize)
403 where
404 T: PartialOrd;
405 /// Possibly the fastest sort for long lists. Wrapper for `muthashsortslice`.
406 fn muthashsort(self, quantify: impl Copy + Fn(&T) -> f64)
407 where
408 T: PartialOrd + Clone;
409 /// Sorts n items from i in self. Used by muthashsort.
410 fn muthashsortslice(
411 self,
412 i: usize,
413 n: usize,
414 min: f64,
415 max: f64,
416 quantify: impl Copy + Fn(&T) -> f64,
417 ) where
418 T: PartialOrd + Clone;
419 /// Mutable insert logsort. Pass in reversed comparator `c` for descending sort
420 fn mutisort<F>(self, rng: Range<usize>, c: F)
421 where
422 T: Copy,
423 F: Fn(&T, &T) -> Ordering;
424}