コード例 #1
0
ファイル: tobinary.cs プロジェクト: svendahl/cap
		public tobinary(byte[] input, Tuple<int, int>[] path, ushort loadaddress)
		{
			this.input = input;

			result = new List<byte>();

			result.Add((byte)(loadaddress & 0xff));
			result.Add((byte)(loadaddress >> 8));

			result.Add(input[0]);
			input_ptr = 1;

			bitbuffer = 1;
			bitbuffer_ptr = result.Count;
			result.Add(0);

			state = new state(input);
			state = new state(state, path[0]);

			for (int i = 1; i < path.Length; i++)
			{
				encodestep(path[i]);
			}

			putbits(constant.prefixcode_short_match);
			result.Add(0);

			while (bitbuffer < 256)
			{
				bitbuffer <<= 1;
			}
			result[bitbuffer_ptr] = (byte)(bitbuffer & 0xff);
		}
コード例 #2
0
ファイル: state.cs プロジェクト: svendahl/cap
		public state(state s, Tuple<int, Tuple<int, int>> ce)
		{
			bitcost = s.bitcost + ce.Item1;
			input = s.input;
			length = ce.Item2.Item1;
			offset = ce.Item2.Item2;
			pkey = s.roffs;
			position = s.position + ce.Item2.Item1;
			roffs = ce.Item2.Item1 > 1 ? ce.Item2.Item2 : s.roffs;
			steps = s.steps + 1;
		}
コード例 #3
0
ファイル: state.cs プロジェクト: svendahl/cap
		public state(state s, Tuple<int,int> e)
		{
			bitcost = s.bitcost + model.edge_cost(e.Item1, e.Item2, s);
			this.input = s.input;
			length = e.Item1;
			offset = e.Item2;
			pkey = s.roffs;
			position = s.position + e.Item1;
			roffs = e.Item1 > 1 ? e.Item2 : s.roffs;
			steps = s.steps + 1;
		}
コード例 #4
0
ファイル: tobinary.cs プロジェクト: svendahl/cap
		private void encodestep(Tuple<int, int> edge)
		{
			int length = edge.Item1;
			int offset = edge.Item2;

			if (!model.edge_valid(length, offset, state))
			{
				throw new Exception("wat!");
			}

			if (length == 1)
			{
				if (offset == 0 && !state.posis0)
				{
					putbits(constant.prefixcode_literal);
					result.Add(input[input_ptr]);
				}
				else
				{
					putbits(constant.prefixcode_byte_match);
					for (int s = 3; s >= 0; s--)
					{
						putbit(((offset >> s) & 1));
					}
				}
			}
			else if (length >= 2 && offset == state.roffs && state.lwm == 0)
			{
				putbits(constant.prefixcode_normal_match);
				putgbits(2);
				putgbits(length);
			}
			else if (length >= 2 && length <= 3 && offset > 0 && offset < 128)
			{
				putbits(constant.prefixcode_short_match);
				result.Add((byte)(offset << 1 | (length & 1)));
			}
			else
			{
				putbits(constant.prefixcode_normal_match);
				putgbits((offset >> 8) + (state.lwm == 0 ? 3 : 2));
				result.Add((byte)(offset & 0xff));
				putgbits(length - (offset < 128 || offset >= 32000 ? 2 : offset >= 1280 ? 1 : 0));
			}
			state = new state(state, edge);
			input_ptr += length;
		}
コード例 #5
0
ファイル: model.cs プロジェクト: svendahl/cap
		public static int edge_cost(int length, int offset, state state)
		{
			int output = 0;

			if (length == 1)
			{
				if (offset >= constant.threshold_bytematch_offset)
				{
					throw new Exception("WAT!");
				}
				else if (state.posis0)
				{
					if (state.position == 0)
					{
						output += constant.bitcost_prefixcode_literal + constant.bitcost_literal;
					}
					else
					{
						output += constant.bitcost_prefixcode_bytematch + constant.bitcost_offset_bytematch;
					}
				}
				else if (offset > 0 && offset < constant.threshold_bytematch_offset && !state.posis0)
				{
					output += constant.bitcost_prefixcode_bytematch + constant.bitcost_offset_bytematch;
				}
				else if (offset == 0)
				{
					output += constant.bitcost_prefixcode_literal + constant.bitcost_literal;
				}
			}
			else if (length >= 2 && offset == state.roffs && state.lwm == 0)
			{
				output += constant.bitcost_prefixcode_normalmatch;
				output += togammacount(2);
				output += togammacount(length);
			}
			else if (length >= 2 && length <= 3 && offset > 0 && offset < constant.threshold_shortmatch_offset)
			{
				output += constant.bitcost_prefixcode_shortmatch;
				output += constant.bitcost_literal;
			}
			else if (
				(length == 2 && offset >= constant.threshold_shortmatch_offset && offset < constant.threshold_length2match_offset) ||
				(length == 3 && offset >= constant.threshold_shortmatch_offset && offset < constant.threshold_length3match_offset) ||
				(length >= 4 && offset >= 1 && offset < constant.threshold_offset)
				)
			{
				output += constant.bitcost_prefixcode_normalmatch;

				int offset_hi = (offset >> 8);
				offset_hi += 2;
				if (state.lwm == 0)
				{
					offset_hi += 1;
				}
				output += togammacount(offset_hi);
				output += 8;

				int ldo = 0;
				if (offset < 128 || offset >= constant.threshold_length3match_offset)
				{
					ldo = 2;
				}
				else if (offset >= constant.threshold_length2match_offset)
				{
					ldo = 1;
				}
				output += togammacount(length - ldo);
			}
			else
			{
				throw new Exception("WAT!");
			}

			return output;
		}
コード例 #6
0
ファイル: model.cs プロジェクト: svendahl/cap
		public static bool edge_valid(int length, int offset, state state)
		{
			bool output = false;

			if (length == 1)
			{
				if (offset == 0)
				{
					output = true;
				}
				else if (offset > -1 && offset < constant.threshold_bytematch_offset)
				{
					if (state.lwm == 0 || (state.lwm == 1 && offset != state.roffs))
					{
						output = true;
					}
				}
			}
			else if (length > 1)
			{
				if (offset == state.roffs && state.lwm == 0 && state.roffs != 0 && offset != state.offset)
				{
					output = true;
				}
				else if (offset != state.offset)
				{
					if (length == 2 && offset > 0 && offset < constant.threshold_length2match_offset)
					{
						output = true;
					}
					else if (length == 3 && offset > 0 && offset < constant.threshold_length3match_offset)
					{
						output = true;
					}
					else if (length > 3 && offset > 0 && offset < constant.threshold_offset)
					{
						if (!(offset == state.roffs && state.lwm == 1))//redundant
						{
							output = true;
						}
					}
				}
			}

			return output;
		}
コード例 #7
0
ファイル: edge.cs プロジェクト: svendahl/cap
		private Tuple<int, int>[] edgesof(int index)
		{
			var state = new state(input);
			int offset = int.MaxValue;
			var output = new List<Tuple<int, int>>();

			var rc = edges_sel(edgesll, index);
			var re = rc.GetEnumerator();
			var lc = edges_sel(edgesls, index);
			var le = lc.GetEnumerator();

			var r = edgesnext(ref re);

			if (r.Item1 > 255/*FIXME: magic*/ && r.Item2 == 1)
			{
				return new Tuple<int, int>[1]{r};
			}

			var l = edgesnext(ref le);

			while (l.Item1 > 0 || r.Item1 > 0)
			{
				if (l.Item1 > r.Item1 || l.Item1 == r.Item1 && l.Item2 < r.Item2)
				{
					if (model.edge_valid(l.Item1, l.Item2, state))
					{
						output.Add(l);
					}

					offset = l.Item2;
					if (l.Item1 == r.Item1)
					{
						r = edgesnext(ref re);
					}
					l = edgesnext(ref le);
				}
				else
				{
					if (model.edge_valid(r.Item1, r.Item2, state))
					{
						output.Add(r);
					}

					offset = r.Item2;
					if (r.Item1 == l.Item1)
					{
						l = edgesnext(ref le);
					}
					r = edgesnext(ref re);
				}
				if (offset == 1)
				{
					break;
				}
				while (l.Item2 >= offset)
				{
					l = edgesnext(ref le);
				}
				while (r.Item2 >= offset)
				{
					r = edgesnext(ref re);
				}
			}

			if (!verify(output, index))
			{
				throw new Exception("edge b0rk");
			}
			return output.ToArray();
		}
コード例 #8
0
ファイル: edge.cs プロジェクト: svendahl/cap
		private IEnumerable<Tuple<int,int>> expand(state state)
		{
			if (state.lwm == 0 && state.roffs > 1 && state.position < input.Length - 2 && input[state.position] == input[state.position - state.roffs] && input[state.position + 1] == input[state.position - state.roffs + 1])
			{
				int rl = 2;
				while (state.position + rl < input.Length && input[state.position + rl] == input[state.position - state.roffs + rl])
				{
					rl++;
				}

				bool yb = oe[state.position].Length > 0 && (oe[state.position][0].Item1 < rl && oe[state.position][0].Item2 != state.roffs);

				while (rl > 1)
				{
					yield return new Tuple<int, int>(rl, state.roffs);
					rl--;
				}

				if (yb)
				{
					yield break;
				}
			}

			if (oe[state.position].Length > 0)
			{
				int current_length = oe[state.position][0].Item1;
				int current_offset = oe[state.position][0].Item2;
				if (current_length > 255/*FIXME: magic*/)
				{
					yield return new Tuple<int, int>(current_length, current_offset);
					yield break;
				}

				foreach (Tuple<int, int> t in oe[state.position])
				{
					while (current_length > t.Item1)
					{
						if (model.edge_valid(current_length, current_offset, state))
						{
							yield return new Tuple<int, int>(current_length, current_offset);
						}
						current_length--;
					}
					current_offset = t.Item2;
				}

				while (current_length > 1)
				{
					if (model.edge_valid(current_length, current_offset, state))
					{
						yield return new Tuple<int, int>(current_length, current_offset);
					}
					current_length--;
				}
			}

			if (state.posis0)
			{
				yield return new Tuple<int, int>(1, 0);
			}
			else if (ll1[state.position] > 0 && model.edge_valid(1, state.position - ll1[state.position], state))
			{
				yield return new Tuple<int, int>(1, state.position - ll1[state.position]);
			}

			if (!(oe[state.position].Length > 0 && oe[state.position][0].Item1 > 32/*FIXME: magic*/) && !state.posis0)
			{
				yield return new Tuple<int, int>(1, 0);
			}
		}
コード例 #9
0
ファイル: edge.cs プロジェクト: svendahl/cap
		public IEnumerable<Tuple<int, Tuple<int,int>>> edges(state state)
		{
			var queue = new pqueue<int, Tuple<int, int>>(0, new Tuple<int, int>(-1, -1));//TODO: test cratio

			int ll = int.MaxValue;
			foreach(Tuple<int,int> t in expand(state))
			{
				queue.enqueue(model.edge_cost(t.Item1, t.Item2, state), t);
				ll = t.Item1;
			}

			if (ll != 1)
			{
				yield return new Tuple<int, Tuple<int, int>>(model.edge_cost(1, 0, state), new Tuple<int, int>(1, 0));
			}

			while (queue.count > 0)
			{
				yield return queue.dequeue();
			}
		}
コード例 #10
0
ファイル: path.cs プロジェクト: svendahl/cap
		private void subpath(int cpos, ref int cend)
		{
			var queue = new pqueue<int, int>(0, 0);
			var cendqueue = new pqueue<int, int>(0, 0);

			foreach(KeyValuePair<int, state> kvp in tree[cpos])
			{
				queue.enqueue(kvp.Value.bitcost, kvp.Value.position);
			}

			while (!queue.empty)
			{
				cpos = queue.dequeue().Item2;

				if (!closed[cpos])
				{
					foreach (KeyValuePair<int, state> kvp in tree[cpos])
					{
						int roffs = kvp.Key;
						state cstate = kvp.Value;

						if (cstate.bitcost <= cost[cpos] + cost_tolerance)
						{
							foreach (Tuple<int, Tuple<int, int>> ccostedge in edge.edges(cstate))
							{
								int cedgecost = ccostedge.Item1;
								Tuple<int, int> cedge = ccostedge.Item2;

								if (!closed[cstate.position + cedge.Item1] && cstate.bitcost + cedgecost <= cost[cstate.position + cedge.Item1] + cost_tolerance)
								{
									var dstate = new state(cstate, ccostedge);

									int tl = dstate.position;
									while (tl > cstate.position)
									{
										cost[tl] = dstate.bitcost < cost[tl] ? dstate.bitcost : cost[tl];
										tl--;
									}

									if (!tree[dstate.position].ContainsKey(dstate.roffs))
									{
										tree[dstate.position].Add(dstate.roffs, dstate);
									}
									else if (dstate.bitcost < tree[dstate.position][dstate.roffs].bitcost || (dstate.bitcost == tree[dstate.position][dstate.roffs].bitcost && dstate.steps < tree[dstate.position][dstate.roffs].steps))
									{
										tree[dstate.position][dstate.roffs] = dstate;
									}

									if (dstate.position < cend)
									{
										queue.enqueue(dstate.bitcost, dstate.position);
									}
									else if (dstate.position == cend)
									{
										cendqueue.enqueue(dstate.bitcost, dstate.position);
									}
									else if (dstate.position > cend)
									{
										if (!cendqueue.empty)
										{
											var t = cendqueue.dequeue();
											queue.enqueue(t.Item1, t.Item2);
										}

										while (!cendqueue.empty)
										{
											cendqueue.dequeue();
										}

										cend = dstate.position;
										cendqueue.enqueue(dstate.bitcost, dstate.position);
									}
									/*else
									{
										throw new Exception("head blown");
									}*/
								}
							}
						}
					}
					closed[cpos] = true;
				}
			}
		}