コード例 #1
0
// reduces a polynomial with respect to a set of polynomials F
Polynomial *normal_form(Polynomial **set, Polynomial *orig, 
                        int index, int num_polys, int *reduced){
    Polynomial *res, *temp; 

    // we must try all quotient and remainders
    Polynomial **quots = (Polynomial **) malloc(sizeof(Polynomial *) * num_polys);
    Polynomial **rems = (Polynomial **) malloc(sizeof(Polynomial *) * num_polys);
     
    res = copy_poly(orig);
    *reduced = 0;
  
    printf("computing some reduction\n");  
    // try to divide using all things in the set 
    for (int i = 0; i < num_polys; i++){
        if (i == index) continue;
        divide_polys(orig, set[i], &(quots[i]), &(rems[i]));
    }

    printf("wtf tried to divide everything\n"); 
    // nothing divided out completely the first time
    // keep trying to divide out stuff recursively
    for (int i = 0; i < num_polys; i++){
        if (i == index) continue;
        
        // remainder is 0, return this right away
        if (rems[i]->terms[0].coeff.num == 0){
            free(res);  
            res = copy_poly(rems[i]);
            break;
        }

        // try to divide recursively
        else if (quots[i]->terms[0].coeff.num != 0){
            temp = normal_form(set, rems[i], index, num_polys, reduced);
            free(res); 
            // it reduced all the way
            if (temp->terms[0].coeff.num == 0){
                res = copy_poly(temp);
                break; 
            }
            else{
                res = copy_poly(rems[i]); 
            }
            free(temp); 
        }
    }

    // free all this stuff
    for (int i = 0; i < num_polys; i++) {
        if (i == index) continue; 
        free(quots[i]);
        free(rems[i]); 
    }

    free(quots);
    free(rems); 

    return res; 
}
コード例 #2
0
ファイル: ReedSolomon.cpp プロジェクト: IngenicC/feelsketch
void CReedSolomon::Modified_Berlekamp_Massey (void) {	

	int L, L2, k, d;
	int psi [MAX_LENGTH], psi2 [MAX_LENGTH], D [MAX_LENGTH];
	int gamma [MAX_LENGTH];
	int iMaxLength = m_iCorrectCodeSize * 2;
	
	/* initialize Gamma, the erasure locator polynomial */
	init_gamma (gamma);

	/* initialize to z */
	copy_poly (D, gamma);
	mul_z_poly (D);
	
	copy_poly (psi, gamma);	
	k = -1;
	L = m_NErasures;
	
	for (int n = m_NErasures; n < m_iCorrectCodeSize; n ++) {
		d = compute_discrepancy (psi, m_synBytes, L, n);
		
		if (d != 0) {
			/* psi2 = psi - d*D */
			for (int i = 0; i < iMaxLength; i++) {
				psi2 [i] = psi [i] ^ gmult (d, D [i]);
			}
			if (L < (n - k)) {
				L2 = n - k;
				k = n - L;
				/* D = scale_poly(ginv(d), psi); */
				for (int i = 0; i < iMaxLength; i ++) {
					D [i] = gmult (psi [i], ginv (d));
				}
				L = L2;
			}
			/* psi = psi2 */
			for (int i = 0; i < iMaxLength; i ++) {
				psi [i] = psi2 [i];
			}
		}
		mul_z_poly (D);
	}
	
	for (int i = 0; i < MAX_LENGTH; i ++) {
		m_Lambda [i] = psi [i];
	}
	compute_modified_omega ();
}
コード例 #3
0
ファイル: reedsolomon.c プロジェクト: ARSekkat/gpac
/* From  Cain, Clark, "Error-Correction Coding For Digital Communications", pp. 216. */
void
Modified_Berlekamp_Massey (void)
{
	int n, L, L2, k, d, i;
	int psi[MAXDEG], psi2[MAXDEG], D[MAXDEG];
	int gamma[MAXDEG];

	/* initialize Gamma, the erasure locator polynomial */
	init_gamma(gamma);

	/* initialize to z */
	copy_poly(D, gamma);
	mul_z_poly(D);

	copy_poly(psi, gamma);
	k = -1;
	L = NErasures;

	for (n = NErasures; n < NPAR; n++) {

		d = compute_discrepancy(psi, synBytes, L, n);

		if (d != 0) {

			/* psi2 = psi - d*D */
			for (i = 0; i < MAXDEG; i++) psi2[i] = psi[i] ^ gmult(d, D[i]);


			if (L < (n-k)) {
				L2 = n-k;
				k = n-L;
				/* D = scale_poly(ginv(d), psi); */
				for (i = 0; i < MAXDEG; i++) D[i] = gmult(psi[i], ginv(d));
				L = L2;
			}

			/* psi = psi2 */
			for (i = 0; i < MAXDEG; i++) psi[i] = psi2[i];
		}

		mul_z_poly(D);
	}

	for(i = 0; i < MAXDEG; i++) Lambda[i] = psi[i];
	compute_modified_omega();


}
コード例 #4
0
ファイル: polynomial.c プロジェクト: AndrewWUw/cs9021
Polynomial add_polys(Polynomial poly1, Polynomial poly2) {
    Polynomial poly = copy_poly(poly1);
    Monomial *current = poly2;
    while (current) {
        add_monom_to_poly(current->coeff, current->degree, &poly);
        current = current->next_monomial;
    }
    return poly;
}
コード例 #5
0
ファイル: polynomial.c プロジェクト: AndrewWUw/cs9021
Polynomial divide_polys(Polynomial poly1, Polynomial poly2) {
    Polynomial tmp = copy_poly(poly1);
    Polynomial quotient = NULL;
    while (tmp) {
        double coeff = (double)tmp->coeff / poly2->coeff;
        int degree = tmp->degree - poly2->degree;
        if (coeff != (int)coeff || degree < 0)
            return NULL;
        Polynomial poly2_copy = copy_poly(poly2);
        multiply_monom_to_poly(-(int)coeff, degree, poly2_copy);
        Polynomial sum = add_polys(tmp, poly2_copy);
        free_poly(poly2_copy);
        free_poly(tmp);
        tmp = sum;
        add_monom_to_poly((int)coeff, degree, &quotient);
    }
    free_poly(tmp);
    return quotient;
    return NULL;
}
コード例 #6
0
ファイル: polynomial.c プロジェクト: AndrewWUw/cs9021
Polynomial multiply_polys(Polynomial poly1, Polynomial poly2) {
    Polynomial product = NULL;
    if (!poly1 || !poly2)
        return product;
    Monomial *current = poly2;
    while (current) {    
        Polynomial poly = copy_poly(poly1);
        multiply_monom_to_poly(current->coeff, current->degree, poly);
        current = current->next_monomial;
        if (!product)
            product = copy_poly(poly);
        else {
            Polynomial sum = add_polys(product, poly);
            free_poly(product);
            product = sum;
        }
        free_poly(poly);
    }
    return product;
}
コード例 #7
0
ファイル: ReedSolomon.cpp プロジェクト: IngenicC/feelsketch
/* gamma = product (1-z*a^Ij) for erasure locs Ij */
void CReedSolomon::init_gamma (int gamma []) {

	int tmp [MAX_LENGTH];
	
	for (int i = 0; i < MAX_LENGTH; i ++) {
		gamma [i]	= 0;
		tmp [i]		= 0;
	}
	gamma[0] = 1;
	for (int e = 0; e < m_NErasures; e ++) {
		copy_poly (tmp, gamma);
		scale_poly (byExpToInt [m_ErasureLocs [e]], tmp);
		mul_z_poly (tmp);
		add_polys (gamma, tmp);
	}
}
コード例 #8
0
ファイル: reedsolomon.c プロジェクト: ARSekkat/gpac
/* gamma = product (1-z*a^Ij) for erasure locs Ij */
void
init_gamma (int gamma[])
{
	int e, tmp[MAXDEG];

	zero_poly(gamma);
	zero_poly(tmp);
	gamma[0] = 1;

	for (e = 0; e < NErasures; e++) {
		copy_poly(tmp, gamma);
		scale_poly(gexp[ErasureLocs[e]], tmp);
		mul_z_poly(tmp);
		add_polys(gamma, tmp);
	}
}
コード例 #9
0
ファイル: rs.c プロジェクト: WTHsieh/diag
static void
compute_genpoly (int nbytes, unsigned short genpoly[])
{
  unsigned short i, tp[256], tp1[256];

  zero_poly(tp1);
  tp1[0] = 1;

  for (i = 1; i <= nbytes; i++) {
    zero_poly(tp);
    tp[0] = gexp[i];		/* set up x+a^n */
    tp[1] = 1;
	  
    mult_polys(genpoly, tp, tp1);
    copy_poly(tp1, genpoly);
  }
}
コード例 #10
0
ファイル: reedsolomon.c プロジェクト: ARSekkat/gpac
static void
compute_genpoly (int nbytes, int genpoly[])
{
	int i, tp[256], tp1[256];

	/* multiply (x + a^n) for n = 1 to nbytes */

	zero_poly(tp1);
	tp1[0] = 1;

	for (i = 1; i <= nbytes; i++) {
		zero_poly(tp);
		tp[0] = gexp[i];        /* set up x+a^n */
		tp[1] = 1;

		mult_polys(genpoly, tp, tp1);
		copy_poly(tp1, genpoly);
	}
}
コード例 #11
0
ファイル: GFMath.cpp プロジェクト: my12doom/pilot2
// Create a generator polynomial for an n byte RS code. 
void init_genpoly_cache(int par)
{
	int i;
	unsigned char tp[256], tp1[256];
	int tmp;

	unsigned char *genpoly = genpoly_cache[par-1];

	//multiply (x + a^n) for n = 1 to nbytes

	zero_poly(tp1, par*2);
	tp1[0] = 1;

	for (i = 1; i <= par; i++) 
	{
		zero_poly(tp, par*2);
		tp[0] = gexp[i];		// set up x+a^n
		tp[1] = 1;

		mult_polys(genpoly, tp, tp1, par*2);
		copy_poly(tp1, genpoly, par*2);
	}

	for(i=0; i<par/2; i++)
	{
		tmp = genpoly[i] ;
		genpoly[i] = genpoly[par-1-i];
		genpoly[par-1-i]=tmp;
	}

	for(i=0; i<256; i++)
	{
		for(int j=0; j<23; j++)
			genpoly_23_mult_cache[i][j] = gmult(i, genpoly_cache[22][j]);
		genpoly_23_mult_cache[i][23] = 0;
	}
}
コード例 #12
0
// does polynomial long division, p1 divided by p2 
void divide_polys(Polynomial *p1, Polynomial *p2, 
                         Polynomial **quot, Polynomial **rem) {
    int max = 2 * p2->num_terms;
    int count = 0; 
    Polynomial *res;
    Polynomial *old_temp, *new_temp; 
    Polynomial *old_div, *new_div; 
    Polynomial **quots; 

    
    // need to allocate some polynomails, let's just assume we need
    // double the space of the dividend and then adjust if it goes over
    *quot = empty_poly(p1->num_vars, 1, p1->vars);
    
    divide_terms(&p1->terms[0], &p2->terms[0], &((*quot)->terms[0]), p1->num_vars);
    
    // not divisible from the get go, so the quot is 0
    // and the remainder is all of p1 
    if ((*quot)->terms[0].coeff.num == 0) {
        *rem = copy_poly(p1); 
        return; 
    }
    
    // the first term was not 0, so we need to set this polynomial in our list of
    // partial quotients. don't forget to malloc space for the list
    quots = (Polynomial **) malloc(sizeof(Polynomial *) * max);
    quots[count] = *quot; 
    count++; 

    // copy the divisor 
    old_div = copy_poly(p1); 
    while(true) {
        res = multiply_polys(quots[count-1], p2);
        
        // get the new dividend
        new_div = subtract_polys(old_div, res); 
        sort_polynomial(new_div);  
        free(old_div);
        
        // see if it can be divided
        quots[count] = empty_poly(p1->num_vars, 1, p1->vars); 
        divide_terms(&new_div->terms[0], &p2->terms[0], 
                     &quots[count]->terms[0], p1->num_vars);  
        if (quots[count]->terms[0].coeff.num == 0) {
            res = new_div;
            break;  
        }
       
        // it divided, time to loop again
        count += 1;
        free(res);
        old_div = new_div;   

        // increase solutions array ?
        if (count == max-1){
            quots = double_poly_array(quots, &max); 
        } 
    }   
    // sum everything in the quotes list
    old_temp = zero_poly(p1); 
    for (int i = 0; i < count; i++) {
        new_temp = add_polys(old_temp, quots[i]);
        free(old_temp);
        free(quots[i]); 
        old_temp = new_temp;  
    }  
    free(quots); 
 
    // set the quotient and remainder 
    *quot = new_temp; 
    *rem = res; 
}
コード例 #13
0
ファイル: pixelize.c プロジェクト: bareid/mangle
int pixel_loop(int pix, int n, polygon *input[/*n*/], int out_max, polygon *output[/*out_max*/]){
  int *child_pix,children;
  int i,j,k,m,out,nout;
  int ier, iprune, np;
  polygon *pixel;
  polygon **poly;
 
  //allocate memory for work array of polygon pointers
  poly=(polygon **) malloc(sizeof(polygon *) * n);
  if(!poly){
    fprintf(stderr, "pixel_loop: failed to allocate memory for %d polygon pointers\n",n);
    return(-1);
  }
  
  // allocate memory for child_pix array
  if(pix==0 && scheme=='d'){
    child_pix=(int *) malloc(sizeof(int) * 117);
    children=117;
    if(!child_pix){
      fprintf(stderr, "pixel_loop: failed to allocate memory for 117 integers\n");
      return(-1);
    }
  }
  else{
    child_pix=(int *) malloc(sizeof(int) * 4);
    children=4;
    if(!child_pix){
      fprintf(stderr, "pixel_loop: failed to allocate memory for %d integers\n", 4);
      return(-1);
    }
  }

  get_child_pixels(pix, child_pix, scheme);
  out=0;
  
  for(i=0;i<children;i++){    
    /*get the current child pixel*/
    pixel=get_pixel(child_pix[i], scheme);
 
    if(!pixel){
      fprintf(stderr, "error in pixel_loop: could not get pixel %d\n", child_pix[i]); 
      return(-1);
    }
    
    /*loop through input polygons to find the ones that overlap with current child pixel*/
    for(j=0;j<n;j++){
      /* skip null polygons */
      if (input[j]->np > 0 && input[j]->cm[0] == 0.){
	poly[j] = 0x0;
	continue;
      }

      np=input[j]->np+pixel->np;
      poly[j]=new_poly(np);
      if(!poly[j]){
	fprintf(stderr, "error in pixel_loop: failed to allocate memory for polygon of %d caps\n", np);
	return(-1);
      }
      /*set poly[j] to the intersection of input[j] and current child pixel*/
      poly_poly(input[j],pixel,poly[j]);
      poly[j]->pixel=pixel->pixel;
    
      iprune = prune_poly(poly[j], mtol);
      if (iprune == -1) {
	fprintf(stderr, "pixelize: failed to prune polygon for pixel %d; continuing ...\n", poly[j]->pixel);
	//return(-1);
      }
      /*if polygon is null, get rid of it*/
      if (iprune >= 2) {
	free_poly(poly[j]);
	poly[j] = 0x0;
      }       
    }
    
    /*copy down non-null polygons*/
    k=0;
    for(j=0;j<n;j++){
      if(poly[j]){
	poly[k++]=poly[j];
      }
    }
    m=k;
    /*nullify the rest of the array, but don't free, since pointers have been copied above*/
    for(j=m;j<n;j++){
      poly[j]=0x0;
    }
    
    /*if we're below the max resolution, recursively call pixel_loop on the current child pixel */ 
    if(m>polys_per_pixel && get_res(child_pix[i],scheme)<res_max){
      //printf("calling pixel loop for pixel %d with %d polygons\n",child_pix[i],m);
      nout=pixel_loop(child_pix[i],m,poly,out_max-out,&output[out]);
      if(nout==-1) return(-1);
      out+=nout;
    }
    else{
      for(k=0;k<m;k++){
	/* check whether exceeded maximum number of polygons */
	if (out >= out_max) {
	  fprintf(stderr, "pixel_loop: total number of polygons exceeded maximum %d\n", NPOLYSMAX);
	  fprintf(stderr, "if you need more space, enlarge NPOLYSMAX in defines.h, and recompile\n");
	  return(-1);
	}
	/*make sure output polygon has enough room */
	ier = room_poly(&output[out], poly[k]->np, DNP, 0);
	if (ier == -1) {
	  fprintf(stderr, "error in pixel_loop: failed to allocate memory for polygon of %d caps\n", poly[i]->np + DNP);
	  return(-1);
	}

	/*copy polygon to output array*/
	copy_poly(poly[k],output[out]);
	out++;    
      }
    }
    /*free up memory for next child pixel*/
    
    free_poly(pixel);
    for(j=0;j<n;j++){
      free_poly(poly[j]);
    }
  }
  free(child_pix);
  free(poly);
  return out;
}
コード例 #14
0
ファイル: split_poly.c プロジェクト: MCTwo/DEIMOS
/*------------------------------------------------------------------------------
  If poly1 overlaps poly2, split poly1 into two parts.

  If poly3 is null on input, then the appropriate return value is returned,
  but poly1 is not actually split.

   Input: *poly1, poly2 are 2 polygons.
	  mtol = initial angular tolerance within which to merge multiple intersections.
  Output: If **poly3 is not null on input, then:
	      *poly1 and *poly3 are 2 split polygons of poly1, if poly1 is split,
		    with *poly1 the part outside poly2,
		    and *poly3 the part intersecting poly2;
	      *poly1 and *poly3 remain untouched if poly1 is not split.
	  If **poly3 is null on input, then *poly1 remains untouched.
  Return value: -1 = error occurred;
		0 = poly1 and poly2 have zero intersection;
		1 = poly2 fully encloses poly1;
		2 = poly2 splits poly1 into two.
*/
int split_poly(polygon **poly1, polygon *poly2, polygon **poly3, double mtol, char bmethod)

{
    static polygon *poly = 0x0, *poly4 = 0x0;

    int ier, ip, iprune, np, np1, verb;
    double area, area_tot, cm, tol;

    /* poly2 is whole sphere, therefore contains poly1 */
    if (poly2->np == 0){
      /* set weight according to balkanization scheme: */
      if(bmethod=='l'){
	//do nothing - this is the default behavior
      }
      else if(bmethod=='a'){
	(*poly1)->weight=(*poly1)->weight + poly2->weight;
      }
      else if(bmethod=='n'){
	(*poly1)->weight=((*poly1)->weight > poly2->weight)? poly2->weight : (*poly1)->weight ;
      }
      else if(bmethod=='x'){
	(*poly1)->weight=((*poly1)->weight > poly2->weight)? (*poly1)->weight : poly2->weight ;
      }
      else{
	fprintf(stderr, "error in split_poly: balkanize method %c not recognized.\n", bmethod);
	return(-1);
      }
      return(1);
    }
    
    /* make sure poly contains enough space for intersection */
    np = (*poly1)->np + poly2->np;
    ier = room_poly(&poly, np, DNP, 0);
    if (ier == -1) goto out_of_memory;

    /* intersection of poly1 and poly2 */
    poly_poly(*poly1, poly2, poly);

    /* suppress coincident boundaries, to make garea happy */
    iprune = trim_poly(poly);

    /* intersection of poly1 and poly2 is null polygon */
    if (iprune >= 2) return(0);

    /* area of intersection */
    tol = mtol;
    verb = 1;
    ier = garea(poly, &tol, verb, &area_tot);
    if (ier) goto error;

    /* poly1 and poly2 have zero intersection */
    if (area_tot == 0.) return(0);

    /* number of caps of poly1 */
    np1 = (*poly1)->np; 

    /* find boundary of poly2 which intersects poly1 */
    verb = 0;

    for (ip = 0; ip < poly2->np; ip++) {

	cm = poly->cm[np1 + ip];
	poly->cm[np1 + ip] = 2.;		/* suppress boundary to be tested */
	tol = mtol;
	ier = garea(poly, &tol, verb, &area);	/* area of intersection sans boundary */
	poly->cm[np1 + ip] = cm;		/* restore tested boundary */

	if (area > area_tot) {			/* boundary intersects poly1 */
	  /* poly2 splits poly1, but do not actually split */
	  if (!poly3) return(2);

	  /* number of caps of poly1 with extra boundary */
	  np = np1 + 1;
	  
	  /* make sure poly3 contains enough space */
	  ier = room_poly(poly3, np, DNP, 0);
	  
	  if (ier == -1) goto out_of_memory;	  
	  
	  /* poly3 is intersection of poly1 and ip'th cap of poly2 */
	  poly_polyn(*poly1, poly2, ip, 1, *poly3);
	  
	  /* prune poly3 */
	  iprune = prune_poly(*poly3, mtol);
	  if (iprune == -1) goto error;
	  /* poly3 may be null because of roundoff: skip to next cap */
	  if (iprune >= 2) continue;
	  
	  /* make sure poly4 contains enough space */
	  ier = room_poly(&poly4, np, DNP, 1);
	  if (ier == -1) goto out_of_memory;
	  
	  /* poly4 is intersection of poly1 and complement of ip'th cap of poly2 */
	  poly_polyn(*poly1, poly2, ip, -1, poly4);
	  
	  /* prune poly4 */
	  iprune = prune_poly(poly4, mtol);
	  if (iprune == -1) goto error;
	  /* poly4 may be null because of roundoff: skip to next cap */
	  if (iprune >= 2) continue;
	  
	  /* make sure poly1 contains enough space */
	  np = poly4->np;
	  ier = room_poly(poly1, np, DNP, 0);
	  if (ier == -1) goto out_of_memory;
	  
	  /* copy poly4 into poly1 */
	  copy_poly(poly4, *poly1);
	  
	  /* poly1 successfully split into poly1 and poly3 */
	  /* set weight according to balkanization scheme: */
	  if(bmethod=='l'){
	    //do nothing - this is the default behavior
	  }
	  else if(bmethod=='a'){
	    (*poly3)->weight=(*poly1)->weight + poly2->weight;
	  }
	  else if(bmethod=='n'){
	    (*poly3)->weight=((*poly1)->weight > poly2->weight)? poly2->weight : (*poly1)->weight ;
	  }
	  else if(bmethod=='x'){
	    (*poly3)->weight=((*poly1)->weight > poly2->weight)? (*poly1)->weight : poly2->weight ;
	  }
	  else{
	    fprintf(stderr, "error in split_poly: balkanize method %c not recognized.\n", bmethod);
	    return(-1);
	  }

	  return(2);

	} else if (area < area_tot) {
	    /* area should be >= area_tot because suppressing a boundary of poly should always increase its area;
	       but this can happen because of roundoff */
	    //fprintf(stderr, "split_poly: area %.16g of polygon with boundary %d suppressed should be >= area %.16g of polygon\n", area, ip, area_tot);
	}
    }
    
    /* poly2 contains poly1 */
    /* set weight according to balkanization scheme: */
    if(bmethod=='l'){
      //do nothing - this is the default behavior
    }
    else if(bmethod=='a'){
      (*poly1)->weight=(*poly1)->weight + poly2->weight;
    }
    else if(bmethod=='n'){
      (*poly1)->weight=((*poly1)->weight > poly2->weight)? poly2->weight : (*poly1)->weight ;
    }
    else if(bmethod=='x'){
      (*poly1)->weight=((*poly1)->weight > poly2->weight)? (*poly1)->weight : poly2->weight ;
    }
    else{
      fprintf(stderr, "error in split_poly: balkanize method %c not recognized.\n", bmethod);
      return(-1);
    }
    return(1);

    /* ---------------- error returns ---------------- */
    error:
    return(-1);

    out_of_memory:
    fprintf(stderr, "split_poly: failed to allocate memory for polygon of %d caps\n", np + DNP);
    return(-1);
}
コード例 #15
0
ファイル: balkanizepolys.c プロジェクト: abensonca/mangle
/*------------------------------------------------------------------------------
  Balkanize overlapping polygons into many disjoint connected polygons.

   Input: npoly = number of polygons.
	  poly = array of pointers to polygons.
	  npolys = maximum number of output polygons.
	  mtol = tolerance angle for multiple intersections.
	  fmt = pointer to format structure.
	  axtol, btol, thtol, ytol = tolerance angles (see documentation).
  Output: polys = array of pointers to polygons.
  Return value: number of disjoint connected polygons,
		or -1 if error occurred.
*/
int balkanize(int npoly, polygon *poly[/*npoly*/], int npolys, polygon *polys[/*npolys*/], long double mtol, format *fmt, long double axtol, long double btol, long double thtol, long double ytol)
{
/* part_poly should lasso one-boundary polygons only if they have too many caps */
#define ALL_ONEBOUNDARY		1
/* how part_poly should tighten lasso */
#define ADJUST_LASSO		1
/* part_poly should force polygon to be split even if no part can be lassoed */
#define	FORCE_SPLIT		1
/* partition_poly should overwrite all original polygons */
#define OVERWRITE_ORIGINAL	2
#define WARNMAX			8
    char *snapped_polys = 0x0;
    int discard, dm, dn, dnp, failed, i, ier, inull, isnap, ip, iprune, j, k, m, n, nadj, np, selfsnap;
    int *start;
    int *total;
    int begin, end, p, max_pixel;
    long double tol;

    poly_sort(npoly, poly, 'p');

    /* allocate memory for pixel info arrays start and total */ 
    max_pixel=poly[npoly-1]->pixel+1; 
    start = (int *) malloc(sizeof(int) * max_pixel);
    if (!start) {
      fprintf(stderr, "balkanize: failed to allocate memory for %d integers\n", max_pixel);
      return(-1);
    }
    total = (int *) malloc(sizeof(int) * max_pixel);
    if (!total) {
      fprintf(stderr, "balkanize: failed to allocate memory for %d integers\n", max_pixel);
      return(-1);
    }

    /* build lists of starting indices of each pixel and total number of polygons in each pixel*/
    ier=pixel_list(npoly, poly, max_pixel, start, total);
    if (ier == -1) {
      fprintf(stderr, "balkanize: error building pixel index lists\n");
      return(-1);
    }

    /* start by pruning all input polygons */
    np = 0;
    inull = 0;
    for (i = 0; i < npoly; i++) {
        tol = mtol;
	iprune = prune_poly(poly[i], tol);
	/* error */
	if (iprune == -1) {
	    fprintf(stderr, "balkanize: initial prune failed at polygon %d\n", poly[i]->id);
	    return(-1);
	}
	/* zero area polygon */
	if (iprune >= 2) {
	    if (WARNMAX > 0 && inull == 0) msg("warning from balkanize: following polygons have zero area & are being discarded:\n");
	    if (inull < WARNMAX) {
	      msg(" %lld", (fmt->newid == 'o')? poly[i]->id : (long long)i);
	    } else if (inull == WARNMAX) {
		msg(" ... more\n");
	    }
	    inull++;
	} else {
	    np++;
	}
    }
    if (WARNMAX > 0 && inull > 0 && inull <= WARNMAX) msg("\n");
    if (inull > 0) {
	msg("balkanize: %d polygons with zero area are being discarded;\n", inull);
    }

    /* number of polygons */
    msg("balkanizing %d polygons ...\n", np);

    /* nullify all output polygons */
    for (i = 0; i < npolys; i++) {
	polys[i] = 0x0;
    }

    /*
      m = starting index of current set of fragments of i'th polygon
      dm = number of current set of fragments of i'th polygon
      n = starting index of new subset of fragments of i'th polygon
      dn = number of new subset of fragments of i'th polygon
    */
    
    msg("balkanize stage 1 (fragment into non-overlapping polygons):\n");
    n = 0;
    dnp = 0;
    ip = 0;
    /* go through each pixel and fragment each polygon against the other polygons in its pixel */
    for(p=0;p<max_pixel;p++){
      
      begin=start[p];
      end=start[p]+total[p];

      /* too many polygons */
      if (n >= npolys) break;

      /* fragment each polygon in turn */

      for (i = begin; i < end; i++) {
	/* skip null polygons */
	if (poly[i]->np > 0 && poly[i]->cm[0] == 0.) continue;
	/* update indices */
	
	m = n;
	dm = 1;
        n = m + dm;
        /* make sure output polygon has enough room */
	
	ier = room_poly(&polys[m], poly[i]->np, DNP, 0);
	if (ier == -1) {
	  fprintf(stderr, "balkanize: failed to allocate memory for polygon of %d caps\n", poly[i]->np + DNP);
	  return(-1);
	}
	
	
        /* copy polygon i into output polygon */
	copy_poly(poly[i], polys[m]);
	
	/* fragment successively against other polygons */
	for (j = begin; j < end; j++) {
	
	  /* skip self, or null polygons */
	  if (j == i || (poly[j]->np > 0 && poly[j]->cm[0] == 0.)) continue;
	  /* keep only one copy of the intersection of i & j */
	  /* intersection inherits weight of polygon being fragmented,
	     so keeping later polygon ensures intersection inherits
	     weight of later polygon */
	  if (i < j) {
	    discard = 1;
	  } else {
	    discard = 0;
	  }
	
	  /* fragment each part of i'th polygon */
	  for (k = m; k < m + dm; k++) {
	 	    /* skip null polygons */
	    if (!polys[k] || (polys[k]->np > 0 && polys[k]->cm[0] == 0.)) continue;
	    /* fragment */
	    tol = mtol;
	    dn = fragment_poly(&polys[k], poly[j], discard, npolys - n, &polys[n], tol, bmethod);
 
	    /* error */
	    if (dn == -1) {
	      fprintf(stderr, "balkanize: UHOH at polygon %lld; continuing ...\n", (fmt->newid == 'o')? polys[i]->id : (long long)ip);
	      continue;
	      /* return(-1); */
	    }

	    /* increment index of next subset of fragments */
	    n += dn;
	    /* increment polygon count */
	    np += dn;
	    dnp += dn;
	    if (!polys[k]) {
	      np--;
	      dnp--;
	    }

	    /* check whether exceeded maximum number of polygons */
	    //printf("(1) n = %d\n", n);
	    if (n > npolys) {
	      fprintf(stderr, "(1) balkanize: total number of polygons (= %d) exceeded maximum %d\n", npoly + n, npoly + npolys);
	      fprintf(stderr, "if you need more space, enlarge NPOLYSMAX in defines.h, and recompile\n");
              fprintf(stderr, "currently, dn = %d, np = %d, dnp = %d, poly[%d]->id = %lld, poly[%d]->pixel = %d\n", dn, np, dnp, i, poly[i]->id, i, poly[i]->pixel);
	      n = npolys;
#ifdef	CARRY_ON_REGARDLESS
	      break;
#else
	      return(-1);
#endif
	    }
	  }

	  /* copy down non-null polygons */
	  dm = 0;
	  for (k = m; k < n; k++) {
	    if (polys[k]) {
	      polys[m + dm] = polys[k];
	      dm++;
	    }
	  }
	
	  /* nullify but don't free, because freeing polys[k] will free polys[m + dm] */
	  for (k = m + dm; k < n; k++) {
	    polys[k] = 0x0;
	  }
	  n = m + dm;
	  if (dm == 0) break;
	}
	/* too many polygons */
	if (n >= npolys) break;
	ip++;
      }
      
    }

    free(start);
    free(total);

    msg("added %d polygons to make %d\n", dnp, np);
    
    // partition disconnected polygons into connected parts  
    msg("balkanize stage 2 (partition disconnected polygons into connected parts):\n");
    m = n;
    dnp = 0;
    ip = 0;
    failed = 0;
    for (i = 0; i < m; i++) {
	// skip null polygons 
	if (!polys[i] || (polys[i]->np > 0 && polys[i]->cm[0] == 0.)) continue;
	// partition disconnected polygons
	tol = mtol;
	ier = partition_poly(&polys[i], npolys - n, &polys[n], tol, ALL_ONEBOUNDARY, ADJUST_LASSO, FORCE_SPLIT, OVERWRITE_ORIGINAL, &dn);
	// error
	if (ier == -1) {
	  fprintf(stderr, "balkanize: UHOH at polygon %lld; continuing ...\n", (fmt->newid == 'o')? polys[i]->id : (long long)ip);
	    continue;
	    // return(-1);
	// failed to partition polygon into desired number of parts
	} else if (ier == 1) {
	  fprintf(stderr, "balkanize: failed to partition polygon %lld fully; partitioned it into %d parts\n", (fmt->newid == 'o')? polys[i]->id : (long long)ip, dn + 1);
	    failed++;
	}
	// increment index of next subset of fragments 
	n += dn;
	// increment polygon count
	np += dn;
	dnp += dn;
	// check whether exceeded maximum number of polygons
	//printf("(2) n = %d\n", n);
	if (n > npolys) {
	    fprintf(stderr, "(2) balkanize: total number of polygons (= %d) exceeded maximum %d\n", n + npoly, npoly + npolys);
	    fprintf(stderr, "if you need more space, enlarge NPOLYSMAX in defines.h, and recompile\n");
	    n = npolys;
#ifdef	CARRY_ON_REGARDLESS
	    break;
#else
	    return(-1);
#endif
	}
	ip++;
    }

    msg("added %d polygons to make %d\n", dnp, np);

    if (failed > 0) {
	msg("balkanize: failed to split %d polygons into desired number of connected parts\n", failed);
	msg(".............................................................................\n");
	msg("Failure to split polygon probably means:\n");
	msg("either (1) you forgot to run snap on all your input polygon files;\n");
	msg("    or (2) the polygon is too small for the numerics to cope with;\n");
	msg("    or (3) you have a weird-shaped polygon.\n");
	msg("You may ignore this warning message if the weights of polygons in the input\n");
	msg("polygon file(s) are already correct, and you do not want to reweight them.\n");
	msg("Similarly, you may ignore this warning message if you do want to reweight the\n");
	msg("polygons, but the weights of the different parts of each unsplit polygon are\n");
	msg("the same.  If you want to reweight the different parts of an unsplit polygon\n");
	msg("with different weights, then you will need to split that polygon by hand.\n");
	msg("Whatever the case, the output file of balkanized polygons constitutes\n");
	msg("a valid mask of non-overlapping polygons, which is safe to use.\n");
	msg(".............................................................................\n");
    }

    /* prune */
    j = 0;
    inull = 0;
    for (i = 0; i < n; i++) {
        tol = mtol;
	iprune = prune_poly(polys[i], tol);
	if (iprune == -1) {
	  fprintf(stderr, "balkanize: failed to prune polygon %lld; continuing ...\n", (fmt->newid == 'o')? polys[i]->id : (long long)j);
	    /* return(-1); */
	}
	if (iprune >= 2) {
	    free_poly(polys[i]);
	    polys[i] = 0x0;
	    inull++;
	} else {
	    polys[j] = polys[i];
	    j++;
	}
    }
    if (inull > 0) msg("balkanize: %d balkanized polygons have zero area, and are being discarded\n", inull);
    n = j;

    /*    
    // allocate snapped_polys array
    snapped_polys = (char *) malloc(sizeof(char) * n);
    if (!snapped_polys) {
	fprintf(stderr, "balkanize: failed to allocate memory for %d characters\n", n);
	return(-1);
    }

    //snap edges of each polygon 
    selfsnap = 1;
    nadj = snap_polys(fmt, n, polys, selfsnap, axtol, btol, thtol, ytol, mtol, WARNMAX, snapped_polys);
    if(nadj==-1){
      msg("balkanize: error snapping balkanized polygons\n");
      return(-1);
    }

    // number of polygons whose edges were snapped
    isnap = 0;
    for (i = 0; i < n; i++) if (snapped_polys[i]) isnap++;
    if (isnap > 0) msg("balkanize: edges of %d balkanized polygons were snapped\n", isnap);

    // prune snapped polygons 
    j = 0;
    inull = 0;
    for (i = 0; i < n; i++) {
	if (snapped_polys[i]) {
	    iprune = prune_poly(polys[i], mtol);
	    if (iprune == -1) {
		fprintf(stderr, "balkanize: failed to prune polygon %lld; continuing ...\n", (fmt->newid == 'o')? polys[i]->id : (long long)j);
		// return(-1); 
	    }
	    if (iprune >= 2) {
		free_poly(polys[i]);
		polys[i] = 0x0;
		inull++;
	    } else {
		polys[j] = polys[i];
		j++;
	    }
	} else {
	    polys[j] = polys[i];
	    j++;
	}
    }
    
    if (inull > 0) msg("balkanize: %d snapped polygons have zero area, and are being discarded\n", inull);
    n = j;

// free snapped_polys array 
    free(snapped_polys);
    */

    if(n!=-1){
      /* sort polygons by pixel number */
      poly_sort(n, polys,'p');
      msg("balkanize: balkans contain %d polygons\n", n); 
    }
 
    /* assign new polygon id numbers in place of inherited ids */
    if (fmt->newid == 'n') {
	for (i = 0; i < n; i++) {
	  polys[i]->id = (long long)i;
	}
    }

    if (fmt->newid == 'p') {
      for (i = 0; i < n; i++) {
	polys[i]->id = (long long)polys[i]->pixel;
      }
    }

   
    return(n);
}