Esempio n. 1
0
static long* all_id_ranges( struct mhdf_FileDesc* desc, int include_null, int* num_ranges_out )
{
  int i, num_ranges = 0;
  struct mhdf_EntDesc* group;
  long* ranges = malloc(2*sizeof(long)*(desc->num_elem_desc + 2 + !!include_null));
  if (include_null) {
    num_ranges = 1;
    ranges[0] = 0;
    ranges[1] = 1;
  }
  for (i = -1; i <= desc->num_elem_desc; ++i) {
    if (i == -1) 
      group = &desc->nodes;
    else if (i == desc->num_elem_desc)
      group = &desc->sets;
    else
      group = &desc->elems[i].desc;

    if (num_ranges && ranges[2*num_ranges - 2] + ranges[2*num_ranges-1] == group->start_id) {
      ranges[2*num_ranges-1] += group->count;
    }
    else {
      ranges[2*num_ranges] = group->start_id;
      ranges[2*num_ranges+1] = group->count;
      ++num_ranges;
    }
  }

  
  *num_ranges_out = merge_ranges( ranges, num_ranges );
  return ranges;
}
Esempio n. 2
0
static long* get_dim_ranges( struct mhdf_FileDesc* desc, int dim, int* num_ranges_out )
{
  long* ranges = 0;
  int i, j;
  const char* const types1D[] = { mhdf_EDGE_TYPE_NAME, 0 };
  const char* const types2D[] = { mhdf_TRI_TYPE_NAME, mhdf_QUAD_TYPE_NAME, mhdf_POLYGON_TYPE_NAME, 0 };
  const char* const types3D[] = { mhdf_TET_TYPE_NAME, mhdf_PYRAMID_TYPE_NAME, mhdf_PRISM_TYPE_NAME,
                                  mdhf_KNIFE_TYPE_NAME, mdhf_HEX_TYPE_NAME, mhdf_POLYHEDRON_TYPE_NAME,
                                  mhdf_SEPTAHEDRON_TYPE_NAME, 0 };
  
  char const* const* typelist;
  switch (dim) {
    case 0:
      *num_ranges_out = 1;
      ranges = malloc(2*sizeof(long));
      ranges[0] = desc->nodes.start_id;
      ranges[1] = desc->nodes.count;
      return ranges;
    case 1:
      typelist = types1D;
      break;
    case 2:
      typelist = types2D;
      break;
    case 3:
      typelist = types3D;
      break;
    default:
      fprintf(stderr,"Internal error at %s:%d: request for entities of dimesion %d\n",
        __FILE__, __LINE__, dim );
      abort();
  }

  *num_ranges_out = 0;
  for (i = 0; i < desc->num_elem_desc; ++i) 
    if (string_contained( desc->elems[i].type, typelist ))
      ++*num_ranges_out;
  ranges = malloc(*num_ranges_out * 2 * sizeof(long));
  for (i = 0, j = 0; i < desc->num_elem_desc; ++i) 
    if (string_contained( desc->elems[i].type, typelist )) {
      ranges[j++]   = desc->elems[i].desc.start_id;
      ranges[j++] = desc->elems[i].desc.count;
    }
    
  *num_ranges_out = merge_ranges( ranges, *num_ranges_out );
  return ranges;  
}
Esempio n. 3
0
static int collapse_ranges(struct match_t *reduced, int nonuniques)
/* collapse together overlapping ranges in the hit list */
{ 
    struct match_t *sp, *tp;
    int spancount, removed = 0;

    /*
     * For two matches to be eligible for merger, all their filenames must
     * match pairwise.  If there are no such matches, these chunks are
     * completely irrelevant to each other.  It might be that for some
     * values of i the filenames are equal and for others not.  In
     * that case the pair of lists of ranges cannot represent the same
     * overlapping segments of text, which is the only case we are
     * interested in.
     *
     * This gives us leverage to apply the qsort trick again.  The naive
     * way to check for range overlaps would be to write a quadratic
     * double loop compairing all matches pairwise.  Instead we can
     * use this sort to partition the matches into spans such that
     * all overlaps must take place within spans.
     */
    qsort(reduced, nonuniques, sizeof(struct match_t), compare_files);

#ifdef DEBUG
    for (sp = reduced; sp < reduced + nonuniques; sp++)
    {
	 struct sorthash_t	*rp;

	 printf("Clique beginning at %d:\n", sp - reduced);
	 for (rp = sp->matches; rp < sp->matches + sp->nmatches; rp++)
	     printf("%s:%d:%d\n",  rp->file->name, rp->hash.start, rp->hash.end);
    }
#endif /* DEBUG */

    /* time to merge overlapping shreds */
    spancount = 0;
    for (sp = reduced; sp < reduced + nonuniques; sp++, spancount--)
    {
	int remaining;

	/*
	 * This optimization drastically reduces the number of compare_files
	 * calls.  The continue condition in the inner loop below would 
	 * otherwise involve one every time for O(n**2) calls; this reduces
	 * the number to O(n).
	 */
	if (spancount <= 0)
	{
	    spancount = 0;
	    for (tp = sp + 1; 
		 !compare_files(sp, tp) && tp < reduced + nonuniques; 
		 tp++)
		spancount++;
	}

	for (tp = sp + 1, remaining = spancount; remaining--; tp++)
	{
#ifdef DEBUG
	    printf("Trying merge of %d into %d\n", tp-reduced, sp-reduced);
#endif /* DEBUG */
	    /* neither must have been deleted */
	    if (!sp->nmatches || !tp->nmatches)
	    {
#ifdef DEBUG
		printf("Null match pointer: %d=%p, %d=%p\n", 
		       sp-reduced, sp->matches, tp-reduced, tp->matches);
#endif /* DEBUG */

		continue;
	    }

	    /* attempt the merge */
	    if (merge_ranges(tp->matches, sp->matches, sp->nmatches))
	    {		 
#ifdef DEBUG
		struct sorthash_t	*rp;

		printf("*** Merged %d into %d\n", tp-reduced, sp-reduced);
		for (rp=sp->matches; rp < sp->matches+sp->nmatches; rp++)
		    printf("%s:%d:%d\n",rp->file->name,rp->hash.start,rp->hash.end);
#endif /* DEBUG */
		removed++;
		sp->nmatches = 0;
	    }
	}
    }

#ifdef DEBUG
    for (sp = reduced; sp < reduced + nonuniques; sp++)
    {
	struct sorthash_t	*rp;

	printf("Clique beginning at %d (%d):\n", sp - reduced, sp->nmatches);
	for (rp = sp->matches; rp < sp->matches + sp->nmatches; rp++)
	    printf("%s:%d:%d\n",  rp->file->name, rp->hash.start, rp->hash.end);
    }
#endif /* DEBUG */

    return(nonuniques - removed);
}