 #include <windows.h>
 #include <stdlib.h>
 #include <math.h>
 extern UINT *Z;
 extern UINT *st;
 extern UINT mem(UINT);
 extern UINT text1(UINT*);

 void razvertmn(UINT a, UINT* b)
 // a - smeshenie v zone zadach polinoma s koeff. v formate
 // "s plav.zapjatoj". b - ukazatel na ish.poziciju
 // dlja predstavlenija etogo polinoma v vichislit.formate:
 // snachala idet jachejka s chislom chlenov polinoma
 // (UINT), zatem - massiv ego koefficientov v formate
 // "double". Starshij koefficient - v konce massiva.

 {UINT i,j;
  i = Z[a];
  i -= 6;
  i >>= 1;
  b[0] = i;
  a += 4;
  j = 1;
  while(!(Z[a] & 0x80000000))
   {i = Z[a];
    b[j] = Z[i+3];
    b[j+1] = Z[i+5];
    j += 2;
    a += 2;
   }
 }

 UINT svertmn(UINT *a)

 // a - ukazatel na predstavlenije mnogochlena v vichislit.
 // formate. Sozdaet v zone zadach ego predstavlenie v
 // logicheskom formate, i vozvrashaet ego smeshenie.
 // Pri neudache vozvrashaet 0xFFFFFFFF.

 {UINT b,n,i,*c;
  n = *a; c = st; a += 1;
  *st = 0x00200104;
  st++;
  for(i = 0; i < n; i++)
   {b= mem(8);
    if(b == 0) return 0xFFFFFFFF;
    Z[b+2] = 0x40200001;
    Z[b+3] = *a;
    Z[b+4] = 0x40200001;
    Z[b+5] = *(a+1);
    a += 2;
    *st = b;
    st++;
   }
  b = text1(c);
  if(b == 0) return 0xFFFFFFFF;
  return b;
 }

 void normmn(UINT *a)

 // a - ukazatel na mnogochlen. Otbrasivaet
 // nulevie starshie chleni.

 {UINT n,*r;
  double *p,*q;
  n = *a; n <<= 1; n--;
  r = a + n;
  p = (double*)r;
  r = a + 1;
  q = (double*)r;
  n = *a;
  if(fabs(*p)<0.00000000001)
   {*p = 0;}
  while(*p == 0 && p != q)
   {n--;
    p--;
    if(fabs(*p)<0.00000000001)
     {*p = 0;}
   }
  *a = n;
 }

 void plusmn(UINT *a, UINT *b)

 // a,b - ukazateli na pervij i vtoroj mnogochleni
 // Vipolnjaet pribavlenie k pervomu vtorogo.
 // Predpolagaetsja, chto posle pervogo imeetsja
 // dostatochno mesta.
 {UINT m,n,k,i,*r;
  double *p,*q;
  m = *a; n = *b;
  if(m < n)
   {k = n - m;
    m <<= 1;
    m++;
    r = a + m;
    p = (double*)r;
    for(i = 0; i < k; i++)
     {p[i] = 0;
     }
    *a = n;
   }
  r = a + 1;
  p = (double*)r;
  r = b + 1;
  q = (double*)r;
  for(i = 0; i < n; i++)
   p[i] = p[i] + q[i];
  normmn(a);
 }

 void umnogmn(UINT *a, UINT *b, UINT *c)

 // a,b - ukazateli na somnogiteli; c - ukazatel
 // na pervuju jachejku nakopitelja proizvedenija.
 // Etot nakopitel ne inicializiruetsja.

 {UINT i,j,m,n;
  double *d,*e,*f,*g,p;
  m = a[0] + b[0]; m--;
  c[0] = m;
  d = (double*)(c+1);
  for(i = 0; i < m; i++)
   d[i] = 0;
  m = a[0];
  n = b[0];
  for(i = 1,d = (double*)(b+1),e = (double*)(c+1); i<= n;
      i++,d++,e++)
   {for(j = 1,f = (double*)(a+1),g = e; j <= m;
        j++, f++, g++)
     {p = (*d)*(*f);
      (*g) += p;
     }
   }
  normmn(c);
 }

 UINT delmnog(UINT *a, UINT *b, UINT *c)

 // a,b - ukazateli na delimoe i delitel;
 // c - ukazatel na nachalo massiva dlja nepolnogo
 // chastnogo. Delit s ostatkom a na b, prichem ostatok
 // poluchaetsja v a. Esli delenie nevozmogno, vozvrashaet
 // 0, inache 1.

 {UINT i,j,m,k,s;
  double *e,*f,*g,p,q;
  i = a[0]; j = b[0];
  m = (i > j ? i-j : 0);
  c[0] = (m + 1);
  e = (double*)(c+1);
  f = (double*)(a+1);
  g = (double*)(b+1);
  i--; j--;
  if(g[j] == 0)return 0;
  while(i >= j && i != 0xFFFFFFFF)
   {p = f[i]/g[j];
    e[m] = p;
    m--;
    f[i] = 0;
    k = j;
    s = i;
    while(k != 0)
     {k--; s--;
      q = g[k] * p;
      f[s] -= q;
     }
    i--;
   }
  a[0] = (i == 0xFFFFFFFF ? 1 :(i+1));
  normmn(a);
  return 1;
 }

 void domnogmn(UINT *a, double b)

 // a - ukazatel na mnogochlen; b - chislo.
 // Vse chleni mnogochlena domnogajutsja na eto chislo.

 {UINT n,i;
  double *f;
  n = a[0];
  f = (double*)(a+1);
  for(i = 0; i < n; i++)
  f[i] *= b;
  normmn(a);
 }

 void minusmn(UINT *a)

 // a - ukazatel na mnogochlen;

 {UINT n,i;
  double *f;
  n = a[0];
  f = (double*)(a+1);
  for(i = 0; i < n; i++)
  f[i] = -f[i];
 }

 void razvmnkomp(UINT a, UINT* b)
 // a - smeshenie v zone zadach polinoma s koeff.
 // v formate "kompleksnoe". b - ukazatel na ish.poziciju
 // dlja predstavlenija etogo polinoma v vichislit.formate:
 // snachala idet jachejka s chislom chlenov polinoma
 // (UINT), zatem - massiv ego koefficientov - par
 // chisel v formate "double". Starshij koefficient - v
 // konce massiva.

 {UINT i,j;
  i = Z[a];
  i -= 6;
  i >>= 1;
  b[0] = i;
  a += 4;
  j = 1;
  while(!(Z[a] & 0x80000000))
   {i = Z[a];
    b[j] = Z[i+3];
    b[j+1] = Z[i+5];
    b[j+2] = Z[i+7];
    b[j+3] = Z[i+9];
    j += 4;
    a += 2;
   }
 }

 UINT svertmnkomp(UINT *a)

 // a - ukazatel na predstavlenije kompleksnogo
 // mnogochlena v vichislit. formate. Sozdaet v
 // zone zadach ego predstavlenie v
 // logicheskom formate, i vozvrashaet ego smeshenie.
 // Pri neudache vozvrashaet 0xFFFFFFFF.

 {UINT b,n,i,*c;
  n = *a; c = st; a += 1;
  *st = 0x00200104;
  st++;
  for(i = 0; i < n; i++)
   {b= mem(12);
    if(b == 0) return 0xFFFFFFFF;
    Z[b+2] = 0x41200001;
    Z[b+3] = *a;
    Z[b+4] = 0x41200001;
    Z[b+5] = *(a+1);
    Z[b+6] = 0x41200001;
    Z[b+7] = *(a+2);
    Z[b+8] = 0x41200001;
    Z[b+9] = *(a+3);
    a += 4;
    *st = b;
    st++;
   }
  b = text1(c);
  if(b == 0) return 0xFFFFFFFF;
  return b;
 }

 void normmnkomp(UINT *a)

 // a - ukazatel na kompleksnij mnogochlen. Otbrasivaet
 // nulevie starshie chleni.

 {UINT n,*r;
  double *p,*q;
  n = *a; n <<= 2; n -= 3;
  r = a + n;
  p = (double*)r;
  r = a + 1;
  q = (double*)r;
  n = *a;
  if(fabs(*p)< 0.00000000001 &&
     fabs(*(p+1))< 0.00000000001)
   {*p = 0; *(p+1) = 0;}
  while(*p == 0 && *(p+1) == 0 && p != q)
   {n --;
    p -=2;
    if(fabs(*p)<0.00000000001 &&
       fabs(*(p+1))<0.00000000001)
     {*p = 0; *(p+1) = 0;}
   }
  *a = n;
 }

 void plusmnkomp(UINT *a, UINT *b)

 // a,b - ukazateli na pervij i vtoroj kompleksnie
 // mnogochleni. Vipolnjaet pribavlenie k pervomu vtorogo.
 // Predpolagaetsja, chto posle pervogo imeetsja
 // dostatochno mesta.

 {UINT m,n,k,i,*r;
  double *p,*q;
  m = *a; n = *b;
  if(m < n)
   {k = n - m;
    k <<= 1;
    m <<= 2;
    m++;
    r = a + m;
    p = (double*)r;
    for(i = 0; i < k; i++)
     {p[i] = 0;}
    *a = n;
   }
  r = a + 1;
  p = (double*)r;
  r = b + 1;
  q = (double*)r;
  n <<= 1;
  for(i = 0; i < n; i++)
   p[i] = p[i] + q[i];
  normmnkomp(a);
 }

 void umnogmnkomp(UINT *a, UINT *b, UINT *c)

 // a,b - ukazateli na kompleksnie somnogiteli;
 // c - ukazatel na pervuju jachejku nakopitelja
 // proizvedenija. Etot nakopitel ne inicializiruetsja.

 {UINT i,j,m,n;
  double *d,*e,*f,*g,p,q;
  m = a[0] + b[0]; m--;
  c[0] = m;
  m *= 2;
  d = (double*)(c+1);
  for(i = 0; i < m; i++)
   d[i] = 0;
  m = a[0];
  n = b[0];
  for(i = 1,d = (double*)(b+1),e = (double*)(c+1); i<= n;
      i++,d += 2,e += 2)
   {for(j = 1,f = (double*)(a+1),g = e; j <= m;
        j++, f += 2, g += 2)
     {p = (*d)*(*f);
      q = *(d+1)*(*(f+1));
      p -= q;
      (*g) += p;
      p = (*d)*(*(f+1));
      q = (*(d+1)*(*f));
      p += q;
      (*(g+1)) += p;
     }
   }
  normmnkomp(c);
 }
void domnogmnkomp(UINT *a, double b, double c)

 // a - ukazatel na kompleksnij mnogochlen; b,c -
 // veshestvennaja i mnimaja chasti kompleksnogo chisla.
 // Vse chleni mnogochlena domnogajutsja na eto chislo.

 {UINT n,i;
  double *f,p,q;
  n = a[0];
  f = (double*)(a+1);
  n <<= 1;
  for(i = 0; i < n; i += 2)
   {p = f[i]*b;
    q = f[i+1]*c;
    p -= q;
    q = f[i]*c;
    f[i] = p;
    p = f[i+1]*b;
    q += p;
    f[i+1] = q;
   }
  normmnkomp(a);
 }

void minusmnkomp(UINT *a)

 // a - ukazatel na kompleksnij mnogochlen;

 {UINT n,i;
  double *f;
  n = a[0];
  n <<= 1;
  f = (double*)(a+1);
  for(i = 0; i < n; i++)
  f[i] = -f[i];
 }

UINT delmnogkomp(UINT *a, UINT *b, UINT *c)

 // a,b - ukazateli na delimoe i delitel;
 // c - ukazatel na nachalo massiva dlja nepolnogo
 // chastnogo. Delit s ostatkom a na b, prichem ostatok
 // poluchaetsja v a. Esli delenie nevozmogno, vozvrashaet
 // 0, inache 1.

 {UINT i,j,m,k,s;
  double *e,*f,*g,p,q,r,t;
  i = a[0]; j = b[0];
  m = (i > j ? i-j : 0);
  c[0] = (m + 1);
  e = (double*)(c+1);
  f = (double*)(a+1);
  g = (double*)(b+1);
  i <<= 1;
  j <<= 1;
  i -= 2; j -= 2;
  m <<= 1;
  if(g[j] == 0 && g[j+1] == 0)return 0;
  while(i >= j && i != 0xFFFFFFFE)
   {p = g[j]*g[j];
    q = g[j+1]*g[j+1];
    p += q;
    q = f[i]*g[j];
    r = f[i+1]*g[j+1];
    q += r;
    q /= p;
    e[m] = q;
    t = f[i+1]*g[j];
    r = f[i]*g[j+1];
    t -= r;
    t /= p;
    e[m+1] = t;
    m -= 2;
    f[i] = 0;
    f[i+1] = 0;
    k = j;
    s = i;
    while(k != 0)
     {k -= 2; s -= 2;
      p = g[k]*q;
      r = g[k+1]*t;
      p -= r;
      f[s] -= p;
      r = g[k]*t;
      p = g[k+1]*q;
      p += r;
      f[s+1] -= p;
     }
    i -= 2;
   }
  i >>= 1;
  a[0] = (i == 0xFFFFFFFF ? 1 :(i+1));
  normmnkomp(a);
  return 1;
 }

