mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-24 08:41:34 +11:00
Add support for all the integer widths
This commit is contained in:
parent
de47dbc5dd
commit
508f33facd
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue