mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-24 00:31:34 +11:00
Merge pull request #43 from gwilymk/add-rem-and-rem-euclid
Add rem and rem euclid implementations for fixnum
This commit is contained in:
commit
e2925eb917
|
@ -1,9 +1,9 @@
|
|||
use core::{
|
||||
fmt::Display,
|
||||
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
|
||||
fmt::{Debug, Display},
|
||||
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign},
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Num<const N: usize>(i32);
|
||||
|
||||
pub fn change_base<const N: usize, const M: usize>(num: Num<N>) -> Num<M> {
|
||||
|
@ -96,6 +96,25 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Rem<T> for Num<N>
|
||||
where
|
||||
T: Into<Num<N>>,
|
||||
{
|
||||
type Output = Self;
|
||||
fn rem(self, modulus: T) -> Self::Output {
|
||||
Num(self.0 % modulus.into().0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> RemAssign<T> for Num<N>
|
||||
where
|
||||
T: Into<Num<N>>,
|
||||
{
|
||||
fn rem_assign(&mut self, modulus: T) {
|
||||
self.0 = (*self % modulus).0
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Neg for Num<N> {
|
||||
type Output = Self;
|
||||
fn neg(self) -> Self::Output {
|
||||
|
@ -107,12 +126,33 @@ impl<const N: usize> Num<N> {
|
|||
pub fn max() -> Self {
|
||||
Num(i32::MAX)
|
||||
}
|
||||
|
||||
pub fn min() -> Self {
|
||||
Num(i32::MIN)
|
||||
}
|
||||
|
||||
pub fn int(&self) -> i32 {
|
||||
self.0 >> N
|
||||
let fractional_part = self.0 & ((1 << N) - 1);
|
||||
let self_as_int = self.0 >> N;
|
||||
|
||||
if self_as_int < 0 && fractional_part != 0 {
|
||||
self_as_int + 1
|
||||
} else {
|
||||
self_as_int
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rem_euclid(&self, rhs: Self) -> Self {
|
||||
let r = *self % rhs;
|
||||
if r < 0.into() {
|
||||
if rhs < 0.into() {
|
||||
r - rhs
|
||||
} else {
|
||||
r + rhs
|
||||
}
|
||||
} else {
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(integral: i32) -> Self {
|
||||
|
@ -183,6 +223,71 @@ fn test_change_base(_gba: &mut super::Gba) {
|
|||
assert_eq!(three + change_base(two), 5.into());
|
||||
}
|
||||
|
||||
#[test_case]
|
||||
fn test_rem_returns_sensible_values_for_integers(_gba: &mut super::Gba) {
|
||||
for i in -50..50 {
|
||||
for j in -50..50 {
|
||||
if j == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let i_rem_j_normally = i % j;
|
||||
let i_fixnum: Num<8> = i.into();
|
||||
|
||||
assert_eq!(i_fixnum % j, i_rem_j_normally.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test_case]
|
||||
fn test_rem_returns_sensible_values_for_non_integers(_gba: &mut super::Gba) {
|
||||
let one: Num<8> = 1.into();
|
||||
let third = one / 3;
|
||||
|
||||
for i in -50..50 {
|
||||
for j in -50..50 {
|
||||
if j == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
// full calculation in the normal way
|
||||
let x: Num<8> = third + i;
|
||||
let y: Num<8> = j.into();
|
||||
|
||||
let truncated_division: Num<8> = (x / y).int().into();
|
||||
|
||||
let remainder = x - truncated_division * y;
|
||||
|
||||
assert_eq!(x % y, remainder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test_case]
|
||||
fn test_rem_euclid_is_always_positive_and_sensible(_gba: &mut super::Gba) {
|
||||
let one: Num<8> = 1.into();
|
||||
let third = one / 3;
|
||||
|
||||
for i in -50..50 {
|
||||
for j in -50..50 {
|
||||
if j == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
// full calculation in the normal way
|
||||
let x: Num<8> = third + i;
|
||||
let y: Num<8> = j.into();
|
||||
|
||||
let truncated_division: Num<8> = (x / y).int().into();
|
||||
|
||||
let remainder = x - truncated_division * y;
|
||||
|
||||
let rem_euclid = x.rem_euclid(y);
|
||||
assert!(rem_euclid > 0.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Display for Num<N> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let integral = self.0 >> N;
|
||||
|
@ -203,3 +308,9 @@ impl<const N: usize> Display for Num<N> {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Debug for Num<N> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "Num<{}>({})", N, self)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue