#![cfg_attr(feature = "cargo-clippy", allow(float_cmp, match_wild_err_arm))]
extern crate ord_subset;
extern crate core;
use ord_subset::OrdSubsetIterExt;
use ord_subset::OrdSubsetSliceExt;
use ord_subset::OrdSubset;
use ord_subset::OrdVar;
use std::f64::INFINITY as INF;
use std::f64::NAN;
const N: usize = 32;
const N_NO_NAN: usize = 30;
const TEST_ARRAY: [f64; N] =
[1.0, 7.0, 26.0, INF, NAN, 0.0, 14.0, 17.0,
27.0, 13.0, 10.0, 3.0, NAN, 25.0, 9.0, 20.0,
16.0, 8.0, -INF, 4.0, 2.0, 22.0, 18.0, 21.0,
15.0, 6.0, 24.0, 19.0, 12.0, 11.0, 5.0, 23.0];
const TEST_ARRAY_NO_NAN: [f64; N_NO_NAN] =
[1.0, 7.0, 26.0, INF, 0.0, 14.0, 17.0,
27.0, 13.0, 10.0, 3.0, 25.0, 9.0, 20.0,
16.0, 8.0, -INF, 4.0, 2.0, 22.0, 18.0, 21.0,
15.0, 6.0, 24.0, 19.0, 12.0, 11.0, 5.0, 23.0];
const SORTED_TEST_ARRAY: [f64; N] =
[-INF, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0,
7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0,
15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0,
23.0, 24.0, 25.0, 26.0, 27.0, INF, NAN, NAN];
const SORTED_TEST_ARRAY_NO_NAN: [f64; N_NO_NAN] =
[-INF, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0,
7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0,
15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0,
23.0, 24.0, 25.0, 26.0, 27.0, INF ];
#[derive(PartialEq, PartialOrd, Clone, Copy)]
struct NotOrdSub();
#[derive(PartialEq, PartialOrd, Clone, Copy)]
struct OrdSub();
impl OrdSubset for OrdSub {
fn is_outside_order(&self) -> bool {
true
}
}
#[test]
fn ord_subset_max() {
let arr = [2.0, 3.0, 5.0, std::f64::NAN];
let max = arr.iter().ord_subset_max().unwrap();
assert_eq!(&5.0, max);
}
#[test]
fn ord_subset_max_by() {
let arr = [2.0, 3.0, 5.0, std::f64::NAN];
let max_by = arr.iter().ord_subset_max_by_key(|num| num.recip()).unwrap();
assert_eq!(&2.0, max_by);
}
#[test]
fn ord_subset_min() {
let arr = [2.0, 3.0, 5.0, std::f64::NAN];
let min = arr.iter().ord_subset_min().unwrap();
assert_eq!(&2.0, min);
}
#[test]
fn ord_subset_min_by() {
let arr = [2.0, 3.0, 5.0, std::f64::NAN];
let min_by = arr.iter().ord_subset_min_by_key(|num| num.recip()).unwrap();
assert_eq!(&5.0, min_by);
}
#[allow(unused)]
fn ord_subset_min_or_max_by_key() {
let array: [NotOrdSub; 0] = [];
array.iter().ord_subset_min_by_key(|_| 0.0);
array.iter().ord_subset_max_by_key(|_| 0.0);
}
#[test]
#[cfg(feature="std")]
fn sort() {
let mut array = TEST_ARRAY;
array.ord_subset_sort();
assert_eq!(&array[0..N_NO_NAN], &SORTED_TEST_ARRAY_NO_NAN);
}
#[test]
#[cfg(feature="std")]
fn sort_rev() {
let mut array = TEST_ARRAY;
array.ord_subset_sort_rev();
let mut rev_sorted_array = SORTED_TEST_ARRAY_NO_NAN;
rev_sorted_array.reverse();
assert_eq!(&array[0..N_NO_NAN], &rev_sorted_array);
}
#[test]
#[cfg(feature="std")]
fn sort_by_key() {
fn key_function(el: &f64) -> f64 {
(el - 13.0).recip()
}
let mut array = TEST_ARRAY;
array.ord_subset_sort_by_key(key_function);
let mut std_sorted_array = TEST_ARRAY_NO_NAN;
std_sorted_array.sort_by_key(|num| OrdVar::new(key_function(num)));
assert_eq!(&array[..N_NO_NAN], &std_sorted_array);
}
#[test]
fn sort_unstable() {
let mut array = TEST_ARRAY;
array.ord_subset_sort_unstable();
assert_eq!(&array[0..N_NO_NAN], &SORTED_TEST_ARRAY_NO_NAN);
}
#[test]
fn sort_unstable_rev() {
let mut array = TEST_ARRAY;
array.ord_subset_sort_unstable_rev();
let mut rev_sorted_array = SORTED_TEST_ARRAY_NO_NAN;
rev_sorted_array.reverse();
assert_eq!(&array[0..N_NO_NAN], &rev_sorted_array);
}
#[test]
fn sort_unstable_by_key() {
fn key_function(el: &f64) -> f64 {
(el - 13.0).recip()
}
let mut array = TEST_ARRAY;
array.ord_subset_sort_unstable_by_key(key_function);
let mut std_sorted_array = TEST_ARRAY_NO_NAN;
std_sorted_array.sort_unstable_by_key(|num| OrdVar::new(key_function(num)));
assert_eq!(&array[..N_NO_NAN], &std_sorted_array);
}
#[test]
fn binary_search() {
let array = SORTED_TEST_ARRAY;
for (i, num) in array.iter().enumerate().take(N_NO_NAN) {
assert_eq!(array.ord_subset_binary_search(num), Ok(i));
}
}
#[test]
fn binary_search_rev() {
let mut array = TEST_ARRAY;
array.ord_subset_sort_unstable_rev();
for (i, num) in array.iter().enumerate().take(N_NO_NAN) {
assert_eq!(array.ord_subset_binary_search_rev(num), Ok(i));
}
}
#[test]
fn binary_search_by_key() {
fn key_function(el: &f64) -> f64 {
(el - 13.0).recip()
}
let mut array = TEST_ARRAY;
array.ord_subset_sort_unstable_by_key(key_function);
for num in array.iter().take(N_NO_NAN) {
let key = key_function(num);
match array.ord_subset_binary_search_by_key(&key, key_function) {
Err(_) => panic!("Did not find correct location of element"),
Ok(pos) => assert_eq!(key_function(&array[pos]), key),
}
}
}
#[test]
fn binary_search_err() {
let array = SORTED_TEST_ARRAY;
for (i, num) in array.iter()
.enumerate()
.filter(|&(_, num)| num.is_finite())
{
let new_num = num + 0.5;
assert_eq!(array.ord_subset_binary_search(&new_num), Err(i+1));
}
}
#[test]
fn binary_search_rev_err() {
let mut array = TEST_ARRAY;
array.ord_subset_sort_unstable_rev();
for (i, num) in array.iter()
.enumerate()
.filter(|&(_, num)| num.is_finite())
{
let new_num = num + 0.5;
assert_eq!(array.ord_subset_binary_search_rev(&new_num), Err(i));
}
}
#[test]
fn binary_search_by_key_err() {
fn key_function(el: &f64) -> f64 {
(el - 13.0).recip()
}
let mut array = TEST_ARRAY;
array.ord_subset_sort_unstable_by_key(key_function);
for num in array.iter().take(N_NO_NAN) {
let key_diff = key_function(&(num+0.01))*1.01 + 0.01;
let pos = array.ord_subset_binary_search_by_key(&key_diff, key_function);
let pos_std = (&array[..N_NO_NAN]).binary_search_by_key(
&OrdVar::new(key_diff),
|num| OrdVar::new(key_function(num))
);
match (pos, pos_std) {
(Err(pos), Err(pos_std)) => assert!(pos == pos_std),
_ => panic!("Inconsistency between this library's and std's binary_search_by_key"),
}
}
}
#[allow(unused)]
fn ord_subset_slice_ext_impl_test() {
fn foo<T: OrdSubsetSliceExt<U> + AsRef<[U]>, U: OrdSubset + Clone>(as_slice: T) {
let element: &U = as_slice.as_ref().first().unwrap();
as_slice.ord_subset_binary_search(element);
as_slice.ord_subset_binary_search_rev(element);
as_slice.ord_subset_binary_search_by_key(element, |_| element.clone());
as_slice.ord_subset_binary_search_by(|_| std::cmp::Ordering::Equal);
}
let mut vec: Vec<OrdSub> = vec![];
let mut arr: [OrdSub; 0] = [];
foo(&vec);
foo(&mut vec);
foo(&arr);
foo(&mut arr);
foo(&arr[..]);
foo(&mut arr[..]);
foo(&&arr[..]);
foo(&mut &mut arr[..]);
foo(& &mut arr[..]);
foo(vec);
foo(arr);
}
#[allow(unused)]
fn ord_subset_mut_slice_ext_impl_test() {
fn sortable<T, U>(mut as_slice: T)
where T: OrdSubsetSliceExt<U> + AsMut<[U]>,
U: OrdSubset,
{
#[cfg(feature="std")]
as_slice.ord_subset_sort();
#[cfg(feature="std")]
as_slice.ord_subset_sort_rev();
#[cfg(feature="std")]
as_slice.ord_subset_sort_by(|_, _| core::cmp::Ordering::Equal);
#[cfg(feature="std")]
as_slice.ord_subset_sort_by_key(|_| 0.0);
as_slice.ord_subset_sort_unstable();
as_slice.ord_subset_sort_unstable_rev();
as_slice.ord_subset_sort_unstable_by(|_, _| core::cmp::Ordering::Equal);
as_slice.ord_subset_sort_unstable_by_key(|_| 0.0);
}
let mut vec: Vec<OrdSub> = vec![];
let mut arr: [OrdSub; 0] = [];
sortable(&mut vec);
sortable(&mut arr);
sortable(&mut arr[..]);
sortable(&mut &mut arr[..]);
sortable(vec);
sortable(arr);
}
#[allow(unused)]
fn non_ord_subset_slice_ext_impl_test() {
fn foo<T: OrdSubsetSliceExt<U> + AsRef<[U]>, U>(as_slice: T) {
let key = OrdSub();
as_slice.ord_subset_binary_search_by_key(&key, |_| key);
}
let mut vec: Vec<NotOrdSub> = vec![];
let mut arr: [NotOrdSub; 0] = [];
foo(&vec);
foo(&mut vec);
foo(&arr);
foo(&mut arr);
foo(&arr[..]);
foo(&mut arr[..]);
foo(&&arr[..]);
foo(&mut &mut arr[..]);
foo(& &mut arr[..]);
foo(vec);
foo(arr);
}
#[allow(unused)]
fn non_ord_subset_mut_slice_ext_impl_test() {
fn sortable<T, U>(mut as_slice: T)
where T: OrdSubsetSliceExt<U> + AsMut<[U]>,
{
let key = OrdSub();
#[cfg(feature="std")]
as_slice.ord_subset_sort_by_key(|_| key);
as_slice.ord_subset_sort_unstable_by_key(|_| key);
}
let mut vec: Vec<NotOrdSub> = vec![];
let mut arr: [NotOrdSub; 0] = [];
sortable(&mut vec);
sortable(&mut arr);
sortable(&mut arr[..]);
sortable(&mut &mut arr[..]);
sortable(vec);
sortable(arr);
}
#[test]
fn binary_search_lifetime() {
#[derive(Debug)]
struct Foo {
property: f32,
}
let xs = vec![
Foo { property: 1. },
Foo { property: 2. },
Foo { property: 3. },
];
let _r = xs.ord_subset_binary_search_by_key(&2., |entry| entry.property);
}
#[cfg(feature="ops")]
use core::ops::{Add, Sub, Mul, Div, Rem,
Neg, AddAssign, SubAssign, MulAssign, DivAssign, RemAssign,
};
#[test]
#[cfg(feature="ops")]
fn ops_correctness_test() {
let infix_ops = [
Add::add, Sub::sub, Mul::mul, Div::div, Rem::rem,
];
let unary_ops = [
Neg::neg,
];
let assign_ops = [
AddAssign::add_assign, SubAssign::sub_assign, MulAssign::mul_assign, DivAssign::div_assign, RemAssign::rem_assign,
];
let infix_ops_ordvar = [
Add::add, Sub::sub, Mul::mul, Div::div, Rem::rem,
];
let unary_ops_ordvar = [
Neg::neg,
];
let assign_ops_ordvar = [
AddAssign::add_assign, SubAssign::sub_assign, MulAssign::mul_assign, DivAssign::div_assign, RemAssign::rem_assign,
];
let nums = (-10..0).chain(1..11i32).map(|n| n as f64).collect::<Vec<_>>();
let combinations = nums.iter().flat_map(|&n1| nums.iter().map(move |&n2| (n1, n2)));
for (num1, num2) in combinations {
for (op, op_ordvar) in infix_ops.iter().zip(infix_ops_ordvar.iter()) {
let res = op(num1, num2);
let res2 = op_ordvar(OrdVar::new(num1), num2);
assert!(res == res2.into_inner())
}
for (op, op_ordvar) in unary_ops.iter().zip(unary_ops_ordvar.iter()) {
let res = op(num1);
let res2 = op_ordvar(OrdVar::new(num1));
assert!(res == res2.into_inner())
}
for (op, op_ordvar) in assign_ops.iter().zip(assign_ops_ordvar.iter()) {
let mut num1 = num1;
let mut ordvar = OrdVar::new(num1);
op(&mut num1, num2);
op_ordvar(&mut ordvar, num2);
assert!(num1 == ordvar.into_inner())
}
}
}