Skip to content

Commit 1250128

Browse files
add ieee754_remainder
1 parent 4bf6408 commit 1250128

File tree

4 files changed

+6352
-16
lines changed

4 files changed

+6352
-16
lines changed

make_binary_op_test_cases.sh

+6-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@ function write_test_case() {
4848
local input="softfloat_round_$sf_rounding_mode softfloat_roundingMode_write_helper"
4949
input+=" 0 softfloat_exceptionFlags_write_helper"
5050
input+=" softfloat_tininess_${tininess_detection_mode,} softfloat_detectTininess_write_helper"
51-
input+=" $value1 $value2 f16_$op"
51+
if [[ "$op" == "ieee754_remainder" ]]; then
52+
input+=" $value1 $value2 f16_rem"
53+
else
54+
input+=" $value1 $value2 f16_$op"
55+
fi
5256
input+=" softfloat_exceptionFlags_read_helper"
5357
input+=" softfloat_flag_inexact"
5458
input+=" softfloat_flag_underflow"
@@ -86,7 +90,7 @@ function write_test_case() {
8690

8791
test_case_list=(0x0000 0x0001 0x03FF 0x0400 0x3C00 0x3C01 0x7BFF 0x7C00 0x7C01 0x7DFF 0x7E00 0x7FFF)
8892
test_case_list+=(0x8000 0x8001 0x83FF 0x8400 0xBC00 0xBC01 0xFBFF 0xFC00 0xFC01 0xFDFF 0xFE00 0xFFFF)
89-
ops=(add sub mul div)
93+
ops=(add sub mul div ieee754_remainder)
9094
rounding_modes=(TiesToEven TowardZero TowardNegative TowardPositive TiesToAway)
9195
tininess_detection_modes=(BeforeRounding AfterRounding)
9296

src/lib.rs

+86-14
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ pub struct PlatformProperties {
741741
pub canonical_nan_mantissa_msb: bool,
742742
pub canonical_nan_mantissa_second_to_msb: bool,
743743
pub canonical_nan_mantissa_rest: bool,
744-
pub add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode,
744+
pub std_bin_ops_nan_propagation_mode: BinaryNaNPropagationMode,
745745
pub fma_nan_propagation_mode: TernaryNaNPropagationMode,
746746
pub fma_inf_zero_qnan_result: FMAInfZeroQNaNResult,
747747
pub round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode,
@@ -795,7 +795,7 @@ macro_rules! platform_properties_constants {
795795
canonical_nan_mantissa_msb,
796796
canonical_nan_mantissa_second_to_msb,
797797
canonical_nan_mantissa_rest,
798-
add_sub_mul_div_nan_propagation_mode,
798+
std_bin_ops_nan_propagation_mode,
799799
fma_nan_propagation_mode,
800800
fma_inf_zero_qnan_result,
801801
round_to_integral_nan_propagation_mode,
@@ -815,7 +815,7 @@ platform_properties_constants! {
815815
canonical_nan_mantissa_second_to_msb: false,
816816
canonical_nan_mantissa_rest: false,
817817
// FIXME: NaN propagation not known to be correct
818-
add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
818+
std_bin_ops_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
819819
fma_nan_propagation_mode: TernaryNaNPropagationMode::ThirdFirstSecondPreferringSNaN,
820820
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult::CanonicalAndGenerateInvalid,
821821
round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode::First,
@@ -826,7 +826,7 @@ platform_properties_constants! {
826826
canonical_nan_mantissa_msb: true,
827827
canonical_nan_mantissa_second_to_msb: false,
828828
canonical_nan_mantissa_rest: false,
829-
add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode::AlwaysCanonical,
829+
std_bin_ops_nan_propagation_mode: BinaryNaNPropagationMode::AlwaysCanonical,
830830
fma_nan_propagation_mode: TernaryNaNPropagationMode::AlwaysCanonical,
831831
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult::CanonicalAndGenerateInvalid,
832832
round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode::AlwaysCanonical,
@@ -838,7 +838,7 @@ platform_properties_constants! {
838838
canonical_nan_mantissa_second_to_msb: false,
839839
canonical_nan_mantissa_rest: false,
840840
// FIXME: NaN propagation not known to be correct
841-
add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecond,
841+
std_bin_ops_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecond,
842842
fma_nan_propagation_mode: TernaryNaNPropagationMode::FirstThirdSecond,
843843
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult::PropagateAndGenerateInvalid,
844844
round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode::First,
@@ -850,7 +850,7 @@ platform_properties_constants! {
850850
canonical_nan_mantissa_second_to_msb: false,
851851
canonical_nan_mantissa_rest: false,
852852
// FIXME: NaN propagation not known to be correct
853-
add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
853+
std_bin_ops_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
854854
fma_nan_propagation_mode: TernaryNaNPropagationMode::ThirdFirstSecondPreferringSNaN,
855855
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult::PropagateAndGenerateInvalid,
856856
round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode::First,
@@ -863,7 +863,7 @@ platform_properties_constants! {
863863
canonical_nan_mantissa_second_to_msb: false,
864864
canonical_nan_mantissa_rest: false,
865865
// FIXME: NaN propagation not known to be correct
866-
add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecond,
866+
std_bin_ops_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecond,
867867
fma_nan_propagation_mode: TernaryNaNPropagationMode::FirstSecondThird,
868868
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult::FollowNaNPropagationMode,
869869
round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode::First,
@@ -875,7 +875,7 @@ platform_properties_constants! {
875875
canonical_nan_mantissa_second_to_msb: true,
876876
canonical_nan_mantissa_rest: true,
877877
// FIXME: NaN propagation not known to be correct
878-
add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
878+
std_bin_ops_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
879879
fma_nan_propagation_mode: TernaryNaNPropagationMode::FirstSecondThirdPreferringSNaN,
880880
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult::FollowNaNPropagationMode,
881881
round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode::First,
@@ -887,7 +887,7 @@ platform_properties_constants! {
887887
canonical_nan_mantissa_second_to_msb: true,
888888
canonical_nan_mantissa_rest: false,
889889
// FIXME: NaN propagation not known to be correct
890-
add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
890+
std_bin_ops_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
891891
fma_nan_propagation_mode: TernaryNaNPropagationMode::FirstSecondThirdPreferringSNaN,
892892
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult::FollowNaNPropagationMode,
893893
round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode::First,
@@ -899,7 +899,7 @@ platform_properties_constants! {
899899
canonical_nan_mantissa_second_to_msb: true,
900900
canonical_nan_mantissa_rest: true,
901901
// FIXME: NaN propagation not known to be correct
902-
add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
902+
std_bin_ops_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
903903
fma_nan_propagation_mode: TernaryNaNPropagationMode::FirstSecondThirdPreferringSNaN,
904904
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult::CanonicalAndGenerateInvalid,
905905
round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode::First,
@@ -2026,7 +2026,7 @@ impl<Bits: FloatBitsType, FT: FloatTraits<Bits = Bits>> Float<FT> {
20262026
}
20272027
match properties
20282028
.platform_properties
2029-
.add_sub_mul_div_nan_propagation_mode
2029+
.std_bin_ops_nan_propagation_mode
20302030
.calculate_propagation_results(self_class, rhs_class)
20312031
{
20322032
BinaryNaNPropagationResults::First => self.to_quiet_nan(),
@@ -2120,7 +2120,7 @@ impl<Bits: FloatBitsType, FT: FloatTraits<Bits = Bits>> Float<FT> {
21202120
}
21212121
match properties
21222122
.platform_properties
2123-
.add_sub_mul_div_nan_propagation_mode
2123+
.std_bin_ops_nan_propagation_mode
21242124
.calculate_propagation_results(self_class, rhs_class)
21252125
{
21262126
BinaryNaNPropagationResults::First => self.to_quiet_nan(),
@@ -2169,7 +2169,7 @@ impl<Bits: FloatBitsType, FT: FloatTraits<Bits = Bits>> Float<FT> {
21692169
}
21702170
match properties
21712171
.platform_properties
2172-
.add_sub_mul_div_nan_propagation_mode
2172+
.std_bin_ops_nan_propagation_mode
21732173
.calculate_propagation_results(self_class, rhs_class)
21742174
{
21752175
BinaryNaNPropagationResults::First => self.to_quiet_nan(),
@@ -2201,6 +2201,78 @@ impl<Bits: FloatBitsType, FT: FloatTraits<Bits = Bits>> Float<FT> {
22012201
)
22022202
}
22032203
}
2204+
pub fn ieee754_remainder(
2205+
&self,
2206+
rhs: &Self,
2207+
rounding_mode: Option<RoundingMode>,
2208+
fp_state: Option<&mut FPState>,
2209+
) -> Self {
2210+
assert_eq!(self.traits, rhs.traits);
2211+
let properties = self.properties();
2212+
let mut default_fp_state = FPState::default();
2213+
let fp_state = fp_state.unwrap_or(&mut default_fp_state);
2214+
let rounding_mode = rounding_mode.unwrap_or(fp_state.rounding_mode);
2215+
let self_class = self.class();
2216+
let rhs_class = rhs.class();
2217+
if self_class.is_nan() || rhs_class.is_nan() {
2218+
if self_class.is_signaling_nan() || rhs_class.is_signaling_nan() {
2219+
fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
2220+
}
2221+
match properties
2222+
.platform_properties
2223+
.std_bin_ops_nan_propagation_mode
2224+
.calculate_propagation_results(self_class, rhs_class)
2225+
{
2226+
BinaryNaNPropagationResults::First => self.to_quiet_nan(),
2227+
BinaryNaNPropagationResults::Second => rhs.to_quiet_nan(),
2228+
BinaryNaNPropagationResults::Canonical => {
2229+
Self::quiet_nan_with_traits(self.traits.clone())
2230+
}
2231+
}
2232+
} else if self_class.is_infinity() || rhs_class.is_zero() {
2233+
fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
2234+
Self::quiet_nan_with_traits(self.traits.clone())
2235+
} else if rhs_class.is_infinity() {
2236+
if self_class.is_zero() {
2237+
self.clone()
2238+
} else {
2239+
Self::from_real_algebraic_number_with_traits(
2240+
&self.to_real_algebraic_number().expect("known to be finite"),
2241+
Some(rounding_mode),
2242+
Some(fp_state),
2243+
self.traits.clone(),
2244+
)
2245+
}
2246+
} else {
2247+
let lhs_value = self.to_real_algebraic_number().expect("known to be finite");
2248+
let rhs_value = rhs.to_real_algebraic_number().expect("known to be finite");
2249+
let quotient = &lhs_value / &rhs_value;
2250+
let floor_quotient = quotient.to_integer_floor();
2251+
let fract_quotient = quotient - RealAlgebraicNumber::from(floor_quotient.clone());
2252+
let selected_quotient = match fract_quotient.cmp(&Ratio::new(1, 2).into()) {
2253+
Ordering::Less => floor_quotient,
2254+
Ordering::Greater => floor_quotient + 1,
2255+
Ordering::Equal => {
2256+
if floor_quotient.is_even() {
2257+
floor_quotient
2258+
} else {
2259+
floor_quotient + 1
2260+
}
2261+
}
2262+
};
2263+
let remainder = lhs_value - rhs_value * RealAlgebraicNumber::from(selected_quotient);
2264+
if remainder.is_zero() {
2265+
Self::signed_zero_with_traits(self.sign(), self.traits.clone())
2266+
} else {
2267+
Self::from_real_algebraic_number_with_traits(
2268+
&remainder,
2269+
Some(rounding_mode),
2270+
Some(fp_state),
2271+
self.traits.clone(),
2272+
)
2273+
}
2274+
}
2275+
}
22042276
/// compute `(self * factor) + term`
22052277
pub fn fused_mul_add(
22062278
&self,
@@ -2671,7 +2743,7 @@ mod tests {
26712743
canonical_nan_sign: Negative, canonical_nan_mantissa_msb: false, \
26722744
canonical_nan_mantissa_second_to_msb: true, \
26732745
canonical_nan_mantissa_rest: true, \
2674-
add_sub_mul_div_nan_propagation_mode: FirstSecondPreferringSNaN, \
2746+
std_bin_ops_nan_propagation_mode: FirstSecondPreferringSNaN, \
26752747
fma_nan_propagation_mode: FirstSecondThirdPreferringSNaN, \
26762748
fma_inf_zero_qnan_result: CanonicalAndGenerateInvalid, \
26772749
round_to_integral_nan_propagation_mode: First, \

src/test_cases.rs

+21
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,27 @@ test_case! {
488488
}
489489
}
490490

491+
test_case! {
492+
#[test_case_file_name = "ieee754_remainder.txt"]
493+
fn test_ieee754_remainder(lhs: F16,
494+
rhs: F16,
495+
rounding_mode: RoundingMode,
496+
tininess_detection_mode: TininessDetectionMode,
497+
#[output] result: F16,
498+
#[output] status_flags: StatusFlags,
499+
) {
500+
let exception_handling_mode = ExceptionHandlingMode::DefaultIgnoreExactUnderflow;
501+
let mut fp_state = FPState {
502+
rounding_mode,
503+
exception_handling_mode,
504+
tininess_detection_mode,
505+
..FPState::default()
506+
};
507+
*result = lhs.ieee754_remainder(&rhs, None, Some(&mut fp_state));
508+
*status_flags = fp_state.status_flags;
509+
}
510+
}
511+
491512
fn mul_add_test_case(
492513
value1: F16,
493514
value2: F16,

0 commit comments

Comments
 (0)