blob: 2fbf22e64b08cb1748da2800774fa2298d2ca196 [file] [log] [blame]
// Copyright 2017 Alkis Evlogimenos
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This crate provides extensions for [`slice`]s.
//!
//! # Examples
//!
//! ```
//! use superslice::*;
//!
//! let b = [1, 3];
//!
//! assert_eq!(b.lower_bound(&1), 0);
//!
//! assert_eq!(b.upper_bound(&1), 1);
//!
//! assert_eq!(b.equal_range(&3), 1..2);
//! ```
//!
//! [`slice`]: https://doc.rust-lang.org/stable/std/primitive.slice.html
use std::cmp::Ordering::{self, Less, Greater};
/// Extends [`slice`] with fast operations on ordered slices.
///
/// [`slice`]: https://doc.rust-lang.org/stable/std/primitive.slice.html
pub trait Ext {
type Item;
/// Returns the index `i` pointing to the first element in the ordered slice
/// that is _not less_ than `x`.
///
/// The slice MUST be ordered by the order defined by its elements.
///
/// # Example:
///
/// ```
/// # use superslice::*;
/// let a = [10, 11, 13, 13, 15];
/// assert_eq!(a.lower_bound(&9), 0);
/// assert_eq!(a.lower_bound(&10), 0);
/// assert_eq!(a.lower_bound(&11), 1);
/// assert_eq!(a.lower_bound(&12), 2);
/// assert_eq!(a.lower_bound(&13), 2);
/// assert_eq!(a.lower_bound(&14), 4);
/// assert_eq!(a.lower_bound(&15), 4);
/// assert_eq!(a.lower_bound(&16), 5);
/// ```
fn lower_bound(&self, x: &Self::Item) -> usize
where
Self::Item: Ord;
/// Returns the index `i` pointing to the first element in the ordered slice
/// for which `f(self[i]) != Less`.
///
/// The slice MUST be ordered by the order defined by the comparator
/// function. The comparator function should take an element and return
/// `Ordering` that is consistent with the ordering of the slice.
///
/// # Example:
///
/// ```
/// # use superslice::*;
/// let b = [1, 2, 3, 6, 9, 9];
/// assert_eq!(b.lower_bound(&3), b.lower_bound_by(|x| x.cmp(&3)));
/// ```
fn lower_bound_by<'a, F>(&'a self, f: F) -> usize
where
F: FnMut(&'a Self::Item) -> Ordering;
/// Returns the index `i` pointing to the first element in the ordered slice
/// for which `f(self[i]) >= k`.
///
/// The slice MUST be ordered by the order defined by the keys of its
/// elements.
///
/// # Example:
///
/// ```
/// # use superslice::*;
/// let b = [1, 2, 3, 6, 9, 9];
/// assert_eq!(b.lower_bound(&3), b.lower_bound_by_key(&6, |x| x * 2));
/// ```
fn lower_bound_by_key<'a, K, F>(&'a self, k: &K, f: F) -> usize
where
F: FnMut(&'a Self::Item) -> K,
K: Ord;
/// Returns the index `i` pointing to the first element in the ordered slice
/// that is _greater_ than `x`.
///
/// The slice MUST be ordered by the order defined by its elements.
///
/// # Example:
///
/// ```
/// # use superslice::*;
/// let a = [10, 11, 13, 13, 15];
/// assert_eq!(a.upper_bound(&9), 0);
/// assert_eq!(a.upper_bound(&10), 1);
/// assert_eq!(a.upper_bound(&11), 2);
/// assert_eq!(a.upper_bound(&12), 2);
/// assert_eq!(a.upper_bound(&13), 4);
/// assert_eq!(a.upper_bound(&14), 4);
/// assert_eq!(a.upper_bound(&15), 5);
/// assert_eq!(a.upper_bound(&16), 5);
/// ```
fn upper_bound(&self, x: &Self::Item) -> usize
where
Self::Item: Ord;
/// Returns the index `i` pointing to the first element in the ordered slice
/// for which `f(self[i]) == Greater`.
///
/// The slice MUST be ordered by the order defined by the comparator
/// function. The comparator function should take an element and return
/// `Ordering` that is consistent with the ordering of the slice.
///
/// # Example:
///
/// ```
/// # use superslice::*;
/// let b = [1, 2, 3, 6, 9, 9];
/// assert_eq!(b.upper_bound(&3), b.upper_bound_by(|x| x.cmp(&3)));
/// ```
fn upper_bound_by<'a, F>(&'a self, f: F) -> usize
where
F: FnMut(&'a Self::Item) -> Ordering;
/// Returns the index `i` pointing to the first element in the ordered slice
/// for which `f(self[i]) > k`.
///
/// The slice MUST be ordered by the order defined by the keys of its
/// elements.
///
/// # Example:
///
/// ```
/// # use superslice::*;
/// let b = [1, 2, 3, 6, 9, 9];
/// assert_eq!(b.lower_bound(&3), b.lower_bound_by_key(&6, |x| x * 2));
fn upper_bound_by_key<'a, K, F>(&'a self, k: &K, f: F) -> usize
where
F: FnMut(&'a Self::Item) -> K,
K: Ord;
/// Returns the [`Range`] `a..b` such that all elements in `self[a..b]` are
/// _equal_ to `x`.
///
/// The slice MUST be ordered by the order defined by its elements.
///
/// # Example:
///
/// ```
/// # use superslice::*;
/// let b = [10, 11, 13, 13, 15];
/// for i in 9..17 {
/// assert_eq!(b.equal_range(&i), (b.lower_bound(&i)..b.upper_bound(&i)));
/// }
/// ```
/// [`Range`]: https://doc.rust-lang.org/stable/std/ops/struct.Range.html
fn equal_range(&self, x: &Self::Item) -> std::ops::Range<usize>
where
Self::Item: Ord;
/// Returns the [`Range`] `a..b` such that for all elements `e` in `self[a..b]`
/// `f(e) == Equal`.
///
/// The slice MUST be ordered by the order defined by the comparator
/// function. The comparator function should take an element and return
/// `Ordering` that is consistent with the ordering of the slice.
///
/// # Example:
///
/// ```
/// # use superslice::*;
/// let b = [10, 11, 13, 13, 15];
/// for i in 9..17 {
/// assert_eq!(b.equal_range(&i), b.equal_range_by(|x| x.cmp(&i)));
/// }
/// ```
/// [`Range`]: https://doc.rust-lang.org/stable/std/ops/struct.Range.html
fn equal_range_by<'a, F>(&'a self, f: F) -> std::ops::Range<usize>
where
F: FnMut(&'a Self::Item) -> Ordering;
/// Returns the [`Range`] `a..b` such that for all elements `e` in `self[a..b]`
/// `f(e) == k`.
///
/// The slice MUST be ordered by the order defined by the keys of its
/// elements.
///
/// # Example:
///
/// ```
/// # use superslice::*;
/// let b = [10, 11, 13, 13, 15];
/// for i in 9..17 {
/// let i2 = i * 2;
/// assert_eq!(b.equal_range(&i), b.equal_range_by_key(&i2, |x| x * 2));
/// }
/// ```
/// [`Range`]: https://doc.rust-lang.org/stable/std/ops/struct.Range.html
fn equal_range_by_key<'a, K, F>(&'a self, k: &K, f: F) -> std::ops::Range<usize>
where
F: FnMut(&'a Self::Item) -> K,
K: Ord;
/// Transforms the slice into the next permutation from the set of all
/// permutations that are lexicographically ordered with respect to the
/// natural order of T. Returns true if such permutation exists, otherwise
/// transforms the range into the first permutation and returns false.
///
/// # Example:
///
/// ```
/// # use superslice::*;
/// let mut b = [2, 1, 3];
/// let mut v = Vec::new();
/// for _ in 0..6 {
/// let x = b.next_permutation();
/// v.push((x, b.to_vec()));
/// }
/// assert_eq!(v, &[(true, [2, 3, 1].to_vec()),
/// (true, [3, 1, 2].to_vec()),
/// (true, [3, 2, 1].to_vec()),
/// (false, [1, 2, 3].to_vec()),
/// (true, [1, 3, 2].to_vec()),
/// (true, [2, 1, 3].to_vec())]);
fn next_permutation(&mut self) -> bool
where
Self::Item: Ord;
/// Transforms the slice into the previous permutation from the set of all
/// permutations that are lexicographically ordered with respect to the
/// natural order of T. Returns true if such permutation exists, otherwise
/// transforms the range into the last permutation and returns false.
///
/// # Example:
///
/// ```
/// # use superslice::*;
/// let mut b = [2, 1, 3];
/// let mut v = Vec::new();
/// for _ in 0..6 {
/// let x = b.prev_permutation();
/// v.push((x, b.to_vec()));
/// }
/// assert_eq!(v, &[(true, [1, 3, 2].to_vec()),
/// (true, [1, 2, 3].to_vec()),
/// (false, [3, 2, 1].to_vec()),
/// (true, [3, 1, 2].to_vec()),
/// (true, [2, 3, 1].to_vec()),
/// (true, [2, 1, 3].to_vec())]);
fn prev_permutation(&mut self) -> bool
where
Self::Item: Ord;
/// Applies `permutation` to the slice. For each element at index `i` the
/// following holds:
///
/// new_self[i] == old_self[permutation[i]]
///
/// The transformation happens in O(N) time and O(1) space. `permutation`
/// is mutated during the transformation but it is restored to its original
/// state on return.
///
/// # Panics
///
/// This function panics if `self` and `permutation` do not have the same
/// length or any value in `permutation` is not in `0..self.len()`.
///
/// # Example:
///
/// ```
/// # use superslice::*;
/// let mut b = ['d', 'a', 'c', 'b'];
/// let mut p = [1, 3, 2, 0];
/// b.apply_permutation(&mut p);
/// assert_eq!(b, ['a', 'b', 'c', 'd']);
/// assert_eq!(p, [1, 3, 2, 0]);
fn apply_permutation(&mut self, permutation: &mut [isize]);
/// Applies the inverse of `permutation` to the slice. For each element at
/// index `i` the following holds:
///
/// new_self[permutation[i]] == old_self[i]
///
/// The transformation happens in O(N) time and O(1) space. `permutation`
/// is mutated during the transformation but it is restored to its original
/// state on return.
///
/// # Panics
///
/// This function panics if `self` and `permutation` do not have the same
/// length or any value in `permutation` is not in `0..self.len()`.
///
/// # Example:
///
/// ```
/// # use superslice::*;
/// let mut b = ['d', 'a', 'c', 'b'];
/// let mut p = [3, 0, 2, 1];
/// b.apply_inverse_permutation(&mut p);
/// assert_eq!(b, ['a', 'b', 'c', 'd']);
/// assert_eq!(p, [3, 0, 2, 1]);
fn apply_inverse_permutation(&mut self, permutation: &mut [isize]);
}
impl<T> Ext for [T] {
type Item = T;
fn lower_bound(&self, x: &Self::Item) -> usize
where
T: Ord,
{
self.lower_bound_by(|y| y.cmp(x))
}
fn lower_bound_by<'a, F>(&'a self, mut f: F) -> usize
where
F: FnMut(&'a Self::Item) -> Ordering,
{
let s = self;
let mut size = s.len();
if size == 0 {
return 0;
}
let mut base = 0usize;
while size > 1 {
let half = size / 2;
let mid = base + half;
let cmp = f(unsafe { s.get_unchecked(mid) });
base = if cmp == Less { mid } else { base };
size -= half;
}
let cmp = f(unsafe { s.get_unchecked(base) });
base + (cmp == Less) as usize
}
fn lower_bound_by_key<'a, K, F>(&'a self, k: &K, mut f: F) -> usize
where
F: FnMut(&'a Self::Item) -> K,
K: Ord,
{
self.lower_bound_by(|e| f(e).cmp(k))
}
fn upper_bound(&self, x: &Self::Item) -> usize
where
T: Ord,
{
self.upper_bound_by(|y| y.cmp(x))
}
fn upper_bound_by<'a, F>(&'a self, mut f: F) -> usize
where
F: FnMut(&'a Self::Item) -> Ordering,
{
let s = self;
let mut size = s.len();
if size == 0 {
return 0;
}
let mut base = 0usize;
while size > 1 {
let half = size / 2;
let mid = base + half;
let cmp = f(unsafe { s.get_unchecked(mid) });
base = if cmp == Greater { base } else { mid };
size -= half;
}
let cmp = f(unsafe { s.get_unchecked(base) });
base + (cmp != Greater) as usize
}
fn upper_bound_by_key<'a, K, F>(&'a self, k: &K, mut f: F) -> usize
where
F: FnMut(&'a Self::Item) -> K,
K: Ord,
{
self.upper_bound_by(|e| f(e).cmp(k))
}
fn equal_range(&self, x: &Self::Item) -> std::ops::Range<usize>
where
T: Ord,
{
self.equal_range_by(|y| y.cmp(x))
}
fn equal_range_by<'a, F>(&'a self, mut f: F) -> std::ops::Range<usize>
where
F: FnMut(&'a Self::Item) -> Ordering,
{
let s = self;
let mut size = s.len();
if size == 0 {
return 0..0;
}
let mut base = (0usize, 0usize);
while size > 1 {
let half = size / 2;
let mid = (base.0 + half, base.1 + half);
let cmp = (
f(unsafe { s.get_unchecked(mid.0) }),
f(unsafe { s.get_unchecked(mid.1) }),
);
base = (
if cmp.0 == Less { mid.0 } else { base.0 },
if cmp.1 == Greater { base.1 } else { mid.1 },
);
size -= half;
}
let cmp = (
f(unsafe { s.get_unchecked(base.0) }),
f(unsafe { s.get_unchecked(base.1) }),
);
(base.0 + (cmp.0 == Less) as usize..base.1 + (cmp.1 != Greater) as usize)
}
fn equal_range_by_key<'a, K, F>(&'a self, k: &K, mut f: F) -> std::ops::Range<usize>
where
F: FnMut(&'a Self::Item) -> K,
K: Ord,
{
self.equal_range_by(|e| f(e).cmp(k))
}
fn next_permutation(&mut self) -> bool
where
Self::Item: Ord
{
// Adapted from http://en.cppreference.com/w/cpp/algorithm/next_permutation.
if self.len() <= 1 { return false; }
let last = self.len() - 1;
let mut a = last;
loop {
let mut b = a;
a -= 1;
if self[a] < self[b] {
b = last;
while self[a] >= self[b] {
b -= 1;
}
self.swap(a, b);
self[a+1..].reverse();
return true;
}
if a == 0 {
self.reverse();
return false;
}
}
}
fn prev_permutation(&mut self) -> bool
where
Self::Item: Ord
{
// Adapted from http://en.cppreference.com/w/cpp/algorithm/prev_permutation.
if self.len() <= 1 { return false; }
let last = self.len() - 1;
let mut a = last;
loop {
let mut b = a;
a -= 1;
if self[b] < self[a] {
b = last;
while self[b] >= self[a] {
b -= 1;
}
self.swap(a, b);
self[a+1..].reverse();
return true;
}
if a == 0 {
self.reverse();
return false;
}
}
}
fn apply_permutation(&mut self, perm: &mut [isize]) {
assert_eq!(self.len(), perm.len());
assert!(self.len() < isize::max_value() as usize);
for i in 0..self.len() as isize {
let mut c = perm[i as usize];
if c < 0 {
perm[i as usize] = !c;
} else if i != c {
loop {
let n = perm[c as usize];
self.swap(c as usize, n as usize);
perm[c as usize] = !n;
c = n;
if i == c { break; }
}
}
}
}
fn apply_inverse_permutation(&mut self, perm: &mut [isize]) {
assert_eq!(self.len(), perm.len());
assert!(self.len() < isize::max_value() as usize);
for i in 0..self.len() as isize {
let mut c = perm[i as usize];
if c < 0 {
perm[i as usize] = !c;
} else if i != c {
loop {
self.swap(c as usize, i as usize);
let n = perm[c as usize];
perm[c as usize] = !n;
c = n;
if i == c { break; }
}
}
}
}
}
pub trait Ext2 {
/// Transforms the slice in the inverse permutation.
///
/// # Panics
///
/// This function panics if any value in `self` is not in `0..self.len()`.
///
/// # Example:
///
/// ```
/// # use superslice::*;
/// let mut p = [1, 3, 2, 0];
/// p.invert_permutation();
/// assert_eq!(p, [3, 0, 2, 1]);
fn invert_permutation(&mut self);
}
impl Ext2 for [isize] {
fn invert_permutation(&mut self) {
assert!(self.len() < isize::max_value() as usize);
for i in 0..self.len() as isize {
let mut c = self[i as usize];
if c < 0 {
self[i as usize] = !c;
} else if i != c {
let mut n = i;
loop {
let t = self[c as usize];
self[c as usize] = !n;
n = c;
c = t;
if c == i {
self[i as usize] = n;
break;
}
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::Ext;
#[test]
fn lower_bound() {
let b: [u32; 0] = [];
assert_eq!(b.lower_bound(&0), 0);
let b = [1, 3, 3, 5];
assert_eq!(b.lower_bound(&0), 0);
assert_eq!(b.lower_bound(&1), 0);
assert_eq!(b.lower_bound(&2), 1);
assert_eq!(b.lower_bound(&3), 1);
assert_eq!(b.lower_bound(&4), 3);
assert_eq!(b.lower_bound(&5), 3);
assert_eq!(b.lower_bound(&6), 4);
}
#[test]
fn upper_bound() {
let b: [u32; 0] = [];
assert_eq!(b.upper_bound(&0), 0);
let b = [1, 3, 3, 5];
assert_eq!(b.upper_bound(&0), 0);
assert_eq!(b.upper_bound(&1), 1);
assert_eq!(b.upper_bound(&2), 1);
assert_eq!(b.upper_bound(&3), 3);
assert_eq!(b.upper_bound(&4), 3);
assert_eq!(b.upper_bound(&5), 4);
assert_eq!(b.upper_bound(&6), 4);
}
#[test]
fn equal_range() {
let b: [u32; 0] = [];
assert_eq!(b.equal_range(&0), 0..0);
let b = [1, 3, 3, 5];
assert_eq!(b.equal_range(&0), 0..0);
assert_eq!(b.equal_range(&1), 0..1);
assert_eq!(b.equal_range(&2), 1..1);
assert_eq!(b.equal_range(&3), 1..3);
assert_eq!(b.equal_range(&4), 3..3);
assert_eq!(b.equal_range(&5), 3..4);
assert_eq!(b.equal_range(&6), 4..4);
}
}