Exemple #1
0
HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
{
  try
  {
    r->OpenResult=0;
    DataSet *Data=new DataSet;
    Data->Cmd.DllError=0;
    Data->OpenMode=r->OpenMode;
    Data->Cmd.FileArgs->AddString("*");

    char an[NM];
    if (r->ArcName==NULL && r->ArcNameW!=NULL)
    {
      WideToChar(r->ArcNameW,an,NM);
      r->ArcName=an;
    }

    Data->Cmd.AddArcName(r->ArcName,r->ArcNameW);
    Data->Cmd.Overwrite=OVERWRITE_ALL;
    Data->Cmd.VersionControl=1;

    Data->Cmd.Callback=r->Callback;
    Data->Cmd.UserData=r->UserData;

    if (!Data->Arc.Open(r->ArcName,r->ArcNameW))
    {
      r->OpenResult=ERAR_EOPEN;
      delete Data;
      return(NULL);
    }
    if (!Data->Arc.IsArchive(false))
    {
      r->OpenResult=Data->Cmd.DllError!=0 ? Data->Cmd.DllError:ERAR_BAD_ARCHIVE;
      delete Data;
      return(NULL);
    }
    r->Flags=Data->Arc.NewMhd.Flags;
    Array<byte> CmtData;
    if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtData,NULL))
    {
      r->Flags|=2;
      size_t Size=CmtData.Size()+1;
      r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
      r->CmtSize=(uint)Min(Size,r->CmtBufSize);
      memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1);
      if (Size<=r->CmtBufSize)
        r->CmtBuf[r->CmtSize-1]=0;
    }
    else
      r->CmtState=r->CmtSize=0;
    if (Data->Arc.Signed)
      r->Flags|=0x20;
    Data->Extract.ExtractArchiveInit(&Data->Cmd,Data->Arc);
    return((HANDLE)Data);
  }
  catch (int ErrCode)
  {
    r->OpenResult=RarErrorToDll(ErrCode);
    return(NULL);
  }
}
/*
 * Consider replacement of currently selected split with the better one.
 */
static inline void
g_box_consider_split(ConsiderSplitContext *context, int dimNum,
					 double rightLower, int minLeftCount,
					 double leftUpper, int maxLeftCount)
{
	int			leftCount,
				rightCount;
	float4		ratio,
				overlap;
	double		range;

	/*
	 * Calculate entries distribution ratio assuming most uniform distribution
	 * of common entries.
	 */
	if (minLeftCount >= (context->entriesCount + 1) / 2)
	{
		leftCount = minLeftCount;
	}
	else
	{
		if (maxLeftCount <= context->entriesCount / 2)
			leftCount = maxLeftCount;
		else
			leftCount = context->entriesCount / 2;
	}
	rightCount = context->entriesCount - leftCount;

	/*
	 * Ratio of split - quotient between size of lesser group and total
	 * entries count.
	 */
	ratio = ((float4) Min(leftCount, rightCount)) /
		((float4) context->entriesCount);

	if (ratio > LIMIT_RATIO)
	{
		bool		selectthis = false;

		/*
		 * The ratio is acceptable, so compare current split with previously
		 * selected one. Between splits of one dimension we search for minimal
		 * overlap (allowing negative values) and minimal ration (between same
		 * overlaps. We switch dimension if find less overlap (non-negative)
		 * or less range with same overlap.
		 */
		if (dimNum == 0)
			range = context->boundingBox.high.x - context->boundingBox.low.x;
		else
			range = context->boundingBox.high.y - context->boundingBox.low.y;

		overlap = (leftUpper - rightLower) / range;

		/* If there is no previous selection, select this */
		if (context->first)
			selectthis = true;
		else if (context->dim == dimNum)
		{
			/*
			 * Within the same dimension, choose the new___ split if it has a
			 * smaller overlap, or same overlap but better ratio.
			 */
			if (overlap < context->overlap ||
				(overlap == context->overlap && ratio > context->ratio))
				selectthis = true;
		}
		else
		{
			/*
			 * Across dimensions, choose the new___ split if it has a smaller
			 * *non-negative* overlap, or same *non-negative* overlap but
			 * bigger range. This condition differs from the one described in
			 * the article. On the datasets where leaf MBRs don't overlap
			 * themselves, non-overlapping splits (i.e. splits which have zero
			 * *non-negative* overlap) are frequently possible. In this case
			 * splits tends to be along one dimension, because most distant
			 * non-overlapping splits (i.e. having lowest negative overlap)
			 * appears to be in the same dimension as in the previous split.
			 * Therefore MBRs appear to be very prolonged along another
			 * dimension, which leads to bad search performance. Using range
			 * as the second split criteria makes MBRs more quadratic. Using
			 * *non-negative* overlap instead of overlap as the first split
			 * criteria gives to range criteria a chance to matter, because
			 * non-overlapping splits are equivalent in this criteria.
			 */
			if (non_negative(overlap) < non_negative(context->overlap) ||
				(range > context->range &&
				 non_negative(overlap) <= non_negative(context->overlap)))
				selectthis = true;
		}

		if (selectthis)
		{
			/* save information about selected split */
			context->first = false;
			context->ratio = ratio;
			context->range = range;
			context->overlap = overlap;
			context->rightLower = rightLower;
			context->leftUpper = leftUpper;
			context->dim = dimNum;
		}
	}
}
double Min(double x, double y, double z){
	return Min(Min(x,y),z);
}
Exemple #4
0
/*
 *	compute_tsvector_stats() -- compute statistics for a tsvector column
 *
 *	This functions computes statistics that are useful for determining @@
 *	operations' selectivity, along with the fraction of non-null rows and
 *	average width.
 *
 *	Instead of finding the most common values, as we do for most datatypes,
 *	we're looking for the most common lexemes. This is more useful, because
 *	there most probably won't be any two rows with the same tsvector and thus
 *	the notion of a MCV is a bit bogus with this datatype. With a list of the
 *	most common lexemes we can do a better job at figuring out @@ selectivity.
 *
 *	For the same reasons we assume that tsvector columns are unique when
 *	determining the number of distinct values.
 *
 *	The algorithm used is Lossy Counting, as proposed in the paper "Approximate
 *	frequency counts over data streams" by G. S. Manku and R. Motwani, in
 *	Proceedings of the 28th International Conference on Very Large Data Bases,
 *	Hong Kong, China, August 2002, section 4.2. The paper is available at
 *	http://www.vldb.org/conf/2002/S10P03.pdf
 *
 *	The Lossy Counting (aka LC) algorithm goes like this:
 *	Let s be the threshold frequency for an item (the minimum frequency we
 *	are interested in) and epsilon the error margin for the frequency. Let D
 *	be a set of triples (e, f, delta), where e is an element value, f is that
 *	element's frequency (actually, its current occurrence count) and delta is
 *	the maximum error in f. We start with D empty and process the elements in
 *	batches of size w. (The batch size is also known as "bucket size" and is
 *	equal to 1/epsilon.) Let the current batch number be b_current, starting
 *	with 1. For each element e we either increment its f count, if it's
 *	already in D, or insert a new triple into D with values (e, 1, b_current
 *	- 1). After processing each batch we prune D, by removing from it all
 *	elements with f + delta <= b_current.  After the algorithm finishes we
 *	suppress all elements from D that do not satisfy f >= (s - epsilon) * N,
 *	where N is the total number of elements in the input.  We emit the
 *	remaining elements with estimated frequency f/N.  The LC paper proves
 *	that this algorithm finds all elements with true frequency at least s,
 *	and that no frequency is overestimated or is underestimated by more than
 *	epsilon.  Furthermore, given reasonable assumptions about the input
 *	distribution, the required table size is no more than about 7 times w.
 *
 *	We set s to be the estimated frequency of the K'th word in a natural
 *	language's frequency table, where K is the target number of entries in
 *	the MCELEM array plus an arbitrary constant, meant to reflect the fact
 *	that the most common words in any language would usually be stopwords
 *	so we will not actually see them in the input.	We assume that the
 *	distribution of word frequencies (including the stopwords) follows Zipf's
 *	law with an exponent of 1.
 *
 *	Assuming Zipfian distribution, the frequency of the K'th word is equal
 *	to 1/(K * H(W)) where H(n) is 1/2 + 1/3 + ... + 1/n and W is the number of
 *	words in the language.	Putting W as one million, we get roughly 0.07/K.
 *	Assuming top 10 words are stopwords gives s = 0.07/(K + 10).  We set
 *	epsilon = s/10, which gives bucket width w = (K + 10)/0.007 and
 *	maximum expected hashtable size of about 1000 * (K + 10).
 *
 *	Note: in the above discussion, s, epsilon, and f/N are in terms of a
 *	lexeme's frequency as a fraction of all lexemes seen in the input.
 *	However, what we actually want to store in the finished pg_statistic
 *	entry is each lexeme's frequency as a fraction of all rows that it occurs
 *	in.  Assuming that the input tsvectors are correctly constructed, no
 *	lexeme occurs more than once per tsvector, so the final count f is a
 *	correct estimate of the number of input tsvectors it occurs in, and we
 *	need only change the divisor from N to nonnull_cnt to get the number we
 *	want.
 */
static void
compute_tsvector_stats(VacAttrStats *stats,
					   AnalyzeAttrFetchFunc fetchfunc,
					   int samplerows,
					   double totalrows)
{
	int			num_mcelem;
	int			null_cnt = 0;
	double		total_width = 0;

	/* This is D from the LC algorithm. */
	HTAB	   *lexemes_tab;
	HASHCTL		hash_ctl;
	HASH_SEQ_STATUS scan_status;

	/* This is the current bucket number from the LC algorithm */
	int			b_current;

	/* This is 'w' from the LC algorithm */
	int			bucket_width;
	int			vector_no,
				lexeme_no;
	LexemeHashKey hash_key;
	TrackItem  *item;

	/*
	 * We want statistics_target * 10 lexemes in the MCELEM array.	This
	 * multiplier is pretty arbitrary, but is meant to reflect the fact that
	 * the number of individual lexeme values tracked in pg_statistic ought to
	 * be more than the number of values for a simple scalar column.
	 */
	num_mcelem = stats->attr->attstattarget * 10;

	/*
	 * We set bucket width equal to (num_mcelem + 10) / 0.007 as per the
	 * comment above.
	 */
	bucket_width = (num_mcelem + 10) * 1000 / 7;

	/*
	 * Create the hashtable. It will be in local memory, so we don't need to
	 * worry about overflowing the initial size. Also we don't need to pay any
	 * attention to locking and memory management.
	 */
	MemSet(&hash_ctl, 0, sizeof(hash_ctl));
	hash_ctl.keysize = sizeof(LexemeHashKey);
	hash_ctl.entrysize = sizeof(TrackItem);
	hash_ctl.hash = lexeme_hash;
	hash_ctl.match = lexeme_match;
	hash_ctl.hcxt = CurrentMemoryContext;
	lexemes_tab = hash_create("Analyzed lexemes table",
							  bucket_width * 7,
							  &hash_ctl,
					HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT);

	/* Initialize counters. */
	b_current = 1;
	lexeme_no = 0;

	/* Loop over the tsvectors. */
	for (vector_no = 0; vector_no < samplerows; vector_no++)
	{
		Datum		value;
		bool		isnull;
		TSVector	vector;
		WordEntry  *curentryptr;
		char	   *lexemesptr;
		int			j;

		vacuum_delay_point();

		value = fetchfunc(stats, vector_no, &isnull);

		/*
		 * Check for null/nonnull.
		 */
		if (isnull)
		{
			null_cnt++;
			continue;
		}

		/*
		 * Add up widths for average-width calculation.  Since it's a
		 * tsvector, we know it's varlena.  As in the regular
		 * compute_minimal_stats function, we use the toasted width for this
		 * calculation.
		 */
		total_width += VARSIZE_ANY(DatumGetPointer(value));

		/*
		 * Now detoast the tsvector if needed.
		 */
		vector = DatumGetTSVector(value);

		/*
		 * We loop through the lexemes in the tsvector and add them to our
		 * tracking hashtable.	Note: the hashtable entries will point into
		 * the (detoasted) tsvector value, therefore we cannot free that
		 * storage until we're done.
		 */
		lexemesptr = STRPTR(vector);
		curentryptr = ARRPTR(vector);
		for (j = 0; j < vector->size; j++)
		{
			bool		found;

			/* Construct a hash key */
			hash_key.lexeme = lexemesptr + curentryptr->pos;
			hash_key.length = curentryptr->len;

			/* Lookup current lexeme in hashtable, adding it if new */
			item = (TrackItem *) hash_search(lexemes_tab,
											 (const void *) &hash_key,
											 HASH_ENTER, &found);

			if (found)
			{
				/* The lexeme is already on the tracking list */
				item->frequency++;
			}
			else
			{
				/* Initialize new tracking list element */
				item->frequency = 1;
				item->delta = b_current - 1;
			}

			/* lexeme_no is the number of elements processed (ie N) */
			lexeme_no++;

			/* We prune the D structure after processing each bucket */
			if (lexeme_no % bucket_width == 0)
			{
				prune_lexemes_hashtable(lexemes_tab, b_current);
				b_current++;
			}

			/* Advance to the next WordEntry in the tsvector */
			curentryptr++;
		}
	}

	/* We can only compute real stats if we found some non-null values. */
	if (null_cnt < samplerows)
	{
		int			nonnull_cnt = samplerows - null_cnt;
		int			i;
		TrackItem **sort_table;
		int			track_len;
		int			cutoff_freq;
		int			minfreq,
					maxfreq;

		stats->stats_valid = true;
		/* Do the simple null-frac and average width stats */
		stats->stanullfrac = (double) null_cnt / (double) samplerows;
		stats->stawidth = total_width / (double) nonnull_cnt;

		/* Assume it's a unique column (see notes above) */
		stats->stadistinct = -1.0;

		/*
		 * Construct an array of the interesting hashtable items, that is,
		 * those meeting the cutoff frequency (s - epsilon)*N.	Also identify
		 * the minimum and maximum frequencies among these items.
		 *
		 * Since epsilon = s/10 and bucket_width = 1/epsilon, the cutoff
		 * frequency is 9*N / bucket_width.
		 */
		cutoff_freq = 9 * lexeme_no / bucket_width;

		i = hash_get_num_entries(lexemes_tab);	/* surely enough space */
		sort_table = (TrackItem **) palloc(sizeof(TrackItem *) * i);

		hash_seq_init(&scan_status, lexemes_tab);
		track_len = 0;
		minfreq = lexeme_no;
		maxfreq = 0;
		while ((item = (TrackItem *) hash_seq_search(&scan_status)) != NULL)
		{
			if (item->frequency > cutoff_freq)
			{
				sort_table[track_len++] = item;
				minfreq = Min(minfreq, item->frequency);
				maxfreq = Max(maxfreq, item->frequency);
			}
		}
		Assert(track_len <= i);

		/* emit some statistics for debug purposes */
		elog(DEBUG3, "tsvector_stats: target # mces = %d, bucket width = %d, "
			 "# lexemes = %d, hashtable size = %d, usable entries = %d",
			 num_mcelem, bucket_width, lexeme_no, i, track_len);

		/*
		 * If we obtained more lexemes than we really want, get rid of those
		 * with least frequencies.	The easiest way is to qsort the array into
		 * descending frequency order and truncate the array.
		 */
		if (num_mcelem < track_len)
		{
			qsort(sort_table, track_len, sizeof(TrackItem *),
				  trackitem_compare_frequencies_desc);
			/* reset minfreq to the smallest frequency we're keeping */
			minfreq = sort_table[num_mcelem - 1]->frequency;
		}
		else
			num_mcelem = track_len;

		/* Generate MCELEM slot entry */
		if (num_mcelem > 0)
		{
			MemoryContext old_context;
			Datum	   *mcelem_values;
			float4	   *mcelem_freqs;

			/*
			 * We want to store statistics sorted on the lexeme value using
			 * first length, then byte-for-byte comparison. The reason for
			 * doing length comparison first is that we don't care about the
			 * ordering so long as it's consistent, and comparing lengths
			 * first gives us a chance to avoid a strncmp() call.
			 *
			 * This is different from what we do with scalar statistics --
			 * they get sorted on frequencies. The rationale is that we
			 * usually search through most common elements looking for a
			 * specific value, so we can grab its frequency.  When values are
			 * presorted we can employ binary search for that.	See
			 * ts_selfuncs.c for a real usage scenario.
			 */
			qsort(sort_table, num_mcelem, sizeof(TrackItem *),
				  trackitem_compare_lexemes);

			/* Must copy the target values into anl_context */
			old_context = MemoryContextSwitchTo(stats->anl_context);

			/*
			 * We sorted statistics on the lexeme value, but we want to be
			 * able to find out the minimal and maximal frequency without
			 * going through all the values.  We keep those two extra
			 * frequencies in two extra cells in mcelem_freqs.
			 */
			mcelem_values = (Datum *) palloc(num_mcelem * sizeof(Datum));
			mcelem_freqs = (float4 *) palloc((num_mcelem + 2) * sizeof(float4));

			/*
			 * See comments above about use of nonnull_cnt as the divisor for
			 * the final frequency estimates.
			 */
			for (i = 0; i < num_mcelem; i++)
			{
				TrackItem  *item = sort_table[i];

				mcelem_values[i] =
					PointerGetDatum(cstring_to_text_with_len(item->key.lexeme,
														  item->key.length));
				mcelem_freqs[i] = (double) item->frequency / (double) nonnull_cnt;
			}
			mcelem_freqs[i++] = (double) minfreq / (double) nonnull_cnt;
			mcelem_freqs[i] = (double) maxfreq / (double) nonnull_cnt;
			MemoryContextSwitchTo(old_context);

			stats->stakind[0] = STATISTIC_KIND_MCELEM;
			stats->staop[0] = TextEqualOperator;
			stats->stanumbers[0] = mcelem_freqs;
			/* See above comment about two extra frequency fields */
			stats->numnumbers[0] = num_mcelem + 2;
			stats->stavalues[0] = mcelem_values;
			stats->numvalues[0] = num_mcelem;
			/* We are storing text values */
			stats->statypid[0] = TEXTOID;
			stats->statyplen[0] = -1;	/* typlen, -1 for varlena */
			stats->statypbyval[0] = false;
			stats->statypalign[0] = 'i';
		}
	}
	else
	{
		/* We found only nulls; assume the column is entirely null */
		stats->stats_valid = true;
		stats->stanullfrac = 1.0;
		stats->stawidth = 0;	/* "unknown" */
		stats->stadistinct = 0.0;		/* "unknown" */
	}

	/*
	 * We don't need to bother cleaning up any of our temporary palloc's. The
	 * hashtable should also go away, as it used a child memory context.
	 */
}
void sim_update(Simulator* sim, Tilemap* map, real dt)
{
	Sim_Body *a, *b;
	for(isize times = 0; times < Sim_Iter_i; ++times) {
//#if 0
		if(sim->sort_axis == 0) {
			body_sort_on_x(sim->bodies, sim->bodies_count);
		} else if(sim->sort_axis == 1) {
			body_sort_on_y(sim->bodies, sim->bodies_count);
		}

//#endif 
		Vec2 center_sum1 = v2(0, 0);
		Vec2 center_sum2 = v2(0, 0);
		Vec2 variance = v2(0, 0);
		for(isize i = 0; i < sim->bodies_count; ++i) {
			a = sim->bodies + i;

			//sweep and prune stuff
			center_sum1 += a->shape.center;
			for(isize q = 0; q < 2; ++q) {
				center_sum2.e[q] += a->shape.center.e[q] * a->shape.center.e[q];
			}

			//if(a->is_static) continue;

			for(isize j = i + 1; j < sim->bodies_count; ++j) {
				b = sim->bodies + j;

				uint64 a_is_static = Has_Flag(a->flags, Body_Flag_Static);
				uint64 b_is_static = Has_Flag(b->flags, Body_Flag_Static);
				if(a_is_static && b_is_static) continue;

//#if 0
				if(sim->sort_axis == 0) {
					if(AABB_x1(b->shape) > AABB_x2(a->shape)) {
						break;
					}
				} else if(sim->sort_axis == 1) {
					if(AABB_y1(b->shape) > AABB_y2(a->shape)) {
						break;
					}
				}
//#endif 
			
				if(aabb_intersect(&a->shape, &b->shape)) {
					Vec2 overlap;
					aabb_overlap(&a->shape, &b->shape, &overlap);
					real ovl_mag = sqrtf(v2_dot(overlap, overlap));
					if (ovl_mag < 0.0001f) continue;
					Vec2 normal = overlap * (1.0f / ovl_mag);

					if(a->id == 0 || b->id  == 0) {
						aabb_intersect(&a->shape, &b->shape);
					}
					

					#define _collision_slop (0.8f)
					if(a_is_static && !b_is_static) {
						b->shape.center += overlap;
						Vec2 relative_velocity = b->velocity;
						real velocity_on_normal = v2_dot(relative_velocity, normal);
						if(velocity_on_normal > 0) continue;

						real e = Min(a->restitution, b->restitution);
						real mag = -1.0f * (1.0f + e) * velocity_on_normal;
						mag /= b->inv_mass;
						Vec2 impulse = mag * normal;
						b->collision_vel += b->inv_mass * impulse;
					} else if(!a_is_static && b_is_static) {
						a->shape.center -= overlap;

						Vec2 relative_velocity = -a->velocity;
						real velocity_on_normal = v2_dot(relative_velocity, normal);
						if(velocity_on_normal > 0) continue;

						real e = Min(a->restitution, b->restitution);
						real mag = -1.0f * (1.0f + e) * velocity_on_normal;
						mag /= a->inv_mass + 0;
						Vec2 impulse = mag * normal;
						a->collision_vel -= a->inv_mass * impulse;
					} else {
						Vec2 separation = Max(ovl_mag - _collision_slop, 0) 
							* (1.0f / (a->inv_mass + b->inv_mass)) * 0.5f * normal;
						a->shape.center -= a->inv_mass * separation;
						b->shape.center += b->inv_mass * separation;

						Vec2 relative_velocity = b->velocity - a->velocity;
						real velocity_on_normal = v2_dot(relative_velocity, normal);
						if(velocity_on_normal > 0) continue;

						real e = Min(a->restitution, b->restitution);
						real mag = -1.0f * (1.0f + e) * velocity_on_normal;
						mag /= a->inv_mass + b->inv_mass;
						Vec2 impulse = mag * normal;
						a->collision_vel -= a->inv_mass * impulse;
						b->collision_vel += b->inv_mass * impulse;
					}
				}
			}
		}

		for(isize i = 0; i < 2; ++i) {
			variance.e[i] = center_sum2.e[i] - center_sum1.e[i] * center_sum1.e[i] / 
				sim->bodies_count;
		}
		
		if(variance.x > variance.y) {
			sim->sort_axis = 0;
		} else {
			sim->sort_axis = 1;
		}

		for(isize i = 0; i < sim->bodies_count; ++i) {
			a = sim->bodies + i;
			if(Has_Flag(a->flags, Body_Flag_Static)) continue;
			Vec2 iter_acl = (a->force * a->inv_mass) / Sim_Iter;
			Vec2 new_vel = a->velocity + (dt * iter_acl);
			Vec2 dpos = (a->velocity + new_vel) * 0.5f;
			dpos *= 1.0f / Sim_Iter;
			a->shape.center += dpos * dt;
			a->shape.center += a->collision_vel / Sim_Iter * dt;
			a->velocity = new_vel;
			Tile_Info* tile = map->info + tilemap_get_at(map, a->shape.center);
			real damping = 1.0f;
			if(Has_Flag(a->flags, Body_Flag_No_Friction)) {
				damping = a->damping;
			} else {
				damping = sqrtf(a->damping * a->damping + 
					tile->friction * tile->friction) * Math_InvSqrt2;
			}
			a->velocity *= powf(damping, Sim_Iter);
			a->velocity += a->collision_vel;
			a->collision_vel = v2(0, 0);
		}

	}
	body_sort_on_id(sim->bodies, sim->bodies_count);
}
Exemple #6
0
void CastRelation()
{
    char ignoreT[objMax];
    int i, saveRev;
    real ratio, t1, t2, t;
    real ppowerT[oNormOpt+1];
    /* Cast the first chart. */

    ciMain = ciCore;
    if (us.fRelocation && us.nRel == rcComposite) {
        OO=us.lonDef;
        AA=us.latDef ;
        NN=us.altDef;
    }
    t1 = CastChart(fTrue);
    cp1 = cp0;
    saveRev = hRevers;
    if (us.nRel == rcTransit || us.nRel == rcProgress)
        for (i = 1; i <= cObjOpt; i++) {
            cp1.dir[i] = 0.0;
            if (i > oNormOpt)
                continue;
            cp1.altdir[i] = 0.0;
        }

#ifdef GRAPH              /* Struct GS is defined with graphics.  */
    if (!gs.nAnim) {
#endif
        if (!FCreateGrid(fFalse))
            return;
        PlanetPPower();
#ifdef GRAPH
    }
#endif

    /* Cast the second chart. */

    ciCore = ciTwin;
    if (us.nRel == rcTransit) {
        for (i = 0; i <= cObjOpt; i++) {
            ignoreT[i] = ignore[i];
            if (us.fSector || us.fAstroGraph)
                ignore[i] = ignore[i] && ignore2[i];
            else
                ignore[i] = ignore2[i];
        }
    } else if (us.nRel == rcProgress) {
        us.fProgress = fTrue;
        is.JDp = MdytszToJulian(MM, DD, YY, TT, SS, ZZ)-rRound;
        ciCore = ciMain;
        for (i = 0; i <= cObjOpt; i++) {
            ignoreT[i] = ignore[i];
            if (us.fSector || us.fAstroGraph)
                ignore[i] = ignore[i] && ignore3[i];
            else
                ignore[i] = ignore3[i];
        }
    }
    if (us.fRelocation && us.nRel == rcComposite) {
        OO=us.lonDef;
        AA=us.latDef ;
        NN=us.altDef;
    }

    t2 = CastChart(fTrue);
    if (us.nRel == rcTransit) {
        for (i = 0; i <= cObjOpt; i++) {
            ignore2[i] = ignore[i];
            ignore[i] = ignoreT[i];
        }
    } else if (us.nRel == rcProgress) {
        us.fProgress = fFalse;
        for (i = 0; i <= cObjOpt; i++) {
            ignore3[i] = ignore[i];
            ignore[i] = ignoreT[i];
        }
    }
    cp2 = cp0;

    if (us.nRel == rcDual) {
        if (!FCreateGrid(fFalse))
            return;
        for (i = 0; i <= oNormOpt; i++)
            ppowerT[i] = ppower1[i];
        PlanetPPower();
        for (i = 0; i <= oNormOpt; i++) {
            ppower2[i] = ppower1[i];
            ppower1[i] = ppowerT[i];
        }
    }

    hRevers = saveRev;
    ciCore = ciMain;

    /* Now combine the two charts based on what relation we are doing.   */
    /* For the standard -r synastry chart, use the house cusps of chart1 */
    /* and the planets positions of chart2.                              */

    ratio = (real)us.nRatio1 / ((real)(us.nRatio1 + us.nRatio2));
    if (us.nRel <= rcSynastry) {
        for (i = 1; i <= cSign; i++)
            chouse[i] = cp1.cusp[i];

        /* For the -rc composite chart, take the midpoints of the planets/houses. */

    } else if (us.nRel == rcComposite) {
        if (fProgressRatio) {
            ratio=(MdytszToJulian(ciThre.mon,ciThre.day,ciThre.yea,ciThre.tim,ciThre.dst,ciThre.zon)-
                   Min(MdytszToJulian(Mon, Day, Yea, Tim, Dst, Zon),
                       MdytszToJulian(ciTwin.mon,ciTwin.day,ciTwin.yea,ciTwin.tim,ciTwin.dst,ciTwin.zon)))/
                  RAbs(MdytszToJulian(Mon, Day, Yea, Tim, Dst, Zon)-
                       MdytszToJulian(ciTwin.mon,ciTwin.day,ciTwin.yea,ciTwin.tim,ciTwin.dst,ciTwin.zon));
        }
        for (i = 0; i <= cObjOpt; i++) {
            planet[i] = Ratio(cp1.obj[i], cp2.obj[i], ratio);
            if (RAbs(cp2.obj[i] - cp1.obj[i]) > rDegHalf)
                planet[i] = Mod(planet[i] + rDegMax*ratio);
            planetalt[i] = Ratio(cp1.alt[i], cp2.alt[i], ratio);
            ret[i] = Ratio(cp1.dir[i], cp2.dir[i], ratio);
            altret[i] = Ratio(cp1.altdir[i], cp2.altdir[i], ratio);
            planetdis[i] = Ratio(cp1.dis[i], cp2.dis[i], ratio);
            disret[i] = Ratio(cp1.disdir[i], cp2.disdir[i], ratio);
        }
        for (i = 1; i <= cSign; i++) {
            chouse[i] = Ratio(cp1.cusp[i], cp2.cusp[i], ratio);
            if (RAbs(cp2.cusp[i] - cp1.cusp[i]) > rDegHalf)
                chouse[i] = Mod(chouse[i] + rDegMax*ratio);
        }

        /* Make sure we don't have any 180 degree errors in house cusp    */
        /* complement pairs, which may happen if the cusps are far apart. */

        for (i = 1; i <= cSign; i++)
            if (MinDistance(chouse[sCap], Mod(chouse[i]-ZFromS(i+3))) > rDegQuad)
                chouse[i] = Mod(chouse[i]+rDegHalf);
        for (i = 1; i <= cSign; i++)
            if (RAbs(MinDistance(chouse[i], planet[oAsc - 1 + i])) > rDegQuad)
                planet[oAsc - 1 + i] = Mod(planet[oAsc - 1 + i]+rDegHalf);

        ciMain.loc="";
        if (!us.fGraphics)
            ciMain.nam=strdup(strcat(strcat(ciMain.nam," and "),ciTwin.nam));

        /* For the -rm time space midpoint chart, calculate the midpoint time and */
        /* place between the two charts and then recast for the new chart info.   */

    } else if (us.nRel == rcMidpoint) {
        if (!is.fDavison) {
            is.T = Ratio(t1, t2, ratio);
            t = (is.T*36525.0)+rRound;
            is.JD = RFloor(t)+2415020.0;
            TT = RFract(t)*24.0;
            /*  ZZ = Ratio(DecToDeg(Zon), DecToDeg(ciTwin.zon), ratio);
              SS = Ratio(DecToDeg(Dst), DecToDeg(ciTwin.dst), ratio);
              TT -= ZZ - SS;
              if (TT < 0.0) {
                TT += 24.0; is.JD -= 1.0;
              }
              if (TT >= 24.0) {
                TT -= 24.0; is.JD += 1.0;
              }*/
            JulianToMdy(is.JD, &MM, &DD, &YY);
            OO = Ratio(DecToDeg(Lon), DecToDeg(ciTwin.lon), ratio);
            if (RAbs(ciTwin.lon-Lon) > rDegHalf)
                OO = Mod(OO+rDegMax*ratio);
            AA = Ratio(DecToDeg(Lat), DecToDeg(ciTwin.lat), ratio);
            NN = Ratio(DecToDeg(Alt), DecToDeg(ciTwin.alt), ratio);
            TT = DegToDec(TT);
            SS=ZZ=0.0; /*SS = DegToDec(SS); ZZ = DegToDec(ZZ);*/
            OO = DegToDec(OO);
            AA = DegToDec(AA);
            ciCore.loc="";
            if (!us.fGraphics)
                ciCore.nam=strdup(strcat(strcat(ciMain.nam," and "),ciTwin.nam));
            ciMain = ciCore;
        }
        else is.T=t1;
        CastChart(fFalse);
        is.fDavison=fTrue;
        /* There are a couple of non-astrological charts, which only require the */
        /* number of days that have passed between the two charts to be done.    */

    } else
        is.JD = RAbs(t2-t1)*36525.0;
    ComputeInHouses();
}
	Vec2 Min( const Vec2 &A, const Vec2 &B )
	{
		return Vec2( Min( A.X(), B.X() ), Min( A.Y(), B.Y() ) );
	}
/*
========================
idSnapShot::ReadDeltaForJob
========================
*/
bool idSnapShot::ReadDeltaForJob( const char* deltaMem, int deltaSize, int visIndex, idSnapShot* templateStates )
{

	bool report = net_verboseSnapshotReport.GetBool();
	net_verboseSnapshotReport.SetBool( false );
	
	lzwCompressionData_t		lzwData;
	idZeroRunLengthCompressor	rleCompressor;
	idLZWCompressor				lzwCompressor( &lzwData );
	int bytesRead = 0; // how many uncompressed bytes we read in. Used to figure out compression ratio
	
	lzwCompressor.Start( ( uint8* )deltaMem, deltaSize );
	
	// Skip past sequence and baseSequence
	int sequence		= 0;
	int baseSequence	= 0;
	
	lzwCompressor.ReadAgnostic( sequence );
	lzwCompressor.ReadAgnostic( baseSequence );
	lzwCompressor.ReadAgnostic( time );
	bytesRead += sizeof( int ) * 3;
	
	int objectNum = 0;
	uint16 delta = 0;
	
	
	while( lzwCompressor.ReadAgnostic( delta, true ) == sizeof( delta ) )
	{
		bytesRead += sizeof( delta );
		
		objectNum += delta;
		if( objectNum >= 0xFFFF )
		{
			// full delta
			if( net_verboseSnapshotCompression.GetBool() )
			{
				float compRatio = static_cast<float>( deltaSize ) / static_cast<float>( bytesRead );
				idLib::Printf( "Snapshot (%d/%d). ReadSize: %d DeltaSize: %d Ratio: %.3f\n", sequence, baseSequence, bytesRead, deltaSize, compRatio );
			}
			return true;
		}
		
		objectState_t& state = FindOrCreateObjectByID( objectNum );
		
		objectSize_t newsize = 0;
		lzwCompressor.ReadAgnostic( newsize );
		bytesRead += sizeof( newsize );
		
		if( newsize == SIZE_STALE )
		{
			NET_VERBOSESNAPSHOT_PRINT( "read delta: object %d goes stale\n", objectNum );
			// sanity
			bool oldVisible = ( state.visMask & ( 1 << visIndex ) ) != 0;
			if( !oldVisible )
			{
				NET_VERBOSESNAPSHOT_PRINT( "ERROR: unexpected already stale\n" );
			}
			state.visMask &= ~( 1 << visIndex );
			state.stale = true;
			// We need to make sure we haven't freed stale objects.
			assert( state.buffer.Size() > 0 );
			// no more data
			continue;
		}
		else if( newsize == SIZE_NOT_STALE )
		{
			NET_VERBOSESNAPSHOT_PRINT( "read delta: object %d no longer stale\n", objectNum );
			// sanity
			bool oldVisible = ( state.visMask & ( 1 << visIndex ) ) != 0;
			if( oldVisible )
			{
				NET_VERBOSESNAPSHOT_PRINT( "ERROR: unexpected not stale\n" );
			}
			state.visMask |= ( 1 << visIndex );
			state.stale = false;
			// the latest state is packed in, get the new size and continue reading the new state
			lzwCompressor.ReadAgnostic( newsize );
			bytesRead += sizeof( newsize );
		}
		
		objectState_t* 	objTemplateState = templateStates->FindObjectByID( objectNum );
		
		if( newsize == 0 )
		{
			// object deleted: reset state now so next one to use it doesn't have old data
			state.deleted = false;
			state.stale = false;
			state.changedCount = 0;
			state.expectedSequence = 0;
			state.visMask = 0;
			state.buffer._Release();
			state.createdFromTemplate = false;
			
			if( objTemplateState != NULL && objTemplateState->buffer.Size() && objTemplateState->expectedSequence < baseSequence )
			{
				idLib::PrintfIf( net_ssTemplateDebug.GetBool(), "Clearing old template state[%d] [%d<%d]\n", objectNum, objTemplateState->expectedSequence, baseSequence );
				objTemplateState->deleted = false;
				objTemplateState->stale = false;
				objTemplateState->changedCount = 0;
				objTemplateState->expectedSequence = 0;
				objTemplateState->visMask = 0;
				objTemplateState->buffer._Release();
			}
			
		}
		else
		{
		
			// new state?
			bool debug = false;
			if( state.buffer.Size() == 0 )
			{
				state.createdFromTemplate = true;
				// Brand new state
				if( objTemplateState != NULL && objTemplateState->buffer.Size() > 0 && sequence >= objTemplateState->expectedSequence )
				{
					idLib::PrintfIf( net_ssTemplateDebug.GetBool(), "\nAdding basestate for new object %d (for SS %d/%d. obj base created in ss %d) deltaSize: %d\n", objectNum, sequence, baseSequence, objTemplateState->expectedSequence, deltaSize );
					state.buffer = objTemplateState->buffer;
					
					if( net_ssTemplateDebug.GetBool() )
					{
						state.Print( "SPAWN STATE" );
						debug = true;
						PrintAlign( "DELTA STATE" );
					}
				}
				else if( net_ssTemplateDebug.GetBool() )
				{
					idLib::Printf( "\nNew snapobject[%d] in snapshot %d/%d but no basestate found locally so creating new\n", objectNum, sequence, baseSequence );
				}
			}
			else
			{
				state.createdFromTemplate = false;
			}
			
			// the buffer shrank or stayed the same
			objectBuffer_t newbuffer( newsize );
			rleCompressor.Start( NULL, &lzwCompressor, newsize );
			objectSize_t compareSize = Min( state.buffer.Size(), newsize );
			for( objectSize_t i = 0; i < compareSize; i++ )
			{
				byte b = rleCompressor.ReadByte();
				newbuffer[i] = state.buffer[i] + b;
				
				if( debug && InDebugRange( i ) )
				{
					idLib::Printf( "%02X", b );
				}
			}
			// Catch leftover
			if( newsize > compareSize )
			{
				rleCompressor.ReadBytes( newbuffer.Ptr() + compareSize, newsize - compareSize );
				
				if( debug )
				{
					for( objectSize_t i = compareSize; i < newsize; i++ )
					{
						if( InDebugRange( i ) )
						{
							idLib::Printf( "%02X", newbuffer[i] );
						}
					}
				}
				
			}
			state.buffer = newbuffer;
			state.changedCount = sequence;
			bytesRead += sizeof( byte ) * newsize;
			if( debug )
			{
				idLib::Printf( "\n" );
				state.Print( "NEW STATE" );
			}
			
			if( report )
			{
				idLib::Printf( "    Obj %d Compressed: Size %d \n", objectNum, rleCompressor.CompressedSize() );
			}
		}
#ifdef SNAPSHOT_CHECKSUMS
		extern uint32 SnapObjChecksum( const uint8 * data, int length );
		if( state.buffer.Size() > 0 )
		{
			uint32 checksum = 0;
			lzwCompressor.ReadAgnostic( checksum );
			bytesRead += sizeof( checksum );
			if( !verify( checksum == SnapObjChecksum( state.buffer.Ptr(), state.buffer.Size() ) ) )
			{
				idLib::Error( " Invalid snapshot checksum" );
			}
		}
#endif
	}
	// partial delta
	return false;
}
/*
========================
idSnapShot::ReadDelta
========================
*/
bool idSnapShot::ReadDelta( idFile* file, int visIndex )
{

	file->ReadBig( time );
	
	int objectNum = 0;
	uint16 delta = 0;
	while( file->ReadBig( delta ) == sizeof( delta ) )
	{
		objectNum += delta;
		if( objectNum >= 0xFFFF )
		{
			// full delta
			return true;
		}
		objectState_t& state = FindOrCreateObjectByID( objectNum );
		objectSize_t newsize = 0;
		file->ReadBig( newsize );
		
		if( newsize == SIZE_STALE )
		{
			NET_VERBOSESNAPSHOT_PRINT( "read delta: object %d goes stale\n", objectNum );
			// sanity
			bool oldVisible = ( state.visMask & ( 1 << visIndex ) ) != 0;
			if( !oldVisible )
			{
				NET_VERBOSESNAPSHOT_PRINT( "ERROR: unexpected already stale\n" );
			}
			state.visMask &= ~( 1 << visIndex );
			state.stale = true;
			// We need to make sure we haven't freed stale objects.
			assert( state.buffer.Size() > 0 );
			// no more data
			continue;
		}
		else if( newsize == SIZE_NOT_STALE )
		{
			NET_VERBOSESNAPSHOT_PRINT( "read delta: object %d no longer stale\n", objectNum );
			// sanity
			bool oldVisible = ( state.visMask & ( 1 << visIndex ) ) != 0;
			if( oldVisible )
			{
				NET_VERBOSESNAPSHOT_PRINT( "ERROR: unexpected not stale\n" );
			}
			state.visMask |= ( 1 << visIndex );
			state.stale = false;
			// the latest state is packed in, get the new size and continue reading the new state
			file->ReadBig( newsize );
		}
		
		if( newsize == 0 )
		{
			// object deleted
			state.buffer._Release();
		}
		else
		{
			objectBuffer_t newbuffer( newsize );
			objectSize_t compareSize = Min( newsize, state.buffer.Size() );
			
			for( objectSize_t i = 0; i < compareSize; i++ )
			{
				uint8 delta = 0;
				file->ReadBig<byte>( delta );
				newbuffer[i] = state.buffer[i] + delta;
			}
			
			if( newsize > compareSize )
			{
				file->Read( newbuffer.Ptr() + compareSize, newsize - compareSize );
			}
			
			state.buffer = newbuffer;
			state.changedCount++;
		}
		
#ifdef SNAPSHOT_CHECKSUMS
		if( state.buffer.Size() > 0 )
		{
			unsigned int checksum = 0;
			file->ReadBig( checksum );
			assert( checksum == MD5_BlockChecksum( state.buffer.Ptr(), state.buffer.Size() ) );
		}
#endif
	}
	
	// partial delta
	return false;
}
Exemple #10
0
/////////////////////////////////////////////////////////////////////////////
// Change lane value to reach a given radius
/////////////////////////////////////////////////////////////////////////////
void K1999::AdjustRadius(int prev, int i, int next, double TargetRInverse, double Security)
{
	double OldLane = tLane[i];

	double Width = Mag((txLeft[i]-txRight[i]),(tyLeft[i]-tyRight[i]));

	//
	// Start by aligning points for a reasonable initial lane
	//
	tLane[i] = (-(ty[next] - ty[prev]) * (txLeft[i] - tx[prev]) +
			(tx[next] - tx[prev]) * (tyLeft[i] - ty[prev])) /
			( (ty[next] - ty[prev]) * (txRight[i] - txLeft[i]) -
			(tx[next] - tx[prev]) * (tyRight[i] - tyLeft[i]));

	// the original algorithm allows going outside the track
	/*
	if (tLane[i] < -0.2)
		tLane[i] = -0.2;
	else if (tLane[i] > 1.2)
		tLane[i] = 1.2;*/
	if (tLane[i] < 0.0)
		tLane[i] = 0.0;
	else if (tLane[i] > 1.0)
		tLane[i] = 1.0;

	UpdateTxTy(i);

	//
	// Newton-like resolution method
	//
	const double dLane = 0.0001;

	double dx = dLane * (txRight[i] - txLeft[i]);
	double dy = dLane * (tyRight[i] - tyLeft[i]);

	double dRInverse = GetRInverse(prev, tx[i] + dx, ty[i] + dy, next);

	if (dRInverse > 0.000000001)
	{
		tLane[i] += (dLane / dRInverse) * TargetRInverse;

		double ExtLane = (SideDistExt + Security) / Width;
		double IntLane = (SideDistInt + Security) / Width;
		if (ExtLane > 0.5)
			ExtLane = 0.5;
		if (IntLane > 0.5)
			IntLane = 0.5;

		if (TargetRInverse >= 0.0)
		{
			if (tLane[i] < IntLane)
				tLane[i] = IntLane;
			if (1 - tLane[i] < ExtLane)
			{
				if (1 - OldLane < ExtLane)
					tLane[i] = Min(OldLane, tLane[i]);
				else
					tLane[i] = 1 - ExtLane;
			}
		}
		else
		{
			if (tLane[i] < ExtLane)
			{
				if (OldLane < ExtLane)
					tLane[i] = Max(OldLane, tLane[i]);
				else
					tLane[i] = ExtLane;
			}
			if (1 - tLane[i] < IntLane)
				tLane[i] = 1 - IntLane;
		}
	}

	UpdateTxTy(i);
}
Exemple #11
0
inline T Clamp(const T x, const T xMin, const T xMax)
{
  return Max(xMin, Min(x, xMax));
}
Exemple #12
0
// Returns file path including the trailing path separator symbol.
void GetFilePath(const wchar *FullName,wchar *Path,int MaxLength)
{
  size_t PathLength=Min(MaxLength-1,PointToName(FullName)-FullName);
  strncpyw(Path,FullName,PathLength);
  Path[PathLength]=0;
}
Exemple #13
0
void CExtension::CreateIcon (int cxWidth, int cyHeight, CG32bitImage **retpIcon) const

//	CreateIcon
//
//	Creates a cover icon for the adventure. The caller is responsible for
//	freeing the result.

	{
	//	Load the image

	CG32bitImage *pBackground = GetCoverImage();
	if (pBackground == NULL || pBackground->GetWidth() == 0 || pBackground->GetHeight() == 0)
		{
		int cxSize = Min(cxWidth, cyHeight);
		*retpIcon = new CG32bitImage;
		(*retpIcon)->Create(cxSize, cxSize);
		return;
		}

	//	Figure out the dimensions of the icon based on the image size and the
	//	desired output.
	//
	//	If the background is larger than the icon size then we need to scale it.

	CG32bitImage *pIcon;
	if (pBackground->GetWidth() > cxWidth || pBackground->GetHeight() > cyHeight)
		{
		int xSrc, ySrc, cxSrc, cySrc;
		Metric rScale;

		//	If we have a widescreen cover image and we want a portrait or
		//	square icon, then we zoom in on the key part of the cover.

		if (pBackground->GetWidth() > 2 * pBackground->GetHeight())
			{
			rScale = (Metric)cyHeight / pBackground->GetHeight();

			cxSrc = (int)(cxWidth / rScale);
			xSrc = Min(pBackground->GetWidth() - cxSrc, pBackground->GetWidth() - (RIGHT_COVER_OFFSET + (cxSrc / 2)));

			ySrc = 0;
			cySrc = pBackground->GetHeight();
			}
		else
			{
			rScale = (Metric)cxWidth / pBackground->GetWidth();
			if (rScale * pBackground->GetHeight() > (Metric)cyHeight)
				rScale = (Metric)cyHeight / pBackground->GetHeight();

			xSrc = 0;
			ySrc = 0;
			cxSrc = pBackground->GetWidth();
			cySrc = pBackground->GetHeight();
			}

		//	Create the icon

		pIcon = new CG32bitImage;
		pIcon->CreateFromImageTransformed(*pBackground,
				xSrc,
				ySrc,
				cxSrc,
				cySrc,
				rScale,
				rScale,
				0.0);
		}

	//	Otherwise we center the image on the icon

	else
		{
		//	Create the icon

		pIcon = new CG32bitImage;
		pIcon->Create(cxWidth, cyHeight);

		//	Blt

		pIcon->Blt(0,
				0,
				pBackground->GetWidth(),
				pBackground->GetHeight(),
				*pBackground,
				(cxWidth - pBackground->GetWidth()) / 2,
				(cyHeight - pBackground->GetHeight()) / 2);
		}

	//	Done

	*retpIcon = pIcon;
	}
Exemple #14
0
int32 refc_find_ref_coors_convex(FMField *ref_coors,
                                 int32 *cells, int32 n_cells,
                                 int32 *status, int32 n_status,
                                 FMField *coors,
                                 Mesh *mesh,
                                 FMField *centroids,
                                 FMField *normals0,
                                 FMField *normals1,
                                 int32 *ics, int32 n_ics,
                                 FMField *eref_coors,
                                 int32 *nodes, int32 n_nodes, int32 n_nodes_col,
                                 FMField *mtx_i,
                                 int32 allow_extrapolation,
                                 float64 close_limit, float64 qp_eps,
                                 int32 i_max, float64 newton_eps)
{
  int32 ip, ic, icell, icell_max = 0, ii, imin, ik, ok, ret = RET_OK;
  int32 xi_ok, hexa_reverse;
  int32 D = mesh->topology->max_dim;
  int32 dim = D - 1;
  int32 nc = mesh->geometry->dim;
  uint32 tri0[] = {0, 1, 3};
  uint32 tri1[] = {2, 3, 1};
  uint32 cell, cell0, cell00, facet;
  uint32 *noffs, *foffs, aux[2];
  uint32 *cell_types = mesh->topology->cell_types;
  float64 vmin, vmax, d_min, tmin, tt, dist;
  float64 *mesh_coors = mesh->geometry->coors;
  float64 buf3[3];
  float64 buf9[9];
  float64 buf_ec_max[8 * 3]; // Max. n_ep * dim.
  FMField point[1], centroid[1], _normals0[1], _normals1[1], e_coors[1], xi[1];
  FMField bc[1];
  Indices cell_vertices[1];
  MeshEntity cell_ent[1];
  MeshConnectivity *cD0 = 0; // D -> 0
  MeshConnectivity *c0D = 0; // 0 -> D
  MeshConnectivity *cDd = 0; // cell -> facet
  MeshConnectivity *cdD = 0; // facet -> cell
  MeshConnectivity *loc = 0;
  MeshConnectivity **locs = 0;

  mesh_setup_connectivity(mesh, D, 0);
  cD0 = mesh->topology->conn[IJ(D, D, 0)];

  mesh_setup_connectivity(mesh, 0, D);
  c0D = mesh->topology->conn[IJ(D, 0, D)];

  mesh_setup_connectivity(mesh, D, dim);
  cDd = mesh->topology->conn[IJ(D, D, dim)];
  noffs = cDd->offsets;

  mesh_setup_connectivity(mesh, dim, D);
  cdD = mesh->topology->conn[IJ(D, dim, D)];

  // Local entities - reference cell edges or faces.
  locs = (dim == 1) ? mesh->entities->edges : mesh->entities->faces;

  fmf_pretend_nc(point, coors->nRow, 1, 1, nc, coors->val);
  fmf_pretend_nc(centroid, centroids->nRow, 1, 1, nc, centroids->val);

  fmf_pretend_nc(xi, 1, 1, 1, nc, buf3);
  fmf_fillC(xi, 0.0);

  vmin = eref_coors->val[0];
  vmax = eref_coors->val[nc];

  for (ip = 0; ip < coors->nRow; ip++) {
    ic = ics[ip];
    /* output("***** %d %d\n", ip, ic); */

    FMF_SetCell(point, ip);
    /* fmf_print(point, stdout, 0); */

    cell = cell0 = cell00 = c0D->indices[c0D->offsets[ic]];

    ok = icell = hexa_reverse = imin = 0;
    d_min = 1e10;
    while (1) {
      /* output("*** %d %d %d\n", icell, cell, hexa_reverse); */
      FMF_SetCell(centroid, cell);
      /* fmf_print(centroid, stdout, 0); */

      cell_ent->ii = cell;
      me_get_incident2(cell_ent, cell_vertices, cD0);

      loc = locs[cell_types[cell]];
      foffs = loc->offsets;

      if (cell_types[cell] != 4) { // No hexahedron -> planar facet.
        fmf_pretend_nc(_normals0, noffs[cell+1] - noffs[cell], 1, 1, nc,
                       normals0->val + nc * noffs[cell]);

        tmin = 1e10;
        for (ii = 0; ii < loc->num; ii++) {
          FMF_SetCell(_normals0, ii);
          ik = loc->indices[foffs[ii]];

          _intersect_line_plane(&tt, centroid->val, point->val,
                                mesh_coors + nc * cell_vertices->indices[ik],
                                _normals0->val, nc);
          if ((tt >= -qp_eps) && (tt < (tmin + qp_eps))) {
            imin = ii;
            tmin = tt;
          }
        }

        if (tmin >= (1.0 - qp_eps)) {
          _get_cell_coors(e_coors, cell_vertices, mesh_coors, nc, buf_ec_max);
          /* fmf_print(e_coors, stdout, 0); */

          xi_ok = _get_xi_dist(&dist, xi,  cell_vertices->num, nc, D,
                               point, e_coors, eref_coors, bc,
                               nodes, n_nodes_col, mtx_i, vmin, vmax,
                               i_max, newton_eps);

          d_min = Min(dist, d_min);
          if (xi_ok && (dist < qp_eps)) {
            ok = 1;
          }
          break;
        }

      } else { // Hexahedron -> non-planar facet in general.
        fmf_pretend_nc(_normals0, noffs[cell+1] - noffs[cell], 1, 1, nc,
                       normals0->val + nc * noffs[cell]);
        fmf_pretend_nc(_normals1, noffs[cell+1] - noffs[cell], 1, 1, nc,
                       normals1->val + nc * noffs[cell]);
        for (ii = 0; ii < loc->num; ii++) {
          FMF_SetCell(_normals0, ii);
          _get_tri_coors(buf9, loc->indices, foffs[ii],
                         tri0, mesh_coors, cell_vertices->indices);
          _intersect_line_triangle(&tt, centroid->val, point->val,
                                   buf9, _normals0->val);
          if ((tt >= -qp_eps) && (tt < 1e10)) {
            ok = 2;
            imin = ii;
            if ((tt >= (1.0 - qp_eps)) || hexa_reverse) {
              _get_cell_coors(e_coors, cell_vertices, mesh_coors, nc,
                              buf_ec_max);

              xi_ok = _get_xi_dist(&dist, xi,  cell_vertices->num, nc, D,
                                   point, e_coors, eref_coors, bc,
                                   nodes, n_nodes_col, mtx_i, vmin, vmax,
                                   i_max, newton_eps);

              d_min = Min(dist, d_min);
              if (xi_ok && (dist < qp_eps)) {
                ok = 1;
              } else {
                hexa_reverse = 1;
              }
            }
            break;
          }

          FMF_SetCell(_normals1, ii);
          _get_tri_coors(buf9, loc->indices, foffs[ii],
                         tri1, mesh_coors, cell_vertices->indices);
          _intersect_line_triangle(&tt, centroid->val, point->val,
                                   buf9, _normals1->val);
          if ((tt >= -qp_eps) && (tt < 1e10)) {
            ok = 2;
            imin = ii;
            if ((tt >= (1.0 - qp_eps)) || hexa_reverse) {
              _get_cell_coors(e_coors, cell_vertices, mesh_coors, nc,
                              buf_ec_max);

              xi_ok = _get_xi_dist(&dist, xi,  cell_vertices->num, nc, D,
                                   point, e_coors, eref_coors, bc,
                                   nodes, n_nodes_col, mtx_i, vmin, vmax,
                                   i_max, newton_eps);

              d_min = Min(dist, d_min);
              if (xi_ok && (dist < qp_eps)) {
                ok = 1;
              } else {
                hexa_reverse = 1;
              }
            }
            break;
          }
        }
        if (ok == 1) {
          break;
        }
        if (ok == 0) {
          errput("cannot intersect bilinear faces!\n");
          ERR_CheckGo(ret);
        }
      }

      facet = cDd->indices[cDd->offsets[cell] + imin];
      if ((cdD->offsets[facet+1] - cdD->offsets[facet]) == 2) {
        aux[0] = cdD->indices[cdD->offsets[facet]];
        aux[1] = cdD->indices[cdD->offsets[facet]+1];
        cell00 = cell0;
        cell0 = cell;
        cell = (aux[0] == cell) ? aux[1] : aux[0];

        if (cell == cell00) { // Ping-pong between two cells.
          hexa_reverse = 1;
        }

      } else { // Boundary facet.
        cell_ent->ii = cell;
        me_get_incident2(cell_ent, cell_vertices, cD0);

        _get_cell_coors(e_coors, cell_vertices, mesh_coors, nc,
                        buf_ec_max);
        xi_ok = _get_xi_dist(&dist, xi,  cell_vertices->num, nc, D,
                             point, e_coors, eref_coors, bc,
                             nodes, n_nodes_col, mtx_i, vmin, vmax,
                             i_max, newton_eps);
        d_min = Min(dist, d_min);
        if (xi_ok && (dist < qp_eps)) {
          ok = 1;
        } else {
          ok = 0;
        }
        break;
      }

      icell++;
      icell_max = Max(icell, icell_max);
      if (icell > 10000) {
        errput("cannot find containing cell!\n");
        ERR_CheckGo(ret);
      }
    }

    /* fmf_print(xi, stdout, 0); */
    /* output("-> %d %d %d %.3e\n", cell, xi_ok, ok, d_min); */

    cells[ip] = cell;

    if (ok != 1) {
      if (!xi_ok) {
        status[ip] = 4;
      } else if (allow_extrapolation) {
        // Try using minimum distance xi.
        if (sqrt(d_min) < close_limit) {
          status[ip] = 1;
        } else {
          status[ip] = 2;
        }
      } else {
        status[ip] = 3;
      }
    } else {
      status[ip] = 0;
    }

    for (ii = 0; ii < nc; ii++) {
      ref_coors->val[nc*ip+ii] = xi->val[ii];
    }
  }
  /* output("%d\n", icell_max); */

 end_label:
  return(ret);
}
/*
 * Verify mbstr to make sure that it has a valid character sequence.
 * mbstr is not necessarily NULL terminated; length of mbstr is
 * specified by len.
 *
 * If OK, return TRUE.	If a problem is found, return FALSE when noError is
 * true; when noError is false, ereport() a descriptive message.
 */
bool
pg_verifymbstr(const char *mbstr, int len, bool noError)
{
	int			l;
	int			i;
	int			encoding;

	/* we do not need any check in single-byte encodings */
	if (pg_database_encoding_max_length() <= 1)
		return true;

	encoding = GetDatabaseEncoding();

	while (len > 0 && *mbstr)
	{
		l = pg_mblen(mbstr);

		/* special UTF-8 check */
		if (encoding == PG_UTF8)
		{
			if (!pg_utf8_islegal((const unsigned char *) mbstr, l))
			{
				if (noError)
					return false;
				ereport(ERROR,
						(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
						 errmsg("invalid UTF-8 byte sequence detected near byte 0x%02x",
								(unsigned char) *mbstr)));
			}
		}
		else
		{
			for (i = 1; i < l; i++)
			{
				/*
				 * we expect that every multibyte char consists of bytes
				 * having the 8th bit set
				 */
				if (i >= len || (mbstr[i] & 0x80) == 0)
				{
					char		buf[8 * 2 + 1];
					char	   *p = buf;
					int			j,
								jlimit;

					if (noError)
						return false;

					jlimit = Min(l, len);
					jlimit = Min(jlimit, 8);	/* prevent buffer overrun */

					for (j = 0; j < jlimit; j++)
						p += sprintf(p, "%02x", (unsigned char) mbstr[j]);

					ereport(ERROR,
							(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
					errmsg("invalid byte sequence for encoding \"%s\": 0x%s",
						   GetDatabaseEncodingName(), buf)));
				}
			}
		}
		len -= l;
		mbstr += l;
	}
	return true;
}
/*
========================
idSnapShot::WriteObject
========================
*/
void idSnapShot::WriteObject( idFile* file, int visIndex, objectState_t* newState, objectState_t* oldState, int& lastobjectNum )
{
	assert( newState != NULL || oldState != NULL );
	
	bool visChange		= false; // visibility changes will be signified with a 0xffff state size
	bool visSendState	= false; // the state is sent when an entity is no longer stale
	
	// Compute visibility changes
	// (we need to do this before writing out object id, because we may not need to write out the id if we early out)
	// (when we don't write out the id, we assume this is an "ack" when we deserialize the objects)
	if( newState != NULL && oldState != NULL )
	{
		// Check visibility
		assert( newState->objectNum == oldState->objectNum );
		
		if( visIndex > 0 )
		{
			bool oldVisible = ( oldState->visMask & ( 1 << visIndex ) ) != 0;
			bool newVisible = ( newState->visMask & ( 1 << visIndex ) ) != 0;
			
			// Force visible if we need to either create or destroy this object
			newVisible |= ( newState->buffer.Size() == 0 ) != ( oldState->buffer.Size() == 0 );
			
			if( !oldVisible && !newVisible )
			{
				// object is stale and ack'ed for this client, write nothing (see 'same object' below)
				return;
			}
			else if( oldVisible && !newVisible )
			{
				NET_VERBOSESNAPSHOT_PRINT( "object %d to client %d goes stale\n", newState->objectNum, visIndex );
				visChange = true;
				visSendState = false;
			}
			else if( !oldVisible && newVisible )
			{
				NET_VERBOSESNAPSHOT_PRINT( "object %d to client %d no longer stale\n", newState->objectNum, visIndex );
				visChange = true;
				visSendState = true;
			}
		}
		
		// Same object, write a delta (never early out during vis changes)
		if( !visChange && newState->buffer.Size() == oldState->buffer.Size() &&
				( ( newState->buffer.Ptr() == oldState->buffer.Ptr() ) || memcmp( newState->buffer.Ptr(), oldState->buffer.Ptr(), newState->buffer.Size() ) == 0 ) )
		{
			// same state, write nothing
			return;
		}
	}
	
	// Get the id of the object we are writing out
	uint16 objectNum;
	if( newState != NULL )
	{
		objectNum = newState->objectNum;
	}
	else if( oldState != NULL )
	{
		objectNum = oldState->objectNum;
	}
	else
	{
		objectNum = 0;
	}
	
	assert( objectNum == 0 || objectNum > lastobjectNum );
	
	// Write out object id (using delta)
	uint16 objectDelta = objectNum - lastobjectNum;
	file->WriteBig( objectDelta );
	lastobjectNum = objectNum;
	
	if( newState == NULL )
	{
		// Deleted, write 0 size
		assert( oldState != NULL );
		file->WriteBig<objectSize_t>( 0 );
	}
	else if( oldState == NULL )
	{
		// New object, write out full state
		assert( newState != NULL );
		// delta against an empty snap
		file->WriteBig( newState->buffer.Size() );
		file->Write( newState->buffer.Ptr(), newState->buffer.Size() );
	}
	else
	{
		// Compare to last object
		assert( newState != NULL && oldState != NULL );
		assert( newState->objectNum == oldState->objectNum );
		
		if( visChange )
		{
			// fake size indicates vis state change
			// NOTE: we may still send a real size and a state below, for 'no longer stale' transitions
			// TMP: send 0xFFFF for going stale and 0xFFFF - 1 for no longer stale
			file->WriteBig<objectSize_t>( visSendState ? SIZE_NOT_STALE : SIZE_STALE );
		}
		if( !visChange || visSendState )
		{
		
			objectSize_t compareSize = Min( newState->buffer.Size(), oldState->buffer.Size() );		// Get the number of bytes that overlap
			
			file->WriteBig( newState->buffer.Size() );										// Write new size
			
			// Compare bytes that overlap
			for( objectSize_t b = 0; b < compareSize; b++ )
			{
				file->WriteBig<byte>( ( 0xFF + 1 + newState->buffer[b] - oldState->buffer[b] ) & 0xFF );
			}
			
			// Write leftover
			if( newState->buffer.Size() > compareSize )
			{
				file->Write( newState->buffer.Ptr() + oldState->buffer.Size(), newState->buffer.Size() - compareSize );
			}
		}
	}
	
#ifdef SNAPSHOT_CHECKSUMS
	if( ( !visChange || visSendState ) && newState != NULL )
	{
		assert( newState->buffer.Size() > 0 );
		unsigned int checksum = MD5_BlockChecksum( newState->buffer.Ptr(), newState->buffer.Size() );
		file->WriteBig( checksum );
	}
#endif
}
Exemple #17
0
/*
 * Find the gtm port and try a connection
 */
static bool
test_gtm_connection()
{
	GTM_Conn	   *conn;
	bool		success = false;
	int			i;
	char		portstr[32];
	char	   *p;
	char	   *q;
	char		connstr[128];	/* Should be way more than enough! */

	*portstr = '\0';

	/*
	 * Look in gtm_opts for a -p switch.
	 *
	 * This parsing code is not amazingly bright; it could for instance
	 * get fooled if ' -p' occurs within a quoted argument value.  Given
	 * that few people pass complicated settings in gtm_opts, it's
	 * probably good enough.
	 */
	for (p = gtm_opts; *p;)
	{
		/* advance past whitespace */
		while (isspace((unsigned char) *p))
			p++;

		if (strncmp(p, "-p", 2) == 0)
		{
			p += 2;
			/* advance past any whitespace/quoting */
			while (isspace((unsigned char) *p) || *p == '\'' || *p == '"')
				p++;
			/* find end of value (not including any ending quote!) */
			q = p;
			while (*q &&
				   !(isspace((unsigned char) *q) || *q == '\'' || *q == '"'))
				q++;
			/* and save the argument value */
			strlcpy(portstr, p, Min((q - p) + 1, sizeof(portstr)));
			/* keep looking, maybe there is another -p */
			p = q;
		}
		/* Advance to next whitespace */
		while (*p && !isspace((unsigned char) *p))
			p++;
	}

	/*
	 * Search config file for a 'port' option.
	 *
	 * This parsing code isn't amazingly bright either, but it should be okay
	 * for valid port settings.
	 */
	if (!*portstr)
	{
		char      **optlines;

		optlines = readfile(conf_file);
		if (optlines != NULL)
		{
			for (; *optlines != NULL; optlines++)
			{
				p = *optlines;

				while (isspace((unsigned char) *p))
					p++;
				if (strncmp(p, "port", 4) != 0)
					continue;
				p += 4;
				while (isspace((unsigned char) *p))
					p++;
				if (*p != '=')
					continue;
				p++;
				/* advance past any whitespace/quoting */
				while (isspace((unsigned char) *p) || *p == '\'' || *p == '"')
					p++;
				/* find end of value (not including any ending quote/comment!) */
				q = p;
				while (*q &&
					   !(isspace((unsigned char) *q) ||
						 *q == '\'' || *q == '"' || *q == '#'))
					q++;
				/* and save the argument value */
				strlcpy(portstr, p, Min((q - p) + 1, sizeof(portstr)));
				/* keep looking, maybe there is another */
			}
		}
	}

	/* Still not found? Use compiled-in default */
#define GTM_DEFAULT_PORT               6666
	if (!*portstr)
		snprintf(portstr, sizeof(portstr), "%d", GTM_DEFAULT_PORT);

	/*
	 * We need to set a connect timeout otherwise on Windows the SCM will
	 * probably timeout first
	 * a PGXC node ID has to be set for GTM connection protocol,
	 * so its value doesn't really matter here.
	 */
	snprintf(connstr, sizeof(connstr),
			 "host=localhost port=%s connect_timeout=5 node_name=one", portstr);

	for (i = 0; i < wait_seconds; i++)
	{
		if ((conn = PQconnectGTM(connstr)) != NULL &&
			(GTMPQstatus(conn) == CONNECTION_OK))
		{
			GTMPQfinish(conn);
			success = true;
			break;
		}
		else
		{
			GTMPQfinish(conn);
			print_msg(".");
			sleep(1); /* 1 sec */
		}
	}

	return success;
}
BOOL vncDesktop:: CalculateSWrect(RECT &rect)
{

	if (!m_Single_hWnd)
	{
		m_server->SingleWindow(false);
		m_SWtoDesktop=TRUE;
		rect.top=0;
		rect.left=0;
		rect.right=m_scrinfo.framebufferWidth;
		rect.bottom=m_scrinfo.framebufferHeight;
		return FALSE;
	}

	if (IsIconic(m_Single_hWnd))
	{
		m_server->SingleWindow(false);
		m_Single_hWnd=NULL;
		m_SWtoDesktop=TRUE;
		rect.top=0;
		rect.left=0;
		rect.right=m_scrinfo.framebufferWidth;
		rect.bottom=m_scrinfo.framebufferHeight;
		return FALSE;
	}
	if ( IsWindowVisible(m_Single_hWnd) && GetWindowRect(m_Single_hWnd,&rect)) 
		{
			RECT taskbar;
			rect.top=Max(rect.top,0);
			rect.left=Max(rect.left,0);
			rect.right=Min(rect.right,m_scrinfo.framebufferWidth);
			rect.bottom=Min(rect.bottom,m_scrinfo.framebufferHeight);
			APPBARDATA pabd;
			pabd.cbSize=sizeof(APPBARDATA);
			SHAppBarMessage(ABM_GETTASKBARPOS, &pabd);
			taskbar.top=Max(pabd.rc.top,0);
			taskbar.left=Max(pabd.rc.left,0);
			taskbar.right=Min(pabd.rc.right,m_scrinfo.framebufferWidth);
			taskbar.bottom=Min(pabd.rc.bottom,m_scrinfo.framebufferHeight);
			///desktop
			if (rect.top==0 && rect.left== 0&& rect.right==m_scrinfo.framebufferWidth && rect.bottom==m_scrinfo.framebufferHeight)
				{
					m_server->SingleWindow(false);
					m_Single_hWnd=NULL;
					rect.top=0;
					rect.left=0;
					rect.right=m_scrinfo.framebufferWidth;
					rect.bottom=m_scrinfo.framebufferHeight;
					return TRUE;
				}
			//taskbar
			if (rect.top>=taskbar.top && rect.left== taskbar.left&& rect.right==taskbar.right && rect.bottom==taskbar.bottom)
			
				{
					rect.top=taskbar.top;
					rect.left=taskbar.left;
					rect.right=taskbar.right;
					rect.bottom=taskbar.bottom;
					if ((m_SWHeight!=(rect.bottom-rect.top)) || (m_SWWidth!=(rect.right-rect.left)))
					m_SWSizeChanged=TRUE;
					m_SWHeight=rect.bottom-rect.top;
					m_SWWidth=rect.right-rect.left;
					return TRUE;	
				}
			//eliminate other little windows
			if ((m_SWHeight!=(rect.bottom-rect.top)) || (m_SWWidth!=(rect.right-rect.left)))
				m_SWSizeChanged=TRUE;
			//vnclog.Print(LL_INTINFO, VNCLOG("screen format %d %d %d %d\n"),
			//		rect.top,
			//		rect.bottom,rect.right,rect.left);
			if ((rect.bottom-rect.top)<64||(rect.right-rect.left)<128 || rect.bottom<0 ||rect.top<0 || rect.right<0 ||
				rect.left<0 || rect.bottom>m_scrinfo.framebufferHeight||rect.top>m_scrinfo.framebufferHeight||
				rect.right>m_scrinfo.framebufferWidth||rect.left>m_scrinfo.framebufferWidth)
			{
				m_server->SingleWindow(false);
				m_Single_hWnd=NULL;
				m_SWtoDesktop=TRUE;
				rect.top=0;
				rect.left=0;
				rect.right=m_scrinfo.framebufferWidth;
				rect.bottom=m_scrinfo.framebufferHeight;
				m_SWSizeChanged=FALSE;
				return FALSE;
			}


			m_SWHeight=rect.bottom-rect.top;
			m_SWWidth=rect.right-rect.left;
			return TRUE;
		}		
	m_server->SingleWindow(false);
	m_Single_hWnd=NULL;
	m_SWtoDesktop=TRUE;
	rect.top=0;
	rect.left=0;
	rect.right=m_scrinfo.framebufferWidth;
	rect.bottom=m_scrinfo.framebufferHeight;
	return FALSE;
}
Exemple #19
0
byte CSurface3DFrame::FitPanel()//Rectangle()
  {
  byte eTryDiv=C3D_DivNxN;
  if (m_p3D->m_pBoundary)
    {
    CSurface3DBoundary &B=*m_p3D->m_pBoundary;
    if (m_dXMin>=B.m_XMin && m_dXMax<=B.m_XMax &&
        m_dYMin>=B.m_YMin && m_dYMax<=B.m_YMax)
      {
      double BYxmn=B.m_FnYx(m_dXMin);
      double BYxmx=B.m_FnYx(m_dXMax);
      double BXymn=B.m_FnXy(m_dYMin);
      double BXymx=B.m_FnXy(m_dYMax);
      byte LCross=(m_dYMin<BYxmn && BYxmn<m_dYMax) ? 1 : 0;
      byte RCross=(m_dYMin<BYxmx && BYxmx<m_dYMax) ? 2 : 0;
      byte BCross=(m_dXMin<BXymn && BXymn<m_dXMax) ? 4 : 0;
      byte TCross=(m_dXMin<BXymx && BXymx<m_dXMax) ? 8 : 0;
      eTryDiv=PanelLayout[LCross+RCross+TCross+BCross].Divs;

      double Val1=dNAN;
      double Val2=dNAN;
      switch (eTryDiv)
        {
        case C3D_Div2V:
          {
          Val1=BCross ? BXymn : BXymx;
          CSurface3DFrame Frames[2];
          Frames[0].Initialise(m_p3D, m_iLevel+1, m_dXMin, Val1,    1, m_dYMin, m_dYMax, 1);
          Frames[1].Initialise(m_p3D, m_iLevel+1, Val1,    m_dXMax, 1, m_dYMin, m_dYMax, 1);
          if (!FitAndTestPanels(2,1, Frames))
            eTryDiv=C3D_DivNxN;
          }
          break;
        case C3D_Div3V:
          {
          Val1=Min(BXymn, BXymx);
          Val2=Max(BXymn, BXymx);
          CSurface3DFrame Frames[3];
          Frames[0].Initialise(m_p3D, m_iLevel+1, m_dXMin, Val1,    1, m_dYMin, m_dYMax, 1);
          Frames[1].Initialise(m_p3D, m_iLevel+1, Val1,    Val2,    1, m_dYMin, m_dYMax, 1);
          Frames[2].Initialise(m_p3D, m_iLevel+1, Val2,    m_dXMax, 1, m_dYMin, m_dYMax, 1);
          if (!FitAndTestPanels(3,1, Frames))
            eTryDiv=C3D_DivNxN;
          }
          break;
        case C3D_Div2H:
          {
          Val1=LCross ? BYxmn : BYxmx;
          CSurface3DFrame Frames[2];
          Frames[0].Initialise(m_p3D, m_iLevel+1, m_dXMin, m_dXMax, 1, m_dYMin,   Val1, 1);
          Frames[1].Initialise(m_p3D, m_iLevel+1, m_dXMin, m_dXMax, 1, Val1,   m_dYMax, 1);
          if (!FitAndTestPanels(1,2, Frames))
            eTryDiv=C3D_DivNxN;
          }
          break;
        case C3D_Div3H:
          {
          Val1=Min(BYxmn, BYxmx);
          Val2=Max(BYxmn, BYxmx);
          CSurface3DFrame Frames[3];
          Frames[0].Initialise(m_p3D, m_iLevel+1, m_dXMin, m_dXMax, 1, m_dYMin,   Val1, 1);
          Frames[1].Initialise(m_p3D, m_iLevel+1, m_dXMin, m_dXMax, 1, Val1,      Val2, 1);
          Frames[2].Initialise(m_p3D, m_iLevel+1, m_dXMin, m_dXMax, 1, Val2,   m_dYMax, 1);
          if (!FitAndTestPanels(1,3, Frames))
            eTryDiv=C3D_DivNxN;
          }
          break;
        case C3D_Div2x2:
          {
          Val1=BCross ? BXymn : BXymx;
          Val2=LCross ? BYxmn : BYxmx;
          CSurface3DFrame Frames[4];
          Frames[0].Initialise(m_p3D, m_iLevel+1, m_dXMin,    Val1, 1, m_dYMin,    Val2, 1);
          Frames[1].Initialise(m_p3D, m_iLevel+1, Val1,    m_dXMax, 1, m_dYMin,    Val2, 1);
          Frames[2].Initialise(m_p3D, m_iLevel+1, m_dXMin,    Val1, 1, Val2,    m_dYMax, 1);
          Frames[3].Initialise(m_p3D, m_iLevel+1, Val1,    m_dXMax, 1, Val2,    m_dYMax, 1);
          if (!FitAndTestPanels(2,2, Frames))
            eTryDiv=C3D_DivNxN;
          }
          break;
        case C3D_DivNxN:
          if (m_nDivsX*m_nDivsY<2)
            DoBreak();
          break;
        case C3D_Bad:
          DoBreak();
        }
      }
    else
      eTryDiv=C3D_Div1x1;
    }
  else
    eTryDiv=C3D_Div1x1;
  
  if (eTryDiv==C3D_Div1x1)
    {
    CSurface3DPanel * pPanel=BuildPanel();
    
    if (m_iLevel>=8)
      DoBreak();

    if (pPanel->CheckFit(this))
      {
      m_eDivision=eTryDiv;
      m_pPanel=pPanel;
      #if dbgSurfaces
      if (dbg3DTrack())
        dbgpln("Add new Panel %-20s %-5s %08x [%2i] %14.8f %14.8f",
               m_p3D->Name(), s_sDivText[m_eDivision], m_pPanel, m_iLevel, 0.5*(m_dXMin+m_dXMax), 0.5*(m_dYMin+m_dYMax));
      #endif
      }
    else
      {
      delete pPanel;
      eTryDiv= C3D_DivNxN;
      #if dbgSurfaces
      if (dbg3DTrack())
        dbgpln("Drill Down    %-20s %-5s %8s [%2i] %14.8f %14.8f",
               m_p3D->Name(), s_sDivText[eTryDiv], "", m_iLevel, 0.5*(m_dXMin+m_dXMax), 0.5*(m_dYMin+m_dYMax));
      #endif
      }
    }
  
  if (eTryDiv==C3D_DivNxN)
    {
    if (m_nDivsX*m_nDivsY<2)
      DoBreak();
    ASSERT(m_Frames==NULL);
    long nElements=m_nDivsX*m_nDivsY;
    m_Frames=new LPCSurface3DFrame[nElements];
    for (int i=0; i<nElements; i++)
      m_Frames[i]= NULL;
    }
  m_eDivision=eTryDiv;
  return eTryDiv;
  }
Exemple #20
0
/*
 * Form a tuple for entry tree.
 *
 * If the tuple would be too big to be stored, function throws a suitable
 * error if errorTooBig is TRUE, or returns NULL if errorTooBig is FALSE.
 *
 * On leaf pages, Index tuple has non-traditional layout. Tuple may contain
 * posting list or root blocknumber of posting tree.
 * Macros: GinIsPostingTree(itup) / GinSetPostingTree(itup, blkno)
 * 1) Posting list
 *		- itup->t_info & INDEX_SIZE_MASK contains total size of tuple as usual
 *		- ItemPointerGetBlockNumber(&itup->t_tid) contains original
 *		  size of tuple (without posting list).
 *		  Macros: GinGetOrigSizePosting(itup) / GinSetOrigSizePosting(itup,n)
 *		- ItemPointerGetOffsetNumber(&itup->t_tid) contains number
 *		  of elements in posting list (number of heap itempointers)
 *		  Macros: GinGetNPosting(itup) / GinSetNPosting(itup,n)
 *		- After standard part of tuple there is a posting list, ie, array
 *		  of heap itempointers
 *		  Macros: GinGetPosting(itup)
 * 2) Posting tree
 *		- itup->t_info & INDEX_SIZE_MASK contains size of tuple as usual
 *		- ItemPointerGetBlockNumber(&itup->t_tid) contains block number of
 *		  root of posting tree
 *		- ItemPointerGetOffsetNumber(&itup->t_tid) contains magic number
 *		  GIN_TREE_POSTING, which distinguishes this from posting-list case
 *
 * Attributes of an index tuple are different for single and multicolumn index.
 * For single-column case, index tuple stores only value to be indexed.
 * For multicolumn case, it stores two attributes: column number of value
 * and value.
 */
IndexTuple
GinFormTuple(Relation index, GinState *ginstate,
			 OffsetNumber attnum, Datum key,
			 ItemPointerData *ipd, uint32 nipd, bool errorTooBig)
{
	bool		isnull[2] = {FALSE, FALSE};
	IndexTuple	itup;
	uint32		newsize;

	if (ginstate->oneCol)
		itup = index_form_tuple(ginstate->origTupdesc, &key, isnull);
	else
	{
		Datum		datums[2];

		datums[0] = UInt16GetDatum(attnum);
		datums[1] = key;
		itup = index_form_tuple(ginstate->tupdesc[attnum - 1], datums, isnull);
	}

	GinSetOrigSizePosting(itup, IndexTupleSize(itup));

	if (nipd > 0)
	{
		newsize = MAXALIGN(SHORTALIGN(IndexTupleSize(itup)) + sizeof(ItemPointerData) * nipd);
		if (newsize > Min(INDEX_SIZE_MASK, GinMaxItemSize))
		{
			if (errorTooBig)
				ereport(ERROR,
						(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
						 errmsg("index row size %lu exceeds maximum %lu for index \"%s\"",
								(unsigned long) newsize,
								(unsigned long) Min(INDEX_SIZE_MASK,
													GinMaxItemSize),
								RelationGetRelationName(index))));
			return NULL;
		}

		itup = repalloc(itup, newsize);

		/* set new size */
		itup->t_info &= ~INDEX_SIZE_MASK;
		itup->t_info |= newsize;

		if (ipd)
			memcpy(GinGetPosting(itup), ipd, sizeof(ItemPointerData) * nipd);
		GinSetNPosting(itup, nipd);
	}
	else
	{
		/*
		 * Gin tuple without any ItemPointers should be large enough to keep
		 * one ItemPointer, to prevent inconsistency between
		 * ginHeapTupleFastCollect and ginEntryInsert called by
		 * ginHeapTupleInsert.	ginHeapTupleFastCollect forms tuple without
		 * extra pointer to heap, but ginEntryInsert (called for pending list
		 * cleanup during vacuum) will form the same tuple with one
		 * ItemPointer.
		 */
		newsize = MAXALIGN(SHORTALIGN(IndexTupleSize(itup)) + sizeof(ItemPointerData));
		if (newsize > Min(INDEX_SIZE_MASK, GinMaxItemSize))
		{
			if (errorTooBig)
				ereport(ERROR,
						(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
						 errmsg("index row size %lu exceeds maximum %lu for index \"%s\"",
								(unsigned long) newsize,
								(unsigned long) Min(INDEX_SIZE_MASK,
													GinMaxItemSize),
								RelationGetRelationName(index))));
			return NULL;
		}

		GinSetNPosting(itup, 0);
	}
	return itup;
}
Exemple #21
0
/*
 * tuplestore_trim	- remove all no-longer-needed tuples
 *
 * Calling this function authorizes the tuplestore to delete all tuples
 * before the oldest read pointer, if no read pointer is marked as requiring
 * REWIND capability.
 *
 * Note: this is obviously safe if no pointer has BACKWARD capability either.
 * If a pointer is marked as BACKWARD but not REWIND capable, it means that
 * the pointer can be moved backward but not before the oldest other read
 * pointer.
 */
void
tuplestore_trim(Tuplestorestate *state)
{
	int			oldest;
	int			nremove;
	int			i;

	/*
	 * Truncation is disallowed if any read pointer requires rewind
	 * capability.
	 */
	if (state->eflags & EXEC_FLAG_REWIND)
		return;

	/*
	 * We don't bother trimming temp files since it usually would mean more
	 * work than just letting them sit in kernel buffers until they age out.
	 */
	if (state->status != TSS_INMEM)
		return;

	/* Find the oldest read pointer */
	oldest = state->memtupcount;
	for (i = 0; i < state->readptrcount; i++)
	{
		if (!state->readptrs[i].eof_reached)
			oldest = Min(oldest, state->readptrs[i].current);
	}

	/*
	 * Note: you might think we could remove all the tuples before the oldest
	 * "current", since that one is the next to be returned.  However, since
	 * tuplestore_gettuple returns a direct pointer to our internal copy of
	 * the tuple, it's likely that the caller has still got the tuple just
	 * before "current" referenced in a slot. So we keep one extra tuple
	 * before the oldest "current".  (Strictly speaking, we could require such
	 * callers to use the "copy" flag to tuplestore_gettupleslot, but for
	 * efficiency we allow this one case to not use "copy".)
	 */
	nremove = oldest - 1;
	if (nremove <= 0)
		return;					/* nothing to do */
	Assert(nremove <= state->memtupcount);

	/* Release no-longer-needed tuples */
	for (i = 0; i < nremove; i++)
	{
		FREEMEM(state, GetMemoryChunkSpace(state->memtuples[i]));
		pfree(state->memtuples[i]);
	}

	/*
	 * Slide the array down and readjust pointers.	This may look pretty
	 * stupid, but we expect that there will usually not be very many
	 * tuple-pointers to move, so this isn't that expensive; and it keeps a
	 * lot of other logic simple.
	 *
	 * In fact, in the current usage for merge joins, it's demonstrable that
	 * there will always be exactly one non-removed tuple; so optimize that
	 * case.
	 */
	if (nremove + 1 == state->memtupcount)
		state->memtuples[0] = state->memtuples[nremove];
	else
		memmove(state->memtuples, state->memtuples + nremove,
				(state->memtupcount - nremove) * sizeof(void *));

	state->memtupcount -= nremove;
	for (i = 0; i < state->readptrcount; i++)
	{
		if (!state->readptrs[i].eof_reached)
			state->readptrs[i].current -= nremove;
	}

	/* mark tuplestore as truncated (used for Assert crosschecks only) */
	state->truncated = true;
}
Exemple #22
0
void CoolingTower::EvalProducts(CNodeEvalIndex & NEI)
  {
  switch (SolveMethod())
    {
    case SM_Direct:
      {
      const int wi = H2OLiq();
      const int si = H2OVap();
      const int ioLiq = IOWithId_Self(ioid_Liq);
      const int ioVap = IOWithId_Self(ioid_Vap);
      const int ioLoss = IOWithId_Self(ioid_LiqLoss);
      const int ioDrift = IOWithId_Self(ioid_DriftLoss);
      
      SpConduit & Ql=*IOConduit(ioLiq);
      SpConduit & Qv=*IOConduit(ioVap);
      
      StkSpConduit QMix("Mix", chLINEID(), this);

      iCycles = Max(2L, iCycles);
      dLGRatio = Range(0.01, dLGRatio, 10.0);
      ClrCI(3);
      ClrCI(4);
      ClrCI(5);
      ClrCI(6);
      dDuty = 0.0;
      SigmaQInPMin(QMix(), som_ALL, Id_2_Mask(ioid_Feed));
      Ql.QCopy(QMix());
      Qv.QCopy(QMix());

      const double QmWaterLiqIn = QMix().VMass[wi];
      const double QmWaterVapIn = QMix().VMass[si];
      const double QmVapIn = QMix().QMass(som_Gas);
      dQmIn = QMix().QMass(som_ALL);
      const flag HasFlw = (dQmIn>UsableMass);
      dTempKFeed = QMix().Temp();
      const double TotHfAtFeedT_Before = QMix().totHf(som_ALL, dTempKFeed, QMix().Press());
      
      //RB.EvalProducts(QMix);
      //EHX.EvalProducts(QMix);

      //double POut = AtmosPress(); //force outlet to Atmos P
      double POut = Std_P; //force outlet to Std_P

      //double AvgCellAgeY=AvgCellAge/(365.25*24.0*60.0*60.0);   
      //double TimeSinceDescaleM=TimeSinceDescale/(365.25*24.0*60.0*60.0/12.0);   
      //double RqdLiqTemp = AirWetBulbT + Approach + AvgCellAgeY*1.1 + TimeSinceDescaleM/12.0*4.0;
      double RqdLiqTemp = dAirWetBulbT + dApproachT;
      double T1 = QMix().Temp();
      double T2 = RqdLiqTemp;
      dLossQm = 0.0;
      bool ValidData;
      switch (iMethod)
        {
        case CTM_Simple: ValidData = (RqdLiqTemp<T1); break;
        case CTM_Merkel: ValidData = (iMerkelCalcType==MCT_TOut ? (dAirWetBulbT<T1) : (RqdLiqTemp<T1)); break;
        }
      if (!HasFlw)
        ValidData = false;
      double RqdLiqTempUsed;
      if (ValidData)
        {
        m_VLE.SetHfInAtZero(QMix());
        if (iMethod==CTM_Simple)
          {
          //const double h1 = QMix().totHf();
          RqdLiqTempUsed = RqdLiqTemp;
          EvapFnd EF(QMix(), RqdLiqTempUsed, POut, m_VLE);//QMix().Press());
          EF.SetTarget(QMix().totHf());
          if (Valid(dEvapFrac))
            {
            EF.SetEstimate(dEvapFrac, 1.0);
            //dEvapFrac = dNAN;
            }
          flag Ok = false;
          dMaxEvapFrac = Range(0.01, dMaxEvapFrac, 1.0);
          int iRet=EF.Start(0.0, dMaxEvapFrac);
          if (iRet==RF_EstimateOK) //estimate is good, solve not required
            {
            Ok = true;
            }
          else
            {
            if (iRet==RF_BadEstimate)
              iRet = EF.Start(0.0, dMaxEvapFrac); // Restart
            if (iRet==RF_OK)
              if (EF.Solve_Brent()==RF_OK)
                Ok = true;
            }
          dEvapFrac = EF.Result(); //use result regardless
          if (!Ok)
            {
            SigmaQInPMin(QMix(), som_ALL, Id_2_Mask(ioid_Feed));
            m_VLE.SetSatPVapFrac(QMix(), dEvapFrac, 0);
            QMix().SetPress(POut);
            RqdLiqTempUsed = QMix().Temp();
            }
          //const double h2 = QMix().totHf();
          //dDuty = h1-h2; this gives 0 (as expected)
          //dDuty is zero because there is no heattransfer with the air
          }
        else
          {
          dAirCp = Max(0.000001, dAirCp);
          dAirWetBulbT = Range(MerkelTMn, dAirWetBulbT, MerkelTMx-10.0);
          if (T1<MerkelTMn || T1>MerkelTMx)
            {
            SetCI(6, true);
            T1 = Range(MerkelTMn, T1, MerkelTMx);
            }

          MerkelTempFnd Fnd(QMix(), *this, T1);
          if (iMerkelCalcType==MCT_KaVL)
            {
            if (T2<MerkelTMn || T2>MerkelTMx)
              {
              SetCI(5, true);
              T2 = Range(MerkelTMn, T2, MerkelTMx);
              RqdLiqTemp = T2;
              }
            dKaVL = Fnd.Function(T2);
            }
          else
            {
            Fnd.SetTarget(dKaVL);
            //Note that for high LG_Ratio (eg>1.0) then ApproachT is higher.

            double Mn = dAirWetBulbT+(T1-dAirWetBulbT)*0.005;
            const double Mx = dAirWetBulbT+(T1-dAirWetBulbT)*0.999;//T1-0.001;
            if (Valid(RqdLiqTemp) && RqdLiqTemp>Mn && RqdLiqTemp<Mx)
              {
              Fnd.SetEstimate(RqdLiqTemp, 1.0);
              //RqdLiqTemp = dNAN;
              }
            flag Ok = false;
            int iRet=Fnd.Start(Mn, Mx);
            if (iRet==RF_EstimateOK) //estimate is good, solve not required
              {
              Ok = true;
              }
            else
              {
              double KaVL_MnTest = Fnd.Function(Mn);
              if (KaVL_MnTest<0.0)
                {
                //Crude fix to find min temp that doesn't cause KaV/L to be negative...
                double fr = 0.01;
                while (KaVL_MnTest<0.0 && fr<0.9)
                  {
                  Mn = dAirWetBulbT+(T1-dAirWetBulbT)*fr;
                  KaVL_MnTest = Fnd.Function(Mn);
                  fr += 0.01;
                  }
                iRet = Fnd.Start(Mn, Mx); // Restart
                }
              if (iRet==RF_OK)
                if (Fnd.Solve_Brent()==RF_OK)
                  Ok = true;
              }
            RqdLiqTemp = Fnd.Result(); //use result regardless
            T2 = RqdLiqTemp;
            if (!Ok)
              {
              const double KaVL_Calc = Fnd.Function(T2);
              SetCI(3, fabs(KaVL_Calc-dKaVL)>1.0e-6);
              }
            dApproachT = RqdLiqTemp - dAirWetBulbT;
            }

          dEvapFactor = Min(dEvapFactor, 0.1); //prevent user from puting a silly large number for this
          dEvapLossQm = dQmIn * dEvapFactor * (C2F(T1)-C2F(T2));//Evaporation Loss: WLe =  Wc * EvapFactor * dT
          dEvapLossQm = Min(dEvapLossQm, QmWaterLiqIn); //limit the amount that can be evaporated


          RqdLiqTempUsed = RqdLiqTemp;

          dEvapFrac = Min(dMaxEvapFrac, (dEvapLossQm+QmWaterVapIn)/GTZ(QmWaterLiqIn+QmWaterVapIn));
          const double h1 = QMix().totHf();
          m_VLE.SetSatPVapFrac(QMix(), dEvapFrac, 0);
          QMix().SetPress(POut);
          QMix().SetTemp(RqdLiqTempUsed);
          const double h2 = QMix().totHf();
          dDuty = h1-h2;

          //dAirEnthOut = AirEnth(T2);
          dAirEnthOut = Fnd.h2 / 0.430210432; //convert from Btu/lb to kJ/kg
          dAirQmIn = dQmIn/dLGRatio;
          dAirTRise = dDuty/GTZ(dAirQmIn)/dAirCp;
          dAirTOut = dAirDryBulbT + dAirTRise;
          dAirMixQm = dAirQmIn + dEvapLossQm;
          const double EvapLossCp = Qv.msCp();
          dAirMixCp = dAirQmIn/GTZ(dAirMixQm)*dAirCp + dEvapLossQm/GTZ(dAirMixQm)*EvapLossCp;
          dAirMixT = dAirQmIn/GTZ(dAirMixQm)*dAirTOut + dEvapLossQm/GTZ(dAirMixQm)*T2;
          }

        double QmWaterVapOut = QMix().VMass[si];
        dQmWaterEvap = Max(0.0, QmWaterVapOut - QmWaterVapIn);
        if (iMethod==CTM_Simple)
          dEvapLossQm=dQmWaterEvap;
        switch (iLossMethod)
          {
          case WLM_None: 
            dDriftLossQm = 0.0;
            dBlowdownLossQm = 0.0;
            dLossQm = 0.0; 
            break;
          case WLM_Frac: 
            dRqdDriftLossFrac = Range(0.0, dRqdDriftLossFrac, 1.0);
            dRqdLossFrac = Range(0.0, dRqdLossFrac, 0.9);
            dLossQm = dQmIn * dRqdLossFrac;
            dDriftLossQm = dLossQm * dRqdDriftLossFrac;
            dBlowdownLossQm = dLossQm - dDriftLossQm;
            break;
          case WLM_Qm: 
            dRqdDriftLossFrac = Range(0.0, dRqdDriftLossFrac, 1.0);
            dLossQm = dRqdLossQm;
            dDriftLossQm = dLossQm * dRqdDriftLossFrac;
            dBlowdownLossQm = dLossQm - dDriftLossQm;
            break;
          case WLM_DriftBlowdown:
            dDriftLossQm = dQmIn * dDriftLossFrac;//Drift Loss: WLd = % of water flow
            dBlowdownLossQm = dEvapLossQm/(iCycles-1);//Blowdown Loss: WLb = WLe / (cycles - 1)
            dLossQm = dDriftLossQm+dBlowdownLossQm;
            break;
          }
        if (dLossQm>dQmIn-dEvapLossQm-QmVapIn)
          {
          SetCI(4, true);
          dLossQm = dQmIn-dEvapLossQm-QmVapIn;
          }
        m_VLE.AddHfOutAtZero(QMix());
        }
      else
        {
        RqdLiqTempUsed = T1;
        dEvapFrac = 0.0;
        dLossQm = 0.0;
        dDriftLossQm = 0.0;
        dBlowdownLossQm = 0.0;
        dEvapLossQm = 0.0;
        dQmWaterEvap = 0.0;
        //if (iMethod==CTM_Merkel)
          {
          dAirEnthOut = TotHfAtFeedT_Before / 0.430210432; //convert from Btu/lb to kJ/kg
          dAirQmIn = 0.0;
          dAirTRise = 0.0;
          dAirTOut = dTempKFeed;
          dAirMixQm = 0.0;
          dAirMixCp = 0.0;
          dAirMixT = dTempKFeed;
          }
        }

      //QMix.ChangeModel(&SMSteamClass);
      const double TotHfAtFeedT_After = QMix().totHf(som_ALL, dTempKFeed, QMix().Press());
      Qv.QSetF(QMix(), som_Gas, 1.0);
      Qv.SetPress(POut);
      Qv.SetTemp(RqdLiqTempUsed);

      const double Qsl = QMix().QMass(som_SL);
      if (ioLoss<0)
        {
        if (ioDrift<0)
          {
          Ql.QSetF(QMix(), som_SL, 1.0);
          Ql.SetPress(POut);
          Ql.SetTemp(RqdLiqTempUsed);
          }
        else
          {
          SpConduit & Qdrift=*IOConduit(ioDrift);
          const double f = dDriftLossQm/GTZ(Qsl);
          Ql.QSetF(QMix(), som_SL, 1.0-f);
          Ql.SetPress(POut);
          Ql.SetTemp(RqdLiqTempUsed);
          Qdrift.QCopy(QMix());
          Qdrift.QSetF(QMix(), som_SL, f);
          Qdrift.SetPress(POut);
          Qdrift.SetTemp(RqdLiqTempUsed);
          }
        }
      else
        {
        SpConduit & Qloss=*IOConduit(ioLoss);
        const double f = dLossQm/GTZ(Qsl);
        Ql.QSetF(QMix(), som_SL, 1.0-f);
        Ql.SetPress(POut);
        Ql.SetTemp(RqdLiqTempUsed);
        if (ioDrift<0)
          {
          Qloss.QCopy(QMix());
          Qloss.QSetF(QMix(), som_SL, f);
          Qloss.SetPress(POut);
          Qloss.SetTemp(RqdLiqTempUsed);
          }
        else
          {
          const double fd = dDriftLossQm/GTZ(Qsl);
          const double fl = f - fd;
          SpConduit & Qdrift=*IOConduit(ioDrift);
          Qdrift.QCopy(QMix());
          Qdrift.QSetF(QMix(), som_SL, fd);
          Qdrift.SetPress(POut);
          Qdrift.SetTemp(RqdLiqTempUsed);
          Qloss.QCopy(QMix());
          Qloss.QSetF(QMix(), som_SL, fl);
          Qloss.SetPress(POut);
          Qloss.SetTemp(RqdLiqTempUsed);
          }
        }

      //results...
      dTotalLossQm = dLossQm+dEvapLossQm;
      dHeatFlow = TotHfAtFeedT_After - TotHfAtFeedT_Before; //what exactly is this???
      dFinalP = Ql.Press();
      dFinalT = Ql.Temp();
      dTempDrop = T1 - dFinalT;
      SetCI(1, HasFlw && RqdLiqTemp>T1);
      SetCI(2, HasFlw && RqdLiqTempUsed>RqdLiqTemp);
      break;
      }
    default:
      MN_Surge::EvalProducts(NEI);
    }
  }
GeometryService::InOut TiltedCylinderIF::InsideOutside(const RealVect& lo,
                                                       const RealVect& hi) const
{

  // Fast Sphere-Box intersection from "Graphics Gems" pp 335-338, 1990

  Real dmin = 0; //distance from cylinder axis to nearest  point in box (squared)
  Real dmax = 0; //distance from cylinder axis to farthest point in box (squared)
  Real ai, bi, a, b;

  Tuple<int,CH_SPACEDIM-1> tanDirs = PolyGeom::computeTanDirs(m_coordDir);
  for (int i=0; i<CH_SPACEDIM-1; ++i)
    {
      ai = m_point[tanDirs[i]] - lo[tanDirs[i]];
      bi = m_point[tanDirs[i]] - hi[tanDirs[i]];
      a = ai * ai;
      b = bi * bi;
      dmax = dmax + Max(a,b);
      if (m_point[tanDirs[i]] < lo[tanDirs[i]] || m_point[tanDirs[i]] > hi[tanDirs[i]]) dmin = dmin + Min(a,b);
    }

  if (m_inside)
    {
      if (dmin >= m_radius2) return GeometryService::Covered;
      if (dmax <  m_radius2) return GeometryService::Regular;
    }
  else
    {
      if (dmin >  m_radius2) return GeometryService::Regular;
      if (dmax <= m_radius2) return GeometryService::Covered;
    }
  return GeometryService::Irregular;
}
Exemple #24
0
/* cube_union_v0 */
NDBOX *
cube_union_v0(NDBOX *a, NDBOX *b)
{
	int			i;
	NDBOX	   *result;
	int			dim;
	int			size;

	/* trivial case */
	if (a == b)
		return a;

	/* swap the arguments if needed, so that 'a' is always larger than 'b' */
	if (DIM(a) < DIM(b))
	{
		NDBOX	   *tmp = b;

		b = a;
		a = tmp;
	}
	dim = DIM(a);

	size = CUBE_SIZE(dim);
	result = palloc0(size);
	SET_VARSIZE(result, size);
	SET_DIM(result, dim);

	/* First compute the union of the dimensions present in both args */
	for (i = 0; i < DIM(b); i++)
	{
		result->x[i] = Min(
						   Min(LL_COORD(a, i), UR_COORD(a, i)),
						   Min(LL_COORD(b, i), UR_COORD(b, i))
			);
		result->x[i + DIM(a)] = Max(
									Max(LL_COORD(a, i), UR_COORD(a, i)),
									Max(LL_COORD(b, i), UR_COORD(b, i))
			);
	}
	/* continue on the higher dimensions only present in 'a' */
	for (; i < DIM(a); i++)
	{
		result->x[i] = Min(0,
						   Min(LL_COORD(a, i), UR_COORD(a, i))
			);
		result->x[i + dim] = Max(0,
								 Max(LL_COORD(a, i), UR_COORD(a, i))
			);
	}

	/*
	 * Check if the result was in fact a point, and set the flag in the datum
	 * accordingly. (we don't bother to repalloc it smaller)
	 */
	if (cube_is_point_internal(result))
	{
		size = POINT_SIZE(dim);
		SET_VARSIZE(result, size);
		SET_POINT_BIT(result);
	}

	return (result);
}
Exemple #25
0
#include ELEM_SCALE_INC
#include ELEM_GERU_INC

namespace elem {
namespace lu {

// Local LU _without_ partial pivoting

template<typename F> 
inline void
UnbFLAME( Matrix<F>& A )
{
    DEBUG_ONLY(CallStackEntry cse("lu::UnbFLAME"))
    const Int m = A.Height();
    const Int n = A.Width();
    const Int minDim = Min(m,n);
    for( Int k=0; k<minDim; ++k )
    {
        auto alpha11 = ViewRange( A, k,   k,   k+1, k+1 );
        auto a12     = ViewRange( A, k,   k+1, k+1, n   );
        auto a21     = ViewRange( A, k+1, k,   m,   k+1 );
        auto A22     = ViewRange( A, k+1, k+1, m,   n   );

        F alpha = alpha11.Get(0,0);
        if( alpha == F(0) )
            throw SingularMatrixException();
        Scale( 1/alpha, a21 );
        Geru( F(-1), a21, a12, A22 );
    }
}
Exemple #26
0
/* cube_inter */
Datum
cube_inter(PG_FUNCTION_ARGS)
{
	NDBOX	   *a = PG_GETARG_NDBOX(0);
	NDBOX	   *b = PG_GETARG_NDBOX(1);
	NDBOX	   *result;
	bool		swapped = false;
	int			i;
	int			dim;
	int			size;

	/* swap the arguments if needed, so that 'a' is always larger than 'b' */
	if (DIM(a) < DIM(b))
	{
		NDBOX	   *tmp = b;

		b = a;
		a = tmp;
		swapped = true;
	}
	dim = DIM(a);

	size = CUBE_SIZE(dim);
	result = (NDBOX *) palloc0(size);
	SET_VARSIZE(result, size);
	SET_DIM(result, dim);

	/* First compute intersection of the dimensions present in both args */
	for (i = 0; i < DIM(b); i++)
	{
		result->x[i] = Max(
						   Min(LL_COORD(a, i), UR_COORD(a, i)),
						   Min(LL_COORD(b, i), UR_COORD(b, i))
			);
		result->x[i + DIM(a)] = Min(
									Max(LL_COORD(a, i), UR_COORD(a, i)),
									Max(LL_COORD(b, i), UR_COORD(b, i))
			);
	}
	/* continue on the higher dimensions only present in 'a' */
	for (; i < DIM(a); i++)
	{
		result->x[i] = Max(0,
						   Min(LL_COORD(a, i), UR_COORD(a, i))
			);
		result->x[i + DIM(a)] = Min(0,
									Max(LL_COORD(a, i), UR_COORD(a, i))
			);
	}

	/*
	 * Check if the result was in fact a point, and set the flag in the datum
	 * accordingly. (we don't bother to repalloc it smaller)
	 */
	if (cube_is_point_internal(result))
	{
		size = POINT_SIZE(dim);
		result = repalloc(result, size);
		SET_VARSIZE(result, size);
		SET_POINT_BIT(result);
	}

	if (swapped)
	{
		PG_FREE_IF_COPY(b, 0);
		PG_FREE_IF_COPY(a, 1);
	}
	else
	{
		PG_FREE_IF_COPY(a, 0);
		PG_FREE_IF_COPY(b, 1);
	}

	/*
	 * Is it OK to return a non-null intersection for non-overlapping boxes?
	 */
	PG_RETURN_NDBOX(result);
}
Exemple #27
0
/*
 * --------------------------------------------------------------------------
 * Double sorting split algorithm. This is used for both boxes and points.
 *
 * The algorithm finds split of boxes by considering splits along each axis.
 * Each entry is first projected as an interval on the X-axis, and different
 * ways to split the intervals into two groups are considered, trying to
 * minimize the overlap of the groups. Then the same is repeated for the
 * Y-axis, and the overall best split is chosen. The quality of a split is
 * determined by overlap along that axis and some other criteria (see
 * g_box_consider_split).
 *
 * After that, all the entries are divided into three groups:
 *
 * 1) Entries which should be placed to the left group
 * 2) Entries which should be placed to the right group
 * 3) "Common entries" which can be placed to any of groups without affecting
 *	  of overlap along selected axis.
 *
 * The common entries are distributed by minimizing penalty.
 *
 * For details see:
 * "A new___ double sorting-based node splitting algorithm for R-tree", A. Korotkov
 * http://syrcose.ispras.ru/2011/files/SYRCoSE2011_Proceedings.pdf#page=36
 * --------------------------------------------------------------------------
 */
Datum
gist_box_picksplit(PG_FUNCTION_ARGS)
{
	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
	GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
	OffsetNumber i,
				maxoff;
	ConsiderSplitContext context;
	BOX		   *box,
			   *leftBox,
			   *rightBox;
	int			dim,
				commonEntriesCount;
	SplitInterval *intervalsLower,
			   *intervalsUpper;
	CommonEntry *commonEntries;
	int			nentries;

	memset(&context, 0, sizeof(ConsiderSplitContext));

	maxoff = entryvec->n - 1;
	nentries = context.entriesCount = maxoff - FirstOffsetNumber + 1;

	/* Allocate arrays for intervals along axes */
	intervalsLower = (SplitInterval *) palloc(nentries * sizeof(SplitInterval));
	intervalsUpper = (SplitInterval *) palloc(nentries * sizeof(SplitInterval));

	/*
	 * Calculate the overall minimum bounding box over all the entries.
	 */
	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
	{
		box = DatumGetBoxP(entryvec->vector[i].key);
		if (i == FirstOffsetNumber)
			context.boundingBox = *box;
		else
			adjustBox(&context.boundingBox, box);
	}

	/*
	 * Iterate over axes for optimal split searching.
	 */
	context.first = true;		/* nothing selected yet */
	for (dim = 0; dim < 2; dim++)
	{
		double		leftUpper,
					rightLower;
		int			i1,
					i2;

		/* Project each entry as an interval on the selected axis. */
		for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
		{
			box = DatumGetBoxP(entryvec->vector[i].key);
			if (dim == 0)
			{
				intervalsLower[i - FirstOffsetNumber].lower = box->low.x;
				intervalsLower[i - FirstOffsetNumber].upper = box->high.x;
			}
			else
			{
				intervalsLower[i - FirstOffsetNumber].lower = box->low.y;
				intervalsLower[i - FirstOffsetNumber].upper = box->high.y;
			}
		}

		/*
		 * Make two arrays of intervals: one sorted by lower bound and another
		 * sorted by upper bound.
		 */
		memcpy(intervalsUpper, intervalsLower,
			   sizeof(SplitInterval) * nentries);
		qsort(intervalsLower, nentries, sizeof(SplitInterval),
			  interval_cmp_lower);
		qsort(intervalsUpper, nentries, sizeof(SplitInterval),
			  interval_cmp_upper);

		/*----
		 * The goal is to form a left and right interval, so that every entry
		 * interval is contained by either left or right interval (or both).
		 *
		 * For example, with the intervals (0,1), (1,3), (2,3), (2,4):
		 *
		 * 0 1 2 3 4
		 * +-+
		 *	 +---+
		 *	   +-+
		 *	   +---+
		 *
		 * The left and right intervals are of the form (0,a) and (b,4).
		 * We first consider splits where b is the lower bound of an entry.
		 * We iterate through all entries, and for each b, calculate the
		 * smallest possible a. Then we consider splits where a is the
		 * uppper bound of an entry, and for each a, calculate the greatest
		 * possible b.
		 *
		 * In the above example, the first loop would consider splits:
		 * b=0: (0,1)-(0,4)
		 * b=1: (0,1)-(1,4)
		 * b=2: (0,3)-(2,4)
		 *
		 * And the second loop:
		 * a=1: (0,1)-(1,4)
		 * a=3: (0,3)-(2,4)
		 * a=4: (0,4)-(2,4)
		 */

		/*
		 * Iterate over lower bound of right group, finding smallest possible
		 * upper bound of left group.
		 */
		i1 = 0;
		i2 = 0;
		rightLower = intervalsLower[i1].lower;
		leftUpper = intervalsUpper[i2].lower;
		while (true)
		{
			/*
			 * Find next lower bound of right group.
			 */
			while (i1 < nentries && rightLower == intervalsLower[i1].lower)
			{
				leftUpper = Max(leftUpper, intervalsLower[i1].upper);
				i1++;
			}
			if (i1 >= nentries)
				break;
			rightLower = intervalsLower[i1].lower;

			/*
			 * Find count of intervals which anyway should be placed to the
			 * left group.
			 */
			while (i2 < nentries && intervalsUpper[i2].upper <= leftUpper)
				i2++;

			/*
			 * Consider found split.
			 */
			g_box_consider_split(&context, dim, rightLower, i1, leftUpper, i2);
		}

		/*
		 * Iterate over upper bound of left group finding greates possible
		 * lower bound of right group.
		 */
		i1 = nentries - 1;
		i2 = nentries - 1;
		rightLower = intervalsLower[i1].upper;
		leftUpper = intervalsUpper[i2].upper;
		while (true)
		{
			/*
			 * Find next upper bound of left group.
			 */
			while (i2 >= 0 && leftUpper == intervalsUpper[i2].upper)
			{
				rightLower = Min(rightLower, intervalsUpper[i2].lower);
				i2--;
			}
			if (i2 < 0)
				break;
			leftUpper = intervalsUpper[i2].upper;

			/*
			 * Find count of intervals which anyway should be placed to the
			 * right group.
			 */
			while (i1 >= 0 && intervalsLower[i1].lower >= rightLower)
				i1--;

			/*
			 * Consider found split.
			 */
			g_box_consider_split(&context, dim,
								 rightLower, i1 + 1, leftUpper, i2 + 1);
		}
	}

	/*
	 * If we failed to find any acceptable splits, use trivial split.
	 */
	if (context.first)
	{
		fallbackSplit(entryvec, v);
		PG_RETURN_POINTER(v);
	}

	/*
	 * Ok, we have now selected the split across one axis.
	 *
	 * While considering the splits, we already determined that there will be
	 * enough entries in both groups to reach the desired ratio, but we did
	 * not memorize which entries go to which group. So determine that now.
	 */

	/* Allocate vectors for results */
	v->spl_left = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
	v->spl_right = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
	v->spl_nleft = 0;
	v->spl_nright = 0;

	/* Allocate bounding boxes of left and right groups */
	leftBox = static_cast<BOX *>(palloc0(sizeof(BOX)));
	rightBox = static_cast<BOX *>(palloc0(sizeof(BOX)));

	/*
	 * Allocate an array for "common entries" - entries which can be placed to
	 * either group without affecting overlap along selected axis.
	 */
	commonEntriesCount = 0;
	commonEntries = (CommonEntry *) palloc(nentries * sizeof(CommonEntry));

	/* Helper macros to place an entry in the left or right group */
#define PLACE_LEFT(box, off)					\
	do {										\
		if (v->spl_nleft > 0)					\
			adjustBox(leftBox, box);			\
		else									\
			*leftBox = *(box);					\
		v->spl_left[v->spl_nleft++] = off;		\
	} while(0)

#define PLACE_RIGHT(box, off)					\
	do {										\
		if (v->spl_nright > 0)					\
			adjustBox(rightBox, box);			\
		else									\
			*rightBox = *(box);					\
		v->spl_right[v->spl_nright++] = off;	\
	} while(0)

	/*
	 * Distribute entries which can be distributed unambiguously, and collect
	 * common entries.
	 */
	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
	{
		double		lower,
					upper;

		/*
		 * Get upper and lower bounds along selected axis.
		 */
		box = DatumGetBoxP(entryvec->vector[i].key);
		if (context.dim == 0)
		{
			lower = box->low.x;
			upper = box->high.x;
		}
		else
		{
			lower = box->low.y;
			upper = box->high.y;
		}

		if (upper <= context.leftUpper)
		{
			/* Fits to the left group */
			if (lower >= context.rightLower)
			{
				/* Fits also to the right group, so "common entry" */
				commonEntries[commonEntriesCount++].index = i;
			}
			else
			{
				/* Doesn't fit to the right group, so join to the left group */
				PLACE_LEFT(box, i);
			}
		}
		else
		{
			/*
			 * Each entry should fit on either left or right group. Since this
			 * entry didn't fit on the left group, it better fit in the right
			 * group.
			 */
			Assert(lower >= context.rightLower);

			/* Doesn't fit to the left group, so join to the right group */
			PLACE_RIGHT(box, i);
		}
	}

	/*
	 * Distribute "common entries", if any.
	 */
	if (commonEntriesCount > 0)
	{
		/*
		 * Calculate minimum number of entries that must be placed in both
		 * groups, to reach LIMIT_RATIO.
		 */
		int			m = ceil(LIMIT_RATIO * (double) nentries);

		/*
		 * Calculate delta between penalties of join "common entries" to
		 * different groups.
		 */
		for (i = 0; i < commonEntriesCount; i++)
		{
			box = DatumGetBoxP(entryvec->vector[commonEntries[i].index].key);
			commonEntries[i].delta = Abs(box_penalty(leftBox, box) -
										 box_penalty(rightBox, box));
		}

		/*
		 * Sort "common entries" by calculated deltas in order to distribute
		 * the most ambiguous entries first.
		 */
		qsort(commonEntries, commonEntriesCount, sizeof(CommonEntry), common_entry_cmp);

		/*
		 * Distribute "common entries" between groups.
		 */
		for (i = 0; i < commonEntriesCount; i++)
		{
			box = DatumGetBoxP(entryvec->vector[commonEntries[i].index].key);

			/*
			 * Check if we have to place this entry in either group to achieve
			 * LIMIT_RATIO.
			 */
			if (v->spl_nleft + (commonEntriesCount - i) <= m)
				PLACE_LEFT(box, commonEntries[i].index);
			else if (v->spl_nright + (commonEntriesCount - i) <= m)
				PLACE_RIGHT(box, commonEntries[i].index);
			else
			{
				/* Otherwise select the group by minimal penalty */
				if (box_penalty(leftBox, box) < box_penalty(rightBox, box))
					PLACE_LEFT(box, commonEntries[i].index);
				else
					PLACE_RIGHT(box, commonEntries[i].index);
			}
		}
	}

	v->spl_ldatum = PointerGetDatum(leftBox);
	v->spl_rdatum = PointerGetDatum(rightBox);
	PG_RETURN_POINTER(v);
}
Exemple #28
0
/* make up a metric in which one box will be 'lower' than the other
   -- this can be useful for sorting and to determine uniqueness */
int32
cube_cmp_v0(NDBOX *a, NDBOX *b)
{
	int			i;
	int			dim;

	dim = Min(DIM(a), DIM(b));

	/* compare the common dimensions */
	for (i = 0; i < dim; i++)
	{
		if (Min(LL_COORD(a, i), UR_COORD(a, i)) >
			Min(LL_COORD(b, i), UR_COORD(b, i)))
			return 1;
		if (Min(LL_COORD(a, i), UR_COORD(a, i)) <
			Min(LL_COORD(b, i), UR_COORD(b, i)))
			return -1;
	}
	for (i = 0; i < dim; i++)
	{
		if (Max(LL_COORD(a, i), UR_COORD(a, i)) >
			Max(LL_COORD(b, i), UR_COORD(b, i)))
			return 1;
		if (Max(LL_COORD(a, i), UR_COORD(a, i)) <
			Max(LL_COORD(b, i), UR_COORD(b, i)))
			return -1;
	}

	/* compare extra dimensions to zero */
	if (DIM(a) > DIM(b))
	{
		for (i = dim; i < DIM(a); i++)
		{
			if (Min(LL_COORD(a, i), UR_COORD(a, i)) > 0)
				return 1;
			if (Min(LL_COORD(a, i), UR_COORD(a, i)) < 0)
				return -1;
		}
		for (i = dim; i < DIM(a); i++)
		{
			if (Max(LL_COORD(a, i), UR_COORD(a, i)) > 0)
				return 1;
			if (Max(LL_COORD(a, i), UR_COORD(a, i)) < 0)
				return -1;
		}

		/*
		 * if all common dimensions are equal, the cube with more dimensions
		 * wins
		 */
		return 1;
	}
	if (DIM(a) < DIM(b))
	{
		for (i = dim; i < DIM(b); i++)
		{
			if (Min(LL_COORD(b, i), UR_COORD(b, i)) > 0)
				return -1;
			if (Min(LL_COORD(b, i), UR_COORD(b, i)) < 0)
				return 1;
		}
		for (i = dim; i < DIM(b); i++)
		{
			if (Max(LL_COORD(b, i), UR_COORD(b, i)) > 0)
				return -1;
			if (Max(LL_COORD(b, i), UR_COORD(b, i)) < 0)
				return 1;
		}

		/*
		 * if all common dimensions are equal, the cube with more dimensions
		 * wins
		 */
		return -1;
	}

	/* They're really equal */
	return 0;
}
Exemple #29
0
int main(int argc, char * argv[])
{
	try
	{
		libmaus2::util::ArgInfo const arginfo(argc,argv);
		std::string const isain = arginfo.getUnparsedRestArg(0);
		std::string const isaout = arginfo.getUnparsedRestArg(1);

		std::string const tmpdir = arginfo.getUnparsedValue("tmpdir",arginfo.getCurDir());
		std::string const tmpout = tmpdir + "/" + arginfo.getDefaultTmpFileName() + "_sort_isa.tmp";

		libmaus2::util::TempFileRemovalContainer::addTempFile(tmpout);

		// std::string const tmpout = isaout + ".tmp";
		uint64_t const sortbufsize = arginfo.getValueUnsignedNumeric<uint64_t>("sortbufsize",16*1024*1024);
		uint64_t const inbufsize = arginfo.getValueUnsignedNumeric<uint64_t>("inbufsize",8*1024);
		bool const verbose = arginfo.getValue<int>("verbose",1);

		libmaus2::aio::OutputStream::unique_ptr_type Ptmp(libmaus2::aio::OutputStreamFactoryContainer::constructUnique(tmpout));
		libmaus2::aio::SortingBufferedOutput< std::pair<uint64_t,uint64_t> >::unique_ptr_type Psortout(
			new libmaus2::aio::SortingBufferedOutput< std::pair<uint64_t,uint64_t> >(*Ptmp,sortbufsize));

		libmaus2::aio::InputStream::unique_ptr_type Pin(libmaus2::aio::InputStreamFactoryContainer::constructUnique(isain));
		libmaus2::aio::SynchronousGenericInput<uint64_t> Sin(*Pin,inbufsize);
		uint64_t v0 = 0, v1 = 0;
		uint64_t c_in = 0;

		while ( Sin.peekNext(v0) )
		{
			bool const ok0 = Sin.getNext(v0);
			assert ( ok0 );
			bool const ok1 = Sin.getNext(v1);
			if ( ! ok1 )
			{
				libmaus2::exception::LibMausException lme;
				lme.getStream() << "Uneven number of words in input file." << std::endl;
				lme.finish();
				throw lme;
			}
			Psortout->put(std::pair<uint64_t,uint64_t>(v1,v0));
			c_in += 1;

			if ( verbose && (c_in & (1024*1024-1)) == 0 )
				std::cerr << "[V] in " << c_in/(1024*1024) << std::endl;
		}
		Psortout->flush();
		std::vector<uint64_t> const blocksizes = Psortout->getBlockSizes();
		Psortout.reset();
		Ptmp->flush();
		Ptmp.reset();

		// libmaus2::aio::InputStream::unique_ptr_type Ptmpin(libmaus2::aio::InputStreamFactoryContainer::constructUnique(tmpout));
		libmaus2::sorting::MergingReadBack< std::pair<uint64_t,uint64_t> >::unique_ptr_type Min(
			new libmaus2::sorting::MergingReadBack< std::pair<uint64_t,uint64_t> >(tmpout,blocksizes)
		);

		std::pair<uint64_t,uint64_t> P;
		libmaus2::aio::OutputStream::unique_ptr_type Pout(libmaus2::aio::OutputStreamFactoryContainer::constructUnique(isaout));
		uint64_t c_out = 0;
		bool gotfirst = false;
		bool gotfirstdif = false;
		bool difconsistent = true;
		uint64_t firstpos = std::numeric_limits<uint64_t>::max();
		uint64_t prevpos = std::numeric_limits<uint64_t>::max();
		uint64_t firstdif = std::numeric_limits<uint64_t>::max();
		libmaus2::util::Histogram hist;
		while ( Min->getNext(P) )
		{
			libmaus2::util::NumberSerialisation::serialiseNumber(*Pout,P.first);
			libmaus2::util::NumberSerialisation::serialiseNumber(*Pout,P.second);

			c_out += 1;

			if ( verbose && (c_out & (1024*1024-1)) == 0 )
				std::cerr << "[V] out " << static_cast<double>(c_out) / c_in << " first pos " << firstpos << " first dif " << firstdif << " consistent " << difconsistent << std::endl;

			if ( ! gotfirst )
			{
				gotfirst = true;
				firstpos = P.first;
			}
			else
			{
				assert ( prevpos != std::numeric_limits<uint64_t>::max() );
				assert ( P.first > prevpos );
				uint64_t const dif = P.first - prevpos;

				hist(dif);

				if ( ! gotfirstdif )
				{
					gotfirstdif = true;
					firstdif = dif;
				}
				else
				{
					if ( dif != firstdif )
						difconsistent = false;
				}
			}
			prevpos = P.first;
		}

		if ( verbose )
			std::cerr << "[V] out " << static_cast<double>(c_out) / c_in << " first pos " << firstpos << " first dif " << firstdif << " consistent " << difconsistent << std::endl;


		Min.reset();
		Pout->flush();
		Pout.reset();

		hist.print(std::cerr);
	}
	catch(std::exception const & ex)
	{
		std::cerr << ex.what() << std::endl;
	}
}
Exemple #30
0
/*
 * bms_subset_compare - compare A and B for equality/subset relationships
 *
 * This is more efficient than testing bms_is_subset in both directions.
 */
BMS_Comparison
bms_subset_compare(const Bitmapset *a, const Bitmapset *b)
{
	BMS_Comparison result;
	int			shortlen;
	int			longlen;
	int			i;

	/* Handle cases where either input is NULL */
	if (a == NULL)
	{
		if (b == NULL)
			return BMS_EQUAL;
		return bms_is_empty(b) ? BMS_EQUAL : BMS_SUBSET1;
	}
	if (b == NULL)
		return bms_is_empty(a) ? BMS_EQUAL : BMS_SUBSET2;
	/* Check common words */
	result = BMS_EQUAL;			/* status so far */
	shortlen = Min(a->nwords, b->nwords);
	for (i = 0; i < shortlen; i++)
	{
		bitmapword	aword = a->words[i];
		bitmapword	bword = b->words[i];

		if ((aword & ~bword) != 0)
		{
			/* a is not a subset of b */
			if (result == BMS_SUBSET1)
				return BMS_DIFFERENT;
			result = BMS_SUBSET2;
		}
		if ((bword & ~aword) != 0)
		{
			/* b is not a subset of a */
			if (result == BMS_SUBSET2)
				return BMS_DIFFERENT;
			result = BMS_SUBSET1;
		}
	}
	/* Check extra words */
	if (a->nwords > b->nwords)
	{
		longlen = a->nwords;
		for (; i < longlen; i++)
		{
			if (a->words[i] != 0)
			{
				/* a is not a subset of b */
				if (result == BMS_SUBSET1)
					return BMS_DIFFERENT;
				result = BMS_SUBSET2;
			}
		}
	}
	else if (a->nwords < b->nwords)
	{
		longlen = b->nwords;
		for (; i < longlen; i++)
		{
			if (b->words[i] != 0)
			{
				/* b is not a subset of a */
				if (result == BMS_SUBSET2)
					return BMS_DIFFERENT;
				result = BMS_SUBSET1;
			}
		}
	}
	return result;
}