2024-08-29 20:16:02 +00:00
|
|
|
use crate::types::I32F32;
|
2024-09-03 00:42:01 +00:00
|
|
|
use crate::types::I256F256;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn you_can_add_numbers(){
|
|
|
|
let a=I256F256::from((3i128*2).pow(4));
|
2024-09-17 21:47:18 +00:00
|
|
|
assert_eq!(a+a,I256F256::from((3i128*2).pow(4)*2));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn to_f32(){
|
|
|
|
let a=I256F256::from(1)>>2;
|
|
|
|
let f:f32=a.into();
|
|
|
|
assert_eq!(f,0.25f32);
|
|
|
|
let f:f32=(-a).into();
|
|
|
|
assert_eq!(f,-0.25f32);
|
|
|
|
let a=I256F256::from(0);
|
|
|
|
let f:f32=(-a).into();
|
|
|
|
assert_eq!(f,0f32);
|
2024-10-01 22:00:06 +00:00
|
|
|
let a=I256F256::from(237946589723468975i64)<<16;
|
2024-09-17 21:47:18 +00:00
|
|
|
let f:f32=a.into();
|
2024-10-01 22:00:06 +00:00
|
|
|
assert_eq!(f,237946589723468975f32*2.0f32.powi(16));
|
2024-09-17 21:47:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn to_f64(){
|
|
|
|
let a=I256F256::from(1)>>2;
|
|
|
|
let f:f64=a.into();
|
|
|
|
assert_eq!(f,0.25f64);
|
|
|
|
let f:f64=(-a).into();
|
|
|
|
assert_eq!(f,-0.25f64);
|
|
|
|
let a=I256F256::from(0);
|
|
|
|
let f:f64=(-a).into();
|
|
|
|
assert_eq!(f,0f64);
|
2024-10-01 22:00:06 +00:00
|
|
|
let a=I256F256::from(237946589723468975i64)<<16;
|
2024-09-17 21:47:18 +00:00
|
|
|
let f:f64=a.into();
|
2024-10-01 22:00:06 +00:00
|
|
|
assert_eq!(f,237946589723468975f64*2.0f64.powi(16));
|
2024-09-03 00:42:01 +00:00
|
|
|
}
|
|
|
|
|
2024-10-01 22:00:30 +00:00
|
|
|
#[test]
|
|
|
|
fn from_f32(){
|
|
|
|
let a=I256F256::from(1)>>2;
|
|
|
|
let b:Result<I256F256,_>=0.25f32.try_into();
|
|
|
|
assert_eq!(b,Ok(a));
|
|
|
|
let a=I256F256::from(-1)>>2;
|
|
|
|
let b:Result<I256F256,_>=(-0.25f32).try_into();
|
|
|
|
assert_eq!(b,Ok(a));
|
|
|
|
let a=I256F256::from(0);
|
|
|
|
let b:Result<I256F256,_>=0.try_into();
|
|
|
|
assert_eq!(b,Ok(a));
|
|
|
|
let a=I256F256::from(0b101011110101001010101010000000000000000000000000000i64)<<16;
|
|
|
|
let b:Result<I256F256,_>=(0b101011110101001010101010000000000000000000000000000u64 as f32*2.0f32.powi(16)).try_into();
|
|
|
|
assert_eq!(b,Ok(a));
|
|
|
|
//I32F32::MAX into f32 is truncated into this value
|
|
|
|
let a=I32F32::raw(0b111111111111111111111111000000000000000000000000000000000000000i64);
|
|
|
|
let b:Result<I32F32,_>=Into::<f32>::into(I32F32::MAX).try_into();
|
|
|
|
assert_eq!(b,Ok(a));
|
|
|
|
//I32F32::MIN hits a special case since it's not representable as a positive signed integer
|
|
|
|
//TODO: don't return an overflow because this is technically possible
|
|
|
|
let a=I32F32::MIN;
|
|
|
|
let b:Result<I32F32,_>=Into::<f32>::into(I32F32::MIN).try_into();
|
|
|
|
assert_eq!(b,Err(crate::fixed::FixedFromFloatError::Overflow));
|
|
|
|
//16 is within the 24 bits of float precision
|
|
|
|
let b:Result<I32F32,_>=Into::<f32>::into(-I32F32::MIN.fix_2()).try_into();
|
|
|
|
assert_eq!(b,Err(crate::fixed::FixedFromFloatError::Overflow));
|
|
|
|
let b:Result<I32F32,_>=f32::MIN_POSITIVE.try_into();
|
|
|
|
assert_eq!(b,Err(crate::fixed::FixedFromFloatError::Underflow));
|
|
|
|
//test many cases
|
|
|
|
for i in 0..64{
|
|
|
|
let a=crate::fixed::Fixed::<2,64>::raw_digit(0b111111111111111111111111000000000000000000000000000000000000000i64)<<i;
|
|
|
|
let f:f32=a.into();
|
|
|
|
let b:Result<crate::fixed::Fixed<2,64>,_>=f.try_into();
|
|
|
|
assert_eq!(b,Ok(a));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn from_f64(){
|
|
|
|
let a=I256F256::from(1)>>2;
|
|
|
|
let b:Result<I256F256,_>=0.25f64.try_into();
|
|
|
|
assert_eq!(b,Ok(a));
|
|
|
|
let a=I256F256::from(-1)>>2;
|
|
|
|
let b:Result<I256F256,_>=(-0.25f64).try_into();
|
|
|
|
assert_eq!(b,Ok(a));
|
|
|
|
let a=I256F256::from(0);
|
|
|
|
let b:Result<I256F256,_>=0.try_into();
|
|
|
|
assert_eq!(b,Ok(a));
|
|
|
|
let a=I256F256::from(0b101011110101001010101010000000000000000000000000000i64)<<16;
|
|
|
|
let b:Result<I256F256,_>=(0b101011110101001010101010000000000000000000000000000u64 as f64*2.0f64.powi(16)).try_into();
|
|
|
|
assert_eq!(b,Ok(a));
|
|
|
|
}
|
|
|
|
|
2024-09-03 00:42:01 +00:00
|
|
|
#[test]
|
|
|
|
fn you_can_shr_numbers(){
|
|
|
|
let a=I32F32::from(4);
|
2024-09-17 21:47:18 +00:00
|
|
|
assert_eq!(a>>1,I32F32::from(2));
|
2024-09-03 00:42:01 +00:00
|
|
|
}
|
2024-08-28 19:17:00 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_wide_mul(){
|
2024-08-29 20:16:02 +00:00
|
|
|
let a=I32F32::ONE;
|
2024-09-03 00:03:01 +00:00
|
|
|
let aa=a.wide_mul_1_1(a);
|
2024-08-28 19:17:00 +00:00
|
|
|
assert_eq!(aa,crate::types::I64F64::ONE);
|
|
|
|
}
|
|
|
|
|
2024-09-09 21:45:47 +00:00
|
|
|
#[test]
|
|
|
|
fn test_wide_div(){
|
|
|
|
let a=I32F32::ONE*4;
|
|
|
|
let b=I32F32::ONE*2;
|
|
|
|
let wide_a=a.wide_mul_1_1(I32F32::ONE);
|
|
|
|
let wide_b=b.wide_mul_1_1(I32F32::ONE);
|
|
|
|
let ab=a.wide_div_1_1(b);
|
|
|
|
assert_eq!(ab,crate::types::I64F64::ONE*2);
|
|
|
|
let wab=wide_a.wide_div_2_1(b);
|
|
|
|
assert_eq!(wab,crate::fixed::Fixed::<3,96>::ONE*2);
|
|
|
|
let awb=a.wide_div_1_2(wide_b);
|
|
|
|
assert_eq!(awb,crate::fixed::Fixed::<3,96>::ONE*2);
|
|
|
|
}
|
|
|
|
|
2024-09-03 00:42:01 +00:00
|
|
|
#[test]
|
|
|
|
fn test_wide_mul_repeated() {
|
|
|
|
let a=I32F32::from(2);
|
|
|
|
let b=I32F32::from(3);
|
|
|
|
|
|
|
|
let w1=a.wide_mul_1_1(b);
|
|
|
|
let w2=w1.wide_mul_2_2(w1);
|
|
|
|
let w3=w2.wide_mul_4_4(w2);
|
|
|
|
|
|
|
|
assert_eq!(w3,I256F256::from((3i128*2).pow(4)));
|
|
|
|
}
|
|
|
|
|
2024-08-28 19:17:00 +00:00
|
|
|
#[test]
|
|
|
|
fn test_bint(){
|
2024-08-29 20:16:02 +00:00
|
|
|
let a=I32F32::ONE;
|
|
|
|
assert_eq!(a*2,I32F32::from(2));
|
2024-08-28 19:17:00 +00:00
|
|
|
}
|
2024-08-29 17:12:08 +00:00
|
|
|
|
2024-09-11 20:59:33 +00:00
|
|
|
#[test]
|
|
|
|
fn test_fix(){
|
2024-09-17 22:10:11 +00:00
|
|
|
assert_eq!(I32F32::ONE.fix_8(),I256F256::ONE);
|
|
|
|
assert_eq!(I32F32::ONE,I256F256::ONE.fix_1());
|
2024-09-18 18:50:34 +00:00
|
|
|
assert_eq!(I32F32::NEG_ONE.fix_8(),I256F256::NEG_ONE);
|
|
|
|
assert_eq!(I32F32::NEG_ONE,I256F256::NEG_ONE.fix_1());
|
2024-09-11 20:59:33 +00:00
|
|
|
}
|
2024-08-29 17:12:08 +00:00
|
|
|
#[test]
|
|
|
|
fn test_sqrt(){
|
2024-08-29 20:16:02 +00:00
|
|
|
let a=I32F32::ONE*4;
|
|
|
|
assert_eq!(a.sqrt(),I32F32::from(2));
|
2024-08-29 17:12:08 +00:00
|
|
|
}
|
2024-08-29 19:13:42 +00:00
|
|
|
#[test]
|
2024-08-29 23:20:10 +00:00
|
|
|
fn test_sqrt_zero(){
|
|
|
|
let a=I32F32::ZERO;
|
|
|
|
assert_eq!(a.sqrt(),I32F32::ZERO);
|
|
|
|
}
|
|
|
|
#[test]
|
2024-08-29 19:13:42 +00:00
|
|
|
fn test_sqrt_low(){
|
2024-08-29 20:16:02 +00:00
|
|
|
let a=I32F32::HALF;
|
2024-09-06 19:49:10 +00:00
|
|
|
let b=a.fixed_mul(a);
|
2024-08-29 19:13:42 +00:00
|
|
|
assert_eq!(b.sqrt(),a);
|
|
|
|
}
|
2024-08-29 20:16:09 +00:00
|
|
|
fn find_equiv_sqrt_via_f64(n:I32F32)->I32F32{
|
|
|
|
//GIMME THEM BITS BOY
|
|
|
|
let &[bits]=n.to_bits().to_bits().digits();
|
|
|
|
let ibits=bits as i64;
|
|
|
|
let f=(ibits as f64)/((1u64<<32) as f64);
|
|
|
|
let f_ans=f.sqrt();
|
2024-08-29 20:30:48 +00:00
|
|
|
let i=(f_ans*((1u64<<32) as f64)) as i64;
|
|
|
|
let r=I32F32::from_bits(bnum::BInt::<1>::from(i));
|
|
|
|
//mimic the behaviour of the algorithm,
|
|
|
|
//return the result if it truncates to the exact answer
|
2024-09-03 00:03:01 +00:00
|
|
|
if (r+I32F32::EPSILON).wide_mul_1_1(r+I32F32::EPSILON)==n.wide_mul_1_1(I32F32::ONE){
|
2024-08-29 20:30:48 +00:00
|
|
|
return r+I32F32::EPSILON;
|
2024-08-29 20:16:09 +00:00
|
|
|
}
|
2024-09-03 00:03:01 +00:00
|
|
|
if (r-I32F32::EPSILON).wide_mul_1_1(r-I32F32::EPSILON)==n.wide_mul_1_1(I32F32::ONE){
|
2024-08-29 20:30:48 +00:00
|
|
|
return r-I32F32::EPSILON;
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
fn test_exact(n:I32F32){
|
|
|
|
assert_eq!(n.sqrt(),find_equiv_sqrt_via_f64(n));
|
2024-08-29 20:16:09 +00:00
|
|
|
}
|
|
|
|
#[test]
|
|
|
|
fn test_sqrt_exact(){
|
2024-08-29 20:30:48 +00:00
|
|
|
//43
|
|
|
|
for i in 0..((i64::MAX as f32).ln() as u32){
|
|
|
|
let n=I32F32::from_bits(bnum::BInt::<1>::from((i as f32).exp() as i64));
|
|
|
|
test_exact(n);
|
|
|
|
}
|
2024-08-29 20:16:09 +00:00
|
|
|
}
|
2024-08-29 22:27:48 +00:00
|
|
|
#[test]
|
|
|
|
fn test_sqrt_max(){
|
|
|
|
let a=I32F32::MAX;
|
|
|
|
test_exact(a);
|
|
|
|
}
|
2024-09-27 01:08:33 +00:00
|
|
|
#[test]
|
|
|
|
#[cfg(all(feature="zeroes",not(feature="deferred-division")))]
|
|
|
|
fn test_zeroes_normal(){
|
|
|
|
// (x-1)*(x+1)
|
|
|
|
// x^2-1
|
|
|
|
let zeroes=I32F32::zeroes2(I32F32::NEG_ONE,I32F32::ZERO,I32F32::ONE);
|
|
|
|
assert_eq!(zeroes,arrayvec::ArrayVec::from_iter([I32F32::NEG_ONE,I32F32::ONE]));
|
|
|
|
let zeroes=I32F32::zeroes2(I32F32::NEG_ONE*3,I32F32::ONE*2,I32F32::ONE);
|
|
|
|
assert_eq!(zeroes,arrayvec::ArrayVec::from_iter([I32F32::NEG_ONE*3,I32F32::ONE]));
|
|
|
|
}
|
|
|
|
#[test]
|
|
|
|
#[cfg(all(feature="zeroes",feature="deferred-division"))]
|
|
|
|
fn test_zeroes_deferred_division(){
|
|
|
|
// (x-1)*(x+1)
|
|
|
|
// x^2-1
|
|
|
|
let zeroes=I32F32::zeroes2(I32F32::NEG_ONE,I32F32::ZERO,I32F32::ONE);
|
|
|
|
assert_eq!(
|
|
|
|
zeroes,
|
|
|
|
arrayvec::ArrayVec::from_iter([
|
|
|
|
ratio_ops::ratio::Ratio::new(I32F32::ONE*2,I32F32::NEG_ONE*2),
|
|
|
|
ratio_ops::ratio::Ratio::new(I32F32::ONE*2,I32F32::ONE*2),
|
|
|
|
])
|
|
|
|
);
|
|
|
|
}
|