@@ -1043,8 +1043,10 @@ inline div_exprt &to_div_expr(exprt &expr)
10431043 return ret;
10441044}
10451045
1046-
1047- // / \brief Modulo
1046+ // / \brief Modulo defined as lhs-(rhs * truncate(lhs/rhs)).
1047+ // / The sign follows the lhs or dividend. This matches C99 and
1048+ // / SMT-LIB's bvsrem but differs from the Euclidian definition
1049+ // / and from SMT-LIB's bvsmod.
10481050class mod_exprt :public binary_exprt
10491051{
10501052public:
@@ -1088,6 +1090,50 @@ inline mod_exprt &to_mod_expr(exprt &expr)
10881090 return ret;
10891091}
10901092
1093+ // / \brief Boute's Euclidean definition of Modulo -- to match SMT-LIB2
1094+ class euclidean_mod_exprt : public binary_exprt
1095+ {
1096+ public:
1097+ euclidean_mod_exprt (exprt _lhs, exprt _rhs)
1098+ : binary_exprt(std::move(_lhs), ID_euclidean_mod, std::move(_rhs))
1099+ {
1100+ }
1101+ };
1102+
1103+ template <>
1104+ inline bool can_cast_expr<euclidean_mod_exprt>(const exprt &base)
1105+ {
1106+ return base.id () == ID_euclidean_mod;
1107+ }
1108+
1109+ inline void validate_expr (const euclidean_mod_exprt &value)
1110+ {
1111+ validate_operands (value, 2 , " Modulo must have two operands" );
1112+ }
1113+
1114+ // / \brief Cast an exprt to a \ref euclidean_mod_exprt
1115+ // /
1116+ // / \a expr must be known to be \ref euclidean_mod_exprt.
1117+ // /
1118+ // / \param expr: Source expression
1119+ // / \return Object of type \ref euclidean_mod_exprt
1120+ inline const euclidean_mod_exprt &to_euclidean_mod_expr (const exprt &expr)
1121+ {
1122+ PRECONDITION (expr.id () == ID_euclidean_mod);
1123+ const euclidean_mod_exprt &ret =
1124+ static_cast <const euclidean_mod_exprt &>(expr);
1125+ validate_expr (ret);
1126+ return ret;
1127+ }
1128+
1129+ // / \copydoc to_euclidean_mod_expr(const exprt &)
1130+ inline euclidean_mod_exprt &to_euclidean_mod_expr (exprt &expr)
1131+ {
1132+ PRECONDITION (expr.id () == ID_euclidean_mod);
1133+ euclidean_mod_exprt &ret = static_cast <euclidean_mod_exprt &>(expr);
1134+ validate_expr (ret);
1135+ return ret;
1136+ }
10911137
10921138// / \brief Remainder of division
10931139class rem_exprt :public binary_exprt
0 commit comments