@@ -818,4 +818,82 @@ TEST_F(ConstantFPRangeTest, getWithout) {
818818 APFloat::getLargest (Sem, /* Negative=*/ true ), APFloat (3.0 )));
819819}
820820
821+ TEST_F (ConstantFPRangeTest, cast) {
822+ const fltSemantics &F16Sem = APFloat::IEEEhalf ();
823+ const fltSemantics &BF16Sem = APFloat::BFloat ();
824+ const fltSemantics &F32Sem = APFloat::IEEEsingle ();
825+ // normal -> normal (exact)
826+ EXPECT_EQ (ConstantFPRange::getNonNaN (APFloat (1.0 ), APFloat (2.0 )).cast (F32Sem),
827+ ConstantFPRange::getNonNaN (APFloat (1 .0f ), APFloat (2 .0f )));
828+ EXPECT_EQ (
829+ ConstantFPRange::getNonNaN (APFloat (-2 .0f ), APFloat (-1 .0f )).cast (Sem),
830+ ConstantFPRange::getNonNaN (APFloat (-2.0 ), APFloat (-1.0 )));
831+ // normal -> normal (inexact)
832+ EXPECT_EQ (
833+ ConstantFPRange::getNonNaN (APFloat (3.141592653589793 ),
834+ APFloat (6.283185307179586 ))
835+ .cast (F32Sem),
836+ ConstantFPRange::getNonNaN (APFloat (3 .14159274f ), APFloat (6 .28318548f )));
837+ // normal -> subnormal
838+ EXPECT_EQ (ConstantFPRange::getNonNaN (APFloat (-5e-8 ), APFloat (5e-8 ))
839+ .cast (F16Sem)
840+ .classify (),
841+ fcSubnormal | fcZero);
842+ // normal -> zero
843+ EXPECT_EQ (ConstantFPRange::getNonNaN (
844+ APFloat::getSmallestNormalized (Sem, /* Negative=*/ true ),
845+ APFloat::getSmallestNormalized (Sem, /* Negative=*/ false ))
846+ .cast (F32Sem)
847+ .classify (),
848+ fcZero);
849+ // normal -> inf
850+ EXPECT_EQ (ConstantFPRange::getNonNaN (APFloat (-65536.0 ), APFloat (65536.0 ))
851+ .cast (F16Sem),
852+ ConstantFPRange::getNonNaN (F16Sem));
853+ // nan -> qnan
854+ EXPECT_EQ (
855+ ConstantFPRange::getNaNOnly (Sem, /* MayBeQNaN=*/ true , /* MayBeSNaN=*/ false )
856+ .cast (F32Sem),
857+ ConstantFPRange::getNaNOnly (F32Sem, /* MayBeQNaN=*/ true ,
858+ /* MayBeSNaN=*/ false ));
859+ EXPECT_EQ (
860+ ConstantFPRange::getNaNOnly (Sem, /* MayBeQNaN=*/ false , /* MayBeSNaN=*/ true )
861+ .cast (F32Sem),
862+ ConstantFPRange::getNaNOnly (F32Sem, /* MayBeQNaN=*/ true ,
863+ /* MayBeSNaN=*/ false ));
864+ EXPECT_EQ (
865+ ConstantFPRange::getNaNOnly (Sem, /* MayBeQNaN=*/ true , /* MayBeSNaN=*/ true )
866+ .cast (F32Sem),
867+ ConstantFPRange::getNaNOnly (F32Sem, /* MayBeQNaN=*/ true ,
868+ /* MayBeSNaN=*/ false ));
869+ // For BF16 -> F32, signaling bit is still lost.
870+ EXPECT_EQ (ConstantFPRange::getNaNOnly (BF16Sem, /* MayBeQNaN=*/ true ,
871+ /* MayBeSNaN=*/ true )
872+ .cast (F32Sem),
873+ ConstantFPRange::getNaNOnly (F32Sem, /* MayBeQNaN=*/ true ,
874+ /* MayBeSNaN=*/ false ));
875+
876+ EnumerateValuesInConstantFPRange (
877+ ConstantFPRange::getFull (APFloat::Float8E4M3 ()),
878+ [&](const APFloat &V) {
879+ bool LosesInfo = false ;
880+
881+ APFloat DoubleV = V;
882+ DoubleV.convert (Sem, APFloat::rmNearestTiesToEven, &LosesInfo);
883+ ConstantFPRange DoubleCR = ConstantFPRange (V).cast (Sem);
884+ EXPECT_TRUE (DoubleCR.contains (DoubleV))
885+ << " Casting " << V << " to double failed. " << DoubleCR
886+ << " doesn't contain " << DoubleV;
887+
888+ auto &FP4Sem = APFloat::Float4E2M1FN ();
889+ APFloat FP4V = V;
890+ FP4V.convert (FP4Sem, APFloat::rmNearestTiesToEven, &LosesInfo);
891+ ConstantFPRange FP4CR = ConstantFPRange (V).cast (FP4Sem);
892+ EXPECT_TRUE (FP4CR.contains (FP4V))
893+ << " Casting " << V << " to FP4E2M1FN failed. " << FP4CR
894+ << " doesn't contain " << FP4V;
895+ },
896+ /* IgnoreNaNPayload=*/ true );
897+ }
898+
821899} // anonymous namespace
0 commit comments