@@ -699,44 +699,83 @@ exprt smt2_parsert::function_application()
699699 if (next_token () != smt2_tokenizert::CLOSE)
700700 throw error (" expected ')' after to_fp" );
701701
702- auto rounding_mode = expression ();
702+ // width_f *includes* the hidden bit
703+ const ieee_float_spect spec (width_f - 1 , width_e);
703704
704- if (next_token () != smt2_tokenizert::NUMERAL)
705- throw error (" expected number after to_fp" );
705+ auto rounding_mode = expression ();
706706
707- auto real_number = smt2_tokenizer. get_buffer ();
707+ auto source_op = expression ();
708708
709709 if (next_token () != smt2_tokenizert::CLOSE)
710710 throw error (" expected ')' at the end of to_fp" );
711711
712- mp_integer significand, exponent;
713-
714- auto dot_pos = real_number.find (' .' );
715- if (dot_pos == std::string::npos)
712+ // There are several options for the source operand:
713+ // 1) real or integer
714+ // 2) bit-vector, which is interpreted as signed 2's complement
715+ // 3) another floating-point format
716+ if (
717+ source_op.type ().id () == ID_real ||
718+ source_op.type ().id () == ID_integer)
716719 {
717- exponent = 0 ;
718- significand = string2integer (real_number);
720+ // For now, we can only do this when
721+ // the source operand is a constant.
722+ if (source_op.id () == ID_constant)
723+ {
724+ mp_integer significand, exponent;
725+
726+ const auto &real_number =
727+ id2string (to_constant_expr (source_op).get_value ());
728+ auto dot_pos = real_number.find (' .' );
729+ if (dot_pos == std::string::npos)
730+ {
731+ exponent = 0 ;
732+ significand = string2integer (real_number);
733+ }
734+ else
735+ {
736+ // remove the '.'
737+ std::string significand_str;
738+ significand_str.reserve (real_number.size ());
739+ for (auto ch : real_number)
740+ {
741+ if (ch != ' .' )
742+ significand_str += ch;
743+ }
744+
745+ exponent =
746+ mp_integer (dot_pos) - mp_integer (real_number.size ()) + 1 ;
747+ significand = string2integer (significand_str);
748+ }
749+
750+ ieee_floatt a (
751+ spec,
752+ static_cast <ieee_floatt::rounding_modet>(
753+ numeric_cast_v<int >(to_constant_expr (rounding_mode))));
754+ a.from_base10 (significand, exponent);
755+ return a.to_expr ();
756+ }
757+ else
758+ throw error ()
759+ << " to_fp for non-constant real expressions is not implemented" ;
719760 }
720- else
761+ else if (source_op. type (). id () == ID_unsignedbv)
721762 {
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);
763+ // The operand is hard-wired to be interpreted as a signed number.
764+ return floatbv_typecast_exprt (
765+ typecast_exprt (
766+ source_op,
767+ signedbv_typet (
768+ to_unsignedbv_type (source_op.type ()).get_width ())),
769+ rounding_mode,
770+ spec.to_type ());
731771 }
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 ();
772+ else if (source_op.type ().id () == ID_floatbv)
773+ {
774+ return floatbv_typecast_exprt (
775+ source_op, rounding_mode, spec.to_type ());
776+ }
777+ else
778+ throw error () << " unexpected sort given as operand to to_fp" ;
740779 }
741780 else
742781 {
0 commit comments