예제 #1
0
		public void setCASettings(ICASettings caSettings) {
			this.caSettings = caSettings;
			Point[] neighb = caSettings.Neighborhood;
			invNeighborhood = new Point[neighb.Length];
			for(int i = 0; i < invNeighborhood.Length; i++) {
				Point p = new Point(neighb[i]);
				p.x *= -1;
				p.y *= -1;
				invNeighborhood[i] = p;
			}
		}
예제 #2
0
			/**
			 * Set the range of points this thread should process
			 *
			 * This causes processing to begin.
			 *
			 * @param pointArr The array of points that need checking
			 * @param start The index to start processing at inclusive
			 * @param end The index to stop processing at exclusive
			 **/
			public void setRange(Point[] pointArr, int start, int end) {
				lock(rangeLock) {
					this.pointArr = pointArr;
					this.start = start;
					this.end = end;
					rangeSet = true;
					Monitor.PulseAll(rangeLock);
				}
			}
예제 #3
0
		/**
		 * Calculate the next state of the point at (x,y)
		 *
		 * This involves constructing the neighborhood taking into account wraparound
		 * Then calling the nextState function
		 *
		 * @param x The x coordinate of the point
		 * @param y The y coordinate of the point
		 *
		 * @return The next state of that point
		 **/
		private uint nextState(int x, int y) {
			Point[] neighborhood = caSettings.Neighborhood;
			uint[] nVals = new uint[neighborhood.Length];
			for(int i = 0; i < neighborhood.Length; i++) {
				Point p = new Point(neighborhood[i]);
				p.x = sanitized(p.x + x);
				p.y = sanitized(p.y + y);
				nVals[i] = board[p.x][p.y];
			}
			return caSettings.nextState(nVals);
		}
예제 #4
0
		/**
		 * Step the simulation one step. Return any state changes.
		 *
		 * This involves calculating which points to check and running nextState on each point.
		 * If the state differs from the current state, mark it down.
		 **/
		public IDictionary<Point, uint> step() {
			IDictionary<Point, uint> changes = new Dictionary<Point, uint>();
			// Initially the entire board needs to be checked.
			if(changed == null) {
				for(int i = 0; i < board.Length; i++) {
					for(int j = 0; j < board[i].Length; j++) {
						uint val = nextState(i,j);
						if(val != board[i][j]) {
							changes[new Point(i,j)] = val;
						}
					}
				}
			// Otherwise check only the points that could have changed
			} else {
				// Calculate the points that need to be checked
				HashSet<Point> points = nextRound(changed);
				// If there are less than  50, just run serially.
				if(points.Count < 50) {
					foreach(Point p in points) {
						uint val = nextState(p.x,p.y);
						if(val != board[p.x][p.y]) {
							changes[p] = val;
						}
					}
				// Otherwise use the step threads
				} else {
					// First copy the points into  an array. This allows for easy partitioning of the work
					Point[] pts = new Point[points.Count];
					points.CopyTo(pts);
					// Because I'm not sure if I need this or not but I might so here it is.
					Thread.MemoryBarrier();
					// Calculate about how many points each thread should check
					int step = pts.Length / stepThreads.Length;
					int start = 0;
					// Set the range of each thread.
					// Once the range is set, that thread will start processing its points asynchronously
					// The final step thread needs to check to the end of the array instead of just <step> places
					for(int i = 0; i < stepThreads.Length; i++) {
						stepThreads[i].setRange(pts, start, ((i + 1) < stepThreads.Length) ? start + step : pts.Length);
						start += step;
					}
					// Join the values each thread comes up with back into one changes map.
					// The results method blocks until the calculations for that thread are available.
					foreach(StepPart p in stepThreads) {
						foreach(KeyValuePair<Point, uint> kv in p.results()) {
							changes[kv.Key] = kv.Value;
						}
					}
				}
			}
			// Update the set of points that changed and update the  board state.
			changed = changes.Keys;
			foreach (Point p in changed) {
				board[p.x][p.y] = changes[p];
			}
			return changes;
		}
예제 #5
0
		public IDictionary<Point, uint> step() {
			IDictionary<Point, uint> changes = new Dictionary<Point, uint>();
			if(changed == null) {
				for(int i = 0; i < board.Length; i++) {
					for(int j = 0; j < board[i].Length; j++) {
						uint val = nextState(i,j);
						if(val != board[i][j]) {
							changes[new Point(i,j)] = val;
						}
					}
				}
			} else {
				HashSet<Point> points = nextRound(changed);
				if(points.Count < 50) {
					foreach(Point p in points) {
						uint val = nextState(p.x,p.y);
						if(val != board[p.x][p.y]) {
							changes[p] = val;
						}
					}
				} else {
					Point[] pts = new Point[points.Count];
					points.CopyTo(pts);
					int step = pts.Length / stepThreads.Length;
					int start = 0;
					for(int i = 0; i < stepThreads.Length; i++) {
						stepThreads[i].setRange(pts, start, ((i + 1) < stepThreads.Length) ? start + step : pts.Length);
						start += step;
					}
					foreach(StepPart p in stepThreads) {
						foreach(KeyValuePair<Point, uint> kv in p.results()) {
							changes[kv.Key] = kv.Value;
						}
					}
				}
			}
			changed = changes.Keys;
			foreach (Point p in changed) {
				board[p.x][p.y] = changes[p];
			}
			return changes;
		}
예제 #6
0
		public void toggleState(Point p) {

			enqueue(() => {
				if(curState == State.Stopped) {
					uint newState = (board[p.x][p.y] + 1) % numStates;
					pendingChanges[p] = newState;
					var dict = new Dictionary<Point, uint>();
					dict[p] = newState;
					updateUI(dict);
				} else {
					sendError(CAErrorType.Update, "Simulation must be stopped before points can be updated");
				}
			});
		}
예제 #7
0
		public void setState(Point p, uint state) {

			enqueue(() => {
				if(curState == State.Stopped) {
					pendingChanges[p] = state;
					var dict = new Dictionary<Point, uint>();
					dict[p] = state;
					updateUI(dict);
				} else {
					sendError(CAErrorType.Update, "Simulation must be stopped before points can be updated");
				}
			});
		}