Created
October 5, 2025 22:23
-
-
Save TethysSvensson/4765c1ca0dbcd9f3fe65a8ac0ac41fc1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| struct NegOne; | |
| struct Zero; | |
| struct Bit0<N>(PhantomData<N>); | |
| struct Bit1<N>(PhantomData<N>); | |
| type One = Bit1<Zero>; | |
| type NegTwo = Bit1<NegOne>; | |
| trait Integer { | |
| const VALUE: i128; | |
| type Add1: Integer; // Calculate (N + 1) as a canonical integer | |
| type Sub1: Integer; // Calculate (N - 1) as a canonical integer | |
| type Neg: Integer; // Calculate (-N) as a canonical integer | |
| type Shift: Integer; // Calculate (N << 1) as a canonical integer | |
| } | |
| impl Integer for Zero { | |
| const VALUE: i128 = 0; | |
| type Add1 = One; | |
| type Sub1 = NegOne; | |
| type Neg = Zero; | |
| type Shift = Zero; | |
| } | |
| impl Integer for NegOne { | |
| const VALUE: i128 = -1; | |
| type Add1 = Zero; | |
| type Sub1 = NegTwo; | |
| type Neg = One; | |
| type Shift = NegTwo; | |
| } | |
| // We require N to be NonZero and not just an Integer in order to only permit canonical integers | |
| impl<N: NonZero> Integer for Bit0<N> { | |
| const VALUE: i128 = N::VALUE << 1; | |
| type Add1 = Bit1<N>; | |
| type Sub1 = Bit1<<N as Integer>::Sub1>; | |
| type Neg = <<N as Integer>::Neg as Integer>::Shift; | |
| type Shift = Bit0<Bit0<N>>; | |
| } | |
| impl<N: Integer> Integer for Bit1<N> { | |
| const VALUE: i128 = (N::VALUE << 1) | 1; | |
| type Add1 = <<N as Integer>::Add1 as Integer>::Shift; | |
| type Sub1 = <N as Integer>::Shift; | |
| type Neg = Bit1<<<N as Integer>::Neg as Integer>::Sub1>; | |
| type Shift = Bit0<Bit1<N>>; | |
| } | |
| trait NonZero: Integer {} | |
| impl NonZero for NegOne {} | |
| impl<N: NonZero> NonZero for Bit0<N> {} | |
| impl<N: Integer> NonZero for Bit1<N> {} | |
| trait Add<Other: Integer>: Integer { | |
| type Result: Integer; | |
| } | |
| impl<N: Integer> Add<N> for Zero { | |
| type Result = N; | |
| } | |
| impl<N: Integer> Add<N> for NegOne { | |
| type Result = <N as Integer>::Sub1; | |
| } | |
| impl<N: NonZero> Add<Zero> for Bit0<N> { | |
| type Result = Bit0<N>; | |
| } | |
| impl<N: NonZero> Add<NegOne> for Bit0<N> { | |
| type Result = Bit1<<N as Integer>::Sub1>; | |
| } | |
| impl<N: NonZero, M: NonZero> Add<Bit0<M>> for Bit0<N> | |
| where | |
| N: Add<M>, | |
| { | |
| type Result = <<N as Add<M>>::Result as Integer>::Shift; | |
| } | |
| impl<N: NonZero, M: Integer> Add<Bit1<M>> for Bit0<N> | |
| where | |
| N: Add<M>, | |
| { | |
| type Result = Bit1<<N as Add<M>>::Result>; | |
| } | |
| impl<N: Integer> Add<Zero> for Bit1<N> { | |
| type Result = Bit1<N>; | |
| } | |
| impl<N: Integer> Add<NegOne> for Bit1<N> { | |
| type Result = <N as Integer>::Shift; | |
| } | |
| impl<N: Integer, M: NonZero> Add<Bit0<M>> for Bit1<N> | |
| where | |
| N: Add<M>, | |
| { | |
| type Result = Bit1<<N as Add<M>>::Result>; | |
| } | |
| impl<N: Integer, M: Integer> Add<Bit1<M>> for Bit1<N> | |
| where | |
| N: Add<M>, | |
| { | |
| type Result = <<<N as Add<M>>::Result as Integer>::Add1 as Integer>::Shift; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment