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#[derive(Copy, Clone, Debug, PartialEq, Eq)]
9pub struct Partition<'head, 'tail, 'n> {
10 pub head: Dim<'head>,
12 pub tail: Dim<'tail>,
14 __marker: PhantomData<Invariant<'n>>,
15}
16impl<'head, 'tail, 'n> Partition<'head, 'tail, 'n> {
17 #[inline]
19 pub const fn midpoint(&self) -> IdxInc<'n> {
20 unsafe { IdxInc::new_unbound(self.head.unbound) }
21 }
22
23 #[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#[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#[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#[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 #[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 #[inline(always)]
156 pub const unsafe fn new_unbound(dim: usize) -> Self {
157 Self {
158 unbound: dim,
159 __marker: PhantomData,
160 }
161 }
162
163 #[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 #[inline(always)]
175 pub const fn unbound(self) -> usize {
176 self.unbound
177 }
178
179 #[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 #[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 #[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 #[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 #[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 #[inline(always)]
251 pub const unsafe fn new_unbound(idx: I) -> Self {
252 Self {
253 unbound: idx,
254 __marker: PhantomData,
255 }
256 }
257
258 #[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 #[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 #[inline(always)]
292 pub const fn unbound(self) -> I {
293 self.unbound
294 }
295
296 #[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 pub const ZERO: Self = unsafe { Self::new_unbound(0) };
308}
309impl<'n, I: Index> IdxInc<'n, I> {
310 #[inline(always)]
314 pub const unsafe fn new_unbound(idx: I) -> Self {
315 Self {
316 unbound: idx,
317 __marker: PhantomData,
318 }
319 }
320
321 #[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 #[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 #[inline(always)]
354 pub const fn unbound(self) -> I {
355 self.unbound
356 }
357
358 #[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 #[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 #[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 #[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 #[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 #[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 #[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 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 #[inline]
504 pub const fn to_incl(self) -> IdxInc<'n, I> {
505 unsafe { IdxInc::new_unbound(self.unbound()) }
506 }
507
508 #[inline]
510 pub fn next(self) -> IdxInc<'n, I> {
511 unsafe { IdxInc::new_unbound(self.unbound() + I::truncate(1)) }
512 }
513
514 #[inline]
516 pub fn excl(self) -> IdxInc<'n, I> {
517 unsafe { IdxInc::new_unbound(self.unbound()) }
518 }
519
520 #[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 #[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 #[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 #[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#[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 #[inline]
574 pub fn from_index(idx: Idx<'n, I>) -> Self {
575 unsafe { Self::new_unbound(idx.unbound()) }
576 }
577
578 #[inline]
580 pub fn none() -> Self {
581 unsafe { Self::new_unbound(I::truncate(usize::MAX)) }
582 }
583
584 #[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 #[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 #[inline]
610 pub unsafe fn new_unbound(idx: I) -> Self {
611 Self {
612 unbound: idx,
613 __marker: PhantomData,
614 }
615 }
616
617 #[inline]
619 pub fn unbound(self) -> I {
620 self.unbound
621 }
622
623 #[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 #[inline]
635 pub fn sx(self) -> MaybeIdx<'n> {
636 unsafe { MaybeIdx::new_unbound(self.unbound.to_signed().sx()) }
637 }
638
639 #[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 #[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 #[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 #[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 #[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#[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 #[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 #[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 #[inline]
748 #[track_caller]
749 pub fn as_ref(&self) -> &[T] {
750 unsafe { &*(self as *const _ as *const _) }
751 }
752
753 #[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 #[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#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
832pub struct One;
833#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
835pub struct Zero;
836#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
838pub struct IdxIncOne<I: Index = usize> {
839 inner: I,
840}
841#[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}