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); }
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; }
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; }
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; }
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; }
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; }
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(); }
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); } }
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(); } }
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; } } }