mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 16:21:33 +11:00
create a number macro that can use floating point numbes
This commit is contained in:
parent
b88cf39a67
commit
6e0cbbe9eb
|
@ -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(
|
||||||
|
|
|
@ -2,8 +2,8 @@ use core::{
|
||||||
cmp::{Eq, Ord, PartialEq, PartialOrd},
|
cmp::{Eq, Ord, PartialEq, PartialOrd},
|
||||||
fmt::{Debug, Display},
|
fmt::{Debug, Display},
|
||||||
ops::{
|
ops::{
|
||||||
Add, AddAssign, BitAnd, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, Shr,
|
Add, AddAssign, BitAnd, BitOr, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign,
|
||||||
Sub, SubAssign,
|
Shl, Shr, Sub, SubAssign,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ pub trait FixedWidthUnsignedInteger:
|
||||||
+ Sub<Output = Self>
|
+ Sub<Output = Self>
|
||||||
+ Not<Output = Self>
|
+ Not<Output = Self>
|
||||||
+ BitAnd<Output = Self>
|
+ BitAnd<Output = Self>
|
||||||
|
+ BitOr<Output = Self>
|
||||||
+ Rem<Output = Self>
|
+ Rem<Output = Self>
|
||||||
+ Div<Output = Self>
|
+ Div<Output = Self>
|
||||||
+ Mul<Output = Self>
|
+ Mul<Output = Self>
|
||||||
|
@ -50,6 +51,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 +70,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 +296,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…
Reference in a new issue