1use crate::CubeSurfacePoint as CratePt;
78use crate::Direction;
79use crate::Rotation;
80use core::convert::identity as id;
81use core::ops::{Div, Mul, MulAssign};
82
83pub type CspLarge = CubeSurfacePoint<true>;
91
92#[doc(hidden)]
93#[allow(non_snake_case)]
94pub const fn CspLarge(x: CratePt) -> CspLarge {
95 CubeSurfacePoint::<true>(x)
96}
97
98pub type CspSmall = CubeSurfacePoint<false>;
106
107#[doc(hidden)]
108#[allow(non_snake_case)]
109pub const fn CspSmall(x: CratePt) -> CspSmall {
110 CubeSurfacePoint::<false>(x)
111}
112
113pub type RgpLarge = ReferenceGroupPoint;
121
122#[doc(hidden)]
123#[allow(non_snake_case)]
124pub const fn RgpLarge(x: crate::ReferenceGroupPoint) -> RgpLarge {
125 ReferenceGroupPoint(x)
126}
127
128pub type OgpLarge = OppositeGroupPoint;
136
137#[doc(hidden)]
138#[allow(non_snake_case)]
139pub const fn OgpLarge(x: crate::OppositeGroupPoint) -> OgpLarge {
140 OppositeGroupPoint(x)
141}
142
143macro_rules! with_lut {
144 ($truefalse: expr; $fnam: ident $(; $vis:vis)?) => {
145
146 #[doc = concat!(
147 "Please refer to the [function of the same name](crate::",
148 stringify!(CubeSurfacePoint),
149 "::",
150 stringify!($fnam),
151 ") in the basic [`",
152 stringify!(CubeSurfacePoint),
153 "`](crate::",
154 stringify!(CubeSurfacePoint),
155 ")."
156 )]
157 $($vis)? const fn $fnam(self) -> Self {
158 type Csp = CubeSurfacePoint::<{ $truefalse }>;
159
160 const fn from_serial_number(x: u8) -> Csp {
161 CubeSurfacePoint::<{ $truefalse }> (
162 CratePt::probs_from_u8(x).$fnam()
163 )
164 }
165
166 const LUT: [Csp; 48] = {
167 let mut result = [Csp::REFERENCE_POINT; 48];
168 let mut i = 48;
169 while i > 0 {
170 i -= 1;
171 result[i] = from_serial_number(i as u8);
172 }
173 result
174 };
175
176 LUT[self.0 as usize]
177 }
178
179 };
180
181 (true; $name: ident, $($names:ident),+ $(; $vis:vis)?) => {
182 with_lut!(true; $name $(; $vis)?);
183 with_lut!(true; $($names),+ $(; $vis)?);
184 };
185
186 (false; $name: ident, $($names:ident),+ $(; $vis:vis)?) => {
187 with_lut!(false; $name $(; $vis)?);
188 with_lut!(false; $($names),+ $(; $vis)?);
189 };
190}
191
192#[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
200pub struct CubeSurfacePoint<const BIG_LUTS: bool>(pub crate::CubeSurfacePoint);
201
202impl<const BIG_LUTS: bool> CubeSurfacePoint<BIG_LUTS> {
203 pub const REFERENCE_POINT: Self = Self(CratePt::REFERENCE_POINT);
206
207 #[doc = concat!(
208 "Please refer to the [function of the same name]",
209 "(crate::CubeSurfacePoint::direction", ") in [`CubeSurfacePoint`]."
210 )]
211 pub const fn direction(self) -> Direction {
212 const fn from_serial_number(x: u8) -> Direction {
213 CratePt::probs_from_u8(x).direction()
214 }
215
216 const LUT: [Direction; 48] = {
217 let ref_pt = CratePt::REFERENCE_POINT;
218 let mut result = [ref_pt.direction(); 48];
219 let mut i = 48;
220 while i > 0 {
221 i -= 1;
222 result[i] = from_serial_number(i as u8);
223 }
224 result
225 };
226 LUT[self.0 as usize]
227 }
228
229 const fn probs_from_u8(x: u8) -> Self {
230 Self(CratePt::probs_from_u8(x))
231 }
232}
233
234impl<const BIG_LUTS: bool> From<CratePt> for CubeSurfacePoint<BIG_LUTS> {
235 fn from(x: CratePt) -> Self {
236 Self(x)
237 }
238}
239
240impl<const BIG_LUTS: bool> From<CubeSurfacePoint<BIG_LUTS>> for CratePt {
241 fn from(x: CubeSurfacePoint<BIG_LUTS>) -> Self {
242 x.0
243 }
244}
245
246impl From<Rotation> for CubeSurfacePoint<true> {
247 fn from(x: Rotation) -> Self {
248 Self(x.corresponding_point)
249 }
250}
251
252impl From<Rotation> for CubeSurfacePoint<false> {
253 fn from(x: Rotation) -> Self {
254 Self(x.corresponding_point)
255 }
256}
257
258impl CubeSurfacePoint<false> {
259 with_lut!(false; one_right_angle_cw, one_right_angle_acw, beside,
260 opposite, opposite_then_beside, flip_sign_of_2, flip_2_and_3; pub);
261 with_lut!(false; swap_x_y, swap_y_z, swap_z_x, reciprocal);
262
263 #[doc = concat!(
264 "Please refer to the [function of the same name
265 ](crate::CubeSurfacePoint::",
266 stringify!(n_right_angles),
267 ") in [`CubeSurfacePoint`](crate::CubeSurfacePoint)."
268 )]
269 pub const fn n_right_angles<const CLOCKWISE: bool>(self, angle: u8) -> Self {
270 let mut angle = angle & 0b11;
271 let mut result = self;
272 while angle > 0 {
273 result = if CLOCKWISE {
274 result.one_right_angle_cw()
275 } else {
276 result.one_right_angle_acw()
277 };
278 angle -= 1;
279 }
280 result
281 }
282
283 #[doc = concat!(
284 "Please refer to the [function of the same name
285 ](crate::CubeSurfacePoint::",
286 stringify!(n_right_angles_acw),
287 ") in [`CubeSurfacePoint`](crate::CubeSurfacePoint)."
288 )]
289 pub const fn n_right_angles_acw(self, angle: u8) -> Self {
290 self.n_right_angles::<false>(angle)
291 }
292
293 #[doc = concat!(
294 "Please refer to the [function of the same name
295 ](crate::CubeSurfacePoint::",
296 stringify!(n_right_angles_cw),
297 ") in [`CubeSurfacePoint`](crate::CubeSurfacePoint)."
298 )]
299 pub const fn n_right_angles_cw(self, angle: u8) -> Self {
300 self.n_right_angles::<true>(angle)
301 }
302}
303
304impl CubeSurfacePoint<true> {
305 with_lut!(true; one_right_angle_cw, one_right_angle_acw, beside,
306 opposite, opposite_then_beside, flip_sign_of_2, flip_2_and_3; pub);
307
308 #[doc = concat!(
309 "Please refer to the [function of the same name
310 ](crate::CubeSurfacePoint::",
311 stringify!(n_right_angles_cw),
312 ") in [`CubeSurfacePoint`](crate::CubeSurfacePoint)."
313 )]
314 pub const fn n_right_angles_cw(self, angle: u8) -> Self {
315 let angle = angle & 0b11;
316 type Csp = CubeSurfacePoint<true>;
317 const LUT: [[Csp; 48]; 4] = {
318 let mut result = [[Csp::REFERENCE_POINT; 48]; 4];
319 let mut i: usize = 48 * 4;
320 while i > 0 {
321 i -= 1;
322 result[i % 4][i / 4] = CubeSurfacePoint::<true>(
323 CratePt::probs_from_u8(i as u8 / 4).n_right_angles_cw(i as u8 % 4),
324 );
325 }
326 result
327 };
328
329 LUT[angle as usize][self.0 as usize]
330 }
331
332 #[doc = concat!(
333 "Please refer to the [function of the same name
334 ](crate::CubeSurfacePoint::",
335 stringify!(n_right_angles_acw),
336 ") in [`CubeSurfacePoint`](crate::CubeSurfacePoint)."
337 )]
338 pub const fn n_right_angles_acw(self, angle: u8) -> Self {
339 let angle = angle & 0b11;
340 type Csp = CubeSurfacePoint<true>;
341 const LUT: [[Csp; 48]; 4] = {
342 let mut result = [[Csp::REFERENCE_POINT; 48]; 4];
343 let mut i: usize = 48 * 4;
344 while i > 0 {
345 i -= 1;
346 result[i % 4][i / 4] = CubeSurfacePoint::<true>(
347 CratePt::probs_from_u8(i as u8 / 4).n_right_angles_acw(i as u8 % 4),
348 );
349 }
350 result
351 };
352
353 LUT[angle as usize][self.0 as usize]
354 }
355
356 pub fn div_alt(self, divisor: Self) -> Rotation {
360 const RECIPROCALS: [CubeSurfacePoint<true>; 48] = {
361 let mut i = 48;
362 let ref_pt = CubeSurfacePoint::<true>::REFERENCE_POINT;
363 let mut result = [ref_pt; 48];
364 while i > 0 {
365 i -= 1;
366 let pt = CratePt::probs_from_u8(i as u8);
367 let siiiigh = ref_pt.0.mul(ref_pt.0.div(pt));
368 result[i] = CubeSurfacePoint::<true>(siiiigh);
369 }
370 result
371 };
372
373 Rotation {
374 corresponding_point: (Rotation {
375 corresponding_point: self.0,
376 } * RECIPROCALS[divisor.0 as usize])
377 .0,
378 }
379 }
380}
381
382impl Mul<Rotation> for CubeSurfacePoint<false> {
384 type Output = Self;
387
388 fn mul(self, rot: Rotation) -> Self::Output {
391 let rot = rot.corresponding_point as u8;
392 let mut result = self;
393
394 if rot & 0b001_000 != 0 {
395 result = result.swap_z_x();
396 }
397
398 if rot & 0b010_000 != 0 {
399 result = result.swap_y_z();
400 }
401
402 if rot & 0b100_000 != 0 {
403 result = result.swap_x_y();
404 }
405
406 let rot = rot & 7;
407
408 Self::probs_from_u8(result.0 as u8 ^ rot)
409 }
410}
411
412impl Mul<Rotation> for CubeSurfacePoint<true> {
414 type Output = Self;
417
418 fn mul(self, rot: Rotation) -> Self::Output {
421 type Csp = CubeSurfacePoint<true>;
422 const fn from_serial_number(x: u16) -> Csp {
423 let rot = crate::Rotation {
424 corresponding_point: CratePt::probs_from_u8((x / 48) as u8),
425 };
426 let surface_point = CratePt::probs_from_u8((x % 48) as u8);
427 CubeSurfacePoint::<true>(rot.mul(surface_point))
428 }
429 const LUT: [[Csp; 48]; 48] = {
430 let mut result = [[Csp::REFERENCE_POINT; 48]; 48];
431 let mut i = 48 * 48;
432 while i > 0 {
433 i -= 1;
434 result[i / 48][i % 48] = from_serial_number(i as u16);
435 }
436 result
437 };
438
439 LUT[rot.corresponding_point as usize][self.0 as usize]
440 }
441}
442
443impl MulAssign<Rotation> for CubeSurfacePoint<true> {
445 fn mul_assign(&mut self, rot: Rotation) {
451 *self = *self * rot;
452 }
453}
454
455impl MulAssign<Rotation> for CubeSurfacePoint<false> {
457 fn mul_assign(&mut self, rot: Rotation) {
463 *self = *self * rot;
464 }
465}
466
467impl Mul<CubeSurfacePoint<true>> for Rotation {
469 type Output = CubeSurfacePoint<true>;
471
472 fn mul(self, cub_sur_pt: Self::Output) -> Self::Output {
475 cub_sur_pt * self
476 }
477}
478
479impl Mul<CubeSurfacePoint<false>> for Rotation {
481 type Output = CubeSurfacePoint<false>;
483
484 fn mul(self, cub_sur_pt: Self::Output) -> Self::Output {
487 cub_sur_pt * self
488 }
489}
490
491impl Div for CubeSurfacePoint<false> {
494 type Output = Rotation;
496
497 fn div(self, divisor: Self) -> Self::Output {
502 let recip = divisor.reciprocal();
503 let rot = Rotation {
504 corresponding_point: self.0,
505 };
506 Rotation {
507 corresponding_point: (recip.mul(rot)).0,
508 }
509 }
510}
511
512impl Div for CubeSurfacePoint<true> {
515 type Output = Rotation;
517
518 fn div(self, divisor: Self) -> Self::Output {
520 const fn from_serial_number(x: u16) -> Rotation {
521 let divisor = CratePt::probs_from_u8((x / 48) as u8);
522
523 let point = CratePt::probs_from_u8((x % 48) as u8);
524 point.div(divisor)
525 }
526
527 const LUT: [[Rotation; 48]; 48] = {
528 let temp_rot = Rotation {
529 corresponding_point: CratePt::REFERENCE_POINT,
530 };
531 let mut result = [[temp_rot; 48]; 48];
532 let mut i = 48 * 48;
533 while i > 0 {
534 i -= 1;
535 result[i % 48][i / 48] = from_serial_number(i as u16);
536 }
537 result
538 };
539
540 let divisor = divisor.0 as usize;
541 let dividend = self.0 as usize;
542 LUT[dividend][divisor]
543 }
544}
545
546use crate::{ImproperRotation, ProperRotation};
547
548impl Mul<ProperRotation> for CubeSurfacePoint<false> {
551 type Output = Self;
554
555 fn mul(self, x: ProperRotation) -> Self {
558 let rot: Rotation = x.into();
559 rot * self
560 }
561}
562
563impl Mul<ProperRotation> for CubeSurfacePoint<true> {
566 type Output = Self;
569
570 fn mul(self, x: ProperRotation) -> Self {
577 let rot: Rotation = x.into();
578 rot * self
579 }
580}
581
582impl Mul<ImproperRotation> for CubeSurfacePoint<false> {
585 type Output = Self;
589
590 fn mul(self, x: ImproperRotation) -> Self {
593 let rot: Rotation = x.into();
594 rot * self
595 }
596}
597
598impl Mul<ImproperRotation> for CubeSurfacePoint<true> {
601 type Output = Self;
605
606 fn mul(self, x: ImproperRotation) -> Self {
613 let rot: Rotation = x.into();
614 rot * self
615 }
616}
617
618impl MulAssign<ProperRotation> for CubeSurfacePoint<true> {
621 fn mul_assign(&mut self, x: ProperRotation) {
631 *self = *self * x;
632 }
633}
634
635impl MulAssign<ImproperRotation> for CubeSurfacePoint<true> {
638 fn mul_assign(&mut self, x: ImproperRotation) {
648 *self = *self * x;
649 }
650}
651
652fn mul_rots_big_luts(rot_1: Rotation, rot_2: Rotation) -> Rotation {
653 let corr_point: CubeSurfacePoint<true> = rot_2.into();
654 (rot_1 * corr_point).into()
655}
656
657fn div_rots_big_luts(rot_1: Rotation, rot_2: Rotation) -> Rotation {
658 let corr_point_1: CubeSurfacePoint<true> = rot_1.into();
659 let corr_point_2: CubeSurfacePoint<true> = rot_2.into();
660 corr_point_1 / corr_point_2
661}
662
663fn mul_rots_small_luts(rot_1: Rotation, rot_2: Rotation) -> Rotation {
664 let corr_point: CubeSurfacePoint<false> = rot_2.into();
665 (rot_1 * corr_point).into()
666}
667
668fn div_rots_small_luts(rot_1: Rotation, rot_2: Rotation) -> Rotation {
669 let corr_point_1: CubeSurfacePoint<false> = rot_1.into();
670 let corr_point_2: CubeSurfacePoint<false> = rot_2.into();
671 corr_point_1 / corr_point_2
672}
673
674pub fn multiply_rotations_luts<const BIG: bool>(rot_1: Rotation, rot_2: Rotation) -> Rotation {
676 [mul_rots_small_luts, mul_rots_big_luts][BIG as usize](rot_1, rot_2)
677}
678
679pub fn divide_rotations_luts<const BIG: bool>(rot_1: Rotation, rot_2: Rotation) -> Rotation {
681 [div_rots_small_luts, div_rots_big_luts][BIG as usize](rot_1, rot_2)
682}
683
684impl MulAssign<ProperRotation> for CubeSurfacePoint<false> {
687 fn mul_assign(&mut self, x: ProperRotation) {
697 *self = *self * x;
698 }
699}
700
701impl MulAssign<ImproperRotation> for CubeSurfacePoint<false> {
704 fn mul_assign(&mut self, x: ImproperRotation) {
714 *self = *self * x;
715 }
716}
717
718macro_rules! with_lut {
719 ($us: ty, $out: path, $fnam: ident, $convert: ident) => {
720
721 #[doc = concat!(
722 "Please refer to the [function of the same name
723 ](crate::CubeSurfacePoint::",
724 stringify!($fnam),
725 ") in
726 [`CubeSurfacePoint`](crate::CubeSurfacePoint)."
727 )]
728 pub const fn $fnam(self) -> $out {
729
730 const fn from_serial_number (i: usize) -> $out {
731 $convert(<$us>::index_to_self(i).0.$fnam())
732 }
733
734 const LUT: [$out; 24] = {
735 let mut result = [from_serial_number(0); 24];
736 let mut i = 24;
737 while i > 0 {
738 i -= 1;
739 result[i] = from_serial_number(i);
740 }
741 result
742 };
743
744 LUT[self.0 as usize >> 1]
745 }
746 };
747
748 (angles; $us: path, $fnam: ident) => {
749 #[doc = concat!(
750 "Please refer to the [function of the same name
751 ](crate::CubeSurfacePoint::",
752 stringify!($fnam),
753 ") in
754 [`CubeSurfacePoint`](crate::CubeSurfacePoint)."
755 )]
756 pub const fn $fnam(self, angle:u8) -> Self {
757 let angle = angle & 0b11;
758
759 const fn from_serial_number (i: usize) -> $us {
760 $us(<$us>::index_to_self(i / 4).0.$fnam((i as u8) % 4))
761 }
762
763 const LUT: [[$us; 24]; 4] = {
764 let mut result = [[from_serial_number(0); 24]; 4];
765 let mut i: usize = 24 * 4;
766 while i > 0 {
767 i -= 1;
768 result[i % 4][i / 4] = from_serial_number(i);
769 }
770 result
771 };
772
773 LUT[angle as usize][self.0 as usize >> 1]
774 }
775 };
776
777 (muldiv; $us: ty, $other: ty, $out: ty, $fnam: ident, $out_to_out: ident $(; $const:tt)? $(.$siiiigh: tt)?) => {
778 #[doc = concat!(
779 "Please refer to the [function of the same name](crate::",
780 stringify!($us),
781 "::",
782 stringify!($fnam),
783 ") in the basic [`",
784 stringify!($us),
785 "`](crate::",
786 stringify!($us),
787 ")."
788 )]
789 $(pub $const)? fn $fnam(self, other: $other) -> $out {
790 const fn from_serial_number(x: usize) -> $out {
791 let us = <$us>::index_to_self(x / 24).0;
792 let other = <$other>::index_to_self(x % 24) $(. $siiiigh)?;
793 $out_to_out(us.$fnam(other))
794 }
795
796 const LUT: [[$out; 24]; 24] = {
797 let mut result = [[from_serial_number(0); 24]; 24];
798 let mut i = 24 * 24;
799 while i > 0 {
800 i -= 1;
801 result[i / 24][i % 24] = from_serial_number(i);
802 }
803 result
804 };
805
806 LUT[self.0 as usize >> 1][other.self_to_index() as usize >> 1]
807 }
808 };
809
810 (everything; $us: ty, $others:ty, $check: ident,
811 $self_to_self:ident, $other_to_other: ident $(,)?) => {
812
813 const fn index_to_self(x: usize) -> $us {
814 let x = (x as u8) * 2;
815 let pt_1 = CratePt::probs_from_u8(x);
816 let pt_2 = CratePt::probs_from_u8(x ^ 1);
817 let result = match (pt_1.$check(), pt_2.$check()) {
818 (Ok(point), Err(_)) => point,
819 (Err(_), Ok(point)) => point,
820 _ => crate::unreachable_semichecked(),
821 };
822 $self_to_self(result)
823 }
824
825 const fn self_to_index(self) -> usize {
826 self.0 as usize
827 }
828
829 with_lut!($us, Direction, direction, id);
830 with_lut!($us, $others, beside, $other_to_other);
831 with_lut!($us, $others, opposite, $other_to_other);
832 with_lut!($us, $others, flip_sign_of_2, $other_to_other);
833 with_lut!($us, $us, opposite_then_beside, $self_to_self);
834 with_lut!($us, $us, flip_2_and_3, $self_to_self);
835 with_lut!($us, $us, one_right_angle_cw, $self_to_self);
836 with_lut!($us, $us, one_right_angle_acw, $self_to_self);
837 with_lut!(angles; $us, n_right_angles_cw);
838 with_lut!(angles; $us, n_right_angles_acw);
839 with_lut!(muldiv; $us, $us, ProperRotation, div_prop, id; const .0);
840 with_lut!(muldiv; $us, $others, ImproperRotation, div_improp, id; const .0);
841 with_lut!(muldiv; $us, ProperRotation, $us, mul_prop, $self_to_self; const);
842 with_lut!(muldiv; $us, ImproperRotation, $others, mul_improp, $other_to_other; const);
843 };
844
845 (impls; $us: ty, $others: ty) => {
846
847 impl Mul<ProperRotation> for $us {
850 type Output = Self;
852 fn mul (self, x: ProperRotation) -> Self::Output {
855 self.mul_prop(x)
856 }
857 }
858
859 impl MulAssign<ProperRotation> for $us {
862 fn mul_assign(&mut self, x: ProperRotation) {
868 *self = *self * x;
869 }
870 }
871
872 impl Mul<ImproperRotation> for $us {
875 type Output = $others;
877 fn mul (self, x: ImproperRotation) -> Self::Output {
880 self.mul_improp(x)
881 }
882 }
883
884 impl Mul<$us> for ProperRotation {
885 type Output = $us;
887 fn mul (self, x: $us) -> Self::Output {
890 x * self
891 }
892 }
893
894 impl Mul<$us> for ImproperRotation {
895 type Output = $others;
897 fn mul (self, x: $us) -> Self::Output {
900 x * self
901 }
902 }
903
904 impl Div for $us {
907 type Output = ProperRotation;
909 fn div (self, x: Self) -> Self::Output {
911 self.div_prop(x)
912 }
913 }
914
915 impl Div<$others> for $us {
918 type Output = ImproperRotation;
920 fn div (self, x: $others) -> Self::Output {
922 self.div_improp(x)
923 }
924 }
925 };
926
927 (impls; $us: ty, $others: ty, $check: ident, $self_to_self: ident, $other_to_other: ident) => {
928 impl From<$us> for CratePt {
931 fn from(x: $us) -> CratePt {
932 x.0.downcast()
933 }
934 }
935
936 impl TryFrom<CratePt> for $us {
938 #[doc = concat!(
939 "If a certain [`CubeSurfacePoint`] does not belong to the [`",
940 stringify!($us),
941 "`]s, it must by necessity belong to the [`",
942 stringify!($others),
943 "`]s."
944 )]
945 type Error = $others;
946
947 fn try_from(x: CratePt) -> Result<Self, Self::Error> {
948 match x.$check() {
949 Ok(point) => {
950 Ok($self_to_self(point))
951 },
952 Err(point) => {
953 Err($other_to_other(point))
954 },
955 }
956 }
957 }
958 };
959
960}
961
962#[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
966pub struct ReferenceGroupPoint(pub crate::ReferenceGroupPoint);
967
968#[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
972pub struct OppositeGroupPoint(pub crate::OppositeGroupPoint);
973
974const fn rgp_to_rgp(x: crate::ReferenceGroupPoint) -> ReferenceGroupPoint {
975 ReferenceGroupPoint(x)
976}
977
978const fn ogp_to_ogp(x: crate::OppositeGroupPoint) -> OppositeGroupPoint {
979 OppositeGroupPoint(x)
980}
981
982impl From<ProperRotation> for ReferenceGroupPoint {
983 fn from(x: ProperRotation) -> Self {
984 Self(x.corresponding_point)
985 }
986}
987
988impl From<ImproperRotation> for OppositeGroupPoint {
989 fn from(x: ImproperRotation) -> Self {
990 Self(x.corresponding_point)
991 }
992}
993
994impl From<CubeSurfacePoint<true>> for Rotation {
995 fn from(corresponding_point: CubeSurfacePoint<true>) -> Self {
996 Self {
997 corresponding_point: corresponding_point.0,
998 }
999 }
1000}
1001
1002impl From<CubeSurfacePoint<false>> for Rotation {
1003 fn from(corresponding_point: CubeSurfacePoint<false>) -> Self {
1004 Self {
1005 corresponding_point: corresponding_point.0,
1006 }
1007 }
1008}
1009
1010impl From<ReferenceGroupPoint> for ProperRotation {
1011 fn from(corresponding_point: ReferenceGroupPoint) -> Self {
1012 Self {
1013 corresponding_point: corresponding_point.0,
1014 }
1015 }
1016}
1017
1018impl From<OppositeGroupPoint> for ImproperRotation {
1019 fn from(corresponding_point: OppositeGroupPoint) -> Self {
1020 Self {
1021 corresponding_point: corresponding_point.0,
1022 }
1023 }
1024}
1025
1026impl ProperRotation {
1027 const fn index_to_self(x: usize) -> Self {
1028 Self {
1029 corresponding_point: ReferenceGroupPoint::index_to_self(x).0,
1030 }
1031 }
1032
1033 const fn self_to_index(self) -> usize {
1034 self.corresponding_point as usize
1035 }
1036}
1037
1038impl ImproperRotation {
1039 const fn index_to_self(x: usize) -> Self {
1040 Self {
1041 corresponding_point: OppositeGroupPoint::index_to_self(x).0,
1042 }
1043 }
1044
1045 const fn self_to_index(self) -> usize {
1046 self.corresponding_point as usize
1047 }
1048}
1049
1050impl ReferenceGroupPoint {
1051 with_lut!(
1052 everything;
1053 ReferenceGroupPoint,
1054 OppositeGroupPoint,
1055 determine_group,
1056 rgp_to_rgp,
1057 ogp_to_ogp,
1058 );
1059
1060 pub fn div_alt(self, x: Self) -> ProperRotation {
1064 const LUT: [ReferenceGroupPoint; 24] = {
1065 let mut result = [ReferenceGroupPoint::index_to_self(0); 24];
1066 let mut i = 24;
1067 while i > 0 {
1068 i -= 1;
1069 result[i] = ReferenceGroupPoint(
1070 ReferenceGroupPoint::index_to_self(0)
1071 .div_prop(ReferenceGroupPoint::index_to_self(i))
1072 .corresponding_point,
1073 );
1074 }
1075 result
1076 };
1077
1078 let corresponding_point = ProperRotation {
1079 corresponding_point: self.0,
1080 } * LUT[x.0 as usize >> 1];
1081 ProperRotation {
1082 corresponding_point: corresponding_point.0,
1083 }
1084 }
1085}
1086
1087impl OppositeGroupPoint {
1088 with_lut!(
1089 everything;
1090 OppositeGroupPoint,
1091 ReferenceGroupPoint,
1092 determine_antigroup,
1093 ogp_to_ogp,
1094 rgp_to_rgp,
1095 );
1096
1097 #[deprecated(note = "It is not yet clear whether this function should \
1101also exist for `OppositeGroupPoint`s.")]
1102 pub fn div_alt(self, x: Self) -> ProperRotation {
1103 const LUT: [OppositeGroupPoint; 24] = {
1104 let mut result = [OppositeGroupPoint::index_to_self(0); 24];
1105 let mut i = 24;
1106 while i > 0 {
1107 i -= 1;
1108 result[i] = OppositeGroupPoint(
1109 ReferenceGroupPoint::index_to_self(0)
1110 .div_improp(OppositeGroupPoint::index_to_self(i))
1111 .corresponding_point,
1112 );
1113 }
1114 result
1115 };
1116
1117 let corresponding_point = ImproperRotation {
1118 corresponding_point: self.0,
1119 } * LUT[x.0 as usize >> 1];
1120 ProperRotation {
1121 corresponding_point: corresponding_point.0,
1122 }
1123 }
1124}
1125
1126with_lut!(impls; ReferenceGroupPoint, OppositeGroupPoint);
1127with_lut!(impls; OppositeGroupPoint, ReferenceGroupPoint);
1128with_lut!(impls;
1129ReferenceGroupPoint,
1130OppositeGroupPoint,
1131determine_group,
1132rgp_to_rgp,
1133ogp_to_ogp
1134);
1135with_lut!(impls;
1136OppositeGroupPoint,
1137ReferenceGroupPoint,
1138determine_antigroup,
1139ogp_to_ogp,
1140rgp_to_rgp
1141);