Add support for all the integer widths

This commit is contained in:
Gwilym Kuiper 2021-06-05 21:17:24 +01:00
parent de47dbc5dd
commit 508f33facd
2 changed files with 68 additions and 48 deletions

View file

@ -7,7 +7,7 @@ use core::{
}, },
}; };
pub trait FixedWidthInteger: pub trait FixedWidthUnsignedInteger:
Sized Sized
+ Copy + Copy
+ PartialOrd + PartialOrd
@ -20,7 +20,6 @@ pub trait FixedWidthInteger:
+ Sub<Output = Self> + Sub<Output = Self>
+ Not<Output = Self> + Not<Output = Self>
+ BitAnd<Output = Self> + BitAnd<Output = Self>
+ Neg<Output = Self>
+ Rem<Output = Self> + Rem<Output = Self>
+ Div<Output = Self> + Div<Output = Self>
+ Mul<Output = Self> + Mul<Output = Self>
@ -31,31 +30,50 @@ pub trait FixedWidthInteger:
fn zero() -> Self; fn zero() -> Self;
fn one() -> Self; fn one() -> Self;
fn ten() -> Self; fn ten() -> Self;
fn abs(self) -> Self;
} }
impl FixedWidthInteger for i32 { pub trait FixedWidthSignedInteger: FixedWidthUnsignedInteger + Neg<Output = Self> {
fn fixed_abs(self) -> Self;
}
macro_rules! fixed_width_unsigned_integer_impl {
($T: ty) => {
impl FixedWidthUnsignedInteger for $T {
fn zero() -> Self { fn zero() -> Self {
0 0
} }
fn one() -> Self { fn one() -> Self {
1 1
} }
fn ten() -> Self { fn ten() -> Self {
10 10
} }
fn abs(self) -> Self {
self.abs()
} }
};
} }
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] macro_rules! fixed_width_signed_integer_impl {
pub struct Num<I: FixedWidthInteger, const N: usize>(I); ($T: ty) => {
impl FixedWidthSignedInteger for $T {
fn fixed_abs(self) -> Self {
self.abs()
}
}
};
}
pub fn change_base<I: FixedWidthInteger, const N: usize, const M: usize>( fixed_width_unsigned_integer_impl!(i16);
fixed_width_unsigned_integer_impl!(u16);
fixed_width_unsigned_integer_impl!(i32);
fixed_width_unsigned_integer_impl!(u32);
fixed_width_signed_integer_impl!(i16);
fixed_width_signed_integer_impl!(i32);
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Num<I: FixedWidthUnsignedInteger, const N: usize>(I);
pub fn change_base<I: FixedWidthUnsignedInteger, const N: usize, const M: usize>(
num: Num<I, N>, num: Num<I, N>,
) -> Num<I, M> { ) -> Num<I, M> {
if N < M { if N < M {
@ -65,7 +83,7 @@ pub fn change_base<I: FixedWidthInteger, const N: usize, const M: usize>(
} }
} }
impl<I: FixedWidthInteger, const N: usize> From<I> for Num<I, N> { impl<I: FixedWidthUnsignedInteger, const N: usize> From<I> for Num<I, N> {
fn from(value: I) -> Self { fn from(value: I) -> Self {
Num(value << N) Num(value << N)
} }
@ -73,7 +91,7 @@ impl<I: FixedWidthInteger, const N: usize> From<I> for Num<I, N> {
impl<I, T, const N: usize> Add<T> for Num<I, N> impl<I, T, const N: usize> Add<T> for Num<I, N>
where where
I: FixedWidthInteger, I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>, T: Into<Num<I, N>>,
{ {
type Output = Self; type Output = Self;
@ -84,7 +102,7 @@ where
impl<I, T, const N: usize> AddAssign<T> for Num<I, N> impl<I, T, const N: usize> AddAssign<T> for Num<I, N>
where where
I: FixedWidthInteger, I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>, T: Into<Num<I, N>>,
{ {
fn add_assign(&mut self, rhs: T) { fn add_assign(&mut self, rhs: T) {
@ -94,7 +112,7 @@ where
impl<I, T, const N: usize> Sub<T> for Num<I, N> impl<I, T, const N: usize> Sub<T> for Num<I, N>
where where
I: FixedWidthInteger, I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>, T: Into<Num<I, N>>,
{ {
type Output = Self; type Output = Self;
@ -105,7 +123,7 @@ where
impl<I, T, const N: usize> SubAssign<T> for Num<I, N> impl<I, T, const N: usize> SubAssign<T> for Num<I, N>
where where
I: FixedWidthInteger, I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>, T: Into<Num<I, N>>,
{ {
fn sub_assign(&mut self, rhs: T) { fn sub_assign(&mut self, rhs: T) {
@ -115,7 +133,7 @@ where
impl<I, T, const N: usize> Mul<T> for Num<I, N> impl<I, T, const N: usize> Mul<T> for Num<I, N>
where where
I: FixedWidthInteger, I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>, T: Into<Num<I, N>>,
{ {
type Output = Self; type Output = Self;
@ -126,7 +144,7 @@ where
impl<I, T, const N: usize> MulAssign<T> for Num<I, N> impl<I, T, const N: usize> MulAssign<T> for Num<I, N>
where where
I: FixedWidthInteger, I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>, T: Into<Num<I, N>>,
{ {
fn mul_assign(&mut self, rhs: T) { fn mul_assign(&mut self, rhs: T) {
@ -136,7 +154,7 @@ where
impl<I, T, const N: usize> Div<T> for Num<I, N> impl<I, T, const N: usize> Div<T> for Num<I, N>
where where
I: FixedWidthInteger, I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>, T: Into<Num<I, N>>,
{ {
type Output = Self; type Output = Self;
@ -147,7 +165,7 @@ where
impl<I, T, const N: usize> DivAssign<T> for Num<I, N> impl<I, T, const N: usize> DivAssign<T> for Num<I, N>
where where
I: FixedWidthInteger, I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>, T: Into<Num<I, N>>,
{ {
fn div_assign(&mut self, rhs: T) { fn div_assign(&mut self, rhs: T) {
@ -157,7 +175,7 @@ where
impl<I, T, const N: usize> Rem<T> for Num<I, N> impl<I, T, const N: usize> Rem<T> for Num<I, N>
where where
I: FixedWidthInteger, I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>, T: Into<Num<I, N>>,
{ {
type Output = Self; type Output = Self;
@ -168,7 +186,7 @@ where
impl<I, T, const N: usize> RemAssign<T> for Num<I, N> impl<I, T, const N: usize> RemAssign<T> for Num<I, N>
where where
I: FixedWidthInteger, I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>, T: Into<Num<I, N>>,
{ {
fn rem_assign(&mut self, modulus: T) { fn rem_assign(&mut self, modulus: T) {
@ -176,14 +194,14 @@ where
} }
} }
impl<I: FixedWidthInteger, const N: usize> Neg for Num<I, N> { impl<I: FixedWidthSignedInteger, const N: usize> Neg for Num<I, N> {
type Output = Self; type Output = Self;
fn neg(self) -> Self::Output { fn neg(self) -> Self::Output {
Num(-self.0) Num(-self.0)
} }
} }
impl<I: FixedWidthInteger, const N: usize> Num<I, N> { impl<I: FixedWidthUnsignedInteger, const N: usize> Num<I, N> {
pub fn from_raw(n: I) -> Self { pub fn from_raw(n: I) -> Self {
Num(n) Num(n)
} }
@ -220,8 +238,14 @@ impl<I: FixedWidthInteger, const N: usize> Num<I, N> {
self.0 >> N self.0 >> N
} }
pub fn new(integral: I) -> Self {
Self(integral << N)
}
}
impl<I: FixedWidthSignedInteger, const N: usize> Num<I, N> {
pub fn abs(self) -> Self { pub fn abs(self) -> Self {
Num(self.0.abs()) Num(self.0.fixed_abs())
} }
/// domain of [0, 1]. /// domain of [0, 1].
@ -246,10 +270,6 @@ impl<I: FixedWidthInteger, const N: usize> Num<I, N> {
let four: I = 4.into(); let four: I = 4.into();
(self - one / four).cos() (self - one / four).cos()
} }
pub fn new(integral: I) -> Self {
Self(integral << N)
}
} }
#[test_case] #[test_case]
@ -380,7 +400,7 @@ fn test_rem_euclid_is_always_positive_and_sensible(_gba: &mut super::Gba) {
} }
} }
impl<I: FixedWidthInteger, const N: usize> Display for Num<I, N> { impl<I: FixedWidthUnsignedInteger, const N: usize> Display for Num<I, N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let integral = self.0 >> N; let integral = self.0 >> N;
let mask: I = (I::one() << N) - I::one(); let mask: I = (I::one() << N) - I::one();
@ -402,7 +422,7 @@ impl<I: FixedWidthInteger, const N: usize> Display for Num<I, N> {
} }
} }
impl<I: FixedWidthInteger, const N: usize> Debug for Num<I, N> { impl<I: FixedWidthUnsignedInteger, const N: usize> Debug for Num<I, N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
use core::any::type_name; use core::any::type_name;

View file

@ -107,8 +107,8 @@ pub fn arc_tan2(x: i16, y: i32) -> i16 {
} }
pub fn affine_matrix( pub fn affine_matrix(
x_scale: Num<i32, 8>, x_scale: Num<i16, 8>,
y_scale: Num<i32, 8>, y_scale: Num<i16, 8>,
rotation: u8, rotation: u8,
) -> AffineMatrixAttributes { ) -> AffineMatrixAttributes {
let mut result = AffineMatrixAttributes { let mut result = AffineMatrixAttributes {
@ -129,8 +129,8 @@ pub fn affine_matrix(
let rotation_for_input = (rotation as u16) << 8; let rotation_for_input = (rotation as u16) << 8;
let input = Input { let input = Input {
y_scale: x_scale.to_raw() as i16, y_scale: x_scale.to_raw(),
x_scale: y_scale.to_raw() as i16, x_scale: y_scale.to_raw(),
rotation: rotation_for_input, rotation: rotation_for_input,
}; };
@ -149,9 +149,9 @@ pub fn affine_matrix(
#[test_case] #[test_case]
fn affine(_gba: &mut crate::Gba) { fn affine(_gba: &mut crate::Gba) {
// expect identity matrix // expect identity matrix
let one: Num<8> = 1.into(); let one: Num<i16, 8> = 1.into();
let aff = affine_matrix(one, one, 0); let aff = affine_matrix(one, one, 0);
assert_eq!(aff.p_a, one.to_raw() as i16); assert_eq!(aff.p_a, one.to_raw());
assert_eq!(aff.p_d, one.to_raw() as i16); assert_eq!(aff.p_d, one.to_raw());
} }