public virtual void WarmupHashHashLongestMatch(int size, uint[] dict, global::encode.hash.HashLongestMatch hasher) { int _g1 = 0; while ((_g1 < size)) { hasher.Store(dict, 0, _g1++); } }
public static void CreateBackwardReferences(int num_bytes, int position, uint[] ringbuffer, int ringbuffer_mask, double[] literal_cost, int literal_cost_mask, int max_backward_limit, int quality, global::encode.hash.Hashers hashers, int hash_type, int[] dist_cache, global::Array <int> last_insert_len, global::Array <object> commands, int commands_off, global::Array <int> num_commands, global::Array <int> num_literals) { unchecked { if ((quality > 9)) { global::encode.hash.HashLongestMatch hasher = hashers.hash_h9; if (((num_bytes >= 3) && (position >= 3))) { hasher.Store(ringbuffer, ((position - 3) & ringbuffer_mask), (position - 3)); hasher.Store(ringbuffer, ((position - 2) & ringbuffer_mask), (position - 2)); hasher.Store(ringbuffer, ((position - 1) & ringbuffer_mask), (position - 1)); } int[] num_matches = global::FunctionMalloc.mallocInt(num_bytes); global::Array <object> matches = global::FunctionMalloc.mallocArray_encode_hash_BackwardMatch(typeof(global::encode.hash.BackwardMatch), (3 * num_bytes)); int cur_match_pos = 0; int i = 0; while (((i + 3) < num_bytes)) { int max_distance = ((int)(global::System.Math.Min(((double)((position + i))), ((double)(max_backward_limit))))); if ((matches.length < (cur_match_pos + 325))) { matches.concat(global::FunctionMalloc.mallocArray_encode_hash_BackwardMatch(typeof(global::encode.hash.BackwardMatch), ((cur_match_pos + 325) - matches.length))); } hasher.FindAllMatches(ringbuffer, ringbuffer_mask, ((uint)((position + i))), ((uint)((num_bytes - i))), ((uint)(max_distance)), num_matches, i, matches, cur_match_pos); hasher.Store(ringbuffer, ((position + i) & ringbuffer_mask), (position + i)); cur_match_pos += ((int)(((int[])(num_matches))[i])); if ((((int)(((int[])(num_matches))[i])) == 1)) { int match_len = ((global::encode.hash.BackwardMatch)(matches[(cur_match_pos - 1)])).length(); if ((match_len > 325)) { int _g1 = 1; while ((_g1 < match_len)) { ++_g1; ++i; hasher.Store(ringbuffer, ((position + i) & ringbuffer_mask), (position + i)); ((int[])(num_matches))[i] = 0; } } } ++i; } int orig_num_literals = num_literals[0]; int orig_last_insert_len = last_insert_len[0]; int[] orig_dist_cache = ((int[])(new int[4])); ((int[])(orig_dist_cache))[0] = ((int)(((int[])(dist_cache))[0])); ((int[])(orig_dist_cache))[1] = ((int)(((int[])(dist_cache))[1])); ((int[])(orig_dist_cache))[2] = ((int)(((int[])(dist_cache))[2])); ((int[])(orig_dist_cache))[3] = ((int)(((int[])(dist_cache))[3])); int orig_num_commands = num_commands[0]; { int _g11 = 0; while ((_g11 < 2)) { global::encode.backward_references.ZopfliCostModel model = new global::encode.backward_references.ZopfliCostModel(); if ((_g11++ == 0)) { model.SetFromLiteralCosts(num_bytes, position, literal_cost, literal_cost_mask); } else { model.SetFromCommands(num_bytes, position, ringbuffer, ringbuffer_mask, commands, ((commands_off + num_commands[0]) - orig_num_commands), orig_last_insert_len); } num_commands[0] = orig_num_commands; num_literals[0] = orig_num_literals; last_insert_len[0] = orig_last_insert_len; global::DefaultFunctions.memcpy_Int(dist_cache, 0, orig_dist_cache, 0, 4); global::encode.Backward_references.ZopfliIterate(num_bytes, position, ringbuffer, ringbuffer_mask, max_backward_limit, model, num_matches, matches, dist_cache, last_insert_len, commands, commands_off, num_commands, num_literals); } } return; } switch (hash_type) { case 1: { global::encode.Backward_references.CreateBackwardReferences_HashLongestMatchQuickly(num_bytes, position, ringbuffer, ringbuffer_mask, max_backward_limit, quality, hashers.hash_h1, dist_cache, last_insert_len, commands, commands_off, num_commands, num_literals); break; } case 2: { global::encode.Backward_references.CreateBackwardReferences_HashLongestMatchQuickly(num_bytes, position, ringbuffer, ringbuffer_mask, max_backward_limit, quality, hashers.hash_h2, dist_cache, last_insert_len, commands, commands_off, num_commands, num_literals); break; } case 3: { global::encode.Backward_references.CreateBackwardReferences_HashLongestMatchQuickly(num_bytes, position, ringbuffer, ringbuffer_mask, max_backward_limit, quality, hashers.hash_h3, dist_cache, last_insert_len, commands, commands_off, num_commands, num_literals); break; } case 4: { global::encode.Backward_references.CreateBackwardReferences_HashLongestMatchQuickly(num_bytes, position, ringbuffer, ringbuffer_mask, max_backward_limit, quality, hashers.hash_h4, dist_cache, last_insert_len, commands, commands_off, num_commands, num_literals); break; } case 5: { global::encode.Backward_references.CreateBackwardReferences_HashLongestMatch(num_bytes, position, ringbuffer, ringbuffer_mask, max_backward_limit, quality, hashers.hash_h5, dist_cache, last_insert_len, commands, commands_off, num_commands, num_literals); break; } case 6: { global::encode.Backward_references.CreateBackwardReferences_HashLongestMatch(num_bytes, position, ringbuffer, ringbuffer_mask, max_backward_limit, quality, hashers.hash_h6, dist_cache, last_insert_len, commands, commands_off, num_commands, num_literals); break; } case 7: { global::encode.Backward_references.CreateBackwardReferences_HashLongestMatch(num_bytes, position, ringbuffer, ringbuffer_mask, max_backward_limit, quality, hashers.hash_h7, dist_cache, last_insert_len, commands, commands_off, num_commands, num_literals); break; } case 8: { global::encode.Backward_references.CreateBackwardReferences_HashLongestMatch(num_bytes, position, ringbuffer, ringbuffer_mask, max_backward_limit, quality, hashers.hash_h8, dist_cache, last_insert_len, commands, commands_off, num_commands, num_literals); break; } case 9: { global::encode.Backward_references.CreateBackwardReferences_HashLongestMatch(num_bytes, position, ringbuffer, ringbuffer_mask, max_backward_limit, quality, hashers.hash_h9, dist_cache, last_insert_len, commands, commands_off, num_commands, num_literals); break; } default: { break; } } } }
public static void CreateBackwardReferences_HashLongestMatch(int num_bytes, int position, uint[] ringbuffer, int ringbuffer_mask, int max_backward_limit, int quality, global::encode.hash.HashLongestMatch hasher, int[] dist_cache, global::Array <int> last_insert_len, global::Array <object> commands, int commands_off, global::Array <int> num_commands, global::Array <int> num_literals) { unchecked { if (((num_bytes >= 3) && (position >= 3))) { hasher.Store(ringbuffer, ((position - 3) & ringbuffer_mask), (position - 3)); hasher.Store(ringbuffer, ((position - 2) & ringbuffer_mask), (position - 2)); hasher.Store(ringbuffer, ((position - 1) & ringbuffer_mask), (position - 1)); } int orig_commands_off = commands_off; int insert_length = last_insert_len[0]; int i = (position & ringbuffer_mask); int i_diff = (position - i); int i_end = (i + num_bytes); int random_heuristics_window_size = (((quality < 9)) ? (64) : (512)); int apply_random_heuristics = (i + random_heuristics_window_size); while (((i + 3) < i_end)) { int max_length = (i_end - i); int max_distance = ((int)(global::System.Math.Min(((double)((i + i_diff))), ((double)(max_backward_limit))))); global::Array <int> best_len = new global::Array <int>(new int[] { 0 }); global::Array <int> best_len_code = new global::Array <int>(new int[] { 0 }); global::Array <int> best_dist = new global::Array <int>(new int[] { 0 }); global::Array <double> best_score = new global::Array <double>(new double[] { 4.0 }); bool match_found = hasher.FindLongestMatch(ringbuffer, ringbuffer_mask, dist_cache, ((uint)((i + i_diff))), ((uint)(max_length)), ((uint)(max_distance)), best_len, best_len_code, best_dist, best_score); if (match_found) { int delayed_backward_references_in_row = 0; while (true) { --max_length; global::Array <int> best_len_2 = new global::Array <int>(new int[] { (((quality < 5)) ? (((int)(global::System.Math.Min(((double)((best_len[0] - 1))), ((double)(max_length)))))) : (0)) }); global::Array <int> best_len_code_2 = new global::Array <int>(new int[] { 0 }); global::Array <int> best_dist_2 = new global::Array <int>(new int[] { 0 }); global::Array <double> best_score_2 = new global::Array <double>(new double[] { 4.0 }); max_distance = ((int)(global::System.Math.Min(((double)(((i + i_diff) + 1))), ((double)(max_backward_limit))))); hasher.Store(ringbuffer, i, (i + i_diff)); match_found = hasher.FindLongestMatch(ringbuffer, ringbuffer_mask, dist_cache, ((uint)(((i + i_diff) + 1))), ((uint)(max_length)), ((uint)(max_distance)), best_len_2, best_len_code_2, best_dist_2, best_score_2); if ((match_found && (best_score_2[0] >= (best_score[0] + 7.0)))) { ++i; ++insert_length; best_len[0] = best_len_2[0]; best_len_code[0] = best_len_code_2[0]; best_dist[0] = best_dist_2[0]; best_score[0] = best_score_2[0]; if ((++delayed_backward_references_in_row < 4)) { continue; } } break; } apply_random_heuristics = ((i + (2 * best_len[0])) + random_heuristics_window_size); max_distance = ((int)(global::System.Math.Min(((double)((i + i_diff))), ((double)(max_backward_limit))))); int distance_code = global::encode.Backward_references.ComputeDistanceCode(best_dist[0], max_distance, quality, dist_cache); if (((best_dist[0] <= max_distance) && (distance_code > 0))) { ((int[])(dist_cache))[3] = ((int)(((int[])(dist_cache))[2])); ((int[])(dist_cache))[2] = ((int)(((int[])(dist_cache))[1])); ((int[])(dist_cache))[1] = ((int)(((int[])(dist_cache))[0])); ((int[])(dist_cache))[0] = best_dist[0]; } global::encode.command.Command command = new global::encode.command.Command(); command.Command4(insert_length, best_len[0], best_len_code[0], distance_code); commands[commands_off++] = command; num_literals[0] += insert_length; insert_length = 0; { int _g1 = 1; int _g = best_len[0]; while ((_g1 < _g)) { int j = _g1++; hasher.Store(ringbuffer, (i + j), ((i + i_diff) + j)); } } i += best_len[0]; } else { ++insert_length; hasher.Store(ringbuffer, i, (i + i_diff)); ++i; if ((i > apply_random_heuristics)) { if ((i > (apply_random_heuristics + (4 * random_heuristics_window_size)))) { int i_jump = ((int)(global::System.Math.Min(((double)((i + 16))), ((double)((i_end - 4)))))); while ((i < i_jump)) { hasher.Store(ringbuffer, i, (i + i_diff)); insert_length += 4; i += 4; } } else { int i_jump1 = ((int)(global::System.Math.Min(((double)((i + 8))), ((double)((i_end - 3)))))); while ((i < i_jump1)) { hasher.Store(ringbuffer, i, (i + i_diff)); insert_length += 2; i += 2; } } } } } insert_length += (i_end - i); last_insert_len[0] = insert_length; num_commands[0] += (commands_off - orig_commands_off); } }