8000 refactor NaN propagation and rename mul_add to fused_mul_add · programmerjake/simple-soft-float@be91595 · GitHub
[go: up one dir, main page]

Skip to content

Commit be91595

Browse files
refactor NaN propagation and rename mul_add to fused_mul_add
1 parent 092418a commit be91595

File tree

2 files changed

+117
-47
lines changed

2 files changed

+117
-47
lines changed

src/lib.rs

Lines changed: 116 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,12 @@ pub enum BinaryNaNPropagationMode {
182182
SecondFirstPreferringSNaN,
183183
}
184184

185+
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
186+
pub enum UnaryNaNPropagationMode {
187+
AlwaysCanonical,
188+
First,
189+
}
190+
185191
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
186192
pub enum BinaryNaNPropagationResults {
187193
Canonical,
@@ -254,25 +260,41 @@ impl BinaryNaNPropagationMode {
254260
}
255261

256262
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
257-
pub enum NaNPropagationResults {
263+
pub enum UnaryNaNPropagationResults {
258264
Canonical,
259265
First,
260-
Second,
261-
Third,
262266
}
263267

264-
impl Default for NaNPropagationResults {
268+
impl Default for UnaryNaNPropagationResults {
265269
fn default() -> Self {
266270
Self::Canonical
267271
}
268272
}
269273

270-
impl From<NaNPropagationMode> for BinaryNaNPropagationMode {
271-
fn from(v: NaNPropagationMode) -> Self {
274+
impl UnaryNaNPropagationMode {
275+
pub fn calculate_propagation_results(
276+
self,
277+
first_class: FloatClass,
278+
) -> UnaryNaNPropagationResults {
279+
match self {
280+
UnaryNaNPropagationMode::AlwaysCanonical => UnaryNaNPropagationResults::Canonical,
281+
UnaryNaNPropagationMode::First => {
282+
if first_class.is_nan() {
283+
UnaryNaNPropagationResults::First
284+
} else {
285+
UnaryNaNPropagationResults::Canonical
286+
}
287+
}
288+
}
289+
}
290+
}
291+
292+
impl From<TernaryNaNPropagationMode> for BinaryNaNPropagationMode {
293+
fn from(v: TernaryNaNPropagationMode) -> Self {
272294
use BinaryNaNPropagationMode::*;
273-
use NaNPropagationMode::*;
295+
use TernaryNaNPropagationMode::*;
274296
match v {
275-
NaNPropagationMode::AlwaysCanonical => BinaryNaNPropagationMode::AlwaysCanonical,
297+
TernaryNaNPropagationMode::AlwaysCanonical => BinaryNaNPropagationMode::AlwaysCanonical,
276298
FirstSecondThird | FirstThirdSecond | ThirdFirstSecond => FirstSecond,
277299
SecondFirstThird | SecondThirdFirst | ThirdSecondFirst => SecondFirst,
278300
FirstSecondThirdPreferringSNaN
@@ -285,8 +307,35 @@ impl From<NaNPropagationMode> for BinaryNaNPropagationMode {
285307
}
286308
}
287309

310+
impl From<BinaryNaNPropagationMode> for UnaryNaNPropagationMode {
311+
fn from(v: BinaryNaNPropagationMode) -> Self {
312+
use BinaryNaNPropagationMode::*;
313+
use UnaryNaNPropagationMode::*;
314+
match v {
315+
BinaryNaNPropagationMode::AlwaysCanonical => UnaryNaNPropagationMode::AlwaysCanonical,
316+
FirstSecond | SecondFirst | FirstSecondPreferringSNaN | SecondFirstPreferringSNaN => {
317+
First
318+
}
319+
}
320+
}
321+
}
322+
323+
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
324+
pub enum TernaryNaNPropagationResults {
325+
Canonical,
326+
First,
327+
Second,
328+
Third,
329+
}
330+
331+
impl Default for TernaryNaNPropagationResults {
332+
fn default() -> Self {
333+
Self::Canonical
334+
}
335+
}
336+
288337
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
289-
pub enum NaNPropagationMode {
338+
pub enum TernaryNaNPropagationMode {
290339
AlwaysCanonical,
291340
FirstSecondThird,
292341
FirstThirdSecond,
@@ -302,22 +351,22 @@ pub enum NaNPropagationMode {
302351
ThirdSecondFirstPreferringSNaN,
303352
}
304353

305-
impl Default for NaNPropagationMode {
306-
fn default() -> NaNPropagationMode {
307-
NaNPropagationMode::AlwaysCanonical
354+
impl Default for TernaryNaNPropagationMode {
355+
fn default() -> TernaryNaNPropagationMode {
356+
TernaryNaNPropagationMode::AlwaysCanonical
308357
}
309358
}
310359

311-
impl NaNPropagationMode {
360+
impl TernaryNaNPropagationMode {
312361
pub fn calculate_propagation_results(
313362
self,
314363
first_class: FloatClass,
315364
second_class: FloatClass,
316365
third_class: FloatClass,
317-
) -> NaNPropagationResults {
366+
) -> TernaryNaNPropagationResults {
318367
#![allow(clippy::cognitive_complexity)]
319-
use NaNPropagationMode::*;
320-
use NaNPropagationResults::*;
368+
use TernaryNaNPropagationMode::*;
369+
use TernaryNaNPropagationResults::*;
321370
match self {
322371
AlwaysCanonical => Canonical,
323372
FirstSecondThird => {
@@ -691,7 +740,8 @@ pub struct PlatformProperties {
691740
pub canonical_nan_mantissa_msb: bool,
692741
pub canonical_nan_mantissa_second_to_msb: bool,
693742
pub canonical_nan_mantissa_rest: bool,
694-
pub nan_propagation_mode: NaNPropagationMode,
743+
pub add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode,
744+
pub fma_nan_propagation_mode: TernaryNaNPropagationMode,
695745
pub fma_inf_zero_qnan_result: FMAInfZeroQNaNResult,
696746
}
697747

@@ -735,8 +785,12 @@ macro_rules! platform_properties_constants {
735785
&self.canonical_nan_mantissa_rest,
736786
)
737787
.field(
738-
"nan_propagation_mode",
739-
&self.nan_propagation_mode,
788+
"add_sub_mul_div_nan_propagation_mode",
789+
&self.add_sub_mul_div_nan_propagation_mode,
790+
)
791+
.field(
792+
"fma_nan_propagation_mode",
793+
&self.fma_nan_propagation_mode,
740794
)
741795
.field(
742796
"fma_inf_zero_qnan_result",
@@ -756,31 +810,38 @@ platform_properties_constants! {
756810
canonical_nan_mantissa_msb: true,
757811
canonical_nan_mantissa_second_to_msb: false,
758812
canonical_nan_mantissa_rest: false,
759-
nan_propagation_mode: NaNPropagationMode::ThirdFirstSecondPreferringSNaN,
813+
// FIXME: NaN propagation not known to be correct
814+
add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
815+
fma_nan_propagation_mode: TernaryNaNPropagationMode::ThirdFirstSecondPreferringSNaN,
760816
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult::CanonicalAndGenerateInvalid,
761817
};
762818
pub const RISC_V: PlatformProperties = PlatformProperties {
763819
canonical_nan_sign: Sign::Positive,
764820
canonical_nan_mantissa_msb: true,
765821
canonical_nan_mantissa_second_to_msb: false,
766822
canonical_nan_mantissa_rest: false,
767-
nan_propagation_mode: NaNPropagationMode::AlwaysCanonical,
823+
add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode::AlwaysCanonical,
824+
fma_nan_propagation_mode: TernaryNaNPropagationMode::AlwaysCanonical,
768825
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult::CanonicalAndGenerateInvalid,
769826
};
770827
pub const POWER: PlatformProperties = PlatformProperties {
771828
canonical_nan_sign: Sign::Positive,
772829
canonical_nan_mantissa_msb: true,
773830
canonical_nan_mantissa_second_to_msb: false,
774831
canonical_nan_mantissa_rest: false,
775-
nan_propagation_mode: NaNPropagationMode::FirstThirdSecond,
832+
// FIXME: NaN propagation not known to be correct
833+
add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecond,
834+
fma_nan_propagation_mode: TernaryNaNPropagationMode::FirstThirdSecond,
776835
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult::PropagateAndGenerateInvalid,
777836
};
778837
pub const MIPS_2008: PlatformProperties = PlatformProperties {
779838
canonical_nan_sign: Sign::Positive,
780839
canonical_nan_mantissa_msb: true,
781840
canonical_nan_mantissa_second_to_msb: false,
782841
canonical_nan_mantissa_rest: false,
783-
nan_propagation_mode: NaNPropagationMode::ThirdFirstSecondPreferringSNaN,
842+
// FIXME: NaN propagation not known to be correct
843+
add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
844+
fma_nan_propagation_mode: TernaryNaNPropagationMode::ThirdFirstSecondPreferringSNaN,
784845
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult::PropagateAndGenerateInvalid,
785846
};
786847
// X86_X87 is not implemented
@@ -789,31 +850,39 @@ platform_properties_constants! {
789850
canonical_nan_mantissa_msb: true,
790851
canonical_nan_mantissa_second_to_msb: false,
791852
canonical_nan_mantissa_rest: false,
792-
nan_propagation_mode: NaNPropagationMode::FirstSecondThird,
853+
// FIXME: NaN propagation not known to be correct
854+
add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecond,
855+
fma_nan_propagation_mode: TernaryNaNPropagationMode::FirstSecondThird,
793856
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult::FollowNaNPropagationMode,
794857
};
795858
pub const SPARC: PlatformProperties = PlatformProperties {
796859
canonical_nan_sign: Sign::Positive,
797860
canonical_nan_mantissa_msb: true,
798861
canonical_nan_mantissa_second_to_msb: true,
799862
canonical_nan_mantissa_rest: true,
800-
nan_propagation_mode: NaNPropagationMode::FirstSecondThirdPreferringSNaN,
863+
// FIXME: NaN propagation not known to be correct
864+
add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
865+
fma_nan_propagation_mode: TernaryNaNPropagationMode::FirstSecondThirdPreferringSNaN,
801866
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult::FollowNaNPropagationMode,
802867
};
803868
pub const HPPA: PlatformProperties = PlatformProperties {
804869
canonical_nan_sign: Sign::Positive,
805870
canonical_nan_mantissa_msb: false,
806871
canonical_nan_mantissa_second_to_msb: true,
807872
canonical_nan_mantissa_rest: false,
808-
nan_propagation_mode: NaNPropagationMode::FirstSecondThirdPreferringSNaN,
873+
// FIXME: NaN propagation not known to be correct
874+
add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
875+
fma_nan_propagation_mode: TernaryNaNPropagationMode::FirstSecondThirdPreferringSNaN,
809876
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult::FollowNaNPropagationMode,
810877
};
811878
pub const MIPS_LEGACY: PlatformProperties = PlatformProperties {
812879
canonical_nan_sign: Sign::Positive,
813880
canonical_nan_mantissa_msb: false,
814881
canonical_nan_mantissa_second_to_msb: true,
815882
canonical_nan_mantissa_rest: true,
816-
nan_propagation_mode: NaNPropagationMode::FirstSecondThirdPreferringSNaN,
883+
// FIXME: NaN propagation not known to be correct
884+
add_sub_mul_div_nan_propagation_mode: BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
885+
fma_nan_propagation_mode: TernaryNaNPropagationMode::FirstSecondThirdPreferringSNaN,
817886
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult::CanonicalAndGenerateInvalid,
818887
};
819888
}
@@ -1880,10 +1949,10 @@ impl<Bits: FloatBitsType, FT: FloatTraits<Bits = Bits>> Float<FT> {
18801949
if self_class.is_signaling_nan() || rhs_class.is_signaling_nan() {
18811950
fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
18821951
}
1883-
match BinaryNaNPropagationMode::from(
1884-
properties.platform_properties.nan_propagation_mode,
1885-
)
1886-
.calculate_propagation_results(self_class, rhs_class)
1952+
match properties
1953+
.platform_properties
1954+
.add_sub_mul_div_nan_propagation_mode
1955+
.calculate_propagation_results(self_class, rhs_class)
18871956
{
18881957
BinaryNaNPropagationResults::First => self.to_quiet_nan(),
18891958
BinaryNaNPropagationResults::Second => rhs.to_quiet_nan(),
@@ -1974,10 +2043,10 @@ impl<Bits: FloatBitsType, FT: FloatTraits<Bits = Bits>> Float<FT> {
19742043
if self_class.is_signaling_nan() || rhs_class.is_signaling_nan() {
19752044
fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
19762045
}
1977-
match BinaryNaNPropagationMode::from(
1978-
properties.platform_properties.nan_propagation_mode,
1979-
)
1980-
.calculate_propagation_results(self_class, rhs_class)
2046+
match properties
2047+
.platform_properties
2048 F438 +
.add_sub_mul_div_nan_propagation_mode
2049+
.calculate_propagation_results(self_class, rhs_class)
19812050
{
19822051
BinaryNaNPropagationResults::First => self.to_quiet_nan(),
19832052
BinaryNaNPropagationResults::Second => rhs.to_quiet_nan(),
@@ -2023,10 +2092,10 @@ impl<Bits: FloatBitsType, FT: FloatTraits<Bits = Bits>> Float<FT> {
20232092
if self_class.is_signaling_nan() || rhs_class.is_signaling_nan() {
20242093
fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
20252094
}
2026-
match BinaryNaNPropagationMode::from(
2027-
properties.platform_properties.nan_propagation_mode,
2028-
)
2029-
.calculate_propagation_results(self_class, rhs_class)
2095+
match properties
2096+
.platform_properties
2097+
.add_sub_mul_div_nan_propagation_mode
2098+
.calculate_propagation_results(self_class, rhs_class)
20302099
{
20312100
BinaryNaNPropagationResults::First => self.to_quiet_nan(),
20322101
BinaryNaNPropagationResults::Second => rhs.to_quiet_nan(),
@@ -2058,7 +2127,7 @@ impl<Bits: FloatBitsType, FT: FloatTraits<Bits = Bits>> Float<FT> {
20582127
}
20592128
}
20602129
/// compute `(self * factor) + term`
2061-
pub fn mul_add(
2130+
pub fn fused_mul_add(
20622131
&self,
20632132
factor: &Self,
20642133
term: &Self,
@@ -2099,13 +2168,13 @@ impl<Bits: FloatBitsType, FT: FloatTraits<Bits = Bits>> Float<FT> {
20992168
}
21002169
match properties
21012170
.platform_properties
2102-
.nan_propagation_mode
2171+
.fma_nan_propagation_mode
21032172
.calculate_propagation_results(self_class, factor_class, term_class)
21042173
{
2105-
NaNPropagationResults::First => self.to_quiet_nan(),
2106-
NaNPropagationResults::Second => factor.to_quiet_nan(),
2107-
NaNPropagationResults::Third => term.to_quiet_nan(),
2108-
NaNPropagationResults::Canonical => {
2174+
TernaryNaNPropagationResults::First => self.to_quiet_nan(),
2175+
TernaryNaNPropagationResults::Second => factor.to_quiet_nan(),
2176+
TernaryNaNPropagationResults::Third => term.to_quiet_nan(),
2177+
TernaryNaNPropagationResults::Canonical => {
21092178
Self::quiet_nan_with_traits(self.traits.clone())
21102179
}
21112180
}
@@ -2314,7 +2383,8 @@ mod tests {
23142383
canonical_nan_sign: Negative, canonical_nan_mantissa_msb: false, \
23152384
canonical_nan_mantissa_second_to_msb: true, \
23162385
canonical_nan_mantissa_rest: true, \
2317-
nan_propagation_mode: FirstSecondThirdPreferringSNaN, \
2386+
add_sub_mul_div_nan_propagation_mode: FirstSecondPreferringSNaN, \
2387+
fma_nan_propagation_mode: FirstSecondThirdPreferringSNaN, \
23182388
fma_inf_zero_qnan_result: CanonicalAndGenerateInvalid, \
23192389
quiet_nan_format: MIPSLegacy }), \
23202390
bits: 0x1234, sign: Positive, exponent_field: 0x04, \

src/test_cases.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ fn mul_add_test_case(
504504
tininess_detection_mode,
505505
..FPState::default()
506506
};
507-
*result = value1.mul_add(&value2, &value3, None, Some(&mut fp_state));
507+
*result = value1.fused_mul_add(&value2, &value3, None, Some(&mut fp_state));
508508
*status_flags = fp_state.status_flags;
509509
}
510510

0 commit comments

Comments
 (0)
0