@@ -500,7 +500,10 @@ exprt smt2_parsert::function_application()
500
500
if (next_token () != smt2_tokenizert::SYMBOL)
501
501
throw error (" expected symbol after '_'" );
502
502
503
- if (has_prefix (smt2_tokenizer.get_buffer (), " bv" ))
503
+ // copy, the reference won't be stable
504
+ const auto id = smt2_tokenizer.get_buffer ();
505
+
506
+ if (has_prefix (id, " bv" ))
504
507
{
505
508
mp_integer i = string2integer (
506
509
std::string (smt2_tokenizer.get_buffer (), 2 , std::string::npos));
@@ -515,10 +518,36 @@ exprt smt2_parsert::function_application()
515
518
516
519
return from_integer (i, unsignedbv_typet (width));
517
520
}
521
+ else if (id == " +oo" || id == " -oo" || id == " NaN" )
522
+ {
523
+ // These are the "plus infinity", "minus infinity" and NaN
524
+ // floating-point literals.
525
+ if (next_token () != smt2_tokenizert::NUMERAL)
526
+ throw error () << " expected number after " << id;
527
+
528
+ auto width_e = std::stoll (smt2_tokenizer.get_buffer ());
529
+
530
+ if (next_token () != smt2_tokenizert::NUMERAL)
531
+ throw error () << " expected second number after " << id;
532
+
533
+ auto width_f = std::stoll (smt2_tokenizer.get_buffer ());
534
+
535
+ if (next_token () != smt2_tokenizert::CLOSE)
536
+ throw error () << " expected ')' after " << id;
537
+
538
+ // width_f *includes* the hidden bit
539
+ const ieee_float_spect spec (width_f - 1 , width_e);
540
+
541
+ if (id == " +oo" )
542
+ return ieee_floatt::plus_infinity (spec).to_expr ();
543
+ else if (id == " -oo" )
544
+ return ieee_floatt::minus_infinity (spec).to_expr ();
545
+ else // NaN
546
+ return ieee_floatt::NaN (spec).to_expr ();
547
+ }
518
548
else
519
549
{
520
- throw error () << " unknown indexed identifier "
521
- << smt2_tokenizer.get_buffer ();
550
+ throw error () << " unknown indexed identifier " << id;
522
551
}
523
552
}
524
553
else if (smt2_tokenizer.get_buffer () == " !" )
@@ -699,44 +728,83 @@ exprt smt2_parsert::function_application()
699
728
if (next_token () != smt2_tokenizert::CLOSE)
700
729
throw error (" expected ')' after to_fp" );
701
730
702
- auto rounding_mode = expression ();
731
+ // width_f *includes* the hidden bit
732
+ const ieee_float_spect spec (width_f - 1 , width_e);
703
733
704
- if (next_token () != smt2_tokenizert::NUMERAL)
705
- throw error (" expected number after to_fp" );
734
+ auto rounding_mode = expression ();
706
735
707
- auto real_number = smt2_tokenizer. get_buffer ();
736
+ auto source_op = expression ();
708
737
709
738
if (next_token () != smt2_tokenizert::CLOSE)
710
739
throw error (" expected ')' at the end of to_fp" );
711
740
712
- mp_integer significand , exponent;
713
-
714
- auto dot_pos = real_number.find (' .' );
715
- if (dot_pos == std::string::npos)
741
+ // There are several options for the source operand:
742
+ // 1) real or integer
743
+ // 2) bit-vector, which is interpreted as signed 2's complement
744
+ // 3) another floating-point format
745
+ if (
746
+ source_op.type ().id () == ID_real ||
747
+ source_op.type ().id () == ID_integer)
716
748
{
717
- exponent = 0 ;
718
- significand = string2integer (real_number);
749
+ // For now, we can only do this when
750
+ // the source operand is a constant.
751
+ if (source_op.id () == ID_constant)
752
+ {
753
+ mp_integer significand , exponent;
754
+
755
+ const auto &real_number =
756
+ id2string (to_constant_expr (source_op).get_value ());
757
+ auto dot_pos = real_number.find (' .' );
758
+ if (dot_pos == std::string::npos)
759
+ {
760
+ exponent = 0 ;
761
+ significand = string2integer (real_number);
762
+ }
763
+ else
764
+ {
765
+ // remove the '.'
766
+ std::string significand_str;
767
+ significand_str.reserve (real_number.size ());
768
+ for (auto ch : real_number)
769
+ {
770
+ if (ch != ' .' )
771
+ significand_str += ch;
772
+ }
773
+
774
+ exponent =
775
+ mp_integer (dot_pos) - mp_integer (real_number.size ()) + 1 ;
776
+ significand = string2integer (significand_str);
777
+ }
778
+
779
+ ieee_floatt a (
780
+ spec,
781
+ static_cast <ieee_floatt::rounding_modet>(
782
+ numeric_cast_v<int >(to_constant_expr (rounding_mode))));
783
+ a.from_base10 (significand , exponent);
784
+ return a.to_expr ();
785
+ }
786
+ else
787
+ throw error ()
788
+ << " to_fp for non-constant real expressions is not implemented" ;
719
789
}
720
- else
790
+ else if (source_op. type (). id () == ID_unsignedbv)
721
791
{
722
- // remove the '.', if any
723
- std::string significand_str;
724
- significand_str.reserve (real_number.size ());
725
- for (auto ch : real_number)
726
- if (ch != ' .' )
727
- significand_str += ch;
728
-
729
- exponent = mp_integer (dot_pos) - mp_integer (real_number.size ()) + 1 ;
730
- significand = string2integer (significand_str);
792
+ // The operand is hard-wired to be interpreted as a signed number.
793
+ return floatbv_typecast_exprt (
794
+ typecast_exprt (
795
+ source_op,
796
+ signedbv_typet (
797
+ to_unsignedbv_type (source_op.type ()).get_width ())),
798
+ rounding_mode,
799
+ spec.to_type ());
731
800
}
732
-
733
- // width_f *includes* the hidden bit
734
- ieee_float_spect spec (width_f - 1 , width_e);
735
- ieee_floatt a (spec);
736
- a.rounding_mode = static_cast <ieee_floatt::rounding_modet>(
737
- numeric_cast_v<int >(to_constant_expr (rounding_mode)));
738
- a.from_base10 (significand , exponent);
739
- return a.to_expr ();
801
+ else if (source_op.type ().id () == ID_floatbv)
802
+ {
803
+ return floatbv_typecast_exprt (
804
+ source_op, rounding_mode, spec.to_type ());
805
+ }
806
+ else
807
+ throw error () << " unexpected sort given as operand to to_fp" ;
740
808
}
741
809
else
742
810
{
@@ -1106,6 +1174,18 @@ void smt2_parsert::setup_expressions()
1106
1174
return with_exprt (op[0 ], op[1 ], op[2 ]);
1107
1175
};
1108
1176
1177
+ expressions[" fp.abs" ] = [this ] {
1178
+ auto op = operands ();
1179
+
1180
+ if (op.size () != 1 )
1181
+ throw error (" fp.abs takes one operand" );
1182
+
1183
+ if (op[0 ].type ().id () != ID_floatbv)
1184
+ throw error (" fp.abs takes FloatingPoint operand" );
1185
+
1186
+ return abs_exprt (op[0 ]);
1187
+ };
1188
+
1109
1189
expressions[" fp.isNaN" ] = [this ] {
1110
1190
auto op = operands ();
1111
1191
0 commit comments