mirror of
https://github.com/italicsjenga/agb.git
synced 2025-01-22 23:26:33 +11:00
Merge pull request #135 from corwinkuiper/number-macro
create a number macro that can use floating point numbes
This commit is contained in:
commit
453e098703
2 changed files with 67 additions and 0 deletions
|
@ -45,6 +45,19 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn num(input: TokenStream) -> TokenStream {
|
||||||
|
let f = syn::parse_macro_input!(input as syn::LitFloat);
|
||||||
|
let v: f64 = f.base10_parse().expect("The number should be parsable");
|
||||||
|
|
||||||
|
let integer = v.trunc();
|
||||||
|
let fractional = v.fract() * (1_u64 << 30) as f64;
|
||||||
|
|
||||||
|
let integer = integer as i32;
|
||||||
|
let fractional = fractional as i32;
|
||||||
|
quote!((#integer, #fractional)).into()
|
||||||
|
}
|
||||||
|
|
||||||
fn random_ident() -> Ident {
|
fn random_ident() -> Ident {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
Ident::new(
|
Ident::new(
|
||||||
|
|
|
@ -50,6 +50,7 @@ pub trait FixedWidthUnsignedInteger:
|
||||||
fn zero() -> Self;
|
fn zero() -> Self;
|
||||||
fn one() -> Self;
|
fn one() -> Self;
|
||||||
fn ten() -> Self;
|
fn ten() -> Self;
|
||||||
|
fn from_as_i32(v: i32) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FixedWidthSignedInteger: FixedWidthUnsignedInteger + Neg<Output = Self> {
|
pub trait FixedWidthSignedInteger: FixedWidthUnsignedInteger + Neg<Output = Self> {
|
||||||
|
@ -68,6 +69,9 @@ macro_rules! fixed_width_unsigned_integer_impl {
|
||||||
fn ten() -> Self {
|
fn ten() -> Self {
|
||||||
10
|
10
|
||||||
}
|
}
|
||||||
|
fn from_as_i32(v: i32) -> Self {
|
||||||
|
v as $T
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -291,6 +295,56 @@ impl<I: FixedWidthUnsignedInteger, const N: usize> Num<I, N> {
|
||||||
pub fn new(integral: I) -> Self {
|
pub fn new(integral: I) -> Self {
|
||||||
Self(integral << N)
|
Self(integral << N)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_from_parts(num: (i32, i32)) -> Self {
|
||||||
|
Self(I::from_as_i32(((num.0) << N) + (num.1 >> (30 - N))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! num {
|
||||||
|
($value:literal) => {{
|
||||||
|
$crate::number::Num::new_from_parts(agb_macros::num!($value))
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test_case]
|
||||||
|
fn test_macro_conversion(_gba: &mut super::Gba) {
|
||||||
|
fn test_positive<A: FixedWidthUnsignedInteger, const B: usize>() {
|
||||||
|
let a: Num<A, B> = num!(1.5);
|
||||||
|
let one = A::one() << B;
|
||||||
|
let b = Num::from_raw(one + (one >> 1));
|
||||||
|
|
||||||
|
assert_eq!(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_negative<A: FixedWidthSignedInteger, const B: usize>() {
|
||||||
|
let a: Num<A, B> = num!(-1.5);
|
||||||
|
let one = A::one() << B;
|
||||||
|
let b = Num::from_raw(one + (one >> 1));
|
||||||
|
|
||||||
|
assert_eq!(a, -b);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_base<const B: usize>() {
|
||||||
|
test_positive::<i32, 8>();
|
||||||
|
test_positive::<i16, 8>();
|
||||||
|
test_positive::<u32, 8>();
|
||||||
|
test_positive::<u16, 8>();
|
||||||
|
|
||||||
|
test_negative::<i32, 8>();
|
||||||
|
test_negative::<i16, 8>();
|
||||||
|
}
|
||||||
|
// some nice powers of two
|
||||||
|
test_base::<8>();
|
||||||
|
test_base::<4>();
|
||||||
|
test_base::<16>();
|
||||||
|
// not a power of two
|
||||||
|
test_base::<10>();
|
||||||
|
// an odd number
|
||||||
|
test_base::<9>();
|
||||||
|
// and a prime
|
||||||
|
test_base::<11>();
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: FixedWidthSignedInteger, const N: usize> Num<I, N> {
|
impl<I: FixedWidthSignedInteger, const N: usize> Num<I, N> {
|
||||||
|
|
Loading…
Add table
Reference in a new issue