use crate::math::general::NumTools;
use std::{intrinsics::transmute, fmt::Debug, ops::{*}, convert::TryFrom};
use core::mem::*;
const BITWISE_ERR1: &str = "Arguments were not the same size in memory. Consider casting the smaller argument.";
const BITWISE_ERR2: &str = "U is bigger than T. Consider reversing the arguments.";
const MANTISSA_MASK_64: u64 = 0b0000000000001111111111111111111111111111111111111111111111111111;
const EXPONENT_MASK_64: u64 = 0b0111111111110000000000000000000000000000000000000000000000000000;
const SET_EXP_ZERO_MASK_64: u64 = 0b0011111111110000000000000000000000000000000000000000000000000000;
const GET_SMANTISSA_MASK_64: u64 = 0b1000000000001111111111111111111111111111111111111111111111111111;
const MANTISSA_MASK_32: u32 = 0b00000000011111111111111111111111;
const EXPONENT_MASK_32: u32 = 0b01111111100000000000000000000000;
const SET_EXP_ZERO_MASK_32: u32 = 0b00111111100000000000000000000000;
const GET_SMANTISSA_MASK_32: u32 = 0b10000000011111111111111111111111;
pub trait SliceOps<T> {
#[must_use]
fn peek(&self) -> T;
fn swap_top(&mut self);
#[must_use]
fn count_of(&self, item: T) -> usize;
#[must_use]
fn positions_of(&self, item: T) -> Vec<usize>;
#[must_use]
fn position_of(&self, t: T) -> Option<usize>;
}
pub trait BitwiseSlice<T, U> {
#[must_use = "This returns the result of the operation, without modifying the original."]
fn xor_with(&self, other: &[U]) -> Vec<T>;
#[must_use = "This returns the result of the operation, without modifying the original."]
fn or_with(&self, other: &[U]) -> Vec<T>;
#[must_use = "This returns the result of the operation, without modifying the original."]
fn and_with(&self, other: &[U]) -> Vec<T>;
}
pub trait BinaryInsert<T> {
fn binary_insert(&mut self, value: T);
fn binary_insert_no_dup(&mut self, value: T);
}
pub trait CharTools {
#[must_use]
fn is_open_bracket(&self) -> bool;
#[must_use]
fn is_closed_bracket(&self) -> bool;
#[must_use]
fn get_opening_bracket(&self) -> Option<char>;
#[must_use]
fn get_closing_bracket(&self) -> Option<char>;
}
pub trait FloatMagic {
type Mantissa;
type Exponent;
type RealExponent;
#[must_use = "This returns the result of the operation, without modifying the original."]
fn raw_mantissa(&self) -> Self::Mantissa;
#[must_use = "This returns the result of the operation, without modifying the original."]
fn raw_exponent(&self) -> Self::Exponent;
#[must_use = "This returns the result of the operation, without modifying the original."]
fn real_mantissa(&self) -> Self;
#[must_use = "This returns the result of the operation, without modifying the original."]
fn real_exponent(&self) -> Self::RealExponent;
#[must_use = "This returns the result of the operation, without modifying the original."]
fn raw_decompose(&self) -> (u8, Self::Exponent, Self::Mantissa);
#[must_use = "This returns the result of the operation, without modifying the original."]
fn real_decompose(&self) -> (u8, Self::RealExponent, Self);
#[must_use]
fn raw_compose(sign: u8, exponent: Self::Exponent, mantissa: Self::Mantissa) -> Self;
}
impl CharTools for char {
#[inline]
fn is_open_bracket(&self) -> bool {
match self {
'(' | '{' | '[' => { true }
_ => { false }
}
}
#[inline]
fn is_closed_bracket(&self) -> bool {
match self {
')' | '}' | ']' => { true }
_ => { false }
}
}
#[inline]
fn get_closing_bracket(&self) -> Option<char> {
match self {
'(' => { Some(')') }
'{' => { Some('}') }
'[' => { Some(']') }
_ => { None }
}
}
#[inline]
fn get_opening_bracket(&self) -> Option<char> {
match self {
')' => { Some('(') }
']' => { Some('[') }
'}' => { Some('{') }
_ => { None }
}
}
}
impl FloatMagic for f32 {
type Mantissa = u32;
type Exponent = u8;
type RealExponent = i16;
#[inline]
fn raw_mantissa(&self) -> Self::Mantissa {
(unsafe { transmute::<f32, u32>(*self) }) & MANTISSA_MASK_32
}
#[inline]
fn raw_exponent(&self) -> Self::Exponent {
((unsafe { transmute::<f32, u32>(*self) } &
EXPONENT_MASK_32) >> 23) as u8
}
#[inline]
fn real_mantissa(&self) -> Self {
unsafe { transmute(transmute::<f32, u32>(*self) &
GET_SMANTISSA_MASK_32 |
SET_EXP_ZERO_MASK_32)
}
}
#[inline]
fn real_exponent(&self) -> Self::RealExponent {
self.raw_exponent() as i16 - 127
}
#[inline]
fn raw_decompose(&self) -> (u8, Self::Exponent, Self::Mantissa) {
(self.is_sign_negative() as u8, self.raw_exponent(), self.raw_mantissa())
}
#[inline]
fn real_decompose(&self) -> (u8, Self::RealExponent, Self) {
(self.is_sign_negative() as u8, self.real_exponent(), self.real_mantissa())
}
#[inline]
fn raw_compose(sign: u8, exponent: Self::Exponent, mantissa: Self::Mantissa) -> Self {
if sign > 1 { panic!("A sign bigger than 1 is not allowed."); }
if mantissa > 8388607 { panic!("A mantissa bigger than 8388607 is not allowed."); }
unsafe { transmute((mantissa |
((exponent as u32) << 23)) |
(sign as u32) << 31) }
}
}
impl FloatMagic for f64 {
type Mantissa = u64;
type Exponent = u16;
type RealExponent = i32;
#[inline]
fn raw_mantissa(&self) -> Self::Mantissa {
(unsafe { transmute::<f64, u64>(*self) } &
MANTISSA_MASK_64)
}
#[inline]
fn raw_exponent(&self) -> Self::Exponent {
((unsafe { transmute::<f64, u64>(*self) } &
EXPONENT_MASK_64) >> 52) as u16
}
#[inline]
fn real_mantissa(&self) -> Self {
unsafe { transmute(transmute::<f64, u64>(*self) &
GET_SMANTISSA_MASK_64 |
SET_EXP_ZERO_MASK_64)
}
}
#[inline]
fn real_exponent(&self) -> Self::RealExponent {
self.raw_exponent() as i32 - 1023
}
#[inline]
fn raw_decompose(&self) -> (u8, Self::Exponent, Self::Mantissa) {
(self.is_sign_negative() as u8, self.raw_exponent(), self.raw_mantissa())
}
#[inline]
fn real_decompose(&self) -> (u8, Self::RealExponent, Self) {
(self.is_sign_negative() as u8, self.real_exponent(), self.real_mantissa())
}
#[inline]
fn raw_compose(sign: u8, exponent: Self::Exponent, mantissa: Self::Mantissa) -> Self {
if sign > 1 { panic!("A sign bigger than 1 is not allowed."); }
if exponent > 2047 { panic!("An exponent bigger than 2047 is not allowed."); }
if mantissa > 4503599627370000 { panic!("A mantissa bigger than 4503599627370000 is not allowed."); }
unsafe { transmute((mantissa |
((exponent as u64) << 52)) |
(sign as u64) << 63) }
}
}
impl<T: Ord + Copy> BinaryInsert<T> for Vec<T> {
fn binary_insert(&mut self, value: T) {
match self.binary_search(&value) {
Ok(pos) => self.insert(pos + 1, value),
Err(pos) => self.insert(pos, value),
}
}
fn binary_insert_no_dup(&mut self, value: T) {
match self.binary_search(&value) {
Ok(_) => { },
Err(pos) => self.insert(pos, value),
}
}
}
impl<T: BitXorAssign +
From<u8> +
From<U> +
Clone +
BitOrAssign +
BitAndAssign +
Shl<Output = T> +
Debug,
U: Clone +
Copy +
Debug +
Shl<Output = U> +
From<u8>>
BitwiseSlice<T, U> for [T]
where
<T as TryFrom<U>>::Error: Debug {
fn xor_with(&self, other: &[U]) -> Vec<T> {
let multiplier: usize = bitwise_preproc::<T, U>(self, other);
let mut _res: Vec<T> = self.to_vec();
for (index, slice) in other.chunks(multiplier).enumerate() {
_res[index] ^= bitwise_from(slice);
}
_res
}
fn or_with(&self, other: &[U]) -> Vec<T> {
let multiplier: usize = bitwise_preproc::<T, U>(self, other);
let mut _res: Vec<T> = self.to_vec();
for (index, slice) in other.chunks(multiplier).enumerate() {
_res[index] |= bitwise_from(slice);
}
_res
}
fn and_with(&self, other: &[U]) -> Vec<T> {
let multiplier: usize = bitwise_preproc::<T, U>(self, other);
let mut _res: Vec<T> = self.to_vec();
for (index, slice) in other.chunks(multiplier).enumerate() {
_res[index] &= bitwise_from(slice);
}
_res
}
}
impl<T: Clone + std::cmp::PartialEq> SliceOps<T> for [T] {
#[inline]
fn peek(&self) -> T {
self[self.len() - 1].clone()
}
#[inline]
fn swap_top(&mut self) {
let a: T = self[self.len() - 1].clone();
let b: T = self[self.len() - 2].clone();
self[self.len() - 1] = b;
self[self.len() - 2] = a;
}
fn count_of(&self, item: T) -> usize {
let mut res: usize = 0;
for i in self {
if i == &item
{ res.inc(); }
}
res
}
fn positions_of(&self, item: T) -> Vec<usize> {
let mut res = Vec::with_capacity(self.len());
for i in self.iter().enumerate() {
if i.1 == &item
{ res.push(i.0); }
}
res
}
#[inline]
fn position_of(&self, t: T) -> Option<usize> {
let mut i: usize = 0;
for v_t in self {
if *v_t == t
{ return Some(i); }
i.inc();
}
None
}
}
#[must_use]
fn bitwise_from<T: From<u8> +
From<U> +
Shl<Output = T> +
BitOrAssign,
U: Copy>
(slice: &[U]) -> T {
let mut end_prod: T = T::from(0);
for (inner_idx, inner_ref) in slice.iter().rev().enumerate() {
end_prod |= T::from(*inner_ref) << ((inner_idx as u8) << 3u8).into();
}
end_prod
}
#[inline(always)]
fn bitwise_preproc<T,U>(a: &[T], b: &[U]) -> usize {
if size_of_val(a) != size_of_val(b)
{ panic!("{}", BITWISE_ERR1); }
let t_size: usize = size_of::<T>();
let u_size: usize = size_of::<U>();
if t_size < u_size
{ panic!("{}", BITWISE_ERR2); }
t_size / u_size
}