bool mk_interp_tail_simplifier::rule_substitution::unify(expr * e1, expr * e2) {
        SASSERT(m_rule);

        //we need to apply the current substitution in order to ensure the unifier 
        //works in an incremental way
        expr_ref e1_s(m);
        expr_ref e2_s(m);
        m_subst.apply(e1,e1_s);
        m_subst.apply(e2,e2_s);
        //and we need to reset the cache as we're going to modify the substitution
        m_subst.reset_cache();

        return m_unif (e1_s, e2_s, m_subst, false);
    }
void				test_baseN(
				    ezpwd::asserter    &assert,
				    const baseN_tests_t &tests )
{

    for ( auto &t : tests ) {
	std::string			e1( std::get<0>( t ));

	// scatter, into raw (unencoded) base-N data, with padding.  An instance of a
	// std::random_access_iterator, to force optimal algorithm (both with and without padding)
	u8vec_t				e1_vec_1;
	SEREZC::scatter_standard( e1.begin(), e1.end(), std::back_insert_iterator<u8vec_t>( e1_vec_1 ));
	u8vec_t				e1_vec_1_no_pad;
	SEREZC::scatter( e1.begin(), e1.end(), std::back_insert_iterator<u8vec_t>( e1_vec_1_no_pad ));
#if defined( DEBUG )
	std::cout << "scatter (rnd.): " << u8vec_t( e1.begin(), e1.end() ) << " --> " << e1_vec_1 << std::endl;
#endif
	if ( assert.ISEQUAL( e1_vec_1.size(), SEREZC::encode_size( e1.size(), ezpwd::serialize::pd_enforce )))
	    std::cout << assert << std::endl;
	if ( assert.ISEQUAL( e1_vec_1_no_pad.size(), SEREZC::encode_size( e1.size() )))
	    std::cout << assert << std::endl;
	if ( assert.ISTRUE( std::search( e1_vec_1.begin(),        e1_vec_1.end(),
					 e1_vec_1_no_pad.begin(), e1_vec_1_no_pad.begin() )
			    == e1_vec_1.begin() ))
	    std::cout << assert << "; failed to find no-pad scatter at front of padded scatter" << std::endl;

	// An instance of a std::forward_iterator, to force use of generic algorithm with more
	// iterator comparisons
	u8vec_t				e1_vec_2;
	{
	    std::istringstream		e1_iss( e1 );
	    std::istreambuf_iterator<char>
					e1_iss_beg( e1_iss ),
					e1_iss_end;
	    SEREZC::scatter( e1_iss_beg, e1_iss_end, std::back_insert_iterator<u8vec_t>( e1_vec_2 ),
					       ezpwd::serialize::pd_enforce );
	}
	if ( assert.ISEQUAL( e1_vec_1, e1_vec_2 ))
	    std::cout << assert << std::endl;	    

	if ( assert.ISEQUAL( std::string( std::get<1>( t )), std::string() << e1_vec_1 ))
	    std::cout << assert << std::endl;
	if ( assert.ISEQUAL( std::string( std::get<1>( t )), std::string() << e1_vec_2 ))
	    std::cout << assert << std::endl;

	// Now, convert the raw scattered 5/6-bit data to base-N RFC4648 Standard symbols, in-place
	std::string		e1_s( e1_vec_1.begin(), e1_vec_1.end() );
	SERSTD::encode( e1_s.begin(), e1_s.end() );
#if defined( DEBUG )
	std::cout << "base32::encode (standard): " << e1_vec_1  << " --> " << e1_s << std::endl;
#endif
	if ( assert.ISEQUAL( e1_s, std::get<2>( t )))
	    std::cout << assert << std::endl;

	// Now get rid of the pad symbols for the base32 ezpwd encoding test
	std::string		e1_e( e1_vec_1.begin(), e1_vec_1.end() );
	while ( e1_e.size() and e1_e.back() == EOF )
	    e1_e.pop_back();
	SEREZC::encode( e1_e.begin(), e1_e.end() );
#if defined( DEBUG )
	std::cout << "base32::encode (ezpwd):    " << e1_vec_1  << " --> " << e1_e << std::endl;
#endif
	if ( assert.ISEQUAL( e1_e, std::get<3>( t )))
	    std::cout << assert << std::endl;
	
	// Decode back to the original 5/6-bit binary data in-place, from both the standard (with
	// pad) and ezcod (not padded) base32 encoded data.

	// _s -- Standard (with padding)
	std::string		d1_s( e1_s );
	SERSTD::decode_standard( d1_s );
	if ( assert.ISEQUAL( std::get<1>( t ), std::string() << u8vec_t( d1_s.begin(), d1_s.end() )))
	    std::cout << assert << std::endl;

	// _e -- Ezcod (without padding)
	std::string		d1_e( e1_e );
	SEREZC::decode( d1_e ); // default is ws_ignored, pd_ignored
	// It will match the decoding, but not include the trailing padding (FF) chars
	if ( assert.ISTRUE( std::get<1>( t ).find( std::string() << u8vec_t( d1_e.begin(), d1_e.end() )) == 0 ))
	    std::cout << assert << std::endl;

	// Finally, gather up the 5-bit chunks back into the original 8-bit data, using pd_ignored
	// (no padding, the default) first, and then pd_enforce.  Make sure that the predicted
	// base32::encode_size is correct.

	u8vec_t			d1_vec_s; // pd_enforce
	SEREZC::gather_standard( d1_s.begin(), d1_s.end(), std::back_insert_iterator<u8vec_t>( d1_vec_s ));
	if ( assert.ISEQUAL( std::get<0>( t ), std::string( d1_vec_s.begin(), d1_vec_s.end() )))
	    std::cout << assert << std::endl;
	if ( assert.ISEQUAL( d1_s.size(), SEREZC::encode_size( std::get<0>( t ).size(), ezpwd::serialize::pd_enforce )))
	    std::cout << assert << "; predicted " << std::get<0>( t ) << " --> " << u8vec_t( d1_s.begin(), d1_s.end() ) <<
		" should be " << SEREZC::encode_size( std::get<0>( t ).size(), ezpwd::serialize::pd_enforce  ) << " bytes " << std::endl;

	u8vec_t			d1_vec_e;  // pd_invalid: default
	SEREZC::gather( d1_e.begin(), d1_e.end(), std::back_insert_iterator<u8vec_t>( d1_vec_e ));
	if ( assert.ISEQUAL( std::get<0>( t ), std::string( d1_vec_e.begin(), d1_vec_e.end() )))
	    std::cout << assert << std::endl;
	if ( assert.ISEQUAL( d1_e.size(), SEREZC::encode_size( std::get<0>( t ).size() ))) // default: pd_ignored
	    std::cout << assert << "; predicted " << std::get<0>( t ) << " --> " <<  u8vec_t( d1_e.begin(), d1_e.end() ) <<
		" should be " << SEREZC::encode_size( std::get<0>( t ).size() ) << " bytes " << std::endl;
    }
}