예제 #1
0
 /* What is the bit cost of moving histogram from cur_symbol to candidate. */
 public static double BrotliHistogramBitCostDistance(
     HistogramLiteral *histogram, HistogramLiteral *candidate)
 {
     if (histogram->total_count_ == 0)
     {
         return(0.0);
     }
     else
     {
         HistogramLiteral tmp = *histogram;
         HistogramLiteral.HistogramAddHistogram(&tmp, candidate);
         return(BitCostLiteral.BrotliPopulationCost(&tmp) - candidate->bit_cost_);
     }
 }
예제 #2
0
            public static void BrotliCompareAndPushToQueue(
                HistogramLiteral *out_, uint *cluster_size, uint idx1,
                uint idx2, size_t max_num_pairs, HistogramPair *pairs,
                size_t *num_pairs)
            {
                bool          is_good_pair = false;
                HistogramPair p            = new HistogramPair();

                if (idx1 == idx2)
                {
                    return;
                }
                if (idx2 < idx1)
                {
                    uint t = idx2;
                    idx2 = idx1;
                    idx1 = t;
                }
                p.idx1       = idx1;
                p.idx2       = idx2;
                p.cost_diff  = 0.5 * ClusterCostDiff(cluster_size[idx1], cluster_size[idx2]);
                p.cost_diff -= out_[idx1].bit_cost_;
                p.cost_diff -= out_[idx2].bit_cost_;

                if (out_[idx1].total_count_ == 0)
                {
                    p.cost_combo = out_[idx2].bit_cost_;
                    is_good_pair = true;
                }
                else if (out_[idx2].total_count_ == 0)
                {
                    p.cost_combo = out_[idx1].bit_cost_;
                    is_good_pair = true;
                }
                else
                {
                    double           threshold = *num_pairs == 0 ? 1e99 : Math.Max(0.0, pairs[0].cost_diff);
                    HistogramLiteral combo     = out_[idx1];
                    double           cost_combo;
                    HistogramLiteral.HistogramAddHistogram(&combo, &out_[idx2]);
                    cost_combo = BitCostLiteral.BrotliPopulationCost(&combo);
                    if (cost_combo < threshold - p.cost_diff)
                    {
                        p.cost_combo = cost_combo;
                        is_good_pair = true;
                    }
                }
                if (is_good_pair)
                {
                    p.cost_diff += p.cost_combo;
                    if (*num_pairs > 0 && HistogramPairIsLess(&pairs[0], &p))
                    {
                        /* Replace the top of the queue if needed. */
                        if (*num_pairs < max_num_pairs)
                        {
                            pairs[*num_pairs] = pairs[0];
                            ++(*num_pairs);
                        }
                        pairs[0] = p;
                    }
                    else if (*num_pairs < max_num_pairs)
                    {
                        pairs[*num_pairs] = p;
                        ++(*num_pairs);
                    }
                }
            }
예제 #3
0
            public static void BrotliClusterHistograms(
                ref MemoryManager m, HistogramLiteral *in_, size_t in_size,
                size_t max_histograms, HistogramLiteral *out_, size_t *out_size,
                uint *histogram_symbols)
            {
                uint * cluster_size         = (uint *)BrotliAllocate(ref m, in_size * sizeof(uint));
                uint * clusters             = (uint *)BrotliAllocate(ref m, in_size * sizeof(uint));
                size_t num_clusters         = 0;
                size_t max_input_histograms = 64;
                size_t pairs_capacity       = max_input_histograms * max_input_histograms / 2;
                /* For the first pass of clustering, we allow all pairs. */
                HistogramPair *pairs =
                    (HistogramPair *)BrotliAllocate(ref m, (pairs_capacity + 1) * sizeof(HistogramPair));
                size_t i;

                for (i = 0; i < in_size; ++i)
                {
                    cluster_size[i] = 1;
                }

                for (i = 0; i < in_size; ++i)
                {
                    out_[i]              = in_[i];
                    out_[i].bit_cost_    = BitCostLiteral.BrotliPopulationCost(&in_[i]);
                    histogram_symbols[i] = (uint)i;
                }

                for (i = 0; i < in_size; i += max_input_histograms)
                {
                    size_t num_to_combine =
                        Math.Min(in_size - i, max_input_histograms);
                    size_t num_new_clusters;
                    size_t j;
                    for (j = 0; j < num_to_combine; ++j)
                    {
                        clusters[num_clusters + j] = (uint)(i + j);
                    }
                    num_new_clusters =
                        BrotliHistogramCombine(out_, cluster_size,
                                               &histogram_symbols[i],
                                               &clusters[num_clusters], pairs,
                                               num_to_combine, num_to_combine,
                                               max_histograms, pairs_capacity);
                    num_clusters += num_new_clusters;
                }

                {
                    /* For the second pass, we limit the total number of histogram pairs.
                     * After this limit is reached, we only keep searching for the best pair. */
                    size_t max_num_pairs = Math.Min(
                        64 * num_clusters, (num_clusters / 2) * num_clusters);
                    BrotliEnsureCapacity(ref m, sizeof(HistogramPair), (void **)&pairs, &pairs_capacity, max_num_pairs + 1);

                    /* Collapse similar histograms. */
                    num_clusters = BrotliHistogramCombine(out_, cluster_size,
                                                          histogram_symbols, clusters,
                                                          pairs, num_clusters, in_size,
                                                          max_histograms, max_num_pairs);
                }
                BrotliFree(ref m, pairs);
                BrotliFree(ref m, cluster_size);
                /* Find the optimal map from original histograms to the final ones. */
                BrotliHistogramRemap(in_, in_size, clusters, num_clusters,
                                     out_, histogram_symbols);
                BrotliFree(ref m, clusters);
                /* Convert the context map to a canonical form. */
                *out_size = BrotliHistogramReindex(ref m, out_, histogram_symbols, in_size);
            }