#define ZEROS_NUM       2
Complex zeros[ZEROS_NUM]={{10.0,0},{-30,0}};
#define POLES_NUM       2
Complex poles[POLES_NUM]={{-20.0,-15.0},{-20.0,15.0}};

F64 scale;

Complex *PoleZeroFind(I64 x,I64 y)
{
  I64 i;
  F64 dd,best_dd=F64_MAX;
  Complex *res=NULL;
  for (i=0;i<POLES_NUM;i++) {
    dd=Sqr(poles[i].x-x)+Sqr(poles[i].y-y);
    if (dd<best_dd) {
      best_dd=dd;
      res=&poles[i];
    }
  }
  for (i=0;i<ZEROS_NUM;i++) {
    dd=Sqr(zeros[i].x-x)+Sqr(zeros[i].y-y);
    if (dd<best_dd) {
      best_dd=dd;
      res=&zeros[i];
    }
  }
  return res;
}

F64 F(Complex *x)
{
  F64 m,a;
  Complex num,denom,n1;

  CPoly(&num,  ZEROS_NUM,zeros,x);
  CPoly(&denom,POLES_NUM,poles,x);
  CDiv(&n1,&num,&denom);

  R2P(&m,&a,n1.x,n1.y);
  if (ms.rb)
    return pi+a;
  else
    return m;
}

F64 MPDraw(CTask *task)
{
  Complex xx;
  I64 x,y,w=task->pix_width,h=task->pix_height,cx=w/2,cy=h/2,
        lo=Gs->num*h/mp_cnt,hi=(Gs->num+1)*h/mp_cnt;
  F64 yy,y_total=0;
  CDC *dc=DCAlias(,task);
  for (y=lo;y<hi;y++) {
    for (x=0;x<w;x++) {
      CEqu(&xx,x-cx,cy-y);
      yy=scale*F(&xx);
      dc->color=Clamp(yy,0,14);
      y_total+=Clamp(yy,-14,14);
      GrPlot(dc,x,y);
    }
  }
  DCDel(dc);
  return y_total;
}

U0 Draw()
{
  CJob *tmpm[MP_PROCESSORS_NUM];
  F64 y_total,old_y_total=F64_MAX;
  I64 i,w=Fs->pix_width,h=Fs->pix_height,cx=w/2,cy=h/2;
  CDC *dc=DCAlias;
  while (TRUE) {
    for (i=0;i<mp_cnt;i++)
      tmpm[i]=JobQue(&MPDraw,Fs,i,0);
    y_total=0;
    for (i=0;i<mp_cnt;i++)
      y_total+=JobResGet(tmpm[i])(F64);

    if (!y_total) break;
    scale*=7*GR_WIDTH*GR_HEIGHT/y_total;
    if (Abs(y_total-old_y_total)<1.0*GR_WIDTH*GR_HEIGHT)
      break;
    old_y_total=y_total;
  }
  dc->color=15;
  GrLine(dc,0,cy,w,cy);
  GrLine(dc,cx,0,cx,h);
  for (i=0;i<ZEROS_NUM;i++)
    GrPrint(dc,cx+zeros[i].x-FONT_WIDTH/2,cy-zeros[i].y-FONT_HEIGHT/2,"o");
  for (i=0;i<POLES_NUM;i++)
    GrPrint(dc,cx+poles[i].x-FONT_WIDTH/2,cy-poles[i].y-FONT_HEIGHT/2,"x");
  DCDel(dc);
}

U0 PoleZeros()
{
  I64 msg_code,arg1,arg2,p11,p22,cx,cy;
  Complex *tmpc=NULL;

  PopUpOk(
        "Drag the poles and zeros with left mouse.\n"
        "Hold right mouse for phase plot.\n"
        );

  SettingsPush; //See SettingsPush
  Fs->win_inhibit=WIG_TASK_DFT-WIF_SELF_FOCUS-WIF_SELF_BORDER;
  GrPaletteSet(gr_palette_gray);
  GrPaletteColorSet(15,0xFFFF00000000); //White is red

  AutoComplete;
  WinBorder;
  WinMax;
  DocClear;
  DCFill;
  scale=1.0;

  try {
    Draw;
    while (TRUE) {
      msg_code=GetMsg(&arg1,&arg2,1<<MSG_KEY_DOWN+1<<MSG_MS_L_DOWN+
            1<<MSG_MS_L_UP+1<<MSG_MS_R_DOWN+1<<MSG_MS_R_UP+1<<MSG_MS_MOVE);
pz_msg:
      cx=Fs->pix_width/2;
      cy=Fs->pix_height/2;
      switch (msg_code) {
        case MSG_MS_L_DOWN:
          tmpc=PoleZeroFind(arg1-cx,cy-arg2);
          break;
        case MSG_MS_MOVE:
          if (tmpc) {
            p11=arg1;p22=arg2;
//get to last mouse move
            while (msg_code=ScanMsg(&arg1,&arg2,
                  1<<MSG_KEY_DOWN+1<<MSG_MS_L_DOWN+
                  1<<MSG_MS_L_UP+1<<MSG_MS_R_DOWN+
                  1<<MSG_MS_R_UP+1<<MSG_MS_MOVE))
              if (msg_code==MSG_MS_MOVE) {
                p11=arg1;p22=arg2;
              } else
                goto pz_msg;

            tmpc->x=p11-cx;
            tmpc->y=cy-p22;
            Draw;
          }
          break;
        case MSG_MS_L_UP:
          if (tmpc) {
            tmpc->x=arg1-cx;
            tmpc->y=cy-arg2;
            tmpc=NULL;
            Draw;
          }
          break;
        case MSG_MS_R_DOWN:
        case MSG_MS_R_UP:
          Draw;
          break;
        case MSG_KEY_DOWN:
          if (arg1==CH_SHIFT_ESC||arg1==CH_ESC)
            goto pz_done;
      }
      Refresh;
    }
pz_done:
    GetMsg(,,1<<MSG_KEY_UP);
  } catch
    PutExcept;
  SettingsPop;
  DCFill;
}

PoleZeros;