@@ -834,7 +834,30 @@ impl<'a> ConstantEvaluator<'a> {
834
834
component_wise_float ! ( self , span, [ arg] , |e| { Ok ( e. cosh( ) . into( ) ) } )
835
835
}
836
836
crate :: MathFunction :: Round => {
837
- component_wise_float ! ( self , span, [ arg] , |e| { Ok ( e. round( ) . into( ) ) } )
837
+ // TODO: Use `f{32,64}.round_ties_even()` when available on stable. This polyfill
838
+ // is shamelessly [~~stolen from~~ inspired by `ndarray-image`][polyfill source],
839
+ // which has licensing compatible with ours. See also
840
+ // <https://github.com/rust-lang/rust/issues/96710>.
841
+ //
842
+ // [polyfill source]: https://github.com/imeka/ndarray-ndimage/blob/8b14b4d6ecfbc96a8a052f802e342a7049c68d8f/src/lib.rs#L98
843
+ fn round_ties_even ( x : f64 ) -> f64 {
844
+ let i = x as i64 ;
845
+ let f = ( x - i as f64 ) . abs ( ) ;
846
+ if f == 0.5 {
847
+ if i & 1 == 1 {
848
+ // -1.5, 1.5, 3.5, ...
849
+ ( x. abs ( ) + 0.5 ) . copysign ( x)
850
+ } else {
851
+ ( x. abs ( ) - 0.5 ) . copysign ( x)
852
+ }
853
+ } else {
854
+ x. round ( )
855
+ }
856
+ }
857
+ component_wise_float ( self , span, [ arg] , |e| match e {
858
+ Float :: Abstract ( [ e] ) => Ok ( round_ties_even ( e) . into ( ) ) ,
859
+ Float :: F32 ( [ e] ) => Ok ( ( round_ties_even ( e as f64 ) as f32 ) . into ( ) ) ,
860
+ } )
838
861
}
839
862
crate :: MathFunction :: Saturate => {
840
863
component_wise_float ! ( self , span, [ arg] , |e| { Ok ( e. clamp( 0. , 1. ) . into( ) ) } )
0 commit comments