use crate::num::arithmetic::traits::ShrRound;
use crate::num::basic::integers::{PrimitiveInt, USIZE_IS_U32};
use crate::num::basic::unsigneds::PrimitiveUnsigned;
use crate::num::conversion::traits::{
FromOtherTypeSlice, SplitInHalf, VecFromOtherType, VecFromOtherTypeSlice, WrappingFrom,
};
use crate::rounding_modes::RoundingMode::*;
use alloc::vec;
use alloc::vec::Vec;
const fn from_other_type_slice_ident<T: PrimitiveUnsigned>(xs: &[T]) -> T {
if xs.is_empty() { T::ZERO } else { xs[0] }
}
macro_rules! impl_slice_traits_ident {
($a:ty) => {
impl FromOtherTypeSlice<$a> for $a {
#[inline]
fn from_other_type_slice(xs: &[$a]) -> Self {
from_other_type_slice_ident(xs)
}
}
impl VecFromOtherTypeSlice<$a> for $a {
#[inline]
fn vec_from_other_type_slice(xs: &[$a]) -> Vec<Self> {
xs.to_vec()
}
}
impl VecFromOtherType<$a> for $a {
#[inline]
fn vec_from_other_type(x: $a) -> Vec<Self> {
::alloc::vec![x]
}
}
};
}
fn from_other_type_slice_large_to_small<
A: PrimitiveUnsigned,
B: PrimitiveUnsigned + WrappingFrom<A>,
>(
xs: &[A],
) -> B {
if xs.is_empty() {
B::ZERO
} else {
B::wrapping_from(xs[0])
}
}
fn vec_from_other_type_slice_large_to_small<
A: PrimitiveUnsigned,
B: PrimitiveUnsigned + WrappingFrom<A>,
>(
xs: &[A],
) -> Vec<B> {
let log_size_ratio = A::LOG_WIDTH - B::LOG_WIDTH;
let mut out = ::alloc::vec![B::ZERO; xs.len() << log_size_ratio];
for (chunk, &u) in out.chunks_exact_mut(1 << log_size_ratio).zip(xs.iter()) {
let mut u = u;
for x in chunk {
*x = B::wrapping_from(u);
u >>= B::WIDTH;
}
}
out
}
fn vec_from_other_type_large_to_small<
A: PrimitiveUnsigned,
B: PrimitiveUnsigned + WrappingFrom<A>,
>(
mut x: A,
) -> Vec<B> {
let mut xs = ::alloc::vec![B::ZERO; 1 << (A::LOG_WIDTH - B::LOG_WIDTH)];
for out in &mut xs {
*out = B::wrapping_from(x);
x >>= B::WIDTH;
}
xs
}
macro_rules! impl_slice_traits_large_to_small {
($a:ident, $b:ident) => {
impl FromOtherTypeSlice<$a> for $b {
#[inline]
fn from_other_type_slice(xs: &[$a]) -> Self {
from_other_type_slice_large_to_small(xs)
}
}
impl VecFromOtherTypeSlice<$a> for $b {
#[inline]
fn vec_from_other_type_slice(xs: &[$a]) -> Vec<Self> {
vec_from_other_type_slice_large_to_small(xs)
}
}
impl VecFromOtherType<$a> for $b {
#[inline]
fn vec_from_other_type(x: $a) -> Vec<Self> {
vec_from_other_type_large_to_small(x)
}
}
};
}
fn from_other_type_slice_small_to_large<
A: PrimitiveUnsigned,
B: PrimitiveUnsigned + WrappingFrom<A>,
>(
xs: &[A],
) -> B {
let mut result = B::ZERO;
let mut offset = 0;
for &u in xs.iter().take(1 << (B::LOG_WIDTH - A::LOG_WIDTH)) {
result |= B::wrapping_from(u) << offset;
offset += A::WIDTH;
}
result
}
fn vec_from_other_type_slice_small_to_large<
A: PrimitiveUnsigned,
B: PrimitiveUnsigned + WrappingFrom<A>,
>(
xs: &[A],
) -> Vec<B> {
let log_size_ratio = B::LOG_WIDTH - A::LOG_WIDTH;
let mut out = ::alloc::vec![B::ZERO; xs.len().shr_round(log_size_ratio, Ceiling).0];
for (x, chunk) in out.iter_mut().zip(xs.chunks(1 << log_size_ratio)) {
*x = from_other_type_slice_small_to_large(chunk);
}
out
}
fn vec_from_other_type_small_to_large<A, B: WrappingFrom<A>>(x: A) -> Vec<B> {
::alloc::vec![B::wrapping_from(x)]
}
macro_rules! impl_slice_traits_small_to_large {
($a:ident, $b:ident) => {
impl FromOtherTypeSlice<$a> for $b {
#[inline]
fn from_other_type_slice(xs: &[$a]) -> Self {
from_other_type_slice_small_to_large(xs)
}
}
impl VecFromOtherTypeSlice<$a> for $b {
#[inline]
fn vec_from_other_type_slice(xs: &[$a]) -> Vec<Self> {
vec_from_other_type_slice_small_to_large(xs)
}
}
impl VecFromOtherType<$a> for $b {
#[inline]
fn vec_from_other_type(x: $a) -> Vec<Self> {
vec_from_other_type_small_to_large(x)
}
}
};
}
apply_to_unsigneds!(impl_slice_traits_ident);
impl_slice_traits_large_to_small!(u16, u8);
impl_slice_traits_large_to_small!(u32, u8);
impl_slice_traits_large_to_small!(u32, u16);
impl_slice_traits_large_to_small!(u64, u8);
impl_slice_traits_large_to_small!(u64, u16);
impl_slice_traits_large_to_small!(u64, u32);
impl_slice_traits_large_to_small!(u128, u8);
impl_slice_traits_large_to_small!(u128, u16);
impl_slice_traits_large_to_small!(u128, u32);
impl_slice_traits_large_to_small!(u128, u64);
impl_slice_traits_large_to_small!(u128, usize);
impl_slice_traits_large_to_small!(usize, u8);
impl_slice_traits_large_to_small!(usize, u16);
impl_slice_traits_small_to_large!(u8, u16);
impl_slice_traits_small_to_large!(u8, u32);
impl_slice_traits_small_to_large!(u8, u64);
impl_slice_traits_small_to_large!(u8, u128);
impl_slice_traits_small_to_large!(u8, usize);
impl_slice_traits_small_to_large!(u16, u32);
impl_slice_traits_small_to_large!(u16, u64);
impl_slice_traits_small_to_large!(u16, u128);
impl_slice_traits_small_to_large!(u16, usize);
impl_slice_traits_small_to_large!(u32, u64);
impl_slice_traits_small_to_large!(u32, u128);
impl_slice_traits_small_to_large!(u64, u128);
impl_slice_traits_small_to_large!(usize, u128);
impl FromOtherTypeSlice<u32> for usize {
fn from_other_type_slice(xs: &[u32]) -> Self {
if USIZE_IS_U32 {
if xs.is_empty() {
0
} else {
Self::wrapping_from(xs[0])
}
} else {
assert_eq!(Self::WIDTH, u64::WIDTH);
let mut result = 0;
let mut offset = 0;
for &u in xs.iter().take(2) {
result |= Self::wrapping_from(u) << offset;
offset += u32::WIDTH;
}
result
}
}
}
impl VecFromOtherTypeSlice<u32> for usize {
fn vec_from_other_type_slice(xs: &[u32]) -> Vec<Self> {
let mut out;
if USIZE_IS_U32 {
out = vec![0; xs.len()];
for (x, &u) in out.iter_mut().zip(xs.iter()) {
*x = Self::wrapping_from(u);
}
} else {
assert_eq!(Self::WIDTH, u64::WIDTH);
out = vec![0; xs.len().shr_round(1, Ceiling).0];
for (x, chunk) in out.iter_mut().zip(xs.chunks(2)) {
*x = Self::from_other_type_slice(chunk);
}
}
out
}
}
impl VecFromOtherType<u32> for usize {
#[inline]
fn vec_from_other_type(x: u32) -> Vec<Self> {
vec![Self::wrapping_from(x)]
}
}
impl FromOtherTypeSlice<u64> for usize {
#[inline]
fn from_other_type_slice(xs: &[u64]) -> Self {
if xs.is_empty() {
0
} else {
Self::wrapping_from(xs[0])
}
}
}
impl VecFromOtherTypeSlice<u64> for usize {
#[allow(arithmetic_overflow)]
fn vec_from_other_type_slice(xs: &[u64]) -> Vec<Self> {
let mut out;
if USIZE_IS_U32 {
out = ::alloc::vec![0; xs.len() << 1];
for (chunk, &u) in out.chunks_exact_mut(2).zip(xs.iter()) {
let mut u = u;
for x in chunk {
*x = Self::wrapping_from(u);
u >>= Self::WIDTH;
}
}
} else {
assert_eq!(Self::WIDTH, u64::WIDTH);
out = ::alloc::vec![0; xs.len()];
for (x, &u) in out.iter_mut().zip(xs.iter()) {
*x = Self::wrapping_from(u);
}
}
out
}
}
impl VecFromOtherType<u64> for usize {
fn vec_from_other_type(x: u64) -> Vec<Self> {
if USIZE_IS_U32 {
let (upper, lower) = x.split_in_half();
::alloc::vec![Self::wrapping_from(lower), Self::wrapping_from(upper)]
} else {
assert_eq!(Self::WIDTH, u64::WIDTH);
::alloc::vec![Self::wrapping_from(x)]
}
}
}
impl FromOtherTypeSlice<usize> for u32 {
#[inline]
fn from_other_type_slice(xs: &[usize]) -> Self {
if xs.is_empty() {
0
} else {
Self::wrapping_from(xs[0])
}
}
}
impl VecFromOtherTypeSlice<usize> for u32 {
#[allow(arithmetic_overflow)]
fn vec_from_other_type_slice(xs: &[usize]) -> Vec<Self> {
let mut out;
if USIZE_IS_U32 {
out = ::alloc::vec![0; xs.len()];
for (x, &u) in out.iter_mut().zip(xs.iter()) {
*x = Self::wrapping_from(u);
}
} else {
assert_eq!(usize::WIDTH, u64::WIDTH);
out = ::alloc::vec![0; xs.len() << 1];
for (chunk, &u) in out.chunks_exact_mut(2).zip(xs.iter()) {
let mut u = u;
for x in chunk {
*x = Self::wrapping_from(u);
u >>= Self::WIDTH;
}
}
}
out
}
}
impl VecFromOtherType<usize> for u32 {
#[allow(arithmetic_overflow)]
fn vec_from_other_type(x: usize) -> Vec<Self> {
if USIZE_IS_U32 {
::alloc::vec![Self::wrapping_from(x)]
} else {
assert_eq!(usize::WIDTH, u64::WIDTH);
let (upper, lower) = u64::wrapping_from(x).split_in_half();
::alloc::vec![lower, upper]
}
}
}
impl FromOtherTypeSlice<usize> for u64 {
fn from_other_type_slice(xs: &[usize]) -> Self {
if USIZE_IS_U32 {
let mut result = 0;
let mut offset = 0;
for &u in xs.iter().take(2) {
result |= Self::wrapping_from(u) << offset;
offset += usize::WIDTH;
}
result
} else {
assert_eq!(usize::WIDTH, Self::WIDTH);
if xs.is_empty() {
0
} else {
Self::wrapping_from(xs[0])
}
}
}
}
impl VecFromOtherTypeSlice<usize> for u64 {
fn vec_from_other_type_slice(xs: &[usize]) -> Vec<Self> {
let mut out;
if USIZE_IS_U32 {
out = ::alloc::vec![0; xs.len().shr_round(1, Ceiling).0];
for (x, chunk) in out.iter_mut().zip(xs.chunks(2)) {
*x = Self::from_other_type_slice(chunk);
}
} else {
assert_eq!(usize::WIDTH, Self::WIDTH);
out = ::alloc::vec![0; xs.len()];
for (x, &u) in out.iter_mut().zip(xs.iter()) {
*x = Self::wrapping_from(u);
}
}
out
}
}
impl VecFromOtherType<usize> for u64 {
#[inline]
fn vec_from_other_type(x: usize) -> Vec<Self> {
::alloc::vec![Self::wrapping_from(x)]
}
}