From cadafb3c4c4cb73eb3b8ea962057cdd74839aae7 Mon Sep 17 00:00:00 2001 From: Brett Saiki Date: Tue, 27 Feb 2024 11:30:47 -0800 Subject: [PATCH] restore some tests --- src/rfloat/round.rs | 2 +- src/split.rs | 11 +- tests/rfloat.rs | 485 ++++++++++++++++++++------------------------ 3 files changed, 232 insertions(+), 266 deletions(-) diff --git a/src/rfloat/round.rs b/src/rfloat/round.rs index ed49258..64f1f77 100644 --- a/src/rfloat/round.rs +++ b/src/rfloat/round.rs @@ -209,7 +209,7 @@ impl RFloatContext { Some(c) => c, None => Integer::zero(), }; - + // rounding bits let (halfway_bit, sticky_bit) = split.rs(); diff --git a/src/split.rs b/src/split.rs index 9c0d3b3..bb2eb36 100644 --- a/src/split.rs +++ b/src/split.rs @@ -1,9 +1,9 @@ use num_traits::Zero; use rug::Integer; -use crate::{util::*, RoundingContext}; use crate::rfloat::RFloat; use crate::Real; +use crate::{util::*, RoundingContext}; /// Result of splitting a [`Real`] at binary digit `n`. #[derive(Clone, Debug)] @@ -66,7 +66,12 @@ impl Split { pub fn new(num: &T, max_p: Option, n: isize) -> Self { assert!(!num.is_nar(), "must be real {:?}", num); let (high, low) = Self::split(num, n); - Self { high, low, max_p, n } + Self { + high, + low, + max_p, + n, + } } /// Extracts the upper value of the split. @@ -103,7 +108,7 @@ impl Split { } /// Rounds this [`Split`] according to a [`RoundingContext`]. - pub fn round(&self, ctx: &Ctx) -> Ctx::Format { + pub fn round(&self, ctx: &Ctx) -> Ctx::Format { ctx.round_split(self.to_owned()) } } diff --git a/tests/rfloat.rs b/tests/rfloat.rs index 9fbcd07..c51e842 100644 --- a/tests/rfloat.rs +++ b/tests/rfloat.rs @@ -10,16 +10,23 @@ fn traits() { assert_eq!(RFloat::radix(), 2, "RFloat is a binary format"); let vals = [ - RFloat::zero(), // 0 - RFloat::one(), // 1 - RFloat::Real(true, -4, Integer::from(7)), // -7 * 2^-4 - RFloat::PosInfinity, // +Inf - RFloat::NegInfinity, // -Inf, - RFloat::Nan, // NaN + RFloat::zero(), // 0 + RFloat::one(), // 1 + RFloat::Real(true, -4, Integer::from(7)), // -7 * 2^-4 + RFloat::PosInfinity, // +Inf + RFloat::NegInfinity, // -Inf, + RFloat::Nan, // NaN ]; // RFloat::sign - let expected = [Some(false), Some(false), Some(true), Some(false), Some(true), None]; + let expected = [ + Some(false), + Some(false), + Some(true), + Some(false), + Some(true), + None, + ]; for (val, &expected) in vals.iter().zip(expected.iter()) { let actual = val.sign(); assert_eq!( @@ -220,263 +227,217 @@ fn round_trivial() { assert!(rounded.is_nar(), "round(-Nan) = Nan"); } -// /// Testing rounding using fixed-point rounding -// #[test] -// fn round_fixed() { -// let one_3_4 = RFloat::Real(false, -2, Integer::from(7)); -// let one_1_2 = RFloat::Real(false, -1, Integer::from(3)); -// let one = RFloat::one(); -// let three_4 = RFloat::Real(false, -2, Integer::from(3)); -// let one_4 = RFloat::Real(false, -2, Integer::from(1)); -// let zero = RFloat::zero(); - -// let neg_one = RFloat::Real(true, 0, Integer::from(1)); - -// // 1 (min_n == -1) => 1 -// let ctx = RFloatContext::new() -// .with_min_n(-1) -// .with_rounding_mode(RoundingMode::ToZero); -// let (_, n) = ctx.round_params(&one); -// let (_, err) = RFloatContext::split_at(&one, n); -// let rounded_one = ctx.round(&one); -// assert_eq!( -// rounded_one, -// RFloat::one(), -// "rounding should not have lost bits" -// ); -// assert!(err.is_zero(), "lost bits should be 0"); - -// // 1 (min_n == 0) => 0 -// let ctx = RFloatContext::new() -// .with_min_n(0) -// .with_rounding_mode(RoundingMode::ToZero); -// let (_, n) = ctx.round_params(&one); -// let (_, err) = RFloatContext::split_at(&one, n); -// let rounded_one = ctx.round(&one); -// assert_eq!(rounded_one, zero, "rounding should truncated to 0"); -// assert_eq!(err, RFloat::one(), "lost bits should be 1"); - -// // -1 (min_n == 0) => 0 -// let ctx = RFloatContext::new() -// .with_min_n(0) -// .with_rounding_mode(RoundingMode::ToZero); -// let (_, n) = ctx.round_params(&neg_one); -// let (_, err) = RFloatContext::split_at(&neg_one, n); -// let rounded_one = ctx.round(&neg_one); -// assert_eq!(rounded_one, zero, "rounding should truncated to 0"); -// assert_eq!(err, neg_one, "lost bits should be -1"); - -// // 1.75 (min_n == -1) => 1 -// let ctx = RFloatContext::new() -// .with_min_n(-1) -// .with_rounding_mode(RoundingMode::ToZero); -// let (_, n) = ctx.round_params(&one_3_4); -// let (_, err) = RFloatContext::split_at(&one_3_4, n); -// let rounded = ctx.round(&one_3_4); -// assert_eq!(rounded, one, "rounding should truncated to 0"); -// assert_eq!(err, three_4, "lost bits should be 3/4"); - -// // 1.75 (min_n == -2) => 1.5 -// let ctx = RFloatContext::new() -// .with_min_n(-2) -// .with_rounding_mode(RoundingMode::ToZero); -// let (_, n) = ctx.round_params(&one_3_4); -// let (_, err) = RFloatContext::split_at(&one_3_4, n); -// let rounded = ctx.round(&one_3_4); -// assert_eq!(rounded, one_1_2, "rounding should truncated to 0"); -// assert_eq!(err, one_4, "lost bits should be 1/4"); - -// // 1 (min_n == 10) => 0 -// let ctx = RFloatContext::new() -// .with_min_n(10) -// .with_rounding_mode(RoundingMode::ToZero); -// let (_, n) = ctx.round_params(&one); -// let (_, err) = RFloatContext::split_at(&one, n); -// let rounded = ctx.round(&one); -// assert_eq!(rounded, zero, "rounding should truncated to 0"); -// assert_eq!(err, one, "lost bits should be 1"); -// } +fn round1(ctx: &RFloatContext, num: &RFloat) -> (RFloat, RFloat) { + let (p, n) = ctx.round_params(num); + let split = Split::new(num, p, n); + let err = split.lost().clone(); + let rounded = split.round(ctx); + (rounded, err) +} -// /// Testing rounding using floating-point rounding -// #[test] -// fn round_float() { -// let one_1_2 = RFloat::Real(false, -1, Integer::from(3)); -// let one_1_4 = RFloat::Real(false, -2, Integer::from(5)); -// let one_1_8 = RFloat::Real(false, -3, Integer::from(9)); -// let one = RFloat::one(); -// let one_4 = RFloat::Real(false, -2, Integer::from(1)); -// let one_8 = RFloat::Real(false, -3, Integer::from(1)); -// let zero = RFloat::zero(); - -// // 1.25, 3 bits - -// // rounding 1.25 with 3 bits, exact -// let ctx = RFloatContext::new().with_max_p(3); -// let (_, n) = ctx.round_params(&one_1_4); -// let (_, err) = RFloatContext::split_at(&one_1_4, n); -// let rounded = ctx.round(&one_1_4); -// assert_eq!(rounded, one_1_4, "rounding should be exact"); -// assert_eq!(err, zero, "lost bits is zero"); - -// // 1.25, 2 bits - -// // rounding 1.25 with 2 bits, round-to-nearest -// let ctx = ctx.with_max_p(2); -// let (_, n) = ctx.round_params(&one_1_4); -// let (_, err) = RFloatContext::split_at(&one_1_4, n); -// let rounded = ctx.round(&one_1_4); -// assert_eq!(rounded, one, "rounding goes to 1"); -// assert_eq!(err, one_4, "lost bits is 1/4"); - -// // rounding 1.25 with 2 bits, round-to-positive -// let ctx = ctx.with_rounding_mode(RoundingMode::ToPositive); -// let (_, n) = ctx.round_params(&one_1_4); -// let (_, err) = RFloatContext::split_at(&one_1_4, n); -// let rounded = ctx.round(&one_1_4); -// assert_eq!(rounded, one_1_2, "rounding goes to 3/2"); -// assert_eq!(err, one_4, "lost bits is -1/4"); - -// // rounding 1.25 with 2 bits, round-to-negative -// let ctx = ctx.with_rounding_mode(RoundingMode::ToNegative); -// let (_, n) = ctx.round_params(&one_1_4); -// let (_, err) = RFloatContext::split_at(&one_1_4, n); -// let rounded = ctx.round(&one_1_4); -// assert_eq!(rounded, one, "rounding goes to 1"); -// assert_eq!(err, one_4, "lost bits is 1/4"); - -// // rounding 1.25 with 2 bits, round-to-even -// let ctx = ctx.with_rounding_mode(RoundingMode::ToEven); -// let (_, n) = ctx.round_params(&one_1_4); -// let (_, err) = RFloatContext::split_at(&one_1_4, n); -// let rounded = ctx.round(&one_1_4); -// assert_eq!(rounded, one, "rounding goes to 1"); -// assert_eq!(err, one_4, "lost bits is 1/4"); - -// // rounding 1.25 with 2 bits, round-to-odd -// let ctx = ctx.with_rounding_mode(RoundingMode::ToOdd); -// let (_, n) = ctx.round_params(&one_1_4); -// let (_, err) = RFloatContext::split_at(&one_1_4, n); -// let rounded = ctx.round(&one_1_4); -// assert_eq!(rounded, one_1_2, "rounding goes to 3/2"); -// assert_eq!(err, one_4, "lost bits is -1/4"); - -// // 1.125, 2 bit - -// // rounding 1.125 with 2 bits, round-to-nearest -// let ctx = ctx.with_rounding_mode(RoundingMode::NearestTiesToEven); -// let (_, n) = ctx.round_params(&one_1_8); -// let (_, err) = RFloatContext::split_at(&one_1_8, n); -// let rounded = ctx.round(&one_1_8); -// assert_eq!(rounded, one, "rounding goes to 1"); -// assert_eq!(err, one_8, "lost bits is 1/8"); - -// // rounding 1.125 with 2 bits, round-to-positive -// let ctx = ctx.with_rounding_mode(RoundingMode::ToPositive); -// let (_, n) = ctx.round_params(&one_1_8); -// let (_, err) = RFloatContext::split_at(&one_1_8, n); -// let rounded = ctx.round(&one_1_8); -// assert_eq!(rounded, one_1_2, "rounding goes to 3/2"); -// assert_eq!(err, one_8, "lost bits is 1/8"); - -// // rounding 1.125 with 2 bits, round-to-negative -// let ctx = ctx.with_rounding_mode(RoundingMode::ToNegative); -// let (_, n) = ctx.round_params(&one_1_8); -// let (_, err) = RFloatContext::split_at(&one_1_8, n); -// let rounded = ctx.round(&one_1_8); -// assert_eq!(rounded, one, "rounding goes to 1"); -// assert_eq!(err, one_8, "lost bits is 1/8"); - -// // rounding 1.125 with 2 bits, round-to-even -// let ctx = ctx.with_rounding_mode(RoundingMode::ToEven); -// let (_, n) = ctx.round_params(&one_1_8); -// let (_, err) = RFloatContext::split_at(&one_1_8, n); -// let rounded = ctx.round(&one_1_8); -// assert_eq!(rounded, one, "rounding goes to 1"); -// assert_eq!(err, one_8, "lost bits is 1/8"); - -// // rounding 1.125 with 2 bits, round-to-odd -// let ctx = ctx.with_rounding_mode(RoundingMode::ToOdd); -// let (_, n) = ctx.round_params(&one_1_8); -// let (_, err) = RFloatContext::split_at(&one_1_8, n); -// let rounded = ctx.round(&one_1_8); -// assert_eq!(rounded, one_1_2, "rounding goes to 3/2"); -// assert_eq!(err, one_8, "lost bits is -3/8"); -// } +/// Testing rounding using fixed-point rounding +#[test] +fn round_fixed() { + let one_3_4 = RFloat::Real(false, -2, Integer::from(7)); + let one_1_2 = RFloat::Real(false, -1, Integer::from(3)); + let one = RFloat::one(); + let three_4 = RFloat::Real(false, -2, Integer::from(3)); + let one_4 = RFloat::Real(false, -2, Integer::from(1)); + let zero = RFloat::zero(); -// /// Testing rounding using floating-point rounding using subnormals -// #[test] -// fn round_float_subnorm() { -// let one = RFloat::one(); -// let half_way = RFloat::Real(false, -3, Integer::from(7)); -// let tiny_val = RFloat::Real(false, -2, Integer::from(3)); -// let one_2 = RFloat::Real(false, -1, Integer::from(1)); -// let one_4 = RFloat::Real(false, -2, Integer::from(1)); -// let one_8 = RFloat::Real(false, -3, Integer::from(1)); - -// // No subnormals, round-to-nearest -// let ctx = RFloatContext::new().with_max_p(2); -// let (_, n) = ctx.round_params(&half_way); -// let (_, err) = RFloatContext::split_at(&half_way, n); -// let rounded = ctx.round(&half_way); -// assert_eq!(one, rounded, "rounding to 1"); -// assert_eq!(err, one_8, "lost bits is 1/8"); - -// // No subnormals, round-away-zero -// let ctx = ctx.with_rounding_mode(RoundingMode::AwayZero); -// let (_, n) = ctx.round_params(&half_way); -// let (_, err) = RFloatContext::split_at(&half_way, n); -// let rounded = ctx.round(&half_way); -// assert_eq!(one, rounded, "rounding to 1"); -// assert_eq!(err, one_8, "lost bits is 1/8"); - -// // No subnormals, round-to-zero -// let ctx = ctx.with_rounding_mode(RoundingMode::ToZero); -// let (_, n) = ctx.round_params(&half_way); -// let (_, err) = RFloatContext::split_at(&half_way, n); -// let rounded = ctx.round(&half_way); -// assert_eq!(tiny_val, rounded, "rounding to 3/4"); -// assert_eq!(err, one_8, "lost bits is 1/8"); - -// // RFloat<2, 4>, round-to-nearest -// let ctx = RFloatContext::new().with_max_p(2).with_min_n(-2); -// let (_, n) = ctx.round_params(&tiny_val); -// let (_, err) = RFloatContext::split_at(&tiny_val, n); -// let rounded = ctx.round(&tiny_val); -// assert_eq!(one, rounded, "rounding to 1"); -// assert_eq!(err, one_4, "lost bits is 1/4"); - -// // RFloat<2, 4>, round-away-zero -// let ctx = ctx.with_rounding_mode(RoundingMode::AwayZero); -// let (_, n) = ctx.round_params(&tiny_val); -// let (_, err) = RFloatContext::split_at(&tiny_val, n); -// let rounded = ctx.round(&tiny_val); -// assert_eq!(one, rounded, "rounding to 1"); -// assert_eq!(err, one_4, "lost bits is 1/4"); - -// // RFloat<2, 4>, round-to-zero -// let ctx = ctx.with_rounding_mode(RoundingMode::ToZero); -// let (_, n) = ctx.round_params(&tiny_val); -// let (_, err) = RFloatContext::split_at(&tiny_val, n); -// let rounded = ctx.round(&tiny_val); -// assert_eq!(one_2, rounded, "rounding to 1/2"); -// assert_eq!(err, one_4, "lost bits is 1/4"); - -// // RFloat<2, 4>, round-to-even -// let ctx = ctx.with_rounding_mode(RoundingMode::ToEven); -// let (_, n) = ctx.round_params(&tiny_val); -// let (_, err) = RFloatContext::split_at(&tiny_val, n); -// let rounded = ctx.round(&tiny_val); -// assert_eq!(one, rounded, "rounding to 1"); -// assert_eq!(err, one_4, "lost bits is 1/4"); - -// // RFloat<2, 4>, round-to-odd -// let ctx = ctx.with_rounding_mode(RoundingMode::ToOdd); -// let (_, n) = ctx.round_params(&tiny_val); -// let (_, err) = RFloatContext::split_at(&tiny_val, n); -// let rounded = ctx.round(&tiny_val); -// assert_eq!(one_2, rounded, "rounding to 1/2"); -// assert_eq!(err, one_4, "lost bits is 1/4"); -// } + let neg_one = RFloat::Real(true, 0, Integer::from(1)); + + // 1 (min_n == -1) => 1 + let ctx = RFloatContext::new() + .with_min_n(-1) + .with_rounding_mode(RoundingMode::ToZero); + let (rounded, err) = round1(&ctx, &one); + assert_eq!(rounded, RFloat::one(), "rounding should not have lost bits"); + assert!(err.is_zero(), "lost bits should be 0"); + + // 1 (min_n == 0) => 0 + let ctx = RFloatContext::new() + .with_min_n(0) + .with_rounding_mode(RoundingMode::ToZero); + let (rounded, err) = round1(&ctx, &one); + assert_eq!(rounded, RFloat::zero(), "rounding should be truncated to 0"); + assert_eq!(err, RFloat::one(), "lost bits should be 1"); + + // -1 (min_n == 0) => 0 + let ctx = RFloatContext::new() + .with_min_n(0) + .with_rounding_mode(RoundingMode::ToZero); + let (rounded, err) = round1(&ctx, &neg_one); + assert_eq!(rounded, zero, "rounding should truncated to 0"); + assert_eq!(err, neg_one, "lost bits should be -1"); + + // 1.75 (min_n == -1) => 1 + let ctx = RFloatContext::new() + .with_min_n(-1) + .with_rounding_mode(RoundingMode::ToZero); + let (rounded, err) = round1(&ctx, &one_3_4); + assert_eq!(rounded, one, "rounding should truncated to 0"); + assert_eq!(err, three_4, "lost bits should be 3/4"); + + // 1.75 (min_n == -2) => 1.5 + let ctx = RFloatContext::new() + .with_min_n(-2) + .with_rounding_mode(RoundingMode::ToZero); + let (rounded, err) = round1(&ctx, &one_3_4); + assert_eq!(rounded, one_1_2, "rounding should truncated to 0"); + assert_eq!(err, one_4, "lost bits should be 1/4"); + + // 1 (min_n == 10) => 0 + let ctx = RFloatContext::new() + .with_min_n(10) + .with_rounding_mode(RoundingMode::ToZero); + let (rounded, err) = round1(&ctx, &one); + assert_eq!(rounded, zero, "rounding should truncated to 0"); + assert_eq!(err, one, "lost bits should be 1"); +} + +/// Testing rounding using floating-point rounding +#[test] +fn round_float() { + let one_1_2 = RFloat::Real(false, -1, Integer::from(3)); + let one_1_4 = RFloat::Real(false, -2, Integer::from(5)); + let one_1_8 = RFloat::Real(false, -3, Integer::from(9)); + let one = RFloat::one(); + let one_4 = RFloat::Real(false, -2, Integer::from(1)); + let one_8 = RFloat::Real(false, -3, Integer::from(1)); + let zero = RFloat::zero(); + + // 1.25, 3 bits + + // rounding 1.25 with 3 bits, exact + let ctx = RFloatContext::new().with_max_p(3); + let (rounded, err) = round1(&ctx, &one_1_4); + assert_eq!(rounded, one_1_4, "rounding should be exact"); + assert_eq!(err, zero, "lost bits is zero"); + + // 1.25, 2 bits + + // rounding 1.25 with 2 bits, round-to-nearest + let ctx = ctx.with_max_p(2); + let (rounded, err) = round1(&ctx, &one_1_4); + assert_eq!(rounded, one, "rounding goes to 1"); + assert_eq!(err, one_4, "lost bits is 1/4"); + + // rounding 1.25 with 2 bits, round-to-positive + let ctx = ctx.with_rounding_mode(RoundingMode::ToPositive); + let (rounded, err) = round1(&ctx, &one_1_4); + assert_eq!(rounded, one_1_2, "rounding goes to 3/2"); + assert_eq!(err, one_4, "lost bits is -1/4"); + + // rounding 1.25 with 2 bits, round-to-negative + let ctx = ctx.with_rounding_mode(RoundingMode::ToNegative); + let (rounded, err) = round1(&ctx, &one_1_4); + assert_eq!(rounded, one, "rounding goes to 1"); + assert_eq!(err, one_4, "lost bits is 1/4"); + + // rounding 1.25 with 2 bits, round-to-even + let ctx = ctx.with_rounding_mode(RoundingMode::ToEven); + let (rounded, err) = round1(&ctx, &one_1_4); + assert_eq!(rounded, one, "rounding goes to 1"); + assert_eq!(err, one_4, "lost bits is 1/4"); + + // rounding 1.25 with 2 bits, round-to-odd + let ctx = ctx.with_rounding_mode(RoundingMode::ToOdd); + let (rounded, err) = round1(&ctx, &one_1_4); + assert_eq!(rounded, one_1_2, "rounding goes to 3/2"); + assert_eq!(err, one_4, "lost bits is -1/4"); + + // 1.125, 2 bit + + // rounding 1.125 with 2 bits, round-to-nearest + let ctx = ctx.with_rounding_mode(RoundingMode::NearestTiesToEven); + let (rounded, err) = round1(&ctx, &one_1_8); + assert_eq!(rounded, one, "rounding goes to 1"); + assert_eq!(err, one_8, "lost bits is 1/8"); + + // rounding 1.125 with 2 bits, round-to-positive + let ctx = ctx.with_rounding_mode(RoundingMode::ToPositive); + let (rounded, err) = round1(&ctx, &one_1_8); + assert_eq!(rounded, one_1_2, "rounding goes to 3/2"); + assert_eq!(err, one_8, "lost bits is 1/8"); + + // rounding 1.125 with 2 bits, round-to-negative + let ctx = ctx.with_rounding_mode(RoundingMode::ToNegative); + let (rounded, err) = round1(&ctx, &one_1_8); + assert_eq!(rounded, one, "rounding goes to 1"); + assert_eq!(err, one_8, "lost bits is 1/8"); + + // rounding 1.125 with 2 bits, round-to-even + let ctx = ctx.with_rounding_mode(RoundingMode::ToEven); + let (rounded, err) = round1(&ctx, &one_1_8); + assert_eq!(rounded, one, "rounding goes to 1"); + assert_eq!(err, one_8, "lost bits is 1/8"); + + // rounding 1.125 with 2 bits, round-to-odd + let ctx = ctx.with_rounding_mode(RoundingMode::ToOdd); + let (rounded, err) = round1(&ctx, &one_1_8); + assert_eq!(rounded, one_1_2, "rounding goes to 3/2"); + assert_eq!(err, one_8, "lost bits is -3/8"); +} + +/// Testing rounding using floating-point rounding using subnormals +#[test] +fn round_float_subnorm() { + let one = RFloat::one(); + let half_way = RFloat::Real(false, -3, Integer::from(7)); + let tiny_val = RFloat::Real(false, -2, Integer::from(3)); + let one_2 = RFloat::Real(false, -1, Integer::from(1)); + let one_4 = RFloat::Real(false, -2, Integer::from(1)); + let one_8 = RFloat::Real(false, -3, Integer::from(1)); + + // No subnormals, round-to-nearest + let ctx = RFloatContext::new().with_max_p(2); + let (rounded, err) = round1(&ctx, &half_way); + assert_eq!(one, rounded, "rounding to 1"); + assert_eq!(err, one_8, "lost bits is 1/8"); + + // No subnormals, round-away-zero + let ctx = ctx.with_rounding_mode(RoundingMode::AwayZero); + let (rounded, err) = round1(&ctx, &half_way); + assert_eq!(one, rounded, "rounding to 1"); + assert_eq!(err, one_8, "lost bits is 1/8"); + + // No subnormals, round-to-zero + let ctx = ctx.with_rounding_mode(RoundingMode::ToZero); + let (rounded, err) = round1(&ctx, &half_way); + assert_eq!(tiny_val, rounded, "rounding to 3/4"); + assert_eq!(err, one_8, "lost bits is 1/8"); + + // RFloat<2, 4>, round-to-nearest + let ctx = RFloatContext::new().with_max_p(2).with_min_n(-2); + let (rounded, err) = round1(&ctx, &tiny_val); + assert_eq!(one, rounded, "rounding to 1"); + assert_eq!(err, one_4, "lost bits is 1/4"); + + // RFloat<2, 4>, round-away-zero + let ctx = ctx.with_rounding_mode(RoundingMode::AwayZero); + let (rounded, err) = round1(&ctx, &tiny_val); + assert_eq!(one, rounded, "rounding to 1"); + assert_eq!(err, one_4, "lost bits is 1/4"); + + // RFloat<2, 4>, round-to-zero + let ctx = ctx.with_rounding_mode(RoundingMode::ToZero); + let (rounded, err) = round1(&ctx, &tiny_val); + assert_eq!(one_2, rounded, "rounding to 1/2"); + assert_eq!(err, one_4, "lost bits is 1/4"); + + // RFloat<2, 4>, round-to-even + let ctx = ctx.with_rounding_mode(RoundingMode::ToEven); + let (rounded, err) = round1(&ctx, &tiny_val); + assert_eq!(one, rounded, "rounding to 1"); + assert_eq!(err, one_4, "lost bits is 1/4"); + + // RFloat<2, 4>, round-to-odd + let ctx = ctx.with_rounding_mode(RoundingMode::ToOdd); + let (rounded, err) = round1(&ctx, &tiny_val); + assert_eq!(one_2, rounded, "rounding to 1/2"); + assert_eq!(err, one_4, "lost bits is 1/4"); +} fn assert_expected_cmp(x: &RFloat, y: &RFloat, expected: &Option) { let actual = x.partial_cmp(y);