@@ -746,6 +746,7 @@ pub struct PlatformProperties {
746
746
pub fma_inf_zero_qnan_result : FMAInfZeroQNaNResult ,
747
747
pub round_to_integral_nan_propagation_mode : UnaryNaNPropagationMode ,
748
748
pub next_up_or_down_nan_propagation_mode : UnaryNaNPropagationMode ,
749
+ pub scale_b_nan_propagation_mode : UnaryNaNPropagationMode ,
749
750
}
750
751
751
752
impl Default for PlatformProperties {
@@ -800,6 +801,7 @@ macro_rules! platform_properties_constants {
800
801
fma_inf_zero_qnan_result,
801
802
round_to_integral_nan_propagation_mode,
802
803
next_up_or_down_nan_propagation_mode,
804
+ scale_b_nan_propagation_mode,
803
805
#[ fn ] quiet_nan_format,
804
806
)
805
807
}
@@ -820,6 +822,7 @@ platform_properties_constants! {
820
822
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult :: CanonicalAndGenerateInvalid ,
821
823
round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
822
824
next_up_or_down_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
825
+ scale_b_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
823
826
} ;
824
827
pub const RISC_V : PlatformProperties = PlatformProperties {
825
828
canonical_nan_sign: Sign :: Positive ,
@@ -831,6 +834,7 @@ platform_properties_constants! {
831
834
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult :: CanonicalAndGenerateInvalid ,
832
835
round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode :: AlwaysCanonical ,
833
836
next_up_or_down_nan_propagation_mode: UnaryNaNPropagationMode :: AlwaysCanonical ,
837
+ scale_b_nan_propagation_mode: UnaryNaNPropagationMode :: AlwaysCanonical ,
834
838
} ;
835
839
pub const POWER : PlatformProperties = PlatformProperties {
836
840
canonical_nan_sign: Sign :: Positive ,
@@ -843,6 +847,7 @@ platform_properties_constants! {
843
847
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult :: PropagateAndGenerateInvalid ,
844
848
round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
845
849
next_up_or_down_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
850
+ scale_b_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
846
851
} ;
847
852
pub const MIPS_2008 : PlatformProperties = PlatformProperties {
848
853
canonical_nan_sign: Sign :: Positive ,
@@ -855,6 +860,7 @@ platform_properties_constants! {
855
860
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult :: PropagateAndGenerateInvalid ,
856
861
round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
857
862
next_up_or_down_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
863
+ scale_b_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
858
864
} ;
859
865
// X86_X87 is not implemented
860
866
pub const X86_SSE : PlatformProperties = PlatformProperties {
@@ -868,6 +874,7 @@ platform_properties_constants! {
868
874
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult :: FollowNaNPropagationMode ,
869
875
round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
870
876
next_up_or_down_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
877
+ scale_b_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
871
878
} ;
872
879
pub const SPARC : PlatformProperties = PlatformProperties {
873
880
canonical_nan_sign: Sign :: Positive ,
@@ -880,6 +887,7 @@ platform_properties_constants! {
880
887
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult :: FollowNaNPropagationMode ,
881
888
round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
882
889
next_up_or_down_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
890
+ scale_b_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
883
891
} ;
884
892
pub const HPPA : PlatformProperties = PlatformProperties {
885
893
canonical_nan_sign: Sign :: Positive ,
@@ -892,6 +900,7 @@ platform_properties_constants! {
892
900
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult :: FollowNaNPropagationMode ,
893
901
round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
894
902
next_up_or_down_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
903
+ scale_b_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
895
904
} ;
896
905
pub const MIPS_LEGACY : PlatformProperties = PlatformProperties {
897
906
canonical_nan_sign: Sign :: Positive ,
@@ -904,6 +913,7 @@ platform_properties_constants! {
904
913
fma_inf_zero_qnan_result: FMAInfZeroQNaNResult :: CanonicalAndGenerateInvalid ,
905
914
round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
906
915
next_up_or_down_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
916
+ scale_b_nan_propagation_mode: UnaryNaNPropagationMode :: First ,
907
917
} ;
908
918
}
909
919
@@ -1827,6 +1837,7 @@ impl<Bits: FloatBitsType, FT: FloatTraits<Bits = Bits>> Float<FT> {
1827
1837
pub fn into_quiet_nan ( mut self ) -> Self {
1828
1838
let properties = self . properties ( ) ;
1829
1839
self . set_exponent_field ( properties. exponent_inf_nan :: < Bits > ( ) ) ;
1840
+ // FIXME: handle nan propagation properly
1830
1841
match properties. quiet_nan_format ( ) {
1831
1842
QuietNaNFormat :: Standard => self . set_mantissa_field_msb ( true ) ,
1832
1843
QuietNaNFormat :: MIPSLegacy => return Self :: quiet_nan_with_traits ( self . traits ) ,
@@ -2234,7 +2245,7 @@ impl<Bits: FloatBitsType, FT: FloatTraits<Bits = Bits>> Float<FT> {
2234
2245
Self :: quiet_nan_with_traits ( self . traits . clone ( ) )
2235
2246
} else if rhs_class. is_infinity ( ) {
2236
2247
if self_class. is_zero ( ) {
2237
- self . clone ( )
2248
+ Self :: signed_zero_with_traits ( self . sign ( ) , self . traits . clone ( ) )
2238
2249
} else {
2239
2250
Self :: from_real_algebraic_number_with_traits (
2240
2251
& self . to_real_algebraic_number ( ) . expect ( "known to be finite" ) ,
@@ -2332,12 +2343,13 @@ impl<Bits: FloatBitsType, FT: FloatTraits<Bits = Bits>> Float<FT> {
2332
2343
{
2333
2344
fp_state. status_flags |= StatusFlags :: INVALID_OPERATION ;
2334
2345
Self :: quiet_nan_with_traits ( self . traits . clone ( ) )
2335
- } else if ( ( self_class. is_zero ( ) || factor_class. is_zero ( ) )
2346
+ } else if ( self_class. is_zero ( ) || factor_class. is_zero ( ) )
2336
2347
&& term_class. is_zero ( )
2337
- && product_sign == term. sign ( ) )
2338
- || term_class. is_infinity ( )
2348
+ && product_sign == term. sign ( )
2339
2349
{
2340
- term. clone ( )
2350
+ Self :: signed_zero_with_traits ( product_sign, self . traits . clone ( ) )
2351
+ } else if term_class. is_infinity ( ) {
2352
+ Self :: signed_infinity_with_traits ( term. sign ( ) , self . traits . clone ( ) )
2341
2353
} else if self_class. is_infinity ( ) || factor_class. is_infinity ( ) {
2342
2354
Self :: signed_infinity_with_traits ( product_sign, self . traits . clone ( ) )
2343
2355
} else {
@@ -2458,7 +2470,7 @@ impl<Bits: FloatBitsType, FT: FloatTraits<Bits = Bits>> Float<FT> {
2458
2470
UnaryNaNPropagationResults :: First => self . to_quiet_nan ( ) ,
2459
2471
}
2460
2472
} else if class. is_infinity ( ) {
2461
- self . clone ( )
2473
+ Self :: signed_infinity_with_traits ( self . sign ( ) , self . traits . clone ( ) )
2462
2474
} else {
2463
2475
let value = self
2464
2476
. round_to_bigint ( exact, Some ( rounding_mode) , Some ( fp_state) )
@@ -2609,6 +2621,60 @@ impl<Bits: FloatBitsType, FT: FloatTraits<Bits = Bits>> Float<FT> {
2609
2621
}
2610
2622
Some ( exponent)
2611
2623
}
2624
+ pub fn scale_b (
2625
+ & self ,
2626
+ mut scale : BigInt ,
2627
+ rounding_mode : Option < RoundingMode > ,
2628
+ fp_state : Option < & mut FPState > ,
2629
+ ) -> Self {
2630
+ let mut default_fp_state = FPState :: default ( ) ;
2631
+ let fp_state = fp_state. unwrap_or ( & mut default_fp_state) ;
2632
+ let rounding_mode = rounding_mode. unwrap_or ( fp_state. rounding_mode ) ;
2633
+ let properties = self . properties ( ) ;
2634
+ let class = self . class ( ) ;
2635
+ if class. is_nan ( ) {
2636
+ if class. is_signaling_nan ( ) {
2637
+ fp_state. status_flags |= StatusFlags :: INVALID_OPERATION ;
2638
+ }
2639
+ match properties
2640
+ . platform_properties ( )
2641
+ . scale_b_nan_propagation_mode
2642
+ . calculate_propagation_results ( class)
2643
+ {
2644
+ UnaryNaNPropagationResults :: Canonical => {
2645
+ Self :: quiet_nan_with_traits ( self . traits . clone ( ) )
2646
+ }
2647
+ UnaryNaNPropagationResults :: First => self . to_quiet_nan ( ) ,
2648
+ }
2649
+ } else if class. is_infinity ( ) {
2650
+ Self :: signed_infinity_with_traits ( self . sign ( ) , self . traits . clone ( ) )
2651
+ } else if class. is_zero ( ) {
2652
+ Self :: signed_zero_with_traits ( self . sign ( ) , self . traits . clone ( ) )
2653
+ } else {
2654
+ let exponent_max_normal: BigInt = properties. exponent_max_normal :: < Bits > ( ) . into ( ) ;
2655
+ let exponent_min_normal: BigInt = properties. exponent_min_normal :: < Bits > ( ) . into ( ) ;
2656
+ let scale_limit: BigInt =
2657
+ ( exponent_max_normal - exponent_min_normal + properties. fraction_width ( ) + 1 ) * 2 ;
2658
+ scale = scale. max ( -& scale_limit) ;
2659
+ scale = scale. min ( scale_limit) ;
2660
+ let mut value = self . to_real_algebraic_number ( ) . expect ( "known to be finite" ) ;
2661
+ if scale. is_positive ( ) {
2662
+ value *= RealAlgebraicNumber :: from (
2663
+ BigInt :: one ( ) << scale. to_usize ( ) . expect ( "rhs won't fit in usize" ) ,
2664
+ ) ;
2665
+ } else {
2666
+ value /= RealAlgebraicNumber :: from (
2667
+ BigInt :: one ( ) << ( -scale) . to_usize ( ) . expect ( "-rhs won't fit in usize" ) ,
2668
+ ) ;
2669
+ }
2670
+ Self :: from_real_algebraic_number_with_traits (
2671
+ & value,
2672
+ Some ( rounding_mode) ,
2673
+ Some ( fp_state) ,
2674
+ self . traits . clone ( ) ,
2675
+ )
2676
+ }
2677
+ }
2612
2678
}
2613
2679
2614
2680
impl < Bits : FloatBitsType , FT : FloatTraits < Bits = Bits > > fmt:: Debug for Float < FT > {
@@ -2775,6 +2841,7 @@ mod tests {
2775
2841
fma_inf_zero_qnan_result: CanonicalAndGenerateInvalid, \
2776
2842
round_to_integral_nan_propagation_mode: First, \
2777
2843
next_up_or_down_nan_propagation_mode: First, \
2844
+ scale_b_nan_propagation_mode: First, \
2778
2845
quiet_nan_format: MIPSLegacy }), \
2779
2846
bits: 0x1234, sign: Positive, exponent_field: 0x04, \
2780
2847
mantissa_field: 0x234, class: PositiveNormal }",
0 commit comments