Skip to main content

faer/utils/
bound.rs

1use crate::{Index, Shape, ShapeIdx, SignedIndex, Unbind, assert};
2use core::fmt;
3use core::marker::PhantomData;
4use core::ops::Range;
5use generativity::Guard;
6type Invariant<'a> = fn(&'a ()) -> &'a ();
7/// splits a range into two segments.
8#[derive(Copy, Clone, Debug, PartialEq, Eq)]
9pub struct Partition<'head, 'tail, 'n> {
10	/// size of the first half.
11	pub head: Dim<'head>,
12	/// size of the second half.
13	pub tail: Dim<'tail>,
14	__marker: PhantomData<Invariant<'n>>,
15}
16impl<'head, 'tail, 'n> Partition<'head, 'tail, 'n> {
17	/// returns the midpoint of the partition.
18	#[inline]
19	pub const fn midpoint(&self) -> IdxInc<'n> {
20		unsafe { IdxInc::new_unbound(self.head.unbound) }
21	}
22
23	/// returns the midpoint of the partition.
24	#[inline]
25	pub const fn flip(&self) -> Partition<'tail, 'head, 'n> {
26		Partition {
27			head: self.tail,
28			tail: self.head,
29			__marker: PhantomData,
30		}
31	}
32}
33/// lifetime branded length
34/// # safety
35/// the type's safety invariant is that all instances of this type with the same
36/// lifetime correspond to the same length.
37#[derive(Copy, Clone)]
38#[repr(transparent)]
39pub struct Dim<'n> {
40	unbound: usize,
41	__marker: PhantomData<Invariant<'n>>,
42}
43impl PartialEq for Dim<'_> {
44	#[inline(always)]
45	fn eq(&self, other: &Self) -> bool {
46		equator::debug_assert!(self.unbound == other.unbound);
47		true
48	}
49}
50impl Eq for Dim<'_> {}
51impl PartialOrd for Dim<'_> {
52	#[inline(always)]
53	fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
54		equator::debug_assert!(self.unbound == other.unbound);
55		Some(core::cmp::Ordering::Equal)
56	}
57}
58impl Ord for Dim<'_> {
59	#[inline(always)]
60	fn cmp(&self, other: &Self) -> core::cmp::Ordering {
61		equator::debug_assert!(self.unbound == other.unbound);
62		core::cmp::Ordering::Equal
63	}
64}
65/// lifetime branded index.
66/// # safety
67/// the type's safety invariant is that all instances of this type are valid
68/// indices for [`Dim<'n>`] and less than or equal to `i::signed::max`.
69#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
70#[repr(transparent)]
71pub struct Idx<'n, I: Index = usize> {
72	unbound: I,
73	__marker: PhantomData<Invariant<'n>>,
74}
75/// lifetime branded partition index.
76/// # safety
77/// the type's safety invariant is that all instances of this type are valid
78/// partition places for [`Dim<'n>`] and less than or equal to `i::signed::max`.
79#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
80#[repr(transparent)]
81pub struct IdxInc<'n, I: Index = usize> {
82	unbound: I,
83	__marker: PhantomData<Invariant<'n>>,
84}
85impl fmt::Debug for Dim<'_> {
86	#[inline]
87	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88		self.unbound.fmt(f)
89	}
90}
91impl<I: Index> fmt::Debug for Idx<'_, I> {
92	#[inline]
93	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94		self.unbound.fmt(f)
95	}
96}
97impl<I: Index> fmt::Debug for IdxInc<'_, I> {
98	#[inline]
99	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100		self.unbound.fmt(f)
101	}
102}
103impl<I: Index> fmt::Debug for MaybeIdx<'_, I> {
104	#[inline]
105	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106		if self.unbound.to_signed() >= I::Signed::truncate(0) {
107			self.unbound.fmt(f)
108		} else {
109			f.write_str("None")
110		}
111	}
112}
113impl<'n, I: Index> PartialEq<Dim<'n>> for Idx<'n, I> {
114	#[inline(always)]
115	fn eq(&self, other: &Dim<'n>) -> bool {
116		equator::debug_assert!(self.unbound.zx() < other.unbound);
117		false
118	}
119}
120impl<'n, I: Index> PartialOrd<Dim<'n>> for Idx<'n, I> {
121	#[inline(always)]
122	fn partial_cmp(&self, other: &Dim<'n>) -> Option<core::cmp::Ordering> {
123		equator::debug_assert!(self.unbound.zx() < other.unbound);
124		Some(core::cmp::Ordering::Less)
125	}
126}
127impl<'n, I: Index> PartialEq<Dim<'n>> for IdxInc<'n, I> {
128	#[inline(always)]
129	fn eq(&self, other: &Dim<'n>) -> bool {
130		equator::debug_assert!(self.unbound.zx() <= other.unbound);
131		self.unbound.zx() == other.unbound
132	}
133}
134impl<'n, I: Index> PartialOrd<Dim<'n>> for IdxInc<'n, I> {
135	#[inline(always)]
136	fn partial_cmp(&self, other: &Dim<'n>) -> Option<core::cmp::Ordering> {
137		equator::debug_assert!(self.unbound.zx() <= other.unbound);
138		Some(if self.unbound.zx() == other.unbound {
139			core::cmp::Ordering::Equal
140		} else {
141			core::cmp::Ordering::Less
142		})
143	}
144}
145impl<'n> Dim<'n> {
146	/// create new branded value with the value `dim`.
147	#[inline(always)]
148	pub fn with<R>(dim: usize, f: impl for<'dim> FnOnce(Dim<'dim>) -> R) -> R {
149		f(unsafe { Self::new_unbound(dim) })
150	}
151
152	/// create new branded value with an arbitrary brand.
153	/// # safety
154	/// see struct safety invariant.
155	#[inline(always)]
156	pub const unsafe fn new_unbound(dim: usize) -> Self {
157		Self {
158			unbound: dim,
159			__marker: PhantomData,
160		}
161	}
162
163	/// create new branded value with a unique brand.
164	#[inline(always)]
165	pub fn new(dim: usize, guard: Guard<'n>) -> Self {
166		_ = guard;
167		Self {
168			unbound: dim,
169			__marker: PhantomData,
170		}
171	}
172
173	/// returns the unconstrained value.
174	#[inline(always)]
175	pub const fn unbound(self) -> usize {
176		self.unbound
177	}
178
179	/// partitions `self` into two segments as specifiedd by the midpoint.
180	#[inline]
181	pub const fn partition<'head, 'tail>(
182		self,
183		midpoint: IdxInc<'n>,
184		head: Guard<'head>,
185		tail: Guard<'tail>,
186	) -> Partition<'head, 'tail, 'n> {
187		_ = (head, tail);
188		unsafe {
189			Partition {
190				head: Dim::new_unbound(midpoint.unbound),
191				tail: Dim::new_unbound(self.unbound - midpoint.unbound),
192				__marker: PhantomData,
193			}
194		}
195	}
196
197	/// partitions `self` into two segments.
198	#[inline]
199	#[track_caller]
200	pub fn head_partition<'head, 'tail>(
201		self,
202		head: Dim<'head>,
203		tail: Guard<'tail>,
204	) -> Partition<'head, 'tail, 'n> {
205		_ = (head, tail);
206		let midpoint = IdxInc::new_checked(head.unbound(), self);
207		unsafe {
208			Partition {
209				head,
210				tail: Dim::new_unbound(self.unbound - midpoint.unbound),
211				__marker: PhantomData,
212			}
213		}
214	}
215
216	/// returns `start` advanced by `len` units, saturated to `self`
217	#[inline]
218	pub fn advance(self, start: Idx<'n>, len: usize) -> IdxInc<'n> {
219		let len = Ord::min(self.unbound.saturating_sub(start.unbound), len);
220		IdxInc {
221			unbound: start.unbound + len,
222			__marker: PhantomData,
223		}
224	}
225
226	/// returns an iterator over the indices between `0` and `self`.
227	#[inline]
228	pub fn indices(
229		self,
230	) -> impl Clone + ExactSizeIterator + DoubleEndedIterator<Item = Idx<'n>> {
231		(0..self.unbound).map(|i| unsafe { Idx::new_unbound(i) })
232	}
233
234	/// returns an iterator over the indices between `0` and `self`.
235	#[inline]
236	#[cfg(feature = "rayon")]
237	pub fn par_indices(
238		self,
239	) -> impl rayon::iter::IndexedParallelIterator<Item = Idx<'n>> {
240		use rayon::prelude::*;
241		(0..self.unbound)
242			.into_par_iter()
243			.map(|i| unsafe { Idx::new_unbound(i) })
244	}
245}
246impl<'n, I: Index> Idx<'n, I> {
247	/// create new branded value with an arbitrary brand.
248	/// # safety
249	/// see struct safety invariant.
250	#[inline(always)]
251	pub const unsafe fn new_unbound(idx: I) -> Self {
252		Self {
253			unbound: idx,
254			__marker: PhantomData,
255		}
256	}
257
258	/// create new branded value with the same brand as `Dim`.
259	/// # safety
260	/// the behavior is undefined unless `idx < dim` and `idx <=
261	/// i::signed::max`.
262	#[inline(always)]
263	pub unsafe fn new_unchecked(idx: I, dim: Dim<'n>) -> Self {
264		equator::debug_assert!(all(
265			idx.zx() < dim.unbound,
266			idx <= I::from_signed(I::Signed::MAX),
267		));
268		Self {
269			unbound: idx,
270			__marker: PhantomData,
271		}
272	}
273
274	/// create new branded value with the same brand as `Dim`.
275	/// # panics
276	/// panics unless `idx < dim` and `idx <= i::signed::max`.
277	#[inline(always)]
278	#[track_caller]
279	pub fn new_checked(idx: I, dim: Dim<'n>) -> Self {
280		equator::assert!(all(
281			idx.zx() < dim.unbound,
282			idx <= I::from_signed(I::Signed::MAX),
283		));
284		Self {
285			unbound: idx,
286			__marker: PhantomData,
287		}
288	}
289
290	/// returns the unconstrained value.
291	#[inline(always)]
292	pub const fn unbound(self) -> I {
293		self.unbound
294	}
295
296	/// zero-extends the internal value into a `usize`.
297	#[inline(always)]
298	pub fn zx(self) -> Idx<'n> {
299		Idx {
300			unbound: self.unbound.zx(),
301			__marker: PhantomData,
302		}
303	}
304}
305impl<'n> IdxInc<'n> {
306	/// zero index
307	pub const ZERO: Self = unsafe { Self::new_unbound(0) };
308}
309impl<'n, I: Index> IdxInc<'n, I> {
310	/// create new branded value with an arbitrary brand.
311	/// # safety
312	/// see struct safety invariant.
313	#[inline(always)]
314	pub const unsafe fn new_unbound(idx: I) -> Self {
315		Self {
316			unbound: idx,
317			__marker: PhantomData,
318		}
319	}
320
321	/// create new branded value with the same brand as `Dim`.
322	/// # safety
323	/// the behavior is undefined unless `idx <= dim`.
324	#[inline(always)]
325	pub unsafe fn new_unchecked(idx: I, dim: Dim<'n>) -> Self {
326		equator::debug_assert!(all(
327			idx.zx() <= dim.unbound,
328			idx <= I::from_signed(I::Signed::MAX),
329		));
330		Self {
331			unbound: idx,
332			__marker: PhantomData,
333		}
334	}
335
336	/// create new branded value with the same brand as `Dim`.
337	/// # panics
338	/// panics unless `idx <= dim`.
339	#[inline(always)]
340	#[track_caller]
341	pub fn new_checked(idx: I, dim: Dim<'n>) -> Self {
342		equator::assert!(all(
343			idx.zx() <= dim.unbound,
344			idx <= I::from_signed(I::Signed::MAX),
345		));
346		Self {
347			unbound: idx,
348			__marker: PhantomData,
349		}
350	}
351
352	/// returns the unconstrained value.
353	#[inline(always)]
354	pub const fn unbound(self) -> I {
355		self.unbound
356	}
357
358	/// zero-extends the internal value into a `usize`.
359	#[inline(always)]
360	pub fn zx(self) -> IdxInc<'n> {
361		IdxInc {
362			unbound: self.unbound.zx(),
363			__marker: PhantomData,
364		}
365	}
366}
367impl<'n> IdxInc<'n> {
368	/// returns an iterator over the indices between `self` and `to`.
369	#[inline]
370	pub fn to(
371		self,
372		upper: IdxInc<'n>,
373	) -> impl Clone + ExactSizeIterator + DoubleEndedIterator<Item = Idx<'n>> {
374		(self.unbound..upper.unbound).map(|i| unsafe { Idx::new_unbound(i) })
375	}
376
377	/// returns an iterator over the indices between `self` and `to`.
378	#[inline]
379	pub fn range_to(
380		self,
381		upper: IdxInc<'n>,
382	) -> impl Clone + ExactSizeIterator + DoubleEndedIterator<Item = Idx<'n>> {
383		(self.unbound..upper.unbound).map(|i| unsafe { Idx::new_unbound(i) })
384	}
385}
386impl Unbind for Dim<'_> {
387	#[inline(always)]
388	unsafe fn new_unbound(idx: usize) -> Self {
389		Self::new_unbound(idx)
390	}
391
392	#[inline(always)]
393	fn unbound(self) -> usize {
394		self.unbound
395	}
396}
397impl<I: Index> Unbind<I> for Idx<'_, I> {
398	#[inline(always)]
399	unsafe fn new_unbound(idx: I) -> Self {
400		Self::new_unbound(idx)
401	}
402
403	#[inline(always)]
404	fn unbound(self) -> I {
405		self.unbound
406	}
407}
408impl<I: Index> Unbind<I> for IdxInc<'_, I> {
409	#[inline(always)]
410	unsafe fn new_unbound(idx: I) -> Self {
411		Self::new_unbound(idx)
412	}
413
414	#[inline(always)]
415	fn unbound(self) -> I {
416		self.unbound
417	}
418}
419impl<I: Index> Unbind<I::Signed> for MaybeIdx<'_, I> {
420	#[inline(always)]
421	unsafe fn new_unbound(idx: I::Signed) -> Self {
422		Self::new_unbound(I::from_signed(idx))
423	}
424
425	#[inline(always)]
426	fn unbound(self) -> I::Signed {
427		self.unbound.to_signed()
428	}
429}
430impl<'dim> ShapeIdx for Dim<'dim> {
431	type Idx<I: Index> = Idx<'dim, I>;
432	type IdxInc<I: Index> = IdxInc<'dim, I>;
433	type MaybeIdx<I: Index> = MaybeIdx<'dim, I>;
434}
435impl<'dim> Shape for Dim<'dim> {}
436impl<'n, I: Index> From<Idx<'n, I>> for IdxInc<'n, I> {
437	#[inline(always)]
438	fn from(value: Idx<'n, I>) -> Self {
439		Self {
440			unbound: value.unbound,
441			__marker: PhantomData,
442		}
443	}
444}
445impl<'n> From<Dim<'n>> for IdxInc<'n> {
446	#[inline(always)]
447	fn from(value: Dim<'n>) -> Self {
448		Self {
449			unbound: value.unbound,
450			__marker: PhantomData,
451		}
452	}
453}
454impl<'n, I: Index> From<Idx<'n, I>> for MaybeIdx<'n, I> {
455	#[inline(always)]
456	fn from(value: Idx<'n, I>) -> Self {
457		Self {
458			unbound: value.unbound,
459			__marker: PhantomData,
460		}
461	}
462}
463impl<'size> Dim<'size> {
464	/// check that the index is bounded by `self`, or panic otherwise.
465	#[track_caller]
466	#[inline]
467	pub fn check<I: Index>(self, idx: I) -> Idx<'size, I> {
468		Idx::new_checked(idx, self)
469	}
470
471	/// check that the index is bounded by `self`, or panic otherwise.
472	#[track_caller]
473	#[inline]
474	pub fn idx<I: Index>(self, idx: I) -> Idx<'size, I> {
475		Idx::new_checked(idx, self)
476	}
477
478	/// check that the index is bounded by `self`, or panic otherwise.
479	#[track_caller]
480	#[inline]
481	pub fn idx_inc<I: Index>(self, idx: I) -> IdxInc<'size, I> {
482		IdxInc::new_checked(idx, self)
483	}
484
485	/// check that the index is bounded by `self`, or return `none` otherwise.
486	#[inline]
487	pub fn try_check<I: Index>(self, idx: I) -> Option<Idx<'size, I>> {
488		if idx.zx() < self.unbound() {
489			Some(unsafe { Idx::new_unbound(idx) })
490		} else {
491			None
492		}
493	}
494}
495impl<'n> Idx<'n> {
496	/// truncate `self` to a smaller type `i`.
497	pub fn truncate<I: Index>(self) -> Idx<'n, I> {
498		unsafe { Idx::new_unbound(I::truncate(self.unbound())) }
499	}
500}
501impl<'n, I: Index> Idx<'n, I> {
502	/// returns the index, bounded inclusively by the value tied to `'n`.
503	#[inline]
504	pub const fn to_incl(self) -> IdxInc<'n, I> {
505		unsafe { IdxInc::new_unbound(self.unbound()) }
506	}
507
508	/// returns the next index, bounded inclusively by the value tied to `'n`.
509	#[inline]
510	pub fn next(self) -> IdxInc<'n, I> {
511		unsafe { IdxInc::new_unbound(self.unbound() + I::truncate(1)) }
512	}
513
514	/// returns the index, bounded inclusively by the value tied to `'n`.
515	#[inline]
516	pub fn excl(self) -> IdxInc<'n, I> {
517		unsafe { IdxInc::new_unbound(self.unbound()) }
518	}
519
520	/// assert that the values of `slice` are all bounded by `size`.
521	#[track_caller]
522	#[inline]
523	pub fn from_slice_mut_checked<'a>(
524		slice: &'a mut [I],
525		size: Dim<'n>,
526	) -> &'a mut [Idx<'n, I>] {
527		Self::from_slice_ref_checked(slice, size);
528		unsafe { &mut *(slice as *mut _ as *mut _) }
529	}
530
531	/// assume that the values of `slice` are all bounded by the value tied to
532	/// `'n`.
533	#[track_caller]
534	#[inline]
535	pub unsafe fn from_slice_mut_unchecked<'a>(
536		slice: &'a mut [I],
537	) -> &'a mut [Idx<'n, I>] {
538		unsafe { &mut *(slice as *mut _ as *mut _) }
539	}
540
541	/// assert that the values of `slice` are all bounded by `size`.
542	#[track_caller]
543	pub fn from_slice_ref_checked<'a>(
544		slice: &'a [I],
545		size: Dim<'n>,
546	) -> &'a [Idx<'n, I>] {
547		for &idx in slice {
548			Self::new_checked(idx, size);
549		}
550		unsafe { &*(slice as *const _ as *const _) }
551	}
552
553	/// assume that the values of `slice` are all bounded by the value tied to
554	/// `'n`.
555	#[track_caller]
556	#[inline]
557	pub unsafe fn from_slice_ref_unchecked<'a>(
558		slice: &'a [I],
559	) -> &'a [Idx<'n, I>] {
560		unsafe { &*(slice as *const _ as *const _) }
561	}
562}
563/// `i` value smaller than the size corresponding to the lifetime `'n`, or
564/// `none`.
565#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
566#[repr(transparent)]
567pub struct MaybeIdx<'n, I: Index = usize> {
568	unbound: I,
569	__marker: PhantomData<Invariant<'n>>,
570}
571impl<'n, I: Index> MaybeIdx<'n, I> {
572	/// returns an index value.
573	#[inline]
574	pub fn from_index(idx: Idx<'n, I>) -> Self {
575		unsafe { Self::new_unbound(idx.unbound()) }
576	}
577
578	/// returns a `none` value.
579	#[inline]
580	pub fn none() -> Self {
581		unsafe { Self::new_unbound(I::truncate(usize::MAX)) }
582	}
583
584	/// returns a constrained index value if `idx` is nonnegative, `none`
585	/// otherwise.
586	#[inline]
587	#[track_caller]
588	pub fn new_checked(idx: I::Signed, size: Dim<'n>) -> Self {
589		assert!((idx.sx() as isize) < size.unbound() as isize);
590		Self {
591			unbound: I::from_signed(idx),
592			__marker: PhantomData,
593		}
594	}
595
596	/// returns a constrained index value if `idx` is nonnegative, `none`
597	/// otherwise.
598	#[inline]
599	pub unsafe fn new_unchecked(idx: I::Signed, size: Dim<'n>) -> Self {
600		debug_assert!((idx.sx() as isize) < size.unbound() as isize);
601		Self {
602			unbound: I::from_signed(idx),
603			__marker: PhantomData,
604		}
605	}
606
607	/// returns a constrained index value if `idx` is nonnegative, `none`
608	/// otherwise.
609	#[inline]
610	pub unsafe fn new_unbound(idx: I) -> Self {
611		Self {
612			unbound: idx,
613			__marker: PhantomData,
614		}
615	}
616
617	/// returns the inner value.
618	#[inline]
619	pub fn unbound(self) -> I {
620		self.unbound
621	}
622
623	/// returns the index if available, or `none` otherwise.
624	#[inline]
625	pub fn idx(self) -> Option<Idx<'n, I>> {
626		if self.unbound.to_signed() >= I::Signed::truncate(0) {
627			Some(unsafe { Idx::new_unbound(self.unbound()) })
628		} else {
629			None
630		}
631	}
632
633	/// sign extend the value.
634	#[inline]
635	pub fn sx(self) -> MaybeIdx<'n> {
636		unsafe { MaybeIdx::new_unbound(self.unbound.to_signed().sx()) }
637	}
638
639	/// assert that the values of `slice` are all bounded by `size`.
640	#[track_caller]
641	#[inline]
642	pub fn from_slice_mut_checked<'a>(
643		slice: &'a mut [I::Signed],
644		size: Dim<'n>,
645	) -> &'a mut [MaybeIdx<'n, I>] {
646		Self::from_slice_ref_checked(slice, size);
647		unsafe { &mut *(slice as *mut _ as *mut _) }
648	}
649
650	/// assume that the values of `slice` are all bounded by the value tied to
651	/// `'n`.
652	#[track_caller]
653	#[inline]
654	pub unsafe fn from_slice_mut_unchecked<'a>(
655		slice: &'a mut [I::Signed],
656	) -> &'a mut [MaybeIdx<'n, I>] {
657		unsafe { &mut *(slice as *mut _ as *mut _) }
658	}
659
660	/// assert that the values of `slice` are all bounded by `size`.
661	#[track_caller]
662	pub fn from_slice_ref_checked<'a>(
663		slice: &'a [I::Signed],
664		size: Dim<'n>,
665	) -> &'a [MaybeIdx<'n, I>] {
666		for &idx in slice {
667			Self::new_checked(idx, size);
668		}
669		unsafe { &*(slice as *const _ as *const _) }
670	}
671
672	/// convert a constrained slice to an unconstrained one.
673	#[track_caller]
674	pub fn as_slice_ref<'a>(slice: &'a [MaybeIdx<'n, I>]) -> &'a [I::Signed] {
675		unsafe { &*(slice as *const _ as *const _) }
676	}
677
678	/// assume that the values of `slice` are all bounded by the value tied to
679	/// `'n`.
680	#[track_caller]
681	#[inline]
682	pub unsafe fn from_slice_ref_unchecked<'a>(
683		slice: &'a [I::Signed],
684	) -> &'a [MaybeIdx<'n, I>] {
685		unsafe { &*(slice as *const _ as *const _) }
686	}
687}
688impl core::ops::Deref for Dim<'_> {
689	type Target = usize;
690
691	#[inline]
692	fn deref(&self) -> &Self::Target {
693		&self.unbound
694	}
695}
696impl<I: Index> core::ops::Deref for MaybeIdx<'_, I> {
697	type Target = I::Signed;
698
699	#[inline]
700	fn deref(&self) -> &Self::Target {
701		bytemuck::cast_ref(&self.unbound)
702	}
703}
704impl<I: Index> core::ops::Deref for Idx<'_, I> {
705	type Target = I;
706
707	#[inline]
708	fn deref(&self) -> &Self::Target {
709		&self.unbound
710	}
711}
712impl<I: Index> core::ops::Deref for IdxInc<'_, I> {
713	type Target = I;
714
715	#[inline]
716	fn deref(&self) -> &Self::Target {
717		&self.unbound
718	}
719}
720/// array of length equal to the value tied to `'n`.
721#[derive(PartialEq, Eq, PartialOrd, Ord)]
722#[repr(transparent)]
723pub struct Array<'n, T> {
724	__marker: PhantomData<Invariant<'n>>,
725	unbound: [T],
726}
727impl<'n, T> Array<'n, T> {
728	/// returns a constrained array after checking that its length matches
729	/// `size`.
730	#[inline]
731	#[track_caller]
732	pub fn from_ref<'a>(slice: &'a [T], size: Dim<'n>) -> &'a Self {
733		assert!(slice.len() == size.unbound());
734		unsafe { &*(slice as *const [T] as *const Self) }
735	}
736
737	/// returns a constrained array after checking that its length matches
738	/// `size`.
739	#[inline]
740	#[track_caller]
741	pub fn from_mut<'a>(slice: &'a mut [T], size: Dim<'n>) -> &'a mut Self {
742		assert!(slice.len() == size.unbound());
743		unsafe { &mut *(slice as *mut [T] as *mut Self) }
744	}
745
746	/// returns the unconstrained slice.
747	#[inline]
748	#[track_caller]
749	pub fn as_ref(&self) -> &[T] {
750		unsafe { &*(self as *const _ as *const _) }
751	}
752
753	/// returns the unconstrained slice.
754	#[inline]
755	#[track_caller]
756	pub fn as_mut<'a>(&mut self) -> &'a mut [T] {
757		unsafe { &mut *(self as *mut _ as *mut _) }
758	}
759
760	/// returns the length of `self`.
761	#[inline]
762	pub fn len(&self) -> Dim<'n> {
763		unsafe { Dim::new_unbound(self.unbound.len()) }
764	}
765}
766impl<T: core::fmt::Debug> core::fmt::Debug for Array<'_, T> {
767	#[inline]
768	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
769		self.unbound.fmt(f)
770	}
771}
772impl<'n, T> core::ops::Index<Range<IdxInc<'n>>> for Array<'n, T> {
773	type Output = [T];
774
775	#[track_caller]
776	fn index(&self, idx: Range<IdxInc<'n>>) -> &Self::Output {
777		#[cfg(debug_assertions)]
778		{
779			&self.unbound[idx.start.unbound()..idx.end.unbound()]
780		}
781		#[cfg(not(debug_assertions))]
782		unsafe {
783			self.unbound
784				.get_unchecked(idx.start.unbound()..idx.end.unbound())
785		}
786	}
787}
788impl<'n, T> core::ops::IndexMut<Range<IdxInc<'n>>> for Array<'n, T> {
789	#[track_caller]
790	fn index_mut(&mut self, idx: Range<IdxInc<'n>>) -> &mut Self::Output {
791		#[cfg(debug_assertions)]
792		{
793			&mut self.unbound[idx.start.unbound()..idx.end.unbound()]
794		}
795		#[cfg(not(debug_assertions))]
796		unsafe {
797			self.unbound
798				.get_unchecked_mut(idx.start.unbound()..idx.end.unbound())
799		}
800	}
801}
802impl<'n, T> core::ops::Index<Idx<'n>> for Array<'n, T> {
803	type Output = T;
804
805	#[track_caller]
806	fn index(&self, idx: Idx<'n>) -> &Self::Output {
807		#[cfg(debug_assertions)]
808		{
809			&self.unbound[idx.unbound()]
810		}
811		#[cfg(not(debug_assertions))]
812		unsafe {
813			self.unbound.get_unchecked(idx.unbound())
814		}
815	}
816}
817impl<'n, T> core::ops::IndexMut<Idx<'n>> for Array<'n, T> {
818	#[track_caller]
819	fn index_mut(&mut self, idx: Idx<'n>) -> &mut Self::Output {
820		#[cfg(debug_assertions)]
821		{
822			&mut self.unbound[idx.unbound()]
823		}
824		#[cfg(not(debug_assertions))]
825		unsafe {
826			self.unbound.get_unchecked_mut(idx.unbound())
827		}
828	}
829}
830/// dimension equal to one
831#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
832pub struct One;
833/// index equal to zero
834#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
835pub struct Zero;
836/// index equal to zero ro one
837#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
838pub struct IdxIncOne<I: Index = usize> {
839	inner: I,
840}
841/// index equal to zero ro one, or a sentinel value
842#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
843pub struct MaybeIdxOne<I: Index = usize> {
844	inner: I,
845}
846impl<I: Index> Unbind<I> for IdxIncOne<I> {
847	#[inline]
848	unsafe fn new_unbound(idx: I) -> Self {
849		Self { inner: idx }
850	}
851
852	#[inline]
853	fn unbound(self) -> I {
854		self.inner
855	}
856}
857impl<I: Index> Unbind<I::Signed> for MaybeIdxOne<I> {
858	#[inline]
859	unsafe fn new_unbound(idx: I::Signed) -> Self {
860		Self {
861			inner: I::from_signed(idx),
862		}
863	}
864
865	#[inline]
866	fn unbound(self) -> I::Signed {
867		self.inner.to_signed()
868	}
869}
870impl<I: Index> Unbind<I> for Zero {
871	#[inline]
872	unsafe fn new_unbound(idx: I) -> Self {
873		equator::debug_assert!(idx.zx() == 0);
874		Zero
875	}
876
877	#[inline]
878	fn unbound(self) -> I {
879		I::truncate(0)
880	}
881}
882impl Unbind for One {
883	#[inline]
884	unsafe fn new_unbound(idx: usize) -> Self {
885		equator::debug_assert!(idx == 1);
886		One
887	}
888
889	#[inline]
890	fn unbound(self) -> usize {
891		1
892	}
893}
894impl<I: Index> From<Zero> for IdxIncOne<I> {
895	fn from(_: Zero) -> Self {
896		Self {
897			inner: I::truncate(0),
898		}
899	}
900}
901impl ShapeIdx for One {
902	type Idx<I: Index> = Zero;
903	type IdxInc<I: Index> = IdxIncOne<I>;
904	type MaybeIdx<I: Index> = MaybeIdxOne<I>;
905}
906impl PartialEq<One> for IdxIncOne {
907	#[inline]
908	fn eq(&self, _: &One) -> bool {
909		self.inner == 1
910	}
911}
912impl PartialOrd<One> for IdxIncOne {
913	#[inline]
914	fn partial_cmp(&self, _: &One) -> Option<core::cmp::Ordering> {
915		if self.inner == 1 {
916			Some(core::cmp::Ordering::Equal)
917		} else {
918			Some(core::cmp::Ordering::Less)
919		}
920	}
921}
922impl PartialEq<One> for Zero {
923	#[inline]
924	fn eq(&self, _: &One) -> bool {
925		false
926	}
927}
928impl PartialOrd<One> for Zero {
929	#[inline]
930	fn partial_cmp(&self, _: &One) -> Option<core::cmp::Ordering> {
931		Some(core::cmp::Ordering::Less)
932	}
933}
934impl Shape for One {
935	const IS_BOUND: bool = true;
936}