use crate::{utils::slice, Entity, Index, Shape, ShapeIdx, SignedIndex, Unbind};
use core::{fmt, marker::PhantomData, ops::Range};
use faer_entity::*;
use generativity::Guard;
use reborrow::*;
type Invariant<'a> = fn(&'a ()) -> &'a ();
#[derive(Copy, Clone)]
pub struct Partition<'head, 'tail, 'n> {
pub head: Dim<'head>,
pub tail: Dim<'tail>,
__marker: PhantomData<Invariant<'n>>,
}
impl<'head, 'tail, 'n> Partition<'head, 'tail, 'n> {
#[inline]
pub const fn midpoint(&self) -> IdxInc<'n> {
unsafe { IdxInc::new_unbound(self.head.unbound) }
}
}
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct Dim<'n> {
unbound: usize,
__marker: PhantomData<Invariant<'n>>,
}
impl PartialEq for Dim<'_> {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
equator::debug_assert!(self.unbound == other.unbound);
true
}
}
impl Eq for Dim<'_> {}
impl PartialOrd for Dim<'_> {
#[inline(always)]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
equator::debug_assert!(self.unbound == other.unbound);
Some(core::cmp::Ordering::Equal)
}
}
impl Ord for Dim<'_> {
#[inline(always)]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
equator::debug_assert!(self.unbound == other.unbound);
core::cmp::Ordering::Equal
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct Idx<'n, I: Index = usize> {
unbound: I,
__marker: PhantomData<Invariant<'n>>,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct IdxInc<'n, I: Index = usize> {
unbound: I,
__marker: PhantomData<Invariant<'n>>,
}
impl fmt::Debug for Dim<'_> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.unbound.fmt(f)
}
}
impl<I: Index> fmt::Debug for Idx<'_, I> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.unbound.fmt(f)
}
}
impl<I: Index> fmt::Debug for IdxInc<'_, I> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.unbound.fmt(f)
}
}
impl<I: Index> fmt::Debug for MaybeIdx<'_, I> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.unbound.to_signed() >= I::Signed::truncate(0) {
self.unbound.fmt(f)
} else {
f.write_str("None")
}
}
}
impl<'n, I: Index> PartialEq<Dim<'n>> for Idx<'n, I> {
#[inline(always)]
fn eq(&self, other: &Dim<'n>) -> bool {
equator::debug_assert!(self.unbound.zx() < other.unbound);
false
}
}
impl<'n, I: Index> PartialOrd<Dim<'n>> for Idx<'n, I> {
#[inline(always)]
fn partial_cmp(&self, other: &Dim<'n>) -> Option<core::cmp::Ordering> {
equator::debug_assert!(self.unbound.zx() < other.unbound);
Some(core::cmp::Ordering::Less)
}
}
impl<'n, I: Index> PartialEq<Dim<'n>> for IdxInc<'n, I> {
#[inline(always)]
fn eq(&self, other: &Dim<'n>) -> bool {
equator::debug_assert!(self.unbound.zx() <= other.unbound);
self.unbound.zx() == other.unbound
}
}
impl<'n, I: Index> PartialOrd<Dim<'n>> for IdxInc<'n, I> {
#[inline(always)]
fn partial_cmp(&self, other: &Dim<'n>) -> Option<core::cmp::Ordering> {
equator::debug_assert!(self.unbound.zx() <= other.unbound);
Some(if self.unbound.zx() == other.unbound {
core::cmp::Ordering::Equal
} else {
core::cmp::Ordering::Less
})
}
}
impl<'n> Dim<'n> {
#[inline(always)]
pub const unsafe fn new_unbound(dim: usize) -> Self {
Self {
unbound: dim,
__marker: PhantomData,
}
}
#[inline(always)]
pub fn new(dim: usize, guard: Guard<'n>) -> Self {
_ = guard;
Self {
unbound: dim,
__marker: PhantomData,
}
}
#[inline(always)]
pub const fn unbound(self) -> usize {
self.unbound
}
#[inline]
pub const fn partition<'head, 'tail>(
self,
midpoint: IdxInc<'n>,
head: Guard<'head>,
tail: Guard<'tail>,
) -> Partition<'head, 'tail, 'n> {
_ = (head, tail);
unsafe {
Partition {
head: Dim::new_unbound(midpoint.unbound),
tail: Dim::new_unbound(self.unbound - midpoint.unbound),
__marker: PhantomData,
}
}
}
#[inline]
pub fn indices(self) -> impl Clone + ExactSizeIterator + DoubleEndedIterator<Item = Idx<'n>> {
(0..self.unbound).map(|i| unsafe { Idx::new_unbound(i) })
}
}
impl<'n, I: Index> Idx<'n, I> {
#[inline(always)]
pub const unsafe fn new_unbound(idx: I) -> Self {
Self {
unbound: idx,
__marker: PhantomData,
}
}
#[inline(always)]
pub unsafe fn new_unchecked(idx: I, dim: Dim<'n>) -> Self {
equator::debug_assert!(all(
idx.zx() < dim.unbound,
idx <= I::from_signed(I::Signed::MAX),
));
Self {
unbound: idx,
__marker: PhantomData,
}
}
#[inline(always)]
pub fn new_checked(idx: I, dim: Dim<'n>) -> Self {
equator::assert!(all(
idx.zx() < dim.unbound,
idx <= I::from_signed(I::Signed::MAX),
));
Self {
unbound: idx,
__marker: PhantomData,
}
}
#[inline(always)]
pub const fn unbound(self) -> I {
self.unbound
}
#[inline(always)]
pub fn zx(self) -> Idx<'n> {
Idx {
unbound: self.unbound.zx(),
__marker: PhantomData,
}
}
}
impl<'n, I: Index> IdxInc<'n, I> {
#[inline(always)]
pub const fn zero() -> Self {
Self {
unbound: unsafe { core::mem::zeroed() },
__marker: PhantomData,
}
}
#[inline(always)]
pub const unsafe fn new_unbound(idx: I) -> Self {
Self {
unbound: idx,
__marker: PhantomData,
}
}
#[inline(always)]
pub unsafe fn new_unchecked(idx: I, dim: Dim<'n>) -> Self {
equator::debug_assert!(all(
idx.zx() <= dim.unbound,
idx <= I::from_signed(I::Signed::MAX),
));
Self {
unbound: idx,
__marker: PhantomData,
}
}
#[inline(always)]
pub fn new_checked(idx: I, dim: Dim<'n>) -> Self {
equator::assert!(all(
idx.zx() <= dim.unbound,
idx <= I::from_signed(I::Signed::MAX),
));
Self {
unbound: idx,
__marker: PhantomData,
}
}
#[inline(always)]
pub const fn unbound(self) -> I {
self.unbound
}
#[inline(always)]
pub fn zx(self) -> IdxInc<'n> {
IdxInc {
unbound: self.unbound.zx(),
__marker: PhantomData,
}
}
}
impl<'n> IdxInc<'n> {
#[inline]
pub fn to(
self,
upper: IdxInc<'n>,
) -> impl Clone + ExactSizeIterator + DoubleEndedIterator<Item = Idx<'n>> {
(self.unbound..upper.unbound).map(|i| unsafe { Idx::new_unbound(i) })
}
#[inline]
pub fn range_to(
self,
upper: IdxInc<'n>,
) -> impl Clone + ExactSizeIterator + DoubleEndedIterator<Item = Idx<'n>> {
(self.unbound..upper.unbound).map(|i| unsafe { Idx::new_unbound(i) })
}
}
impl Unbind for Dim<'_> {
#[inline(always)]
unsafe fn new_unbound(idx: usize) -> Self {
Self::new_unbound(idx)
}
#[inline(always)]
fn unbound(self) -> usize {
self.unbound
}
}
impl<I: Index> Unbind<I> for Idx<'_, I> {
#[inline(always)]
unsafe fn new_unbound(idx: I) -> Self {
Self::new_unbound(idx)
}
#[inline(always)]
fn unbound(self) -> I {
self.unbound
}
}
impl<I: Index> Unbind<I> for IdxInc<'_, I> {
#[inline(always)]
unsafe fn new_unbound(idx: I) -> Self {
Self::new_unbound(idx)
}
#[inline(always)]
fn unbound(self) -> I {
self.unbound
}
}
impl<'dim> ShapeIdx for Dim<'dim> {
type Idx<I: Index> = Idx<'dim, I>;
type IdxInc<I: Index> = IdxInc<'dim, I>;
}
impl<'dim> Shape for Dim<'dim> {}
impl<'n, I: Index> From<Idx<'n, I>> for IdxInc<'n, I> {
#[inline(always)]
fn from(value: Idx<'n, I>) -> Self {
Self {
unbound: value.unbound,
__marker: PhantomData,
}
}
}
impl<'size> Dim<'size> {
#[track_caller]
#[inline]
pub fn check<I: Index>(self, idx: I) -> Idx<'size, I> {
Idx::new_checked(idx, self)
}
#[inline]
pub fn try_check<I: Index>(self, idx: I) -> Option<Idx<'size, I>> {
if idx.zx() < self.unbound() {
Some(unsafe { Idx::new_unbound(idx) })
} else {
None
}
}
}
impl<'n> Idx<'n> {
pub fn truncate<I: Index>(self) -> Idx<'n, I> {
unsafe { Idx::new_unbound(I::truncate(self.unbound())) }
}
}
impl<'n, I: Index> Idx<'n, I> {
#[inline]
pub const fn to_inclusive(self) -> IdxInc<'n, I> {
unsafe { IdxInc::new_unbound(self.unbound()) }
}
#[inline]
pub fn next(self) -> IdxInc<'n, I> {
unsafe { IdxInc::new_unbound(self.unbound() + I::truncate(1)) }
}
#[track_caller]
#[inline]
pub fn from_slice_mut_checked<'a>(slice: &'a mut [I], size: Dim<'n>) -> &'a mut [Idx<'n, I>] {
Self::from_slice_ref_checked(slice, size);
unsafe { &mut *(slice as *mut _ as *mut _) }
}
#[track_caller]
#[inline]
pub unsafe fn from_slice_mut_unchecked<'a>(slice: &'a mut [I]) -> &'a mut [Idx<'n, I>] {
unsafe { &mut *(slice as *mut _ as *mut _) }
}
#[track_caller]
pub fn from_slice_ref_checked<'a>(slice: &'a [I], size: Dim<'n>) -> &'a [Idx<'n, I>] {
for &idx in slice {
Self::new_checked(idx, size);
}
unsafe { &*(slice as *const _ as *const _) }
}
#[track_caller]
#[inline]
pub unsafe fn from_slice_ref_unchecked<'a>(slice: &'a [I]) -> &'a [Idx<'n, I>] {
unsafe { &*(slice as *const _ as *const _) }
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
pub struct MaybeIdx<'n, I: Index = usize> {
unbound: I,
__marker: PhantomData<Invariant<'n>>,
}
impl<'n, I: Index> MaybeIdx<'n, I> {
#[inline]
pub fn from_index(idx: Idx<'n, I>) -> Self {
unsafe { Self::new_unbound(idx.unbound()) }
}
#[inline]
pub fn none() -> Self {
unsafe { Self::new_unbound(I::truncate(usize::MAX)) }
}
#[inline]
pub fn new_checked(idx: I::Signed, size: Dim<'n>) -> Self {
assert!((idx.sx() as isize) < size.unbound() as isize);
Self {
unbound: I::from_signed(idx),
__marker: PhantomData,
}
}
#[inline]
pub unsafe fn new_unchecked(idx: I::Signed, size: Dim<'n>) -> Self {
debug_assert!((idx.sx() as isize) < size.unbound() as isize);
Self {
unbound: I::from_signed(idx),
__marker: PhantomData,
}
}
#[inline]
pub unsafe fn new_unbound(idx: I) -> Self {
Self {
unbound: idx,
__marker: PhantomData,
}
}
#[inline]
pub fn unbound(self) -> I {
self.unbound
}
#[inline]
pub fn idx(self) -> Option<Idx<'n, I>> {
if self.unbound.to_signed() >= I::Signed::truncate(0) {
Some(unsafe { Idx::new_unbound(self.unbound()) })
} else {
None
}
}
#[inline]
pub fn sx(self) -> MaybeIdx<'n> {
unsafe { MaybeIdx::new_unbound(self.unbound.to_signed().sx()) }
}
#[track_caller]
#[inline]
pub fn from_slice_mut_checked<'a>(
slice: &'a mut [I::Signed],
size: Dim<'n>,
) -> &'a mut [MaybeIdx<'n, I>] {
Self::from_slice_ref_checked(slice, size);
unsafe { &mut *(slice as *mut _ as *mut _) }
}
#[track_caller]
#[inline]
pub unsafe fn from_slice_mut_unchecked<'a>(
slice: &'a mut [I::Signed],
) -> &'a mut [MaybeIdx<'n, I>] {
unsafe { &mut *(slice as *mut _ as *mut _) }
}
#[track_caller]
pub fn from_slice_ref_checked<'a>(
slice: &'a [I::Signed],
size: Dim<'n>,
) -> &'a [MaybeIdx<'n, I>] {
for &idx in slice {
Self::new_checked(idx, size);
}
unsafe { &*(slice as *const _ as *const _) }
}
#[track_caller]
pub fn as_slice_ref<'a>(slice: &'a [MaybeIdx<'n, I>]) -> &'a [I::Signed] {
unsafe { &*(slice as *const _ as *const _) }
}
#[track_caller]
#[inline]
pub unsafe fn from_slice_ref_unchecked<'a>(slice: &'a [I::Signed]) -> &'a [MaybeIdx<'n, I>] {
unsafe { &*(slice as *const _ as *const _) }
}
}
impl core::ops::Deref for Dim<'_> {
type Target = usize;
#[inline]
fn deref(&self) -> &Self::Target {
&self.unbound
}
}
impl<I: Index> core::ops::Deref for Idx<'_, I> {
type Target = I;
#[inline]
fn deref(&self) -> &Self::Target {
&self.unbound
}
}
impl<I: Index> core::ops::Deref for MaybeIdx<'_, I> {
type Target = I::Signed;
#[inline]
fn deref(&self) -> &Self::Target {
bytemuck::cast_ref(&self.unbound)
}
}
impl<I: Index> core::ops::Deref for IdxInc<'_, I> {
type Target = I;
#[inline]
fn deref(&self) -> &Self::Target {
&self.unbound
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct Array<'n, T> {
__marker: PhantomData<Invariant<'n>>,
unbound: [T],
}
pub struct ArrayGroup<'n, 'a, E: Entity> {
__marker: PhantomData<Invariant<'n>>,
unbound: slice::SliceGroup<'a, E>,
}
pub struct ArrayGroupMut<'n, 'a, E: Entity> {
__marker: PhantomData<Invariant<'n>>,
unbound: slice::SliceGroupMut<'a, E>,
}
impl<E: Entity> core::fmt::Debug for ArrayGroup<'_, '_, E> {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.unbound.fmt(f)
}
}
impl<E: Entity> core::fmt::Debug for ArrayGroupMut<'_, '_, E> {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.unbound.fmt(f)
}
}
impl<E: Entity> Copy for ArrayGroup<'_, '_, E> {}
impl<E: Entity> Clone for ArrayGroup<'_, '_, E> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<'short, 'n, 'a, E: Entity> reborrow::ReborrowMut<'short> for ArrayGroup<'n, 'a, E> {
type Target = ArrayGroup<'n, 'short, E>;
#[inline]
fn rb_mut(&'short mut self) -> Self::Target {
*self
}
}
impl<'short, 'n, 'a, E: Entity> reborrow::Reborrow<'short> for ArrayGroup<'n, 'a, E> {
type Target = ArrayGroup<'n, 'short, E>;
#[inline]
fn rb(&'short self) -> Self::Target {
*self
}
}
impl<'short, 'n, 'a, E: Entity> reborrow::ReborrowMut<'short> for ArrayGroupMut<'n, 'a, E> {
type Target = ArrayGroupMut<'n, 'short, E>;
#[inline]
fn rb_mut(&'short mut self) -> Self::Target {
ArrayGroupMut {
__marker: PhantomData,
unbound: self.unbound.rb_mut(),
}
}
}
impl<'short, 'n, 'a, E: Entity> reborrow::Reborrow<'short> for ArrayGroupMut<'n, 'a, E> {
type Target = ArrayGroup<'n, 'short, E>;
#[inline]
fn rb(&'short self) -> Self::Target {
ArrayGroup {
__marker: PhantomData,
unbound: self.unbound.rb(),
}
}
}
impl<'n, 'a, E: Entity> ArrayGroupMut<'n, 'a, E> {
#[inline]
pub fn new(slice: GroupFor<E, &'a mut [E::Unit]>, len: Dim<'n>) -> Self {
let slice = slice::SliceGroupMut::<'_, E>::new(slice);
assert!(slice.len() == len.unbound());
ArrayGroupMut {
__marker: PhantomData,
unbound: slice,
}
}
#[inline]
pub fn into_slice(self) -> GroupFor<E, &'a mut [E::Unit]> {
self.unbound.into_inner()
}
#[inline]
pub fn subslice(self, range: Range<IdxInc<'n>>) -> GroupFor<E, &'a mut [E::Unit]> {
unsafe {
slice::SliceGroupMut::<'_, E>::new(self.into_slice())
.subslice_unchecked(range.start.unbound()..range.end.unbound())
.into_inner()
}
}
#[inline]
pub fn read(&self, j: Idx<'n>) -> E {
self.rb().read(j)
}
#[inline]
pub fn write(&mut self, j: Idx<'n>, value: E) {
unsafe {
slice::SliceGroupMut::new(self.rb_mut().into_slice())
.write_unchecked(j.unbound(), value)
}
}
}
impl<'n, 'a, E: Entity> ArrayGroup<'n, 'a, E> {
#[inline]
pub fn new(slice: GroupFor<E, &'a [E::Unit]>, len: Dim<'n>) -> Self {
let slice = slice::SliceGroup::<'_, E>::new(slice);
assert!(slice.rb().len() == len.unbound());
ArrayGroup {
__marker: PhantomData,
unbound: slice,
}
}
#[inline]
pub fn into_slice(self) -> GroupFor<E, &'a [E::Unit]> {
self.unbound.into_inner()
}
#[inline]
pub fn subslice(self, range: Range<IdxInc<'n>>) -> GroupFor<E, &'a [E::Unit]> {
unsafe {
slice::SliceGroup::<'_, E>::new(self.into_slice())
.subslice_unchecked(range.start.unbound()..range.end.unbound())
.into_inner()
}
}
#[inline]
pub fn read(&self, j: Idx<'n>) -> E {
unsafe { slice::SliceGroup::new(self.into_slice()).read_unchecked(j.unbound()) }
}
}
impl<'n, T> Array<'n, T> {
#[inline]
#[track_caller]
pub fn from_ref<'a>(slice: &'a [T], size: Dim<'n>) -> &'a Self {
assert!(slice.len() == size.unbound());
unsafe { &*(slice as *const [T] as *const Self) }
}
#[inline]
#[track_caller]
pub fn from_mut<'a>(slice: &'a mut [T], size: Dim<'n>) -> &'a mut Self {
assert!(slice.len() == size.unbound());
unsafe { &mut *(slice as *mut [T] as *mut Self) }
}
#[inline]
#[track_caller]
pub fn as_ref(&self) -> &[T] {
unsafe { &*(self as *const _ as *const _) }
}
#[inline]
#[track_caller]
pub fn as_mut<'a>(&mut self) -> &'a mut [T] {
unsafe { &mut *(self as *mut _ as *mut _) }
}
#[inline]
pub fn len(&self) -> Dim<'n> {
unsafe { Dim::new_unbound(self.unbound.len()) }
}
}
impl<T: core::fmt::Debug> core::fmt::Debug for Array<'_, T> {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.unbound.fmt(f)
}
}
impl<'n, T> core::ops::Index<Range<IdxInc<'n>>> for Array<'n, T> {
type Output = [T];
#[track_caller]
fn index(&self, idx: Range<IdxInc<'n>>) -> &Self::Output {
#[cfg(debug_assertions)]
{
&self.unbound[idx.start.unbound()..idx.end.unbound()]
}
#[cfg(not(debug_assertions))]
unsafe {
self.unbound
.get_unchecked(idx.start.unbound()..idx.end.unbound())
}
}
}
impl<'n, T> core::ops::IndexMut<Range<IdxInc<'n>>> for Array<'n, T> {
#[track_caller]
fn index_mut(&mut self, idx: Range<IdxInc<'n>>) -> &mut Self::Output {
#[cfg(debug_assertions)]
{
&mut self.unbound[idx.start.unbound()..idx.end.unbound()]
}
#[cfg(not(debug_assertions))]
unsafe {
self.unbound
.get_unchecked_mut(idx.start.unbound()..idx.end.unbound())
}
}
}
impl<'n, T> core::ops::Index<Idx<'n>> for Array<'n, T> {
type Output = T;
#[track_caller]
fn index(&self, idx: Idx<'n>) -> &Self::Output {
#[cfg(debug_assertions)]
{
&self.unbound[idx.unbound()]
}
#[cfg(not(debug_assertions))]
unsafe {
self.unbound.get_unchecked(idx.unbound())
}
}
}
impl<'n, T> core::ops::IndexMut<Idx<'n>> for Array<'n, T> {
#[track_caller]
fn index_mut(&mut self, idx: Idx<'n>) -> &mut Self::Output {
#[cfg(debug_assertions)]
{
&mut self.unbound[idx.unbound()]
}
#[cfg(not(debug_assertions))]
unsafe {
self.unbound.get_unchecked_mut(idx.unbound())
}
}
}