Skip to content

Commit ce32507

Browse files
authored
Merge pull request #6059 from diffblue/smt2_parser_fp
add support for parsing SMT-LIB2 to_fp
2 parents f5b18ff + 7e7d992 commit ce32507

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
basic-fp1.smt2
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^unsat$
7+
--
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
(set-logic FP)
2+
3+
(define-fun Areal () (_ FloatingPoint 11 53) ((_ to_fp 11 53) roundNearestTiesToEven 1.185043))
4+
(define-fun Ahexa () (_ FloatingPoint 11 53) (fp #b0 #b01111111111 #x2f5efa615a8df))
5+
6+
; should be the same
7+
(assert (not (= Areal Ahexa)))
8+
9+
(check-sat)

src/solvers/smt2/smt2_parser.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,60 @@ exprt smt2_parsert::function_application()
684684
else
685685
return nil_exprt();
686686
}
687+
else if(id == "to_fp")
688+
{
689+
if(next_token() != smt2_tokenizert::NUMERAL)
690+
throw error("expected number after to_fp");
691+
692+
auto width_e = std::stoll(smt2_tokenizer.get_buffer());
693+
694+
if(next_token() != smt2_tokenizert::NUMERAL)
695+
throw error("expected second number after to_fp");
696+
697+
auto width_f = std::stoll(smt2_tokenizer.get_buffer());
698+
699+
if(next_token() != smt2_tokenizert::CLOSE)
700+
throw error("expected ')' after to_fp");
701+
702+
auto rounding_mode = expression();
703+
704+
if(next_token() != smt2_tokenizert::NUMERAL)
705+
throw error("expected number after to_fp");
706+
707+
auto real_number = smt2_tokenizer.get_buffer();
708+
709+
if(next_token() != smt2_tokenizert::CLOSE)
710+
throw error("expected ')' at the end of to_fp");
711+
712+
mp_integer significand, exponent;
713+
714+
auto dot_pos = real_number.find('.');
715+
if(dot_pos == std::string::npos)
716+
{
717+
exponent = 0;
718+
significand = string2integer(real_number);
719+
}
720+
else
721+
{
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);
731+
}
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();
740+
}
687741
else
688742
{
689743
throw error() << "unknown indexed identifier '"

0 commit comments

Comments
 (0)