function _matcho(
        uint t_pay_amt,    
        ERC20 t_pay_gem,   
        uint t_buy_amt,    
        ERC20 t_buy_gem,   
        uint pos,          
        bool rounding      
    )
        internal
        returns (uint id)
    {
        uint best_maker_id;    
        uint t_buy_amt_old;              
        uint m_buy_amt;        
        uint m_pay_amt;        

        require(pos == 0
               || !isActive(pos)
               || t_buy_gem == offers[pos].buy_gem
                  && t_pay_gem == offers[pos].pay_gem);

        
        while (_best[t_buy_gem][t_pay_gem] > 0) {
            best_maker_id = _best[t_buy_gem][t_pay_gem];
            m_buy_amt = offers[best_maker_id].buy_amt;
            m_pay_amt = offers[best_maker_id].pay_amt;

            
            
            
            
            
            
            if (mul(m_buy_amt, t_buy_amt) > mul(t_pay_amt, m_pay_amt) +
                (rounding ? m_buy_amt + t_buy_amt + t_pay_amt + m_pay_amt : 0))
            {
                break;
            }
            
            

            buy(best_maker_id, min(m_pay_amt, t_buy_amt));
            t_buy_amt_old = t_buy_amt;
            t_buy_amt = sub(t_buy_amt, min(m_pay_amt, t_buy_amt));
            t_pay_amt = mul(t_buy_amt, t_pay_amt) / t_buy_amt_old;

            if (t_pay_amt == 0 || t_buy_amt == 0) {
                break;
            }
        }

        if (t_buy_amt > 0 && t_pay_amt > 0) {
            
            id = super.offer(t_pay_amt, t_pay_gem, t_buy_amt, t_buy_gem);
            
            _sort(id, pos);
        }
    }