#![cfg_attr(feature = "nightly", feature(ptr_offset_from))]
#![cfg_attr(feature = "nightly", feature(test))]
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
#[cfg(all(not(test), not(feature = "std")))]
extern crate core as std;
macro_rules! binary_group {
(struct $name:ident, $elem:ty) => {
impl<'a, T: 'a> $name<'a, T> {
#[inline]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline]
pub fn remainder_len(&self) -> usize {
self.0.remainder_len()
}
}
impl<'a, T: 'a> Iterator for $name<'a, T>
where T: PartialEq,
{
type Item = $elem;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
fn last(mut self) -> Option<Self::Item> {
self.0.next_back()
}
}
impl<'a, T: 'a> DoubleEndedIterator for $name<'a, T>
where T: PartialEq,
{
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back()
}
}
impl<'a, T: 'a> FusedIterator for $name<'a, T>
where T: PartialEq,
{ }
}
}
mod linear_group_by;
mod binary_group_by;
mod exponential_group_by;
use std::cmp::{self, Ordering};
pub use self::linear_group_by::{
LinearGroupBy,
LinearGroup,
LinearGroupByMut,
LinearGroupMut,
};
pub use self::binary_group_by::{
BinaryGroupBy,
BinaryGroup,
BinaryGroupByMut,
BinaryGroupMut,
};
pub use self::exponential_group_by::{
ExponentialGroupBy,
ExponentialGroup,
ExponentialGroupByMut,
ExponentialGroupMut,
};
#[cfg(feature = "nightly")]
#[inline]
unsafe fn offset_from<T>(to: *const T, from: *const T) -> usize {
to.offset_from(from) as usize
}
#[cfg(not(feature = "nightly"))]
#[inline]
unsafe fn offset_from<T>(to: *const T, from: *const T) -> usize {
use std::mem;
(to as usize - from as usize) / mem::size_of::<T>()
}
#[inline]
pub fn exponential_search<T>(slice: &[T], elem: &T) -> Result<usize, usize>
where T: Ord
{
exponential_search_by(slice, |x| x.cmp(elem))
}
#[inline]
pub fn exponential_search_by<T, F>(slice: &[T], mut f: F) -> Result<usize, usize>
where F: FnMut(&T) -> Ordering,
{
let mut index = 1;
while index < slice.len() && f(&slice[index]) == Ordering::Less {
index *= 2;
}
let half_bound = index / 2;
let bound = cmp::min(index + 1, slice.len());
match slice[half_bound..bound].binary_search_by(f) {
Ok(pos) => Ok(half_bound + pos),
Err(pos) => Err(half_bound + pos),
}
}
#[inline]
pub fn exponential_search_by_key<T, B, F>(slice: &[T], b: &B, mut f: F) -> Result<usize, usize>
where F: FnMut(&T) -> B,
B: Ord
{
exponential_search_by(slice, |k| f(k).cmp(b))
}
pub trait GroupBy<T> {
fn linear_group_by<P>(&self, predicate: P) -> LinearGroupBy<T, P>
where P: FnMut(&T, &T) -> bool;
fn linear_group(&self) -> LinearGroup<T>
where T: PartialEq;
fn binary_group_by<P>(&self, predicate: P) -> BinaryGroupBy<T, P>
where P: FnMut(&T, &T) -> bool;
fn binary_group(&self) -> BinaryGroup<T>
where T: PartialEq;
fn exponential_group_by<P>(&self, predicate: P) -> ExponentialGroupBy<T, P>
where P: FnMut(&T, &T) -> bool;
fn exponential_group(&self) -> ExponentialGroup<T>
where T: PartialEq;
}
pub trait GroupByMut<T>
{
fn linear_group_by_mut<P>(&mut self, predicate: P) -> LinearGroupByMut<T, P>
where P: FnMut(&T, &T) -> bool;
fn linear_group_mut(&mut self) -> LinearGroupMut<T>
where T: PartialEq;
fn binary_group_by_mut<P>(&mut self, predicate: P) -> BinaryGroupByMut<T, P>
where P: FnMut(&T, &T) -> bool;
fn binary_group_mut(&mut self) -> BinaryGroupMut<T>
where T: PartialEq;
fn exponential_group_by_mut<P>(&mut self, predicate: P) -> ExponentialGroupByMut<T, P>
where P: FnMut(&T, &T) -> bool;
fn exponential_group_mut(&mut self) -> ExponentialGroupMut<T>
where T: PartialEq;
}
impl<T> GroupBy<T> for [T]
{
fn linear_group_by<P>(&self, predicate: P) -> LinearGroupBy<T, P>
where P: FnMut(&T, &T) -> bool,
{
LinearGroupBy::new(self, predicate)
}
fn linear_group(&self) -> LinearGroup<T>
where T: PartialEq,
{
LinearGroup::new(self)
}
fn binary_group_by<P>(&self, predicate: P) -> BinaryGroupBy<T, P>
where P: FnMut(&T, &T) -> bool,
{
BinaryGroupBy::new(self, predicate)
}
fn binary_group(&self) -> BinaryGroup<T>
where T: PartialEq,
{
BinaryGroup::new(self)
}
fn exponential_group_by<P>(&self, predicate: P) -> ExponentialGroupBy<T, P>
where P: FnMut(&T, &T) -> bool,
{
ExponentialGroupBy::new(self, predicate)
}
fn exponential_group(&self) -> ExponentialGroup<T>
where T: PartialEq,
{
ExponentialGroup::new(self)
}
}
impl<T> GroupByMut<T> for [T]
{
fn linear_group_by_mut<P>(&mut self, predicate: P) -> LinearGroupByMut<T, P>
where P: FnMut(&T, &T) -> bool,
{
LinearGroupByMut::new(self, predicate)
}
fn linear_group_mut(&mut self) -> LinearGroupMut<T>
where T: PartialEq,
{
LinearGroupMut::new(self)
}
fn binary_group_by_mut<P>(&mut self, predicate: P) -> BinaryGroupByMut<T, P>
where P: FnMut(&T, &T) -> bool,
{
BinaryGroupByMut::new(self, predicate)
}
fn binary_group_mut(&mut self) -> BinaryGroupMut<T>
where T: PartialEq,
{
BinaryGroupMut::new(self)
}
fn exponential_group_by_mut<P>(&mut self, predicate: P) -> ExponentialGroupByMut<T, P>
where P: FnMut(&T, &T) -> bool,
{
ExponentialGroupByMut::new(self, predicate)
}
fn exponential_group_mut(&mut self) -> ExponentialGroupMut<T>
where T: PartialEq,
{
ExponentialGroupMut::new(self)
}
}