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
+ Copy
+ PartialOrd
@ -20,7 +20,6 @@ pub trait FixedWidthInteger:
+ Sub<Output = Self>
+ Not<Output = Self>
+ BitAnd<Output = Self>
+ Neg<Output = Self>
+ Rem<Output = Self>
+ Div<Output = Self>
+ Mul<Output = Self>
@ -31,31 +30,50 @@ pub trait FixedWidthInteger:
fn zero() -> Self;
fn one() -> 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 {
0
}
fn one() -> Self {
1
}
fn ten() -> Self {
10
}
fn abs(self) -> Self {
self.abs()
}
};
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Num<I: FixedWidthInteger, const N: usize>(I);
macro_rules! fixed_width_signed_integer_impl {
($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<I, 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 {
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>
where
I: FixedWidthInteger,
I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>,
{
type Output = Self;
@ -84,7 +102,7 @@ where
impl<I, T, const N: usize> AddAssign<T> for Num<I, N>
where
I: FixedWidthInteger,
I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>,
{
fn add_assign(&mut self, rhs: T) {
@ -94,7 +112,7 @@ where
impl<I, T, const N: usize> Sub<T> for Num<I, N>
where
I: FixedWidthInteger,
I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>,
{
type Output = Self;
@ -105,7 +123,7 @@ where
impl<I, T, const N: usize> SubAssign<T> for Num<I, N>
where
I: FixedWidthInteger,
I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>,
{
fn sub_assign(&mut self, rhs: T) {
@ -115,7 +133,7 @@ where
impl<I, T, const N: usize> Mul<T> for Num<I, N>
where
I: FixedWidthInteger,
I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>,
{
type Output = Self;
@ -126,7 +144,7 @@ where
impl<I, T, const N: usize> MulAssign<T> for Num<I, N>
where
I: FixedWidthInteger,
I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>,
{
fn mul_assign(&mut self, rhs: T) {
@ -136,7 +154,7 @@ where
impl<I, T, const N: usize> Div<T> for Num<I, N>
where
I: FixedWidthInteger,
I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>,
{
type Output = Self;
@ -147,7 +165,7 @@ where
impl<I, T, const N: usize> DivAssign<T> for Num<I, N>
where
I: FixedWidthInteger,
I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>,
{
fn div_assign(&mut self, rhs: T) {
@ -157,7 +175,7 @@ where
impl<I, T, const N: usize> Rem<T> for Num<I, N>
where
I: FixedWidthInteger,
I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>,
{
type Output = Self;
@ -168,7 +186,7 @@ where
impl<I, T, const N: usize> RemAssign<T> for Num<I, N>
where
I: FixedWidthInteger,
I: FixedWidthUnsignedInteger,
T: Into<Num<I, N>>,
{
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;
fn neg(self) -> Self::Output {
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 {
Num(n)
}
@ -220,8 +238,14 @@ impl<I: FixedWidthInteger, const N: usize> Num<I, 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 {
Num(self.0.abs())
Num(self.0.fixed_abs())
}
/// domain of [0, 1].
@ -246,10 +270,6 @@ impl<I: FixedWidthInteger, const N: usize> Num<I, N> {
let four: I = 4.into();
(self - one / four).cos()
}
pub fn new(integral: I) -> Self {
Self(integral << N)
}
}
#[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 {
let integral = self.0 >> N;
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 {
use core::any::type_name;

View file

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