{"id":33939522,"url":"https://github.com/liborty/indxvec","last_synced_at":"2025-12-12T15:34:09.451Z","repository":{"id":37299056,"uuid":"378631757","full_name":"liborty/indxvec","owner":"liborty","description":"Rust crate for efficient  sorting, merging, ranking, searching and reversing of generic vectors.","archived":false,"fork":false,"pushed_at":"2024-08-06T21:21:31.000Z","size":356,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-09-21T03:46:33.676Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/liborty.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-06-20T11:46:12.000Z","updated_at":"2024-08-28T16:36:27.000Z","dependencies_parsed_at":"2024-07-27T02:52:08.727Z","dependency_job_id":null,"html_url":"https://github.com/liborty/indxvec","commit_stats":{"total_commits":213,"total_committers":2,"mean_commits":106.5,"dds":"0.014084507042253502","last_synced_commit":"e4e58d941279bcf537e454a6549619ccf4bf8a6e"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/liborty/indxvec","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liborty%2Findxvec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liborty%2Findxvec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liborty%2Findxvec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liborty%2Findxvec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/liborty","download_url":"https://codeload.github.com/liborty/indxvec/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liborty%2Findxvec/sbom","scorecard":{"id":588040,"data":{"date":"2025-08-11","repo":{"name":"github.com/liborty/indxvec","commit":"731c20785ccfd5c37a8a3dab85d0985ed81e3653"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.4,"checks":[{"name":"Code-Review","score":0,"reason":"Found 2/25 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/test.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/liborty/indxvec/test.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/liborty/indxvec/test.yml/main?enable=pin","Info:   0 out of   1 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 7 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T21:06:04.773Z","repository_id":37299056,"created_at":"2025-08-20T21:06:04.773Z","updated_at":"2025-08-20T21:06:04.773Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27685519,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-12T02:00:06.775Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-12T15:34:05.350Z","updated_at":"2025-12-12T15:34:09.439Z","avatar_url":"https://github.com/liborty.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Indxvec [![crates.io](https://img.shields.io/crates/v/indxvec?logo=rust)](https://crates.io/crates/indxvec) [![crates.io](https://img.shields.io/crates/d/indxvec?logo=rust)](https://crates.io/crates/indxvec) [![GitHub last commit](https://img.shields.io/github/last-commit/liborty/indxvec/HEAD?logo=github)](https://github.com/liborty/indxvec) [![Actions Status](https://github.com/liborty/indxvec/workflows/test/badge.svg)](https://github.com/liborty/indxvec/actions)\n\nAuthor: Libor Spacek\n\n## Usage\n\nWritten using 100% safe Rust.\n\nThe following will import everything:\n\n```rust\nuse indxvec::{ here, qsortf64(), MinMax, Search, Indices, Vecops, Mutops, Printing, printing::* };\n```\n\n## Description\n\nVectors sorting, searching, indexing, ranking, merging, reversing, intersecting, printing, ..\n\n`Indxvec` is lightweight and has no dependencies. The methods of all traits can be functionally chained to achieve numerous manipulations of `Ranges`, `Vec`s, and their indices, in compact form.\n\nThe facilities provided are:\n\n* general binary search\n* ranking, sorting (merge sort and hash sort), merging, indexing, selecting, partitioning\n* many useful operations on generic vectors and their indices\n* set operations\n* serialising generic slices and slices of vectors to Strings: `to_plainstr()`\n* printing and writing generic slices and slices of vectors: `pvec()`, `wvec(\u0026mut f)`\n* coloured pretty printing (ANSI terminal output, mainly for testing)\n* macro `here!()` for more informative errors reporting\n\nIt is highly recommended to read and run [`tests/tests.rs`](https://github.com/liborty/indxvec/blob/main/tests/tests.rs) to learn from examples of usage therein. Use a single thread to run them to keep the output in the right order. It is necessary to run the timing benchmark `sorts()` on its own for meaningful results.\n\n```bash\ncargo test --release -- --test-threads=1 --nocapture\ncargo test sorts --release -- --nocapture\n```\n\nOr just clicking the above `test` badge leads to the logs of the automated test run.\n\n## Glossary\n\n* **Sort Index** - is a vec of subscripts to the data, such that the first subscript identifies the smallest item in the data, and so on (in ascending order). The data is unchanged. Suitable for bulky data that are not easily moved. It answers the question: 'what data item occupies a given sort position?'.\n\n* **Subspace Index** - lists the subscripts (dimensions) to be retained when projecting to a subspace.\n\n* **Reversing an index** - sort index can be reversed by generic reversal operation `revs()`, or `mutrevs()`. This has the effect of changing between ascending/descending sort orders without re-sorting or even reversing the (possibly bulky) actual data.\n\n* **Rank Index** - corresponds to the given data order, listing the sort positions (ranks) for the data items, e.g.the third entry in the rank index gives the rank of the third data item. Some statistical measures require ranks of data. It answers the question: 'what are the sort positions of the  data items?'.\n\n* **Inverting an index** - sort index and rank index are mutually inverse. Thus they can be easily switched by `invindex()`. This is usually the easiest way to obtain rank index. They will both be equal to `0..n` for data that is already in ascending order.\n\n* **Complement of an index** - beware that the standard reversal will not convert directly between ascending and descending ranks. This purpose is served by `complindex()`. Alternatively, descending ranks can be reconstructed by applying `invindex()` to a descending sort index.\n\n* **Selecting** - given a subspace index and some data vector, collects components of that vector corresponding to the dimensions present in the index and ignores the rest (i.e. it projects the data to the subspace defined by the index).\n\n* **Unindexing** - given an explicit sort index and some data, `unindex()` will pick the data in the new order defined by the sort index. It can be used to efficiently transform lots of data vectors into the same (fixed) order. For example: Suppose we have vectors: `keys` and `data_1,..data_n`, not explicitly joined together in some common data structure. The sort index obtained by e.g.: `let index = keys.hashsort_indexed();` can then be efficiently applied to sort the data vectors individually: `index.unindex(data_n,true)` (false to obtain a descending order at no extra cost).\n\n## Trait Search\n\nIs implemented for `RangeInclusive\u003cT\u003e`, specifying the range of search. Its binary search methods are not restricted to explicit data of any particular type. Probing of data is done by the comparator closure `cmpr`, which captures some data item from somewhere and a target and defines their comparison. Data subscripts are not limited to `usize`. The comparator specified in the call can be easily logically reversed, e.g. `|data_item,target| target.cmp(data_item)`. These methods will then work on data in implicit descending order.\n\n```rust\n/// Binary search algoritms implemented on RangeInclusive\u003cT\u003e.\n/// Using a closure `cmpr` to sample and compare data to captured target.\npub trait Search\u003cT\u003e {\n    /// Unchecked  Ok(first hit) or Err(insert order of a missing item).\n    fn binary_by(self, cmpr: impl FnMut(T) -\u003e Ordering) -\u003e Result \u003cT,T\u003e;\n    /// Unchecked first hit or insert order, and the final search range.\n    fn binary_any(\u0026self, cmpr: impl FnMut(T) -\u003e Ordering) -\u003e (T, Range\u003cT\u003e);\n    /// General Binary Search, returns the range of all matching items\n    fn binary_all(\u0026self, cmpr: impl FnMut(T)-\u003e Ordering) -\u003e Range\u003cT\u003e;\n}\n```\n\n**`binary_by`**\n\nBinary search within an inclusive range. When the target is missing, its insert position is returned as `Err\u003cT\u003e`.  \nSame as `std::slice::binary_search_by()` but is more general.\n\n**`binary_any`**\n\nfinds and returns the first hit and its last enclosing range. The returned range is used by `binary_all` to constrain its search for all matches. Also, `binary_any` can be used on its own when any matching item will do. For example, to iteratively solve non-linear equations, using range values of `f64` type (see [`tests/tests.rs`](https://github.com/liborty/indxvec/blob/main/tests/tests.rs)).\n\n**`binary_all`**\n\nBinary search that finds all the matches. This implementation is uniquely general. It is also very fast, especially over long ranges.\n\nSearches within the given `RangeInclusive\u003cT\u003e` (self). It can be used in functionally chained 'builder style APIs', that select the subrange closer bracketing the target.\n\nThe range values can be of any generic type T (satisfying the listed bounds), e.g. usize for indexing in-memory, u128 for searching whole disks or internet,\nf64 for solving equations...\n\nComparator closure `cmpr` is comparing data against a target captured from its environment.\nUsing closures enables custom comparisons of user's own data types. Also, this code is agnostic about the type of the target (and of the data)!\n\nWhen the target is in order before self.start, empty `self.start..self.start` range is returned.  \nWhen the target is in order after self.end, `self.end..self.end` is returned.  \nWhen the target is not found, then `ip..ip` is returned, where `ip` is its insert position.\n\nOtherwise the range of all consecutive values `PartiallyEqual` to the target is returned.\n\nThe first hit encountered will be anywhere within some unknown number of matching items. The algorithm then conducts two more binary searches in both directions away from the first hit. These secondary searches are applied only within the last (narrowest) range found during the main search. First non-matching items in both directions are found, giving the full enclosed matching range.\n\n## Trait `Indices`\n\n```rust\nuse indxvec::{Indices};\n```\n\nThe methods of this trait are implemented for slices of subscripts, i.e. they take the type `\u0026[usize]` as input (self) and produce new index `Vec\u003cusize\u003e`, new data vector `Vec\u003cT\u003e` or `Vec\u003cf64\u003e`, or other results, as appropriate. Please see the Glossary for descriptions of the indices and the operations on them.\n\n```rust\npub trait Indices {\n    /// Indices::newindex(n) creates a new index without rePartialOrdering\n    fn newindex(n: usize) -\u003e Vec\u003cusize\u003e {\n        Vec::from_iter(0..n)\n    }\n    /// Invert an index - turns a sort order into rank order and vice-versa\n    fn invindex(self) -\u003e Vec\u003cusize\u003e;\n    /// complement of an index - reverses the ranking order\n    fn complindex(self) -\u003e Vec\u003cusize\u003e;\n    /// Using a subspace index, projects `v`, into it. \n    fn select\u003cT:Clone\u003e(self, v: \u0026[T]) -\u003e Vec\u003cT\u003e;\n    /// Given a complete (sort) index, extracts indicated values from `v`\n    fn unindex\u003cT:Clone\u003e(self, v: \u0026[T], ascending: bool) -\u003e Vec\u003cT\u003e;\n    /// Correlation coefficient of two \u0026[usize] slices.\n    /// Pearsons on raw data, Spearman's when applied to ranks.\n    fn ucorrelation(self, v: \u0026[usize]) -\u003e f64;\n    /// Potentially useful clone-recast of \u0026[usize] to Vec\u003cf64\u003e\n    fn indx_to_f64(self) -\u003e Vec\u003cf64\u003e;\n}\n```\n\n## Trait Vecops\n\n```rust\nuse indxvec::Vecops;\n```\n\nThe methods of this trait are applicable to all generic slices `\u0026[T]` (the data). Thus they will work on all Rust primitive numeric end types, such as f64. They can also work on slices holding any arbitrarily complex end type `T`, as long as the often required traits, `Ord` and/or `Clone`, are  implemented for `T`. The methods are too numerous to list here, please see their declarations in `lib.rs` and their source in `vecops.rs`.\n\n## Trait Mutops\n\n```rust\nuse indxvec::Mutops;\n```\n\nThis trait contains mutable reverse and mutable sort methods. They all overwrite `self` with their outputs. When we do not need to preserve the original order, this is often the most efficient way to sort. Non-destructive versions are implemented in trait `Vecops`.\n\n### mutisort\n\nIt is often useful to avoid trait constrains on the end-type being sorted, such as `Ord` or  `Partial_Ord`. Such constraints are 'sticky' and have to be then applied everywhere.\nOur new `mutisort` (insert log sort) sidesteps these problems by taking a custom closure comparator. Its complexity is the best achievable for comparator sorts. It is almost as fast as the std provided sort, which eventually beats it only because it can take advantage of unstable Rust mem moves. Tested on floats, `mutisort` is actually faster up to the data length of about 4500. Additionally, `mutisort` allows sorting just within a specified range (sub-slice).\n\nThe comparator closure argument can be easily reversed to carry out descending sort.\n\nIts non destructive versions are `Vecops::isort_indexed`, which returns an explicit sort index and `Vcops::isort_refs()` which returns references `Vec\u003c\u0026T\u003e` in the sort order and is a bit faster. Neither of these two copies the potentially bulky end-types (the data items).\n\n```rust\n/// Mutable Operators on `\u0026mut[T]`\npub trait Mutops\u003cT\u003e {\n    /// Associated method `part` partitions `s: \u0026mut [\u0026T]` within range `rng`, using comparator `c`.  \n    /// Suitable pivot should be selected and placed in `s[rng.start]`.  \n    /// Returns the boundaries of the rearranged partitions, (eqstart,gtstart), where  \n    /// `rng.start..eqstart` (may be empty) contains references to items lesser than the pivot,  \n    /// `gtstart-eqstart` is the number (\u003e= 1) of items equal to the pivot (contains undefined references)  \n    /// `gtstart..rng.end` (may be empty) contains references to items greater than the pivot.\n    fn part(\n        s: \u0026mut [\u0026T],\n        rng: \u0026Range\u003cusize\u003e,\n        c: \u0026mut impl FnMut(\u0026T, \u0026T) -\u003e Ordering,\n    ) -\u003e (usize, usize) {\n        // get pivot from the first location\n        let pivot = s[rng.start];\n        let mut eqstart = rng.start;\n        let mut gtstart = eqstart + 1;\n        for t in rng.start + 1..rng.end {\n            match c(s[t], pivot) {\n                Less =\u003e {\n                    s[eqstart] = s[t];\n                    eqstart += 1;\n                    s[t] = s[gtstart];\n                    gtstart += 1;\n                }\n                Equal =\u003e {\n                    s[t] = s[gtstart];\n                    gtstart += 1;\n                }\n                Greater =\u003e (),\n            }\n        }\n        (eqstart, gtstart)\n    }\n\n    /// partitions by bitmask\n    fn part_binary(self, rng: \u0026Range\u003cusize\u003e, bitmask: u64) -\u003e usize\n    where\n        T: Copy, u64: From\u003cT\u003e;\n    /// mutable reversal of \u0026mut[T]\n    fn mutrevs(self);\n    /// swaps two indexed items into ascending order\n    fn mutsorttwo(self, i0: usize, i1: usize) -\u003e bool\n    where\n        T: PartialOrd;\n    /// mutably sorts three indexed items into ascending order\n    fn mutsortthree(self, i0: usize, i1: usize, i2: usize)\n    where\n        T: PartialOrd;\n    /// Possibly the fastest sort for long lists. Wrapper for `muthashsortslice`.\n    fn muthashsort(self, quantify: impl Copy + Fn(\u0026T) -\u003e f64)\n    where\n        T: PartialOrd + Clone;\n    /// Sorts n items from i in self. Used by muthashsort.\n    fn muthashsortslice(\n        self,\n        i: usize,\n        n: usize,\n        min: f64,\n        max: f64,\n        quantify: impl Copy + Fn(\u0026T) -\u003e f64,\n    ) where\n        T: PartialOrd + Clone;\n    /// Mutable insert logsort. Pass in reversed comparator `c` for descending sort\n    fn mutisort\u003cF\u003e(self, rng: Range\u003cusize\u003e, c: F)\n    where\n        T: Copy,\n        F: Fn(\u0026T, \u0026T) -\u003e Ordering;\n}\n```\n\n## Trait `Printing`\n\n```rust\nuse indxvec::Printing;    // the trait methods\nuse indxvec::printing::*; // the ANSI colour constants\n```\n\nSee `tests/tests.rs` for examples of usage.\n\nSuitable for printing or writing to files up to 4-tuples of differing type items, all kinds of Vecs and slices and irregularly shaped 2D matrices.\n\nSerializes tuples: `\u0026(T,U)`, `\u0026(T,U,V)`, `\u0026(T,U,V,W)`  \nand slices: `\u0026[T]`, `\u0026[\u0026[T]]`, `\u0026[Vec\u003cT\u003e]`.\n\nAdditionally, `wvec` writes contents of self as plain space separated values (`.ssv`) to File, possibly raising io::Error(s):\n\n```rust\nfn wvec(self,f:\u0026mut File) -\u003e Result\u003c(), io::Error\u003e where Self: Sized;\n```\n\nSimilarly, `pvec` prints to `stdout`:\n\n```rust\nfn pvec(self) where Self: Sized;\n```\n\nAll above listed types are converted to Strings and optionally decorated and coloured. Included are methods and constants to render the resulting String in six primary bold ANSI terminal colours.\n\nNote that all these types are unprintable in standard Rust (they do not have `Display` implemented). Which is a big stumbling block for beginners. The methods of this trait convert all these types to printable (writeable) strings.\n\nThe colouring methods add the relevant colouring to the string output. This makes testing output much prettier and avoids reliance on Debug mode in production code. For finer control of the colouring, import the colour constants from  `printing::*` and use them in formatting strings manually. For example, switching colours:\n\n```rust  \nuse indxvec::printing::*; // ANSI colours constants\nprintln!(\"{GR}green text, {RD}red warning, {BL}feeling blue{UN}\");\n```\n\nNote that all of these colouring interpolations set their own new colour regardless of the previous settings. Interpolating `{UN}` resets the terminal to its default foreground rendering.\n`UN` is automatically appended at the end of strings produced by the colouring methods `rd()..cy()`. Be careful to always close with one of these, or explicit `{UN}`. Otherwise all the following output will continue with the last selected colour foreground rendering!\n\nExample from `tests/tests.rs`:\n\n```rust\nprintln!(\"Memsearch for {BL}{midval}{UN}, found at: {}\", \n    vm.memsearch(midval)\n    .map_or_else(||\"None\".rd(),|x| x.gr())\n);\n```\n\n`memsearch` returns `Option(None)`, when `midval` is not found in `vm`. Here, `None` will be printed in red, while any found item will be printed in green. Since x has been converted to `String` by `.gr()`, both closures return the same types, as required by `map_or_else`.\n\n## Struct and Utility Functions\n\n```rust\nuse indxvec::{MinMax,here};\n```\n\n* `pub struct Minmax` holds minimum and maximum values of a `Vec` and their indices.\n* `here!()` is a macro giving the filename, line number and function name of the place from where it was invoked. It can be interpolated into any error/tracing messages and reports.\n* `qsortf64()` applies `sort_unstable_by()` to a mutable slice of f64s safely, using `total_cmp()`.\n\n## Release Notes (Latest First)\n\n**Version 1.9.5** Added `best_k_indexed` and `subspace` to `Vecops`, to construct a `subspace index`. Added `select` to Indices to apply `subspace index` to a data vector, projecting it efficiently to that subspace.\n\n**Version 1.9.1** Stopped Trait Printing consuming single items by implementing it for `\u0026T` rather than `T`.\n\n**Version 1.9.0** Fn closure argument in trait Search changed to FnMut on user request. Added method `partbinary` to trait Mutops\n\n**Version 1.8.9** Added associated function `part` to trait `Mutops` (call it as: `\u003c\u0026mut [T]\u003e::part(s, \u0026rng, c)`).  \nAdded method `ref_vec` and associated function `deref_vec` to trait `Vecops`.\n\n**Version 1.8.8** Upgraded to `ran 2.0`.\n\n**Version 1.8.7** Improved `isort_refs()` and `isort_indexed`.\n\n**Version 1.8.6** Added `isort_refs()` suitable for bulky end-types. Added `best_k`, possibly the fastest way to extract and sort k greatest or smallest items (by custom comparator).\n\n**Version 1.8.5** Added new algorithm 'insert log sort': `mutisort()` and `isort_indexed()` to `Mutops` and `Vecops` traits respectively. Also to `tests.rs`.\n\n**Version 1.8.4** Added `binary_by()` to trait `Search`. It behaves like  `std::slice::binary_search_by()` but is more general, not expecting explicit data of any particular type. Nor is the indexing limited to `usize`.\n\n**Version 1.8.3** Added `\u0026str` argument to macro `here(msg:\u0026str)` to incorporate payload error messages. Changed `ierror` to `idx_error`. It now returns `Result` (Err variant), that can be more conveniently processed upstream with just the `?` operator.  It is not really used in the code yet, so this improvement should be backwards compatible.\nExample: `return idx_error(\"size\",here!(\"my specific further message\"))?` will do all the necessary IdxError reporting for the `Size` variant, plus output the custom message with file, line location and method name.\n\n**Version 1.8.2** Some minor tidying up and additions to tests. Upped dependencies.\n\n**Version 1.8.1** Added function `qsortf64()` which sorts safely f64s.\n\n**Version 1.8.0** Changed trait of closure arguments from `\u0026mut FnMut(\u0026T)` to `Fn(T)`, which is adequate and simpler.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fliborty%2Findxvec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fliborty%2Findxvec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fliborty%2Findxvec/lists"}