@@ -462,6 +462,55 @@ public void testFpSpecialValueEquality() {
462462 bitwuzla .pop (1 );
463463 }
464464
465+ // fp_value_to_real_str() transforms FP to their REAL string representation. But this loses
466+ // the sign in negative zero and NaN, as well as positive/negative infinity are returned with
467+ // their type wrapped in their fp.to_real transformation term.
468+ // (FP-)Terms that don't evaluate to a concrete value throw an IllegalArgumentException. This
469+ // also goes for constructed terms (e.g. (3.0 + 1.0)) or terms of other types.
470+ // As long as an FP Term is created with a fixed value, we get this value as REAL back.
471+ // Model evaluation is possible and tested in testFpModel
472+ @ Test
473+ public void testFpToRealString () {
474+ Sort fpSort = termManager .mk_fp_sort (5 , 11 );
475+
476+ Term zero = termManager .mk_fp_pos_zero (fpSort );
477+ assertThat (zero .fp_value_to_real_str ()).isEqualTo ("0.0" );
478+ Term negZero = termManager .mk_fp_neg_zero (fpSort );
479+ assertThat (negZero .fp_value_to_real_str ()).isEqualTo ("0.0" );
480+
481+ Term posInf = termManager .mk_fp_pos_inf (fpSort );
482+ assertThat (posInf .fp_value_to_real_str ()).isEqualTo ("(fp.to_real (_ +oo 5 11))" );
483+ Term negInf = termManager .mk_fp_neg_inf (fpSort );
484+ assertThat (negInf .fp_value_to_real_str ()).isEqualTo ("(fp.to_real (_ -oo 5 11))" );
485+
486+ Term nan = termManager .mk_fp_nan (fpSort );
487+ assertThat (nan .fp_value_to_real_str ()).isEqualTo ("(fp.to_real (_ NaN 5 11))" );
488+
489+ Term rm = termManager .mk_rm_value (RoundingMode .RNE );
490+ Term one = termManager .mk_fp_value (fpSort , rm , "1" );
491+ assertThat (one .fp_value_to_real_str ()).isEqualTo ("1.0" );
492+ Term two = termManager .mk_fp_value (fpSort , rm , "2" , "1" );
493+ assertThat (two .fp_value_to_real_str ()).isEqualTo ("2.0" );
494+
495+ Term cons = termManager .mk_const (fpSort , "cons" );
496+
497+ // Constants without evaluation throw IllegalArgumentException for fp_value_to_real_str()
498+ assertThrows (IllegalArgumentException .class , cons ::fp_value_to_real_str );
499+
500+ // Constructed FP terms are also disallowed from using fp_value_to_real_str()
501+ assertThrows (
502+ IllegalArgumentException .class ,
503+ () -> termManager .mk_term (Kind .FP_ADD , rm , two , one ).fp_value_to_real_str ());
504+
505+ // It is not allowed to use fp_value_to_real_str() on other types (bool here)
506+ assertThrows (
507+ IllegalArgumentException .class ,
508+ () -> termManager .mk_term (Kind .NOT , posInf ).fp_value_to_real_str ());
509+ assertThrows (
510+ IllegalArgumentException .class ,
511+ () -> termManager .mk_term (Kind .FP_EQUAL , posInf , negInf ).fp_value_to_real_str ());
512+ }
513+
465514 @ Test
466515 public void testFpModel () {
467516 Sort fpSort = termManager .mk_fp_sort (5 , 11 );
@@ -482,11 +531,17 @@ public void testFpModel() {
482531 // Get model value as String
483532 String aString = a .toString ();
484533 assertThat (aString ).isEqualTo ("a" );
485- String aValue = bitwuzla .get_value (a ).toString ();
534+ Term aValue = bitwuzla .get_value (a );
535+ String aValueString = aValue .toString ();
486536
487- assertThat (aValue ).isEqualTo ("(fp #b0 #b10000 #b1000000000)" );
537+ assertThat (aValueString ).isEqualTo ("(fp #b0 #b10000 #b1000000000)" );
488538 assertThat (one .toString ()).isEqualTo ("(fp #b0 #b01111 #b0000000000)" );
489539 assertThat (two .toString ()).isEqualTo ("(fp #b0 #b10000 #b0000000000)" );
540+
541+ // We can use fp_value_to_real_str() to get the real string representation of FPs
542+ assertThat (aValue .fp_value_to_real_str ()).isEqualTo ("3.0" );
543+ assertThat (one .fp_value_to_real_str ()).isEqualTo ("1.0" );
544+ assertThat (two .fp_value_to_real_str ()).isEqualTo ("2.0" );
490545 }
491546
492547 @ Test
0 commit comments