예제 #1
0
void free_cell(vtab_p table, int row, int col) {
	cell_p c_ptr = GET_CELL_PTR(row, col);
	if ((c_ptr->type == CELL_TYPE_STRING)
	    && (c_ptr->flags & CELL_FLAG_FREEABLE)
	    && (c_ptr->s != NULL)) {
		free(c_ptr->s);
	}
	memset(c_ptr, 0, sizeof(cell_t));
}
예제 #2
0
void zero_table_data(vtab_p table, int type) {
	// Sets data area of table to zeros of specified type
	for (int row = table->header_rows; (row < ALL_TABLE_ROWS); row++) {
		for (int col = table->header_cols; (col < ALL_TABLE_COLS); col++) {
			cell_p c_ptr = GET_CELL_PTR(row, col);
			memset(c_ptr, 0, sizeof(cell_t));
			c_ptr->type = type;
		}
	}
}
예제 #3
0
void sort_rows_descending_by_col(vtab_p table, int start_row, int stop_row, int col) {
	// Rearrange row_ix_map[] indices so the rows will be in
	// descending order by the value in the specified column
	for (int ix = start_row; (ix <= stop_row); ix++) {
		int biggest_ix = ix;
		cell_p biggest_ix_c_ptr = GET_CELL_PTR(table->row_ix_map[ix], col);
		for (int iy = ix + 1; (iy <= stop_row); iy++) {
			cell_p iy_c_ptr = GET_CELL_PTR(table->row_ix_map[iy], col);
			if (biggest_ix_c_ptr->d < iy_c_ptr->d) {
				biggest_ix_c_ptr = iy_c_ptr;
				biggest_ix = iy;
			}
		}
		if (biggest_ix != ix) {
			int tmp = table->row_ix_map[ix];
			table->row_ix_map[ix] = table->row_ix_map[biggest_ix];
			table->row_ix_map[biggest_ix] = tmp;
		}
	}
}
예제 #4
0
/**
 * Fills the world with specified number of people and zombies.
 * The people are of different age; zombies are "brand new".
 */
void randomDistribution(WorldPtr world, int people, int zombies, simClock clock) {
	world->stats.clock = clock;
	world->stats.infectedFemales = 0;
	world->stats.infectedMales = 0;

	for (int i = 0; i < people;) {
		int x = randomInt(world->xStart, world->xEnd);
		int y = randomInt(world->yStart, world->yEnd);
		CellPtr cellPtr = GET_CELL_PTR(world, x, y);
		if (cellPtr->type != NONE) {
			continue;
		}

		newHuman(cellPtr, clock);
		if (cellPtr->gender == FEMALE) {
			world->stats.humanFemales++;
		} else {
			world->stats.humanMales++;
		}

		i++;
	}

	for (int i = 0; i < zombies;) {
		int x = randomInt(world->xStart, world->xEnd);
		int y = randomInt(world->yStart, world->yEnd);
		CellPtr cellPtr = GET_CELL_PTR(world, x, y);
		if (cellPtr->type != NONE) {
			continue;
		}

		newZombie(cellPtr, clock);
		world->stats.zombies++;

		i++;
	}
}
예제 #5
0
void auto_set_col_width(vtab_p table, int col, int min_width, int max_width) {
	int width = min_width;
	for (int row = 0; (row < ALL_TABLE_ROWS); row++) {
		cell_p c_ptr = GET_CELL_PTR(row, col);
		if (c_ptr->type == CELL_TYPE_REPCHAR) {
			continue;
		}
		char *p = fmt_cell_data(c_ptr, max_width, (int)(table->col_decimal_places[col]));
		int l = strlen(p);
		if (width < l) {
			width = l;
		}
	}
	width += USUAL_GUTTER_WIDTH;
	if (width > max_width) {
		width = max_width;
	}
	table->col_width[col] = (uint8_t)width;
}
예제 #6
0
void display_table(vtab_p table,
		      int screen_width,
		      int show_unseen_rows,
		      int show_unseen_cols,
		      int show_zero_rows,
		      int show_zero_cols)
{
	// Set row and column flags according to whether data in rows and cols
	// has been assigned, and is currently non-zero.
	int some_seen_data = 0;
	int some_non_zero_data = 0;
	for (int row = table->header_rows; (row < ALL_TABLE_ROWS); row++) {
		for (int col = table->header_cols; (col < ALL_TABLE_COLS); col++) {
			cell_p c_ptr = GET_CELL_PTR(row, col);
			// Currently, "seen data" includes not only numeric data, but also
			// any strings, etc -- anything non-NULL (other than rephcars).
			if ((c_ptr->type != CELL_TYPE_NULL) && (c_ptr->type != CELL_TYPE_REPCHAR)) {
				some_seen_data = 1;
				set_row_flag(table, row, ROW_FLAG_SEEN_DATA);
				set_col_flag(table, col, COL_FLAG_SEEN_DATA);
				// Currently, "non-zero data" includes not only numeric data,
				// but also any strings, etc -- anything non-zero (other than
				// repchars, which are already excluded above).  So, note a
				// valid non-NULL pointer to an empty string would still be
				// counted as non-zero data.
				if (c_ptr->l != (int64_t)0) {
					some_non_zero_data = 1;
					set_row_flag(table, row, ROW_FLAG_NON_ZERO_DATA);
					set_col_flag(table, col, COL_FLAG_NON_ZERO_DATA);
				}
			}
		}
	}
	if (!some_seen_data) {
		printf("Table has no data.\n");
		return;
	}
	if (!some_non_zero_data && !show_zero_rows && !show_zero_cols) {
		printf("Table has no non-zero data.\n");
		return;
	}
	// Start with first data column and try to display table,
	// folding lines as necessary per screen_width
	int col = -1;
	int data_col = table->header_cols;
	while (data_col < ALL_TABLE_COLS) {
		// Skip data columns until we have one to display
		if ((!test_col_flag(table, data_col, COL_FLAG_ALWAYS_SHOW)) &&
		    (((!show_unseen_cols) && (!test_col_flag(table, data_col, COL_FLAG_SEEN_DATA))) ||
		     ((!show_zero_cols)   && (!test_col_flag(table, data_col, COL_FLAG_NON_ZERO_DATA))))) {
			data_col += 1;
			continue;
		}
		// Display blank line between table sections
		if (col > 0) {
			printf("\n");
		}
		// For each row, display as many columns as possible
		for (int row_ix = 0; (row_ix < ALL_TABLE_ROWS); row_ix++) {
			int row = table->row_ix_map[row_ix];
			// If past the header rows, conditionally skip rows
			if ((row >= table->header_rows) && (!test_row_flag(table, row, ROW_FLAG_ALWAYS_SHOW))) {
				// Optionally skip row if no data seen or if all zeros
				if (((!show_unseen_rows) && (!test_row_flag(table, row, ROW_FLAG_SEEN_DATA))) ||
				    ((!show_zero_rows)   && (!test_row_flag(table, row, ROW_FLAG_NON_ZERO_DATA)))) {
					continue;
				}
			}
			// Begin a new row...
			int cur_line_width = 0;
			// All lines start with the left header columns
			for (col = 0; (col < table->header_cols); col++) {
				display_justified_cell(GET_CELL_PTR(row, col),
						       (int)(table->row_flags[row]),
						       (int)(table->col_flags[col]),
						       (int)(table->col_width[col]),
						       (int)(table->col_decimal_places[col]));
				cur_line_width += (int)(table->col_width[col]);
			}
			// Reset column index to starting data column for each new row
			col = data_col;
			// Try to display as many data columns as possible in every section
			for (;;) {
				// See if we should print this column
				if (test_col_flag(table, col, COL_FLAG_ALWAYS_SHOW) ||
				    (((show_unseen_cols) || (test_col_flag(table, col, COL_FLAG_SEEN_DATA))) &&
				     ((show_zero_cols)   || (test_col_flag(table, col, COL_FLAG_NON_ZERO_DATA))))) {
					display_justified_cell(GET_CELL_PTR(row, col),
							       (int)(table->row_flags[row]),
							       (int)(table->col_flags[col]),
							       (int)(table->col_width[col]),
							       (int)(table->col_decimal_places[col]));
					cur_line_width += (int)(table->col_width[col]);
				}
				col += 1;
				// End the line if no more columns or next column would exceed screen width
				if ((col >= ALL_TABLE_COLS) ||
				    ((cur_line_width + (int)(table->col_width[col])) > screen_width)) {
					break;
				}
			}
			printf("\n");
		}
		// Remember next starting data column for next section
		data_col = col;
	}
}
예제 #7
0
void clear_assign(vtab_p table, int row, int col) {
	cell_p c_ptr = GET_CELL_PTR(row, col);
	memset(c_ptr, 0, sizeof(cell_t));
}
예제 #8
0
void long_addto(vtab_p table, int row, int col, int64_t l) {
	cell_p c_ptr = GET_CELL_PTR(row, col);
	c_ptr->type = CELL_TYPE_LONG;
	c_ptr->l += l;
}
예제 #9
0
void double_addto(vtab_p table, int row, int col, double d) {
	cell_p c_ptr = GET_CELL_PTR(row, col);
	c_ptr->type = CELL_TYPE_DOUBLE;
	c_ptr->d += d;
}
예제 #10
0
void repchar_assign(vtab_p table, int row, int col, char c) {
	cell_p c_ptr = GET_CELL_PTR(row, col);
	c_ptr->type = CELL_TYPE_REPCHAR;
	c_ptr->c[0] = c;
}
예제 #11
0
void string_assign(vtab_p table, int row, int col, char *s) {
	cell_p c_ptr = GET_CELL_PTR(row, col);
	c_ptr->type = CELL_TYPE_STRING;
	c_ptr->s = s;
}
예제 #12
0
int test_cell_flag(vtab_p table, int row, int col, int flag) {
	cell_p c_ptr = GET_CELL_PTR(row, col);
	return ((c_ptr->flags & (uint32_t)flag) != 0);
}
예제 #13
0
void clear_cell_flag(vtab_p table, int row, int col, int flag) {
	cell_p c_ptr = GET_CELL_PTR(row, col);
	c_ptr->flags &= (uint32_t)~flag;
}
예제 #14
0
void set_cell_flag(vtab_p table, int row, int col, int flag) {
	cell_p c_ptr = GET_CELL_PTR(row, col);
	c_ptr->flags |= (uint32_t)flag;
}
예제 #15
0
/**
 * Order of actions:
 * a) death of human or infected
 * b) decomposition of zombie
 * c) transition of infected to zombie
 */
static void simulateStep1(WorldPtr input, WorldPtr output) {
	simClock clock = output->clock;
// we want to force static scheduling because we suppose that the load
// is distributed evenly over the map and we need to have predictable locking
#ifdef _OPENMP
	// at least three columns per thread
	int threads = omp_get_max_threads();
	int numThreads = MIN(MAX(input->localWidth / 3, 1), threads);
#pragma omp parallel for num_threads(numThreads) schedule(static)
#endif
	for (int x = input->xStart; x < input->xEnd; x++) {
		Stats stats = NO_STATS;
		for (int y = input->yStart; y <= input->yEnd; y++) {
			EntityPtr entity = GET_CELL_PTR(input, x, y);
			if (entity->type == NONE) {
				continue;
			}

			// Death of living entity
			if (entity->type == HUMAN || entity->type == INFECTED) {
				if (randomDouble() < getDeathRate(entity, clock)) {
					if (entity->type == HUMAN) {
						if (entity->gender == FEMALE) {
							stats.humanFemalesDied++;
						} else {
							stats.humanMalesDied++;
						}
					} else {
						if (entity->gender == FEMALE) {
							stats.infectedFemalesDied++;
						} else {
							stats.infectedMalesDied++;
						}
					}
					LOG_EVENT("A %s died\n",
							entity->type == HUMAN ? "Human" : "Infected");
					// just forget this entity
					entity->type = NONE;
				}
			}

			// Decompose Zombie
			if (entity->type == ZOMBIE) {
				if (randomDouble() < getDecompositionRate(entity, clock)) {
					stats.zombiesDecomposed++;
					LOG_EVENT("A Zombie decomposed\n");
					// just forgot this entity
					entity->type = NONE;
				}
			}

			// Convert Infected to Zombie
			if (entity->type == INFECTED) {
				if (randomDouble() < PROBABILITY_BECOME_ZOMBIE) {
					if (entity->gender == FEMALE) {
						stats.infectedFemalesBecameZombies++;
					} else {
						stats.infectedMalesBecameZombies++;
					}
					toZombie(entity, clock);
					LOG_EVENT("An Infected became Zombie\n");
				}
			}
		}
#ifdef _OPENMP
#pragma omp critical (StatsCriticalRegion2)
#endif
		{
			mergeStats(&output->stats, stats, true);
		}
	}
}
예제 #16
0
/**
 * Order of actions:
 * a) transition of human into infected
 * b) giving birth to children - changes input
 * c) making love - changes input
 * d) movement
 */
static void simulateStep2(WorldPtr input, WorldPtr output) {
	simClock clock = output->clock;
	// notice that we iterate over xx and yy
	// and the real x and y are randomly switched between two directions
	double xxDir = randomDouble();
	double yyDir = randomDouble();

	// we want to force static scheduling because we suppose that the load
	// is distributed evenly over the map and we need to have predictable locking
#ifdef _OPENMP
	// at least three columns per thread
	int threads = omp_get_max_threads();
	int numThreads = MIN(MAX(input->localWidth / 3, 1), threads);
#pragma omp parallel for num_threads(numThreads) schedule(static)
#endif
	for (int xx = input->xStart; xx <= input->xEnd; xx++) {
		int x = (xxDir < 0.5) ? xx : (input->xEnd + input->xStart - xx);
		// stats are counted per column and summed at the end
		Stats stats = NO_STATS;
		lockColumn(output, x);
		for (int yy = input->yStart; yy <= input->yEnd; yy++) {
			int y = (yyDir < 0.5) ? yy : (input->yEnd + input->yStart - yy);
			Entity entity = GET_CELL(input, x, y);
			if (entity.type == NONE) {
				continue;
			}

			// Convert Human to Infected
			if (entity.type == HUMAN) {
				int zombieCount = countNeighbouringZombies(input, x, y);
				double infectionChance = zombieCount * PROBABILITY_INFECTION;

				if (randomDouble() <= infectionChance) {
					if (entity.gender == FEMALE) {
						stats.humanFemalesBecameInfected++;
					} else {
						stats.humanMalesBecameInfected++;
					}
					toInfected(&entity, clock);
					LOG_EVENT("A Human became infected\n");
				}
			}

			// Here are performed natural processed of humans and infected
			if (entity.type == HUMAN || entity.type == INFECTED) {
				// giving birth
				if (entity.gender == FEMALE && entity.children > 0) {
					if (entity.origin + entity.borns <= clock) {
						if (entity.type == HUMAN) {
							stats.humanFemalesGivingBirth++;
						} else {
							stats.infectedFemalesGivingBirth++;
						}

						Entity * freePtr;
						while (entity.children > 0 && (freePtr =
								getFreeAdjacent(input, output, x, y)) != NULL) {
							Entity child = giveBirth(&entity, clock);
							if (child.type == HUMAN) {
								if (child.gender == FEMALE) {
									stats.humanFemalesBorn++;
								} else {
									stats.humanMalesBorn++;
								}
							} else {
								if (child.gender == FEMALE) {
									stats.infectedFemalesBorn++;
								} else {
									stats.infectedMalesBorn++;
								}
							}
							*freePtr = child;
							LOG_EVENT("A %s child was born\n",
									child.type == HUMAN ? "Human" : "Infected");
						}
					} else {
						if (entity.type == HUMAN) {
							stats.humanFemalesPregnant++;
						} else {
							stats.infectedFemalesPregnant++;
						}
					}
				}

				// making love
				if (entity.gender == FEMALE && entity.children == 0
						&& clock >= entity.origin + entity.fertilityStart
						&& clock < entity.origin + entity.fertilityEnd) { // can have baby
					EntityPtr adjacentMale = findAdjacentFertileMale(input, x,
							y, clock);
					if (adjacentMale != NULL) {
						stats.couplesMakingLove++;
						makeLove(&entity, adjacentMale, clock, input->stats);

						stats.childrenConceived += entity.children;
						LOG_EVENT("A couple made love\n");
					}
				}
			}

			if (entity.type == HUMAN) {
				if (entity.gender == FEMALE) {
					stats.humanFemales++;
				} else {
					stats.humanMales++;
				}
			} else if (entity.type == INFECTED) {
				if (entity.gender == FEMALE) {
					stats.infectedFemales++;
				} else {
					stats.infectedMales++;
				}
			} else {
				stats.zombies++;
			}

			// MOVEMENT

			bearing bearing_ = getBearing(input, x, y); // optimal bearing
			bearing_ += getRandomBearing() * BEARING_FLUCTUATION;

			Direction dir = bearingToDirection(bearing_);
			if (dir != STAY) {
				double bearingRandomQuotient = (randomDouble() - 0.5)
						* BEARING_ABS_QUOTIENT_VARIANCE
						+ BEARING_ABS_QUOTIENT_MEAN;
				entity.bearing = bearing_ / cabsf(bearing_)
						* bearingRandomQuotient;
			} else {
				entity.bearing = bearing_;
			}

			// some randomness in direction
			// the entity will never go in the opposite direction
			if (dir != STAY) {
				if (randomDouble() < getMaxSpeed(&entity, clock)) {
					double dirRnd = randomDouble();
					if (dirRnd < DIRECTION_MISSED) {
						dir = DIRECTION_CCW(dir); // turn counter-clock-wise
					} else if (dirRnd < DIRECTION_MISSED * 2) {
						dir = DIRECTION_CW(dir); // turn clock-wise
					} else if (dirRnd
							> DIRECTION_FOLLOW + DIRECTION_MISSED * 2) {
						dir = STAY;
					}
				} else {
					dir = STAY;
				}
			} else {
				// if the entity would STAY, we'll try again to make it move
				// to make the entity bearing variable in terms of absolute value
				double bearingRandomQuotient = (randomDouble() - 0.5)
						* BEARING_ABS_QUOTIENT_VARIANCE
						+ BEARING_ABS_QUOTIENT_MEAN;

				bearing_ += getRandomBearing() * bearingRandomQuotient;
				dir = bearingToDirection(bearing_);
			}

			// we will try to find the cell in the chosen direction
			CellPtr destPtr = NULL;
			if (dir != STAY) {
				destPtr = IF_CAN_MOVE_TO(x, y, dir);
				if (randomDouble() < MOVEMENT_TRY_ALTERNATIVE) {
					if (destPtr == NULL) {
						destPtr = IF_CAN_MOVE_TO(x, y, DIRECTION_CCW(dir));
					}
					if (destPtr == NULL) {
						destPtr = IF_CAN_MOVE_TO(x, y, DIRECTION_CW(dir));
					}
				}
			}
			if (destPtr == NULL) {
				destPtr = GET_CELL_PTR(output, x, y);
			}

			// actual assignment of entity to its destination
			*destPtr = entity;
		}
		unlockColumn(output, x);
#ifdef _OPENMP
#pragma omp critical (StatsCriticalRegion2)
#endif
		{
			mergeStats(&output->stats, stats, true);
		}
	}
}