@@ -1119,7 +1119,7 @@ br_status arith_rewriter::mk_idiv_core(expr * arg1, expr * arg2, expr_ref & resu
1119
1119
return BR_REWRITE3;
1120
1120
}
1121
1121
}
1122
- if (divides (arg1, arg2, result)) {
1122
+ if (get_divides (arg1, arg2, result)) {
1123
1123
expr_ref zero (m_util.mk_int (0 ), m);
1124
1124
result = m.mk_ite (m.mk_eq (zero, arg2), m_util.mk_idiv (arg1, zero), result);
1125
1125
return BR_REWRITE_FULL;
@@ -1137,7 +1137,7 @@ br_status arith_rewriter::mk_idiv_core(expr * arg1, expr * arg2, expr_ref & resu
1137
1137
//
1138
1138
// implement div ab ac = floor( ab / ac) = floor (b / c) = div b c
1139
1139
//
1140
- bool arith_rewriter::divides (expr* num, expr* den, expr_ref& result) {
1140
+ bool arith_rewriter::get_divides (expr* num, expr* den, expr_ref& result) {
1141
1141
expr_fast_mark1 mark;
1142
1142
rational num_r (1 ), den_r (1 );
1143
1143
expr* num_e = nullptr , *den_e = nullptr ;
@@ -1229,70 +1229,71 @@ static rational symmod(rational const& a, rational const& b) {
1229
1229
if (2 *r > b) r -= b;
1230
1230
return r;
1231
1231
}
1232
-
1232
+
1233
1233
br_status arith_rewriter::mk_mod_core (expr * arg1, expr * arg2, expr_ref & result) {
1234
1234
set_curr_sort (arg1->get_sort ());
1235
- numeral x, y;
1236
- bool is_num_x = m_util.is_numeral (arg1, x);
1237
- bool is_num_y = m_util.is_numeral (arg2, y);
1238
- if (is_num_x && is_num_y && !y.is_zero ()) {
1239
- result = m_util.mk_int (mod (x, y));
1235
+ numeral v1, v2;
1236
+ bool is_int;
1237
+ bool is_num1 = m_util.is_numeral (arg1, v1, is_int);
1238
+ bool is_num2 = m_util.is_numeral (arg2, v2, is_int);
1239
+
1240
+ if (is_num1 && is_num2 && !v2.is_zero ()) {
1241
+ result = m_util.mk_numeral (mod (v1, v2), is_int);
1240
1242
return BR_DONE;
1241
1243
}
1242
1244
1243
- if (is_num_y && y. is_int () && (y .is_one () || y .is_minus_one ())) {
1245
+ if (is_num2 && is_int && (v2 .is_one () || v2 .is_minus_one ())) {
1244
1246
result = m_util.mk_numeral (numeral (0 ), true );
1245
1247
return BR_DONE;
1246
1248
}
1247
1249
1248
- if (arg1 == arg2 && !is_num_y ) {
1250
+ if (arg1 == arg2 && !is_num2 ) {
1249
1251
expr_ref zero (m_util.mk_int (0 ), m);
1250
1252
result = m.mk_ite (m.mk_eq (arg2, zero), m_util.mk_mod (zero, zero), zero);
1251
1253
return BR_DONE;
1252
1254
}
1253
1255
1254
1256
// mod is idempotent on non-zero modulus.
1255
1257
expr* t1, *t2;
1256
- if (m_util.is_mod (arg1, t1, t2) && t2 == arg2 && is_num_y && y.is_int () && !y.is_zero ()) {
1257
- result = arg1;
1258
- return BR_DONE;
1259
- }
1260
-
1261
- rational lo, hi;
1262
- if (is_num_y && get_range (arg1, lo, hi) && 0 <= lo && hi < y) {
1258
+ if (m_util.is_mod (arg1, t1, t2) && t2 == arg2 && is_num2 && is_int && !v2.is_zero ()) {
1263
1259
result = arg1;
1264
1260
return BR_DONE;
1265
1261
}
1266
1262
1267
1263
// propagate mod inside only if there is something to reduce.
1268
- if (is_num_y && y. is_int () && y .is_pos () && (is_add (arg1) || is_mul (arg1))) {
1264
+ if (is_num2 && is_int && v2 .is_pos () && (is_add (arg1) || is_mul (arg1))) {
1269
1265
TRACE (" mod_bug" , tout << " mk_mod:\n " << mk_ismt2_pp (arg1, m) << " \n " << mk_ismt2_pp (arg2, m) << " \n " ;);
1270
1266
expr_ref_buffer args (m);
1271
1267
bool change = false ;
1272
1268
for (expr* arg : *to_app (arg1)) {
1273
1269
rational arg_v;
1274
- if (m_util.is_numeral (arg, arg_v) && mod (arg_v, y ) != arg_v) {
1270
+ if (m_util.is_numeral (arg, arg_v) && mod (arg_v, v2 ) != arg_v) {
1275
1271
change = true ;
1276
- args.push_back (m_util.mk_numeral (mod (arg_v, y ), true ));
1272
+ args.push_back (m_util.mk_numeral (mod (arg_v, v2 ), true ));
1277
1273
}
1278
1274
else if (m_util.is_mod (arg, t1, t2) && t2 == arg2) {
1279
1275
change = true ;
1280
1276
args.push_back (t1);
1281
1277
}
1282
- else if (m_util.is_mul (arg, t1, t2) && m_util.is_numeral (t1, arg_v) && symmod (arg_v, y ) != arg_v) {
1278
+ else if (m_util.is_mul (arg, t1, t2) && m_util.is_numeral (t1, arg_v) && symmod (arg_v, v2 ) != arg_v) {
1283
1279
change = true ;
1284
- args.push_back (m_util.mk_mul (m_util.mk_numeral (symmod (arg_v, y ), true ), t2));
1280
+ args.push_back (m_util.mk_mul (m_util.mk_numeral (symmod (arg_v, v2 ), true ), t2));
1285
1281
}
1286
1282
else {
1287
1283
args.push_back (arg);
1288
1284
}
1289
1285
}
1290
- if (!change) {
1291
- return BR_FAILED; // did not find any target for applying simplification
1286
+ if (change) {
1287
+ result = m_util.mk_mod (m.mk_app (to_app (arg1)->get_decl (), args.size (), args.data ()), arg2);
1288
+ TRACE (" mod_bug" , tout << " mk_mod result: " << mk_ismt2_pp (result, m) << " \n " ;);
1289
+ return BR_REWRITE3;
1292
1290
}
1293
- result = m_util.mk_mod (m.mk_app (to_app (arg1)->get_decl (), args.size (), args.data ()), arg2);
1294
- TRACE (" mod_bug" , tout << " mk_mod result: " << mk_ismt2_pp (result, m) << " \n " ;);
1295
- return BR_REWRITE3;
1291
+ }
1292
+
1293
+ expr* x, *y;
1294
+ if (is_num2 && v2.is_pos () && m_util.is_mul (arg1, x, y) && m_util.is_numeral (x, v1, is_int) && divides (v1, v2)) {
1295
+ result = m_util.mk_mul (x, m_util.mk_mod (y, m_util.mk_int (v2/v1)));
1296
+ return BR_REWRITE1;
1296
1297
}
1297
1298
1298
1299
return BR_FAILED;
0 commit comments