dir = q->tavl_link[0] != y;
y->tavl_balance--;
if (y->tavl_balance == -1)
  break;
else if (y->tavl_balance == -2)
  {
    struct tavl_node *x = y->tavl_link[0];
    assert (x != NULL);
    if (x->tavl_balance == +1)
      {
        struct tavl_node *w;

        assert (x->tavl_balance == +1);
        w = x->tavl_link[1];
        x->tavl_link[1] = w->tavl_link[0];
        w->tavl_link[0] = x;
        y->tavl_link[0] = w->tavl_link[1];
        w->tavl_link[1] = y;
        if (w->tavl_balance == -1)
          x->tavl_balance = 0, y->tavl_balance = +1;
        else if (w->tavl_balance == 0)
          x->tavl_balance = y->tavl_balance = 0;
        else /* |w->tavl_balance == +1| */
          x->tavl_balance = -1, y->tavl_balance = 0;
        w->tavl_balance = 0;
        if (w->tavl_tag[0] == TAVL_THREAD)
          {
            x->tavl_tag[1] = TAVL_THREAD;
            x->tavl_link[1] = w;
            w->tavl_tag[0] = TAVL_CHILD;
          }
        if (w->tavl_tag[1] == TAVL_THREAD)
          {
            y->tavl_tag[0] = TAVL_THREAD;
            y->tavl_link[0] = w;
            w->tavl_tag[1] = TAVL_CHILD;
          }
        q->tavl_link[dir] = w;
      }
    else
      {
        q->tavl_link[dir] = x;

        if (x->tavl_balance == 0)
          {
            y->tavl_link[0] = x->tavl_link[1];
            x->tavl_link[1] = y;
            x->tavl_balance = +1;
            y->tavl_balance = -1;
            break;
          }
        else /* |x->tavl_balance == -1| */
          {
            if (x->tavl_tag[1] == TAVL_CHILD)
              y->tavl_link[0] = x->tavl_link[1];
            else
              {
                y->tavl_tag[0] = TAVL_THREAD;
                x->tavl_tag[1] = TAVL_CHILD;
              }
            x->tavl_link[1] = y;
            y->tavl_balance = x->tavl_balance = 0;
          }
      }
  }
