mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 19:52:29 +00:00 
			
		
		
		
	
							parent
							
								
									5e0c34cae2
								
							
						
					
					
						commit
						5f81913292
					
				
					 2 changed files with 39 additions and 19 deletions
				
			
		|  | @ -133,6 +133,11 @@ public: | |||
|         if (mk_eq_core(lhs, rhs, result) == BR_FAILED) | ||||
|             result = mk_eq(lhs, rhs); | ||||
|     } | ||||
|     expr_ref mk_eq_rw(expr* lhs, expr* rhs) { | ||||
|         expr_ref r(m()); | ||||
|         mk_eq(lhs, rhs, r); | ||||
|         return r; | ||||
|     } | ||||
|     void mk_iff(expr * lhs, expr * rhs, expr_ref & result) { mk_eq(lhs, rhs, result); } | ||||
|     void mk_xor(expr * lhs, expr * rhs, expr_ref & result); | ||||
|     void mk_and(unsigned num_args, expr * const * args, expr_ref & result) { | ||||
|  | @ -187,6 +192,11 @@ public: | |||
|         if (mk_ite_core(c, t, e, result) == BR_FAILED) | ||||
|             result = m().mk_ite(c, t, e); | ||||
|     } | ||||
|     expr_ref mk_ite(expr * c, expr * t, expr * e) { | ||||
|         expr_ref r(m()); | ||||
|         mk_ite(c, t, e, r); | ||||
|         return r; | ||||
|     } | ||||
|     void mk_distinct(unsigned num_args, expr * const * args, expr_ref & result) { | ||||
|         if (mk_distinct_core(num_args, args, result) == BR_FAILED) | ||||
|             result = m().mk_distinct(num_args, args); | ||||
|  | @ -195,6 +205,11 @@ public: | |||
|         if (mk_not_core(t, result) == BR_FAILED) | ||||
|             result = m().mk_not(t); | ||||
|     } | ||||
|     expr_ref mk_not(expr* t) { | ||||
|         expr_ref r(m()); | ||||
|         mk_not(t, r); | ||||
|         return r; | ||||
|     } | ||||
| 
 | ||||
|     void mk_nand(unsigned num_args, expr * const * args, expr_ref & result); | ||||
|     void mk_nor(unsigned num_args, expr * const * args, expr_ref & result); | ||||
|  |  | |||
|  | @ -25,6 +25,7 @@ Notes: | |||
| #include "ast/ast_pp.h" | ||||
| #include "ast/rewriter/expr_safe_replace.h" | ||||
| #include "ast/rewriter/rewriter_def.h" | ||||
| #include "ast/rewriter/th_rewriter.h" | ||||
| #include "tactic/tactic.h" | ||||
| #include "tactic/core/reduce_invertible_tactic.h" | ||||
| #include "tactic/core/collect_occs.h" | ||||
|  | @ -306,6 +307,11 @@ private: | |||
|             } | ||||
|             if (!rest) return false; | ||||
| 
 | ||||
|             // so far just support numeral
 | ||||
|             rational r; | ||||
|             if (!m_bv.is_numeral(rest, r))  | ||||
|                 return false; | ||||
| 
 | ||||
|             // create case split on
 | ||||
|             // divisbility of 2
 | ||||
|             // v * t -> 
 | ||||
|  | @ -318,31 +324,30 @@ private: | |||
|             // to reproduce the original v from t
 | ||||
|             // solve for v*t = extract[sz-1:i](v') ++ zero[i-1:0]
 | ||||
|             // using values for t and v'
 | ||||
|             // thus
 | ||||
|             //
 | ||||
|             //    udiv(extract[sz-1:i](v') ++ zero[i-1:0], t)
 | ||||
|             // thus let t' = t / 2^i
 | ||||
|             // and t'' = the multiplicative inverse of t'
 | ||||
|             // then t'' * v' * t = t'' * v' * t' * 2^i = v' * 2^i = extract[sz-1:i](v') ++ zero[i-1:0]
 | ||||
|             // so t'' *v' works 
 | ||||
|             // 
 | ||||
|             // TBD: this argument is flawed. Unit test breaks with either
 | ||||
|             // the above or udiv(v, t)
 | ||||
| 
 | ||||
|             unsigned sz = m_bv.get_bv_size(p); | ||||
|             expr_ref bit1(m_bv.mk_numeral(1, 1), m); | ||||
|             new_v = m_bv.mk_numeral(0, sz); | ||||
|             for (unsigned i = sz; i-- > 0; ) { | ||||
|                 expr_ref extr_i(m_bv.mk_extract(i, i, rest), m); | ||||
|                 expr_ref cond(m.mk_eq(extr_i, bit1), m); | ||||
|                 expr_ref part(v, m); | ||||
|                 if (i > 0) { | ||||
|                     part = m_bv.mk_concat(m_bv.mk_extract(sz-1, i, v), m_bv.mk_numeral(0, i)); | ||||
|                 } | ||||
|                 new_v = m.mk_ite(cond, part, new_v); | ||||
| 
 | ||||
|              | ||||
|             unsigned sh = 0; | ||||
|             while (r.is_pos() && r.is_even()) { | ||||
|                 r /= rational(2); | ||||
|                 ++sh; | ||||
|             } | ||||
|             if (mc) { | ||||
|             if (r.is_pos() && sh > 0) { | ||||
|                 new_v = m_bv.mk_concat(m_bv.mk_extract(sz-1, sh, v), m_bv.mk_numeral(0, sh)); | ||||
|             } | ||||
|             if (mc && !r.is_zero()) { | ||||
|                 ensure_mc(mc); | ||||
|                 expr_ref div(m), def(m); | ||||
|                 div = m.mk_app(m_bv.get_fid(), OP_BUDIV_I, v, rest); | ||||
|                 def = m_bv.mk_numeral(0, sz); | ||||
|                 def = m.mk_ite(m.mk_eq(def, rest), def, div); | ||||
|                 expr_ref def(m); | ||||
|                 rational inv_r; | ||||
|                 VERIFY(m_bv.mult_inverse(r, sz, inv_r)); | ||||
|                 def = m_bv.mk_bv_mul(m_bv.mk_numeral(inv_r, sz), v); | ||||
|                 (*mc)->add(v, def); | ||||
|                 TRACE("invertible_tactic", tout << def << "\n";); | ||||
|             } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue