LLVMFuzzerTestOneInput:
    6|  5.02k|extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    7|  5.02k|  std::string jpeg_data(reinterpret_cast<const char*>(data), size);
    8|       |
    9|       |  // Ignore large images, to prevent timeouts.
   10|  5.02k|  guetzli::JPEGData jpg_header;
   11|  5.02k|  if (!guetzli::ReadJpeg(data, size, guetzli::JPEG_READ_HEADER, &jpg_header)) {
  ------------------
  |  Branch (11:7): [True: 756, False: 4.27k]
  ------------------
   12|    756|    return 0;
   13|    756|  }
   14|  4.27k|  static constexpr int kMaxPixels = 10000;
   15|  4.27k|  if (static_cast<int64_t>(jpg_header.width) * jpg_header.height > kMaxPixels) {
  ------------------
  |  Branch (15:7): [True: 19, False: 4.25k]
  ------------------
   16|     19|    return 0;
   17|     19|  }
   18|       |
   19|       |  // TODO(robryk): Use nondefault parameters.
   20|  4.25k|  guetzli::Params params;
   21|  4.25k|  std::string jpeg_out;
   22|  4.25k|  (void)guetzli::Process(params, nullptr, jpeg_data, &jpeg_out);
   23|       |  // TODO(robryk): Verify output distance if Process() succeeded.
   24|  4.25k|  return 0;
   25|  4.27k|}

_ZN7guetzli21ButteraugliComparatorC2EiiPKNSt3__16vectorIhNS1_9allocatorIhEEEEfPNS_12ProcessStatsE:
   55|  2.54k|    : width_(width),
   56|  2.54k|      height_(height),
   57|  2.54k|      target_distance_(target_distance),
   58|  2.54k|      rgb_orig_(*rgb),
   59|  2.54k|      comparator_(LinearRgb(width_, height_, *rgb)),
   60|  2.54k|      distance_(0.0),
   61|  2.54k|      stats_(stats) {}
_ZN7guetzli21ButteraugliComparator7CompareERKNS_11OutputImageE:
   63|   143k|void ButteraugliComparator::Compare(const OutputImage& img) {
   64|   143k|  std::vector<ImageF> rgb0 =
   65|   143k|      ::butteraugli::OpsinDynamicsImage(LinearRgb(width_, height_, rgb_orig_));
   66|   143k|  std::vector<std::vector<float> > rgb(3, std::vector<float>(width_ * height_));
   67|   143k|  img.ToLinearRGB(&rgb);
   68|   143k|  const std::vector<ImageF> rgb_planes = PlanesFromPacked(width_, height_, rgb);
   69|   143k|  std::vector<float>(width_ * height_).swap(distmap_);
   70|   143k|  ImageF distmap;
   71|   143k|  comparator_.Diffmap(rgb_planes, distmap);
   72|   143k|  CopyToPacked(distmap, &distmap_);
   73|   143k|  distance_ = ::butteraugli::ButteraugliScoreFromDiffmap(distmap);
   74|       |  GUETZLI_LOG(stats_, " BA[100.00%%] D[%6.4f]", distance_);
  ------------------
  |  |   29|   143k|  do {                                                             \
  |  |   30|   143k|    char debug_string[1024];                                       \
  |  |   31|   143k|    int res = snprintf(debug_string, sizeof(debug_string),         \
  |  |   32|   143k|                       __VA_ARGS__);                               \
  |  |   33|   143k|    assert(res > 0 && "expected successful printing");             \
  |  |   34|   143k|    (void)res;                                                     \
  |  |   35|   143k|    debug_string[sizeof(debug_string) - 1] = '\0';                 \
  |  |   36|   143k|    ::guetzli::PrintDebug(                      \
  |  |   37|   143k|         stats, std::string(debug_string));        \
  |  |   38|   143k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (38:12): [Folded, False: 143k]
  |  |  ------------------
  ------------------
  |  Branch (74:3): [True: 143k, False: 0]
  |  Branch (74:3): [True: 143k, Folded]
  |  Branch (74:3): [True: 143k, False: 0]
  ------------------
   75|   143k|}
_ZN7guetzli21ButteraugliComparator21StartBlockComparisonsEv:
  415|  3.56k|void ButteraugliComparator::StartBlockComparisons() {
  416|  3.56k|  std::vector<ImageF> dummy(3);
  417|  3.56k|  std::vector<ImageF> rgb0 =
  418|  3.56k|      ::butteraugli::OpsinDynamicsImage(LinearRgb(width_, height_, rgb_orig_));
  419|  3.56k|  ::butteraugli::Mask(rgb0, rgb0,
  420|  3.56k|                      &mask_xyz_, &dummy);
  421|  3.56k|}
_ZN7guetzli21ButteraugliComparator22FinishBlockComparisonsEv:
  423|  3.56k|void ButteraugliComparator::FinishBlockComparisons() {
  424|  3.56k|  mask_xyz_.clear();
  425|  3.56k|}
_ZN7guetzli21ButteraugliComparator11SwitchBlockEiiii:
  428|   125k|                                        int factor_x, int factor_y) {
  429|   125k|  block_x_ = block_x;
  430|   125k|  block_y_ = block_y;
  431|   125k|  factor_x_ = factor_x;
  432|   125k|  factor_y_ = factor_y;
  433|   125k|  per_block_pregamma_.resize(factor_x_ * factor_y_);
  434|   125k|  const double* lut = Srgb8ToLinearTable();
  435|   264k|  for (int off_y = 0, bx = 0; off_y < factor_y_; ++off_y) {
  ------------------
  |  Branch (435:31): [True: 139k, False: 125k]
  ------------------
  436|   308k|    for (int off_x = 0; off_x < factor_x_; ++off_x, ++bx) {
  ------------------
  |  Branch (436:25): [True: 168k, False: 139k]
  ------------------
  437|   168k|      per_block_pregamma_[bx].resize(3, std::vector<float>(kDCTBlockSize));
  438|   168k|      int block_xx = block_x_ * factor_x_ + off_x;
  439|   168k|      int block_yy = block_y_ * factor_y_ + off_y;
  440|  1.51M|      for (int iy = 0, i = 0; iy < 8; ++iy) {
  ------------------
  |  Branch (440:31): [True: 1.35M, False: 168k]
  ------------------
  441|  12.1M|        for (int ix = 0; ix < 8; ++ix, ++i) {
  ------------------
  |  Branch (441:26): [True: 10.8M, False: 1.35M]
  ------------------
  442|  10.8M|          int x = std::min(8 * block_xx + ix, width_ - 1);
  443|  10.8M|          int y = std::min(8 * block_yy + iy, height_ - 1);
  444|  10.8M|          int px = y * width_ + x;
  445|  43.2M|          for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (445:27): [True: 32.4M, False: 10.8M]
  ------------------
  446|  32.4M|            per_block_pregamma_[bx][c][i] = lut[rgb_orig_[3 * px + c]];
  447|  32.4M|          }
  448|  10.8M|        }
  449|  1.35M|      }
  450|   168k|      per_block_pregamma_[bx] =
  451|   168k|          ::butteraugli::PackedFromPlanes(::butteraugli::OpsinDynamicsImage(
  452|   168k|              ::butteraugli::PlanesFromPacked(8, 8, per_block_pregamma_[bx])));
  453|   168k|    }
  454|   139k|  }
  455|   125k|}
_ZNK7guetzli21ButteraugliComparator12CompareBlockERKNS_11OutputImageEii:
  458|  6.00M|                                           int off_x, int off_y) const {
  459|  6.00M|  int block_x = block_x_ * factor_x_ + off_x;
  460|  6.00M|  int block_y = block_y_ * factor_y_ + off_y;
  461|  6.00M|  int xmin = 8 * block_x;
  462|  6.00M|  int ymin = 8 * block_y;
  463|  6.00M|  int block_ix = off_y * factor_x_ + off_x;
  464|  6.00M|  const std::vector<std::vector<float> >& rgb0 =
  465|  6.00M|      per_block_pregamma_[block_ix];
  466|       |
  467|  6.00M|  std::vector<std::vector<float> > rgb1(3, std::vector<float>(kDCTBlockSize));
  468|  6.00M|  img.ToLinearRGB(xmin, ymin, 8, 8, &rgb1);
  469|  6.00M|  rgb1 = ::butteraugli::PackedFromPlanes(::butteraugli::OpsinDynamicsImage(
  470|  6.00M|      ::butteraugli::PlanesFromPacked(8, 8, rgb1)));
  471|       |
  472|  6.00M|  double b0[3 * kDCTBlockSize];
  473|  6.00M|  double b1[3 * kDCTBlockSize];
  474|  24.0M|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (474:19): [True: 18.0M, False: 6.00M]
  ------------------
  475|  1.17G|    for (int ix = 0; ix < kDCTBlockSize; ++ix) {
  ------------------
  |  Branch (475:22): [True: 1.15G, False: 18.0M]
  ------------------
  476|  1.15G|      b0[c * kDCTBlockSize + ix] = rgb0[c][ix];
  477|  1.15G|      b1[c * kDCTBlockSize + ix] = rgb1[c][ix];
  478|  1.15G|    }
  479|  18.0M|  }
  480|  6.00M|  double diff_xyz[3] = { 0.0 };
  481|  6.00M|  ButteraugliBlockDiff(b0, b1, diff_xyz);
  482|       |
  483|  6.00M|  double diff = 0.0;
  484|  24.0M|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (484:19): [True: 18.0M, False: 6.00M]
  ------------------
  485|  18.0M|    diff += diff_xyz[c] * mask_xyz_[c].Row(ymin)[xmin];
  486|  18.0M|  }
  487|  6.00M|  return sqrt(diff);
  488|  6.00M|}
_ZNK7guetzli21ButteraugliComparator15BlockErrorLimitEv:
  490|  1.35M|float ButteraugliComparator::BlockErrorLimit() const {
  491|  1.35M|  return target_distance_;
  492|  1.35M|}
_ZN7guetzli21ButteraugliComparator34ComputeBlockErrorAdjustmentWeightsEiidiiRKNSt3__16vectorIfNS1_9allocatorIfEEEEPS5_:
  500|   133k|      std::vector<float>* block_weight) {
  501|   133k|  const double target_distance = target_distance_ * target_mul;
  502|   133k|  const int sizex = 8 * factor_x;
  503|   133k|  const int sizey = 8 * factor_y;
  504|   133k|  const int block_width = (width_ + sizex - 1) / sizex;
  505|   133k|  const int block_height = (height_ + sizey - 1) / sizey;
  506|   133k|  std::vector<float> max_dist_per_block(block_width * block_height);
  507|   882k|  for (int block_y = 0; block_y < block_height; ++block_y) {
  ------------------
  |  Branch (507:25): [True: 748k, False: 133k]
  ------------------
  508|  5.79M|    for (int block_x = 0; block_x < block_width; ++block_x) {
  ------------------
  |  Branch (508:27): [True: 5.04M, False: 748k]
  ------------------
  509|  5.04M|      int block_ix = block_y * block_width + block_x;
  510|  5.04M|      int x_max = std::min(width_, sizex * (block_x + 1));
  511|  5.04M|      int y_max = std::min(height_, sizey * (block_y + 1));
  512|  5.04M|      float max_dist = 0.0;
  513|  44.7M|      for (int y = sizey * block_y; y < y_max; ++y) {
  ------------------
  |  Branch (513:37): [True: 39.7M, False: 5.04M]
  ------------------
  514|   358M|        for (int x = sizex * block_x; x < x_max; ++x) {
  ------------------
  |  Branch (514:39): [True: 318M, False: 39.7M]
  ------------------
  515|   318M|          max_dist = std::max(max_dist, distmap[y * width_ + x]);
  516|   318M|        }
  517|  39.7M|      }
  518|  5.04M|      max_dist_per_block[block_ix] = max_dist;
  519|  5.04M|    }
  520|   748k|  }
  521|   882k|  for (int block_y = 0; block_y < block_height; ++block_y) {
  ------------------
  |  Branch (521:25): [True: 748k, False: 133k]
  ------------------
  522|  5.79M|    for (int block_x = 0; block_x < block_width; ++block_x) {
  ------------------
  |  Branch (522:27): [True: 5.04M, False: 748k]
  ------------------
  523|  5.04M|      int block_ix = block_y * block_width + block_x;
  524|  5.04M|      float max_local_dist = static_cast<float>(target_distance);
  525|  5.04M|      int x_min = std::max(0, block_x - max_block_dist);
  526|  5.04M|      int y_min = std::max(0, block_y - max_block_dist);
  527|  5.04M|      int x_max = std::min(block_width, block_x + 1 + max_block_dist);
  528|  5.04M|      int y_max = std::min(block_height, block_y + 1 + max_block_dist);
  529|  20.3M|      for (int y = y_min; y < y_max; ++y) {
  ------------------
  |  Branch (529:27): [True: 15.3M, False: 5.04M]
  ------------------
  530|  66.7M|        for (int x = x_min; x < x_max; ++x) {
  ------------------
  |  Branch (530:29): [True: 51.3M, False: 15.3M]
  ------------------
  531|  51.3M|          max_local_dist =
  532|  51.3M|              std::max(max_local_dist, max_dist_per_block[y * block_width + x]);
  533|  51.3M|        }
  534|  15.3M|      }
  535|  5.04M|      if (direction > 0) {
  ------------------
  |  Branch (535:11): [True: 578k, False: 4.46M]
  ------------------
  536|   578k|        if (max_dist_per_block[block_ix] <= target_distance &&
  ------------------
  |  Branch (536:13): [True: 362k, False: 215k]
  ------------------
  537|   362k|            max_local_dist <= 1.1 * target_distance) {
  ------------------
  |  Branch (537:13): [True: 313k, False: 48.6k]
  ------------------
  538|   313k|          (*block_weight)[block_ix] = 1.0;
  539|   313k|        }
  540|  4.46M|      } else {
  541|  4.46M|        constexpr double kLocalMaxWeight = 0.5;
  542|  4.46M|        if (max_dist_per_block[block_ix] <=
  ------------------
  |  Branch (542:13): [True: 2.75M, False: 1.71M]
  ------------------
  543|  4.46M|            (1 - kLocalMaxWeight) * target_distance +
  544|  4.46M|            kLocalMaxWeight * max_local_dist) {
  545|  2.75M|          continue;
  546|  2.75M|        }
  547|  6.30M|        for (int y = y_min; y < y_max; ++y) {
  ------------------
  |  Branch (547:29): [True: 4.59M, False: 1.71M]
  ------------------
  548|  17.1M|          for (int x = x_min; x < x_max; ++x) {
  ------------------
  |  Branch (548:31): [True: 12.5M, False: 4.59M]
  ------------------
  549|  12.5M|            int d = std::max(std::abs(y - block_y), std::abs(x - block_x));
  550|  12.5M|            int ix = y * block_width + x;
  551|  12.5M|            (*block_weight)[ix] = std::max<float>(
  552|  12.5M|                (*block_weight)[ix], 1.0f / (d + 1.0f));
  553|  12.5M|          }
  554|  4.59M|        }
  555|  1.71M|      }
  556|  5.04M|    }
  557|   748k|  }
  558|   133k|}
_ZNK7guetzli21ButteraugliComparator15ScoreOutputSizeEi:
  560|   143k|double ButteraugliComparator::ScoreOutputSize(int size) const {
  561|   143k|  return ScoreJPEG(distance_, size, target_distance_);
  562|   143k|}
butteraugli_comparator.cc:_ZN7guetzli12_GLOBAL__N_19LinearRgbEmmRKNSt3__16vectorIhNS1_9allocatorIhEEEE:
   34|   149k|                              const std::vector<uint8_t>& rgb) {
   35|   149k|  const double* lut = Srgb8ToLinearTable();
   36|   149k|  std::vector<ImageF> planes = CreatePlanes<float>(xsize, ysize, 3);
   37|   599k|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (37:19): [True: 449k, False: 149k]
  ------------------
   38|  21.1M|    for (size_t y = 0; y < ysize; ++y) {
  ------------------
  |  Branch (38:24): [True: 20.7M, False: 449k]
  ------------------
   39|  20.7M|      const uint8_t* const BUTTERAUGLI_RESTRICT row_in = &rgb[3 * xsize * y];
   40|  20.7M|      float* const BUTTERAUGLI_RESTRICT row_out = planes[c].Row(y);
   41|  1.07G|      for (size_t x = 0; x < xsize; ++x) {
  ------------------
  |  Branch (41:26): [True: 1.05G, False: 20.7M]
  ------------------
   42|  1.05G|        row_out[x] = lut[row_in[3 * x + c]];
   43|  1.05G|      }
   44|  20.7M|    }
   45|   449k|  }
   46|   149k|  return planes;
   47|   149k|}
butteraugli_comparator.cc:_ZN7guetzli12_GLOBAL__N_120ButteraugliBlockDiffEPdS1_S1_:
  384|  6.00M|                          double* diff_xyb) {
  385|  6.00M|  const double *csf8x8 = GetContrastSensitivityMatrix();
  386|  6.00M|  double avgdiff_xyb[3] = {0.0};
  387|  1.15G|  for (int i = 0; i < 3 * kBlockSize; ++i) {
  ------------------
  |  Branch (387:19): [True: 1.15G, False: 6.00M]
  ------------------
  388|  1.15G|    avgdiff_xyb[i / kBlockSize] += xyb0[i] - xyb1[i];
  389|  1.15G|  }
  390|  24.0M|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (390:19): [True: 18.0M, False: 6.00M]
  ------------------
  391|  18.0M|    double avgdiff = avgdiff_xyb[c] / kBlockSize;
  392|  18.0M|    diff_xyb[c] += 4.0 * avgdiff * avgdiff;
  393|  18.0M|  }
  394|  6.00M|  double x_diff[kBlockSize];
  395|  6.00M|  double y_diff[kBlockSize];
  396|  6.00M|  double b_diff[kBlockSize];
  397|   390M|  for (int i = 0; i < kBlockSize; ++i) {
  ------------------
  |  Branch (397:19): [True: 384M, False: 6.00M]
  ------------------
  398|   384M|    x_diff[i] = (xyb0[i] - xyb1[i]);
  399|   384M|    y_diff[i] = (xyb0[kBlockSize + i] - xyb1[kBlockSize + i]);
  400|   384M|    b_diff[i] = (xyb0[2 * kBlockSize + i] - xyb1[2 * kBlockSize + i]);
  401|   384M|  }
  402|  6.00M|  ButteraugliFFTSquared(x_diff);
  403|  6.00M|  ButteraugliFFTSquared(y_diff);
  404|  6.00M|  ButteraugliFFTSquared(b_diff);
  405|   204M|  for (size_t i = kBlockEdgeHalf; i < kBlockHalf + kBlockEdgeHalf + 1; ++i) {
  ------------------
  |  Branch (405:35): [True: 198M, False: 6.00M]
  ------------------
  406|   198M|    double d = csf8x8[i];
  407|   198M|    diff_xyb[0] += d * x_diff[i];
  408|   198M|    diff_xyb[1] += d * y_diff[i];
  409|   198M|    diff_xyb[2] += d * b_diff[i];
  410|   198M|  }
  411|  6.00M|}
butteraugli_comparator.cc:_ZN7guetzli12_GLOBAL__N_128GetContrastSensitivityMatrixEv:
   93|  6.00M|static const double *GetContrastSensitivityMatrix() {
   94|  6.00M|  static double csf8x8[kBlockHalf + kBlockEdgeHalf + 1] = {
   95|  6.00M|    0.0,  // no 8x8 dc, enough 'dc' is calculated from low/mid freq images.
   96|  6.00M|    0.0,
   97|  6.00M|    0.0,
   98|  6.00M|    0.0,
   99|  6.00M|    0.3831134973,
  100|  6.00M|    0.676303603859,
  101|  6.00M|    1.1550451483,
  102|  6.00M|    8,
  103|  6.00M|    8,
  104|  6.00M|    0.692062533689,
  105|  6.00M|    0.847511538605,
  106|  6.00M|    0.498250875965,
  107|  6.00M|    0.36198671102,
  108|  6.00M|    0.308982169883,
  109|  6.00M|    0.1312701920435,
  110|  6.00M|    4.71274312228,
  111|  6.00M|    1.1550451483,
  112|  6.00M|    0.847511538605,
  113|  6.00M|    4.71274312228,
  114|  6.00M|    0.991205724152,
  115|  6.00M|    1.30229591239,
  116|  6.00M|    0.627264168628,
  117|  6.00M|    0.4,
  118|  6.00M|    0.1312701920435,
  119|  6.00M|    0.676303603859,
  120|  6.00M|    0.498250875965,
  121|  6.00M|    0.991205724152,
  122|  6.00M|    0.5,
  123|  6.00M|    0.3831134973,
  124|  6.00M|    0.349686450518,
  125|  6.00M|    0.627264168628,
  126|  6.00M|    0.308982169883,
  127|  6.00M|    0.3831134973,
  128|  6.00M|    0.36198671102,
  129|  6.00M|    1.30229591239,
  130|  6.00M|    0.3831134973,
  131|  6.00M|    0.323078800177,
  132|  6.00M|  };
  133|  6.00M|  return &csf8x8[0];
  134|  6.00M|}
butteraugli_comparator.cc:_ZN7guetzli12_GLOBAL__N_121ButteraugliFFTSquaredEPd:
  357|  18.0M|void ButteraugliFFTSquared(double block[kBlockSize]) {
  358|  18.0M|  double global_mul = 0.000064;
  359|  18.0M|  Complex block_c[kBlockSize];
  360|  18.0M|  assert(kBlockEdge == 8);
  ------------------
  |  Branch (360:3): [True: 18.0M, Folded]
  ------------------
  361|   162M|  for (int y = 0; y < kBlockEdge; ++y) {
  ------------------
  |  Branch (361:19): [True: 144M, False: 18.0M]
  ------------------
  362|   144M|    RealFFT8(block + y * kBlockEdge, block_c + y * kBlockEdge);
  363|   144M|  }
  364|  18.0M|  TransposeBlock(block_c);
  365|  18.0M|  double r0[kBlockEdge];
  366|  18.0M|  double r1[kBlockEdge];
  367|   162M|  for (int x = 0; x < kBlockEdge; ++x) {
  ------------------
  |  Branch (367:19): [True: 144M, False: 18.0M]
  ------------------
  368|   144M|    r0[x] = block_c[x].real;
  369|   144M|    r1[x] = block_c[kBlockHalf + x].real;
  370|   144M|  }
  371|  18.0M|  RealFFT8(r0, block_c);
  372|  18.0M|  RealFFT8(r1, block_c + kBlockHalf);
  373|  72.1M|  for (int y = 1; y < kBlockEdgeHalf; ++y) {
  ------------------
  |  Branch (373:19): [True: 54.0M, False: 18.0M]
  ------------------
  374|  54.0M|    FFT8(block_c + y * kBlockEdge);
  375|  54.0M|  }
  376|   612M|  for (int i = kBlockEdgeHalf; i < kBlockHalf + kBlockEdgeHalf + 1; ++i) {
  ------------------
  |  Branch (376:32): [True: 594M, False: 18.0M]
  ------------------
  377|   594M|    block[i] = abssq(block_c[i]);
  378|   594M|    block[i] *= global_mul;
  379|   594M|  }
  380|  18.0M|}
butteraugli_comparator.cc:_ZN7guetzli12_GLOBAL__N_18RealFFT8EPKdPNS0_7ComplexE:
  282|   180M|void RealFFT8(const double* in, Complex* out) {
  283|   180M|  double t1, t2, t3, t5, t6, t7, t8;
  284|   180M|  t8 = in[6];
  285|   180M|  t5 = in[2] - t8;
  286|   180M|  t8 += in[2];
  287|   180M|  out[2].real = t8;
  288|   180M|  out[6].imag = -t5;
  289|   180M|  out[4].imag = t5;
  290|   180M|  t8 = in[4];
  291|   180M|  t3 = in[0] - t8;
  292|   180M|  t8 += in[0];
  293|   180M|  out[0].real = t8;
  294|   180M|  out[4].real = t3;
  295|   180M|  out[6].real = t3;
  296|   180M|  t7 = in[5];
  297|   180M|  t3 = in[1] - t7;
  298|   180M|  t7 += in[1];
  299|   180M|  out[1].real = t7;
  300|   180M|  t8 = in[7];
  301|   180M|  t5 = in[3] - t8;
  302|   180M|  t8 += in[3];
  303|   180M|  out[3].real = t8;
  304|   180M|  t2 = -t5;
  305|   180M|  t6 = t3 - t5;
  306|   180M|  t8 = kSqrtHalf;
  307|   180M|  t6 *= t8;
  308|   180M|  out[5].real = out[4].real - t6;
  309|   180M|  t1 = t3 + t5;
  310|   180M|  t1 *= t8;
  311|   180M|  out[5].imag = out[4].imag - t1;
  312|   180M|  t6 += out[4].real;
  313|   180M|  out[4].real = t6;
  314|   180M|  t1 += out[4].imag;
  315|   180M|  out[4].imag = t1;
  316|   180M|  t5 = t2 - t3;
  317|   180M|  t5 *= t8;
  318|   180M|  out[7].imag = out[6].imag - t5;
  319|   180M|  t2 += t3;
  320|   180M|  t2 *= t8;
  321|   180M|  out[7].real = out[6].real - t2;
  322|   180M|  t2 += out[6].real;
  323|   180M|  out[6].real = t2;
  324|   180M|  t5 += out[6].imag;
  325|   180M|  out[6].imag = t5;
  326|   180M|  t5 = out[2].real;
  327|   180M|  t1 = out[0].real - t5;
  328|   180M|  t7 = out[3].real;
  329|   180M|  t5 += out[0].real;
  330|   180M|  t3 = out[1].real - t7;
  331|   180M|  t7 += out[1].real;
  332|   180M|  t8 = t5 + t7;
  333|   180M|  out[0].real = t8;
  334|   180M|  t5 -= t7;
  335|   180M|  out[1].real = t5;
  336|   180M|  out[2].imag = t3;
  337|   180M|  out[3].imag = -t3;
  338|   180M|  out[3].real = t1;
  339|   180M|  out[2].real = t1;
  340|   180M|  out[0].imag = 0;
  341|   180M|  out[1].imag = 0;
  342|       |
  343|       |  // Reorder to the correct output order.
  344|       |  // TODO(szabadka): Modify the above computation so that this is not needed.
  345|   180M|  Complex tmp = out[2];
  346|   180M|  out[2] = out[3];
  347|   180M|  out[3] = out[5];
  348|   180M|  out[5] = out[7];
  349|   180M|  out[7] = out[4];
  350|   180M|  out[4] = out[1];
  351|   180M|  out[1] = out[6];
  352|   180M|  out[6] = tmp;
  353|   180M|}
butteraugli_comparator.cc:_ZN7guetzli12_GLOBAL__N_114TransposeBlockEPNS0_7ComplexE:
  145|  18.0M|static void TransposeBlock(Complex data[kBlockSize]) {
  146|   162M|  for (int i = 0; i < kBlockEdge; i++) {
  ------------------
  |  Branch (146:19): [True: 144M, False: 18.0M]
  ------------------
  147|   648M|    for (int j = 0; j < i; j++) {
  ------------------
  |  Branch (147:21): [True: 504M, False: 144M]
  ------------------
  148|   504M|      std::swap(data[kBlockEdge * i + j], data[kBlockEdge * j + i]);
  149|   504M|    }
  150|   144M|  }
  151|  18.0M|}
butteraugli_comparator.cc:_ZN7guetzli12_GLOBAL__N_14FFT8EPNS0_7ComplexE:
  186|  54.0M|void FFT8(Complex* a) {
  187|  54.0M|  double t1, t2, t3, t4, t5, t6, t7, t8;
  188|       |
  189|  54.0M|  t7 = a[4].imag;
  190|  54.0M|  t4 = a[0].imag - t7;
  191|  54.0M|  t7 += a[0].imag;
  192|  54.0M|  a[0].imag = t7;
  193|       |
  194|  54.0M|  t8 = a[6].real;
  195|  54.0M|  t5 = a[2].real - t8;
  196|  54.0M|  t8 += a[2].real;
  197|  54.0M|  a[2].real = t8;
  198|       |
  199|  54.0M|  t7 = a[6].imag;
  200|  54.0M|  a[6].imag = t4 - t5;
  201|  54.0M|  t4 += t5;
  202|  54.0M|  a[4].imag = t4;
  203|       |
  204|  54.0M|  t6 = a[2].imag - t7;
  205|  54.0M|  t7 += a[2].imag;
  206|  54.0M|  a[2].imag = t7;
  207|       |
  208|  54.0M|  t8 = a[4].real;
  209|  54.0M|  t3 = a[0].real - t8;
  210|  54.0M|  t8 += a[0].real;
  211|  54.0M|  a[0].real = t8;
  212|       |
  213|  54.0M|  a[4].real = t3 - t6;
  214|  54.0M|  t3 += t6;
  215|  54.0M|  a[6].real = t3;
  216|       |
  217|  54.0M|  t7 = a[5].real;
  218|  54.0M|  t3 = a[1].real - t7;
  219|  54.0M|  t7 += a[1].real;
  220|  54.0M|  a[1].real = t7;
  221|       |
  222|  54.0M|  t8 = a[7].imag;
  223|  54.0M|  t6 = a[3].imag - t8;
  224|  54.0M|  t8 += a[3].imag;
  225|  54.0M|  a[3].imag = t8;
  226|  54.0M|  t1 = t3 - t6;
  227|  54.0M|  t3 += t6;
  228|       |
  229|  54.0M|  t7 = a[5].imag;
  230|  54.0M|  t4 = a[1].imag - t7;
  231|  54.0M|  t7 += a[1].imag;
  232|  54.0M|  a[1].imag = t7;
  233|       |
  234|  54.0M|  t8 = a[7].real;
  235|  54.0M|  t5 = a[3].real - t8;
  236|  54.0M|  t8 += a[3].real;
  237|  54.0M|  a[3].real = t8;
  238|       |
  239|  54.0M|  t2 = t4 - t5;
  240|  54.0M|  t4 += t5;
  241|       |
  242|  54.0M|  t6 = t1 - t4;
  243|  54.0M|  t8 = kSqrtHalf;
  244|  54.0M|  t6 *= t8;
  245|  54.0M|  a[5].real = a[4].real - t6;
  246|  54.0M|  t1 += t4;
  247|  54.0M|  t1 *= t8;
  248|  54.0M|  a[5].imag = a[4].imag - t1;
  249|  54.0M|  t6 += a[4].real;
  250|  54.0M|  a[4].real = t6;
  251|  54.0M|  t1 += a[4].imag;
  252|  54.0M|  a[4].imag = t1;
  253|       |
  254|  54.0M|  t5 = t2 - t3;
  255|  54.0M|  t5 *= t8;
  256|  54.0M|  a[7].imag = a[6].imag - t5;
  257|  54.0M|  t2 += t3;
  258|  54.0M|  t2 *= t8;
  259|  54.0M|  a[7].real = a[6].real - t2;
  260|  54.0M|  t2 += a[6].real;
  261|  54.0M|  a[6].real = t2;
  262|  54.0M|  t5 += a[6].imag;
  263|  54.0M|  a[6].imag = t5;
  264|       |
  265|  54.0M|  FFT4(a);
  266|       |
  267|       |  // Reorder to the correct output order.
  268|       |  // TODO(szabadka): Modify the above computation so that this is not needed.
  269|  54.0M|  Complex tmp = a[2];
  270|  54.0M|  a[2] = a[3];
  271|  54.0M|  a[3] = a[5];
  272|  54.0M|  a[5] = a[7];
  273|  54.0M|  a[7] = a[4];
  274|  54.0M|  a[4] = a[1];
  275|  54.0M|  a[1] = a[6];
  276|  54.0M|  a[6] = tmp;
  277|  54.0M|}
butteraugli_comparator.cc:_ZN7guetzli12_GLOBAL__N_14FFT4EPNS0_7ComplexE:
  154|  54.0M|inline void FFT4(Complex* a) {
  155|  54.0M|  double t1, t2, t3, t4, t5, t6, t7, t8;
  156|  54.0M|  t5 = a[2].real;
  157|  54.0M|  t1 = a[0].real - t5;
  158|  54.0M|  t7 = a[3].real;
  159|  54.0M|  t5 += a[0].real;
  160|  54.0M|  t3 = a[1].real - t7;
  161|  54.0M|  t7 += a[1].real;
  162|  54.0M|  t8 = t5 + t7;
  163|  54.0M|  a[0].real = t8;
  164|  54.0M|  t5 -= t7;
  165|  54.0M|  a[1].real = t5;
  166|  54.0M|  t6 = a[2].imag;
  167|  54.0M|  t2 = a[0].imag - t6;
  168|  54.0M|  t6 += a[0].imag;
  169|  54.0M|  t5 = a[3].imag;
  170|  54.0M|  a[2].imag = t2 + t3;
  171|  54.0M|  t2 -= t3;
  172|  54.0M|  a[3].imag = t2;
  173|  54.0M|  t4 = a[1].imag - t5;
  174|  54.0M|  a[3].real = t1 + t4;
  175|  54.0M|  t1 -= t4;
  176|  54.0M|  a[2].real = t1;
  177|  54.0M|  t5 += a[1].imag;
  178|  54.0M|  a[0].imag = t6 + t5;
  179|  54.0M|  t6 -= t5;
  180|  54.0M|  a[1].imag = t6;
  181|  54.0M|}
butteraugli_comparator.cc:_ZN7guetzli12_GLOBAL__N_15abssqERKNS0_7ComplexE:
  141|   594M|inline double abssq(const Complex& c) {
  142|   594M|  return c.real * c.real + c.imag * c.imag;
  143|   594M|}

_ZNK7guetzli21ButteraugliComparator10DistanceOKEd:
   51|  41.4k|  bool DistanceOK(double target_mul) const override {
   52|  41.4k|    return distance_ <= target_mul * target_distance_;
   53|  41.4k|  }
_ZNK7guetzli21ButteraugliComparator7distmapEv:
   55|   122k|  const std::vector<float> distmap() const override { return distmap_; }

_ZN7guetzli24ColorTransformYCbCrToRGBEPh:
  211|   727M|inline void ColorTransformYCbCrToRGB(uint8_t* pixel) {
  212|   727M|  int y  = pixel[0];
  213|   727M|  int cb = pixel[1];
  214|   727M|  int cr = pixel[2];
  215|   727M|  pixel[0] = kRangeLimit[y + kCrToRedTable[cr]];
  216|   727M|  pixel[1] = kRangeLimit[y +
  217|   727M|                         ((kCrToGreenTable[cr] + kCbToGreenTable[cb]) >> 16)];
  218|   727M|  pixel[2] = kRangeLimit[y + kCbToBlueTable[cb]];
  219|   727M|}

_ZN7guetzli10ComparatorC2Ev:
   31|  2.54k|  Comparator() {}
_ZN7guetzli10ComparatorD2Ev:
   32|  2.54k|  virtual ~Comparator() {}

_ZN7guetzli10PrintDebugEPNS_12ProcessStatsENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
   21|  9.33M|void PrintDebug(ProcessStats* stats, std::string s) {
   22|  9.33M|  if (stats->debug_output) {
  ------------------
  |  Branch (22:7): [True: 0, False: 9.33M]
  ------------------
   23|      0|    stats->debug_output->append(s);
   24|      0|  }
   25|  9.33M|  if (stats->debug_output_file) {
  ------------------
  |  Branch (25:7): [True: 0, False: 9.33M]
  ------------------
   26|      0|    fprintf(stats->debug_output_file, "%s", s.c_str());
   27|      0|  }
   28|  9.33M|}

_ZN7guetzli8SetDepthEiPNS_11HuffmanTreeEPhi:
   26|  2.25M|bool SetDepth(int p0, HuffmanTree *pool, uint8_t *depth, int max_depth) {
   27|  2.25M|  int stack[17];
   28|  2.25M|  int level = 0;
   29|  2.25M|  int p = p0;
   30|  2.25M|  assert(max_depth <= 16);
  ------------------
  |  Branch (30:3): [True: 2.25M, False: 0]
  ------------------
   31|  2.25M|  stack[0] = -1;
   32|  50.5M|  while (true) {
  ------------------
  |  Branch (32:10): [True: 50.5M, Folded]
  ------------------
   33|  50.5M|    if (pool[p].index_left_ >= 0) {
  ------------------
  |  Branch (33:9): [True: 24.1M, False: 26.3M]
  ------------------
   34|  24.1M|      level++;
   35|  24.1M|      if (level > max_depth) return false;
  ------------------
  |  Branch (35:11): [True: 0, False: 24.1M]
  ------------------
   36|  24.1M|      stack[level] = pool[p].index_right_or_value_;
   37|  24.1M|      p = pool[p].index_left_;
   38|  24.1M|      continue;
   39|  26.3M|    } else {
   40|  26.3M|      depth[pool[p].index_right_or_value_] = static_cast<uint8_t>(level);
   41|  26.3M|    }
   42|  52.7M|    while (level >= 0 && stack[level] == -1) level--;
  ------------------
  |  Branch (42:12): [True: 50.5M, False: 2.25M]
  |  Branch (42:26): [True: 26.3M, False: 24.1M]
  ------------------
   43|  26.3M|    if (level < 0) return true;
  ------------------
  |  Branch (43:9): [True: 2.25M, False: 24.1M]
  ------------------
   44|  24.1M|    p = stack[level];
   45|  24.1M|    stack[level] = -1;
   46|  24.1M|  }
   47|  2.25M|}
_ZN7guetzli17CreateHuffmanTreeEPKjmiPNS_11HuffmanTreeEPh:
   77|  2.27M|                       uint8_t *depth) {
   78|       |  // For block sizes below 64 kB, we never need to do a second iteration
   79|       |  // of this loop. Probably all of our block sizes will be smaller than
   80|       |  // that, so this loop is mostly of academic interest. If we actually
   81|       |  // would need this, we would be better off with the Katajainen algorithm.
   82|  2.27M|  for (uint32_t count_limit = 1; ; count_limit *= 2) {
   83|  2.27M|    size_t n = 0;
   84|   587M|    for (size_t i = length; i != 0;) {
  ------------------
  |  Branch (84:29): [True: 585M, False: 2.27M]
  ------------------
   85|   585M|      --i;
   86|   585M|      if (data[i]) {
  ------------------
  |  Branch (86:11): [True: 26.3M, False: 559M]
  ------------------
   87|  26.3M|        const uint32_t count = std::max<uint32_t>(data[i], count_limit);
   88|  26.3M|        tree[n++] = HuffmanTree(count, -1, static_cast<int16_t>(i));
   89|  26.3M|      }
   90|   585M|    }
   91|       |
   92|  2.27M|    if (n == 1) {
  ------------------
  |  Branch (92:9): [True: 19.2k, False: 2.25M]
  ------------------
   93|  19.2k|      depth[tree[0].index_right_or_value_] = 1;      // Only one element.
   94|  19.2k|      break;
   95|  19.2k|    }
   96|       |
   97|  2.25M|    std::sort(tree, tree + n, SortHuffmanTree);
   98|       |
   99|       |    // The nodes are:
  100|       |    // [0, n): the sorted leaf nodes that we start with.
  101|       |    // [n]: we add a sentinel here.
  102|       |    // [n + 1, 2n): new parent nodes are added here, starting from
  103|       |    //              (n+1). These are naturally in ascending order.
  104|       |    // [2n]: we add a sentinel at the end as well.
  105|       |    // There will be (2n+1) elements at the end.
  106|  2.25M|    const HuffmanTree sentinel(~static_cast<uint32_t>(0), -1, -1);
  107|  2.25M|    tree[n] = sentinel;
  108|  2.25M|    tree[n + 1] = sentinel;
  109|       |
  110|  2.25M|    size_t i = 0;      // Points to the next leaf node.
  111|  2.25M|    size_t j = n + 1;  // Points to the next non-leaf node.
  112|  26.3M|    for (size_t k = n - 1; k != 0; --k) {
  ------------------
  |  Branch (112:28): [True: 24.1M, False: 2.25M]
  ------------------
  113|  24.1M|      size_t left, right;
  114|  24.1M|      if (tree[i].total_count_ <= tree[j].total_count_) {
  ------------------
  |  Branch (114:11): [True: 12.9M, False: 11.1M]
  ------------------
  115|  12.9M|        left = i;
  116|  12.9M|        ++i;
  117|  12.9M|      } else {
  118|  11.1M|        left = j;
  119|  11.1M|        ++j;
  120|  11.1M|      }
  121|  24.1M|      if (tree[i].total_count_ <= tree[j].total_count_) {
  ------------------
  |  Branch (121:11): [True: 13.3M, False: 10.7M]
  ------------------
  122|  13.3M|        right = i;
  123|  13.3M|        ++i;
  124|  13.3M|      } else {
  125|  10.7M|        right = j;
  126|  10.7M|        ++j;
  127|  10.7M|      }
  128|       |
  129|       |      // The sentinel node becomes the parent node.
  130|  24.1M|      size_t j_end = 2 * n - k;
  131|  24.1M|      tree[j_end].total_count_ =
  132|  24.1M|          tree[left].total_count_ + tree[right].total_count_;
  133|  24.1M|      tree[j_end].index_left_ = static_cast<int16_t>(left);
  134|  24.1M|      tree[j_end].index_right_or_value_ = static_cast<int16_t>(right);
  135|       |
  136|       |      // Add back the last sentinel node.
  137|  24.1M|      tree[j_end + 1] = sentinel;
  138|  24.1M|    }
  139|  2.25M|    if (SetDepth(static_cast<int>(2 * n - 1), &tree[0], depth, tree_limit)) {
  ------------------
  |  Branch (139:9): [True: 2.25M, False: 0]
  ------------------
  140|       |      /* We need to pack the Huffman tree in tree_limit bits. If this was not
  141|       |         successful, add fake entities to the lowest values and retry. */
  142|  2.25M|      break;
  143|  2.25M|    }
  144|  2.25M|  }
  145|  2.27M|}
entropy_encode.cc:_ZN7guetzliL15SortHuffmanTreeERKNS_11HuffmanTreeES2_:
   51|  86.4M|                                   const HuffmanTree& v1) {
   52|  86.4M|  if (v0.total_count_ != v1.total_count_) {
  ------------------
  |  Branch (52:7): [True: 66.3M, False: 20.1M]
  ------------------
   53|  66.3M|    return v0.total_count_ < v1.total_count_;
   54|  66.3M|  }
   55|  20.1M|  return v0.index_right_or_value_ > v1.index_right_or_value_;
   56|  86.4M|}

_ZN7guetzli11HuffmanTreeC2Ev:
   29|  1.17G|  HuffmanTree() {}
_ZN7guetzli11HuffmanTreeC2Ejss:
   31|  28.6M|      : total_count_(count),
   32|  28.6M|        index_left_(left),
   33|  28.6M|        index_right_or_value_(right) {
   34|  28.6M|  }

_ZN7guetzli16Log2FloorNonZeroEj:
   24|   361M|inline int Log2FloorNonZero(uint32_t n) {
   25|   361M|#ifdef __GNUC__
   26|   361M|  return 31 ^ __builtin_clz(n);
   27|       |#else
   28|       |  unsigned int result = 0;
   29|       |  while (n >>= 1) result++;
   30|       |  return result;
   31|       |#endif
   32|   361M|}
_ZN7guetzli9Log2FloorEj:
   34|  25.1M|inline int Log2Floor(uint32_t n) {
   35|  25.1M|  return n == 0 ? -1 : Log2FloorNonZero(n);
  ------------------
  |  Branch (35:10): [True: 21.2M, False: 3.83M]
  ------------------
   36|  25.1M|}

_ZN7guetzli21NewSrgb8ToLinearTableEv:
   23|      1|const double* NewSrgb8ToLinearTable() {
   24|      1|  double* table = new double[256];
   25|      1|  int i = 0;
   26|     12|  for (; i < 11; ++i) {
  ------------------
  |  Branch (26:10): [True: 11, False: 1]
  ------------------
   27|     11|    table[i] = i / 12.92;
   28|     11|  }
   29|    246|  for (; i < 256; ++i) {
  ------------------
  |  Branch (29:10): [True: 245, False: 1]
  ------------------
   30|    245|    table[i] = 255.0 * std::pow(((i / 255.0) + 0.055) / 1.055, 2.4);
   31|    245|  }
   32|      1|  return table;
   33|      1|}
_ZN7guetzli18Srgb8ToLinearTableEv:
   35|  6.42M|const double* Srgb8ToLinearTable() {
   36|  6.42M|  static const double* const kSrgb8ToLinearTable = NewSrgb8ToLinearTable();
   37|  6.42M|  return kSrgb8ToLinearTable;
   38|  6.42M|}

_ZN7guetzli16ComputeBlockIDCTEPKsPh:
  139|  22.6M|void ComputeBlockIDCT(const coeff_t* block, uint8_t* out) {
  140|  22.6M|  coeff_t colidcts[kDCTBlockSize];
  141|  22.6M|  const int kColScale = 11;
  142|  22.6M|  const int kColRound = 1 << (kColScale - 1);
  143|   203M|  for (int x = 0; x < 8; ++x) {
  ------------------
  |  Branch (143:19): [True: 181M, False: 22.6M]
  ------------------
  144|   181M|    int colbuf[8] = { 0 };
  145|   181M|    Compute1dIDCT(&block[x], 8, colbuf);
  146|  1.62G|    for (int y = 0; y < 8; ++y) {
  ------------------
  |  Branch (146:21): [True: 1.44G, False: 181M]
  ------------------
  147|  1.44G|      colidcts[8 * y + x] = (colbuf[y] + kColRound) >> kColScale;
  148|  1.44G|    }
  149|   181M|  }
  150|  22.6M|  const int kRowScale = 18;
  151|  22.6M|  const int kRowRound = 257 << (kRowScale - 1);  // includes offset by 128
  152|   203M|  for (int y = 0; y < 8; ++y) {
  ------------------
  |  Branch (152:19): [True: 181M, False: 22.6M]
  ------------------
  153|   181M|    const int rowidx = 8 * y;
  154|   181M|    int rowbuf[8] = { 0 };
  155|   181M|    Compute1dIDCT(&colidcts[rowidx], 1, rowbuf);
  156|  1.62G|    for (int x = 0; x < 8; ++x) {
  ------------------
  |  Branch (156:21): [True: 1.44G, False: 181M]
  ------------------
  157|  1.44G|      out[rowidx + x] =
  158|  1.44G|          std::max(0, std::min(255, (rowbuf[x] + kRowRound) >> kRowScale));
  159|  1.44G|    }
  160|   181M|  }
  161|  22.6M|}
_ZN7guetzli13Compute1dIDCTEPKsiPi:
   41|   362M|inline void Compute1dIDCT(const coeff_t* in, const int stride, int out[8]) {
   42|   362M|  int tmp0, tmp1, tmp2, tmp3, tmp4;
   43|       |
   44|   362M|  tmp1 = kIDCTMatrix[0] * in[0];
   45|   362M|  out[0] = out[1] = out[2] = out[3] = out[4] = out[5] = out[6] = out[7] = tmp1;
   46|       |
   47|   362M|  tmp0 = in[stride];
   48|   362M|  tmp1 = kIDCTMatrix[ 1] * tmp0;
   49|   362M|  tmp2 = kIDCTMatrix[ 9] * tmp0;
   50|   362M|  tmp3 = kIDCTMatrix[17] * tmp0;
   51|   362M|  tmp4 = kIDCTMatrix[25] * tmp0;
   52|   362M|  out[0] += tmp1;
   53|   362M|  out[1] += tmp2;
   54|   362M|  out[2] += tmp3;
   55|   362M|  out[3] += tmp4;
   56|   362M|  out[4] -= tmp4;
   57|   362M|  out[5] -= tmp3;
   58|   362M|  out[6] -= tmp2;
   59|   362M|  out[7] -= tmp1;
   60|       |
   61|   362M|  tmp0 = in[2 * stride];
   62|   362M|  tmp1 = kIDCTMatrix[ 2] * tmp0;
   63|   362M|  tmp2 = kIDCTMatrix[10] * tmp0;
   64|   362M|  out[0] += tmp1;
   65|   362M|  out[1] += tmp2;
   66|   362M|  out[2] -= tmp2;
   67|   362M|  out[3] -= tmp1;
   68|   362M|  out[4] -= tmp1;
   69|   362M|  out[5] -= tmp2;
   70|   362M|  out[6] += tmp2;
   71|   362M|  out[7] += tmp1;
   72|       |
   73|   362M|  tmp0 = in[3 * stride];
   74|   362M|  tmp1 = kIDCTMatrix[ 3] * tmp0;
   75|   362M|  tmp2 = kIDCTMatrix[11] * tmp0;
   76|   362M|  tmp3 = kIDCTMatrix[19] * tmp0;
   77|   362M|  tmp4 = kIDCTMatrix[27] * tmp0;
   78|   362M|  out[0] += tmp1;
   79|   362M|  out[1] += tmp2;
   80|   362M|  out[2] += tmp3;
   81|   362M|  out[3] += tmp4;
   82|   362M|  out[4] -= tmp4;
   83|   362M|  out[5] -= tmp3;
   84|   362M|  out[6] -= tmp2;
   85|   362M|  out[7] -= tmp1;
   86|       |
   87|   362M|  tmp0 = in[4 * stride];
   88|   362M|  tmp1 = kIDCTMatrix[ 4] * tmp0;
   89|   362M|  out[0] += tmp1;
   90|   362M|  out[1] -= tmp1;
   91|   362M|  out[2] -= tmp1;
   92|   362M|  out[3] += tmp1;
   93|   362M|  out[4] += tmp1;
   94|   362M|  out[5] -= tmp1;
   95|   362M|  out[6] -= tmp1;
   96|   362M|  out[7] += tmp1;
   97|       |
   98|   362M|  tmp0 = in[5 * stride];
   99|   362M|  tmp1 = kIDCTMatrix[ 5] * tmp0;
  100|   362M|  tmp2 = kIDCTMatrix[13] * tmp0;
  101|   362M|  tmp3 = kIDCTMatrix[21] * tmp0;
  102|   362M|  tmp4 = kIDCTMatrix[29] * tmp0;
  103|   362M|  out[0] += tmp1;
  104|   362M|  out[1] += tmp2;
  105|   362M|  out[2] += tmp3;
  106|   362M|  out[3] += tmp4;
  107|   362M|  out[4] -= tmp4;
  108|   362M|  out[5] -= tmp3;
  109|   362M|  out[6] -= tmp2;
  110|   362M|  out[7] -= tmp1;
  111|       |
  112|   362M|  tmp0 = in[6 * stride];
  113|   362M|  tmp1 = kIDCTMatrix[ 6] * tmp0;
  114|   362M|  tmp2 = kIDCTMatrix[14] * tmp0;
  115|   362M|  out[0] += tmp1;
  116|   362M|  out[1] += tmp2;
  117|   362M|  out[2] -= tmp2;
  118|   362M|  out[3] -= tmp1;
  119|   362M|  out[4] -= tmp1;
  120|   362M|  out[5] -= tmp2;
  121|   362M|  out[6] += tmp2;
  122|   362M|  out[7] += tmp1;
  123|       |
  124|   362M|  tmp0 = in[7 * stride];
  125|   362M|  tmp1 = kIDCTMatrix[ 7] * tmp0;
  126|   362M|  tmp2 = kIDCTMatrix[15] * tmp0;
  127|   362M|  tmp3 = kIDCTMatrix[23] * tmp0;
  128|   362M|  tmp4 = kIDCTMatrix[31] * tmp0;
  129|   362M|  out[0] += tmp1;
  130|   362M|  out[1] += tmp2;
  131|   362M|  out[2] += tmp3;
  132|   362M|  out[3] += tmp4;
  133|   362M|  out[4] -= tmp4;
  134|   362M|  out[5] -= tmp3;
  135|   362M|  out[6] -= tmp2;
  136|   362M|  out[7] -= tmp1;
  137|   362M|}

_ZN7guetzli9BitWriterC2Em:
   33|   143k|  explicit BitWriter(size_t length) : len(length),
   34|   143k|                                      data(new uint8_t[len]),
   35|   143k|                                      pos(0),
   36|   143k|                                      put_buffer(0),
   37|   143k|                                      put_bits(64),
   38|   143k|                                      overflow(false) {}
_ZN7guetzli9BitWriter9WriteBitsEim:
   40|   288M|  void WriteBits(int nbits, uint64_t bits) {
   41|   288M|    put_bits -= nbits;
   42|   288M|    put_buffer |= (bits << put_bits);
   43|   288M|    if (put_bits <= 16) {
  ------------------
  |  Branch (43:9): [True: 13.0M, False: 275M]
  ------------------
   44|       |      // At this point we are ready to emit the most significant 6 bytes of
   45|       |      // put_buffer_ to the output.
   46|       |      // The JPEG format requires that after every 0xff byte in the entropy
   47|       |      // coded section, there is a zero byte, therefore we first check if any of
   48|       |      // the 6 most significant bytes of put_buffer_ is 0xff.
   49|  13.0M|      if (HasZeroByte(~put_buffer | 0xffff)) {
  ------------------
  |  Branch (49:11): [True: 284k, False: 12.7M]
  ------------------
   50|       |        // We have a 0xff byte somewhere, examine each byte and append a zero
   51|       |        // byte if necessary.
   52|   284k|        EmitByte((put_buffer >> 56) & 0xff);
   53|   284k|        EmitByte((put_buffer >> 48) & 0xff);
   54|   284k|        EmitByte((put_buffer >> 40) & 0xff);
   55|   284k|        EmitByte((put_buffer >> 32) & 0xff);
   56|   284k|        EmitByte((put_buffer >> 24) & 0xff);
   57|   284k|        EmitByte((put_buffer >> 16) & 0xff);
   58|  12.7M|      } else if (pos + 6 < len) {
  ------------------
  |  Branch (58:18): [True: 12.7M, False: 0]
  ------------------
   59|       |        // We don't have any 0xff bytes, output all 6 bytes without checking.
   60|  12.7M|        data[pos] = (put_buffer >> 56) & 0xff;
   61|  12.7M|        data[pos + 1] = (put_buffer >> 48) & 0xff;
   62|  12.7M|        data[pos + 2] = (put_buffer >> 40) & 0xff;
   63|  12.7M|        data[pos + 3] = (put_buffer >> 32) & 0xff;
   64|  12.7M|        data[pos + 4] = (put_buffer >> 24) & 0xff;
   65|  12.7M|        data[pos + 5] = (put_buffer >> 16) & 0xff;
   66|  12.7M|        pos += 6;
   67|  12.7M|      } else {
   68|      0|        overflow = true;
   69|      0|      }
   70|  13.0M|      put_buffer <<= 48;
   71|  13.0M|      put_bits += 48;
   72|  13.0M|    }
   73|   288M|  }
_ZN7guetzli11HasZeroByteEm:
   27|  13.0M|inline uint64_t HasZeroByte(uint64_t x) {
   28|  13.0M|  return (x - 0x0101010101010101ULL) & ~x & 0x8080808080808080ULL;
   29|  13.0M|}
_ZN7guetzli9BitWriter8EmitByteEi:
   76|  2.49M|  void EmitByte(int byte) {
   77|  2.49M|    if (pos < len) {
  ------------------
  |  Branch (77:9): [True: 2.49M, False: 0]
  ------------------
   78|  2.49M|      data[pos++] = byte;
   79|  2.49M|    } else {
   80|      0|      overflow = true;
   81|      0|    }
   82|  2.49M|    if (byte == 0xff) {
  ------------------
  |  Branch (82:9): [True: 299k, False: 2.19M]
  ------------------
   83|   299k|      EmitByte(0);
   84|   299k|    }
   85|  2.49M|  }
_ZN7guetzli9BitWriter18JumpToByteBoundaryEv:
   87|   143k|  void JumpToByteBoundary() {
   88|   502k|    while (put_bits <= 56) {
  ------------------
  |  Branch (88:12): [True: 358k, False: 143k]
  ------------------
   89|   358k|      int c = (put_buffer >> 56) & 0xff;
   90|   358k|      EmitByte(c);
   91|   358k|      put_buffer <<= 8;
   92|   358k|      put_bits += 8;
   93|   358k|    }
   94|   143k|    if (put_bits < 64) {
  ------------------
  |  Branch (94:9): [True: 124k, False: 18.8k]
  ------------------
   95|   124k|      int padmask = 0xff >> (64 - put_bits);
   96|   124k|      int c = ((put_buffer >> 56) & ~padmask) | padmask;
   97|   124k|      EmitByte(c);
   98|   124k|    }
   99|   143k|    put_buffer = 0;
  100|   143k|    put_bits = 64;
  101|   143k|  }

_ZNK7guetzli8JPEGData5Is420Ev:
   24|  4.39k|bool JPEGData::Is420() const {
   25|  4.39k|  return (components.size() == 3 &&
  ------------------
  |  Branch (25:11): [True: 4.39k, False: 0]
  ------------------
   26|  4.39k|          max_h_samp_factor == 2 &&
  ------------------
  |  Branch (26:11): [True: 3.62k, False: 770]
  ------------------
   27|  3.62k|          max_v_samp_factor == 2 &&
  ------------------
  |  Branch (27:11): [True: 3.61k, False: 3]
  ------------------
   28|  3.61k|          components[0].h_samp_factor == 2 &&
  ------------------
  |  Branch (28:11): [True: 3.61k, False: 1]
  ------------------
   29|  3.61k|          components[0].v_samp_factor == 2 &&
  ------------------
  |  Branch (29:11): [True: 3.61k, False: 1]
  ------------------
   30|  3.61k|          components[1].h_samp_factor == 1 &&
  ------------------
  |  Branch (30:11): [True: 3.61k, False: 1]
  ------------------
   31|  3.61k|          components[1].v_samp_factor == 1 &&
  ------------------
  |  Branch (31:11): [True: 3.61k, False: 1]
  ------------------
   32|  3.61k|          components[2].h_samp_factor == 1 &&
  ------------------
  |  Branch (32:11): [True: 3.61k, False: 1]
  ------------------
   33|  3.61k|          components[2].v_samp_factor == 1);
  ------------------
  |  Branch (33:11): [True: 3.61k, False: 1]
  ------------------
   34|  4.39k|}
_ZNK7guetzli8JPEGData5Is444Ev:
   36|  3.35k|bool JPEGData::Is444() const {
   37|  3.35k|  return (components.size() == 3 &&
  ------------------
  |  Branch (37:11): [True: 3.35k, False: 0]
  ------------------
   38|  3.35k|          max_h_samp_factor == 1 &&
  ------------------
  |  Branch (38:11): [True: 1.53k, False: 1.81k]
  ------------------
   39|  1.53k|          max_v_samp_factor == 1 &&
  ------------------
  |  Branch (39:11): [True: 1.53k, False: 3]
  ------------------
   40|  1.53k|          components[0].h_samp_factor == 1 &&
  ------------------
  |  Branch (40:11): [True: 1.53k, False: 0]
  ------------------
   41|  1.53k|          components[0].v_samp_factor == 1 &&
  ------------------
  |  Branch (41:11): [True: 1.53k, False: 0]
  ------------------
   42|  1.53k|          components[1].h_samp_factor == 1 &&
  ------------------
  |  Branch (42:11): [True: 1.53k, False: 0]
  ------------------
   43|  1.53k|          components[1].v_samp_factor == 1 &&
  ------------------
  |  Branch (43:11): [True: 1.53k, False: 0]
  ------------------
   44|  1.53k|          components[2].h_samp_factor == 1 &&
  ------------------
  |  Branch (44:11): [True: 1.53k, False: 0]
  ------------------
   45|  1.53k|          components[2].v_samp_factor == 1);
  ------------------
  |  Branch (45:11): [True: 1.53k, False: 0]
  ------------------
   46|  3.35k|}
_ZN7guetzli15SaveQuantTablesEPA64_KiPNS_8JPEGDataE:
   70|   151k|void SaveQuantTables(const int q[3][kDCTBlockSize], JPEGData* jpg) {
   71|   151k|  const size_t kTableSize = kDCTBlockSize * sizeof(q[0][0]);
   72|   151k|  jpg->quant.clear();
   73|   151k|  int num_tables = 0;
   74|   539k|  for (size_t i = 0; i < jpg->components.size(); ++i) {
  ------------------
  |  Branch (74:22): [True: 388k, False: 151k]
  ------------------
   75|   388k|    JPEGComponent* comp = &jpg->components[i];
   76|       |    // Check if we have this quant table already.
   77|   388k|    bool found = false;
   78|   433k|    for (int j = 0; j < num_tables; ++j) {
  ------------------
  |  Branch (78:21): [True: 259k, False: 174k]
  ------------------
   79|   259k|      if (memcmp(&q[i][0], &jpg->quant[j].values[0], kTableSize) == 0) {
  ------------------
  |  Branch (79:11): [True: 213k, False: 45.7k]
  ------------------
   80|   213k|        comp->quant_idx = j;
   81|   213k|        found = true;
   82|   213k|        break;
   83|   213k|      }
   84|   259k|    }
   85|   388k|    if (!found) {
  ------------------
  |  Branch (85:9): [True: 174k, False: 213k]
  ------------------
   86|   174k|      JPEGQuantTable table;
   87|   174k|      memcpy(&table.values[0], &q[i][0], kTableSize);
   88|   174k|      table.precision = 0;
   89|  11.3M|      for (int k = 0; k < kDCTBlockSize; ++k) {
  ------------------
  |  Branch (89:23): [True: 11.1M, False: 174k]
  ------------------
   90|  11.1M|        assert(table.values[k] >= 0);
  ------------------
  |  Branch (90:9): [True: 11.1M, False: 0]
  ------------------
   91|  11.1M|        assert(table.values[k] < (1 << 16));
  ------------------
  |  Branch (91:9): [True: 11.1M, False: 0]
  ------------------
   92|  11.1M|        if (table.values[k] > 0xff) {
  ------------------
  |  Branch (92:13): [True: 5.68k, False: 11.1M]
  ------------------
   93|  5.68k|          table.precision = 1;
   94|  5.68k|        }
   95|  11.1M|      }
   96|   174k|      table.index = num_tables;
   97|   174k|      comp->quant_idx = num_tables;
   98|   174k|      jpg->quant.push_back(table);
   99|   174k|      ++num_tables;
  100|   174k|    }
  101|   388k|  }
  102|   151k|}

_ZN7guetzli8JPEGDataC2Ev:
  169|  9.27k|  JPEGData() : width(0),
  170|  9.27k|               height(0),
  171|  9.27k|               version(0),
  172|  9.27k|               max_h_samp_factor(1),
  173|  9.27k|               max_v_samp_factor(1),
  174|  9.27k|               MCU_rows(0),
  175|  9.27k|               MCU_cols(0),
  176|  9.27k|               restart_interval(0),
  177|  9.27k|               original_jpg(NULL),
  178|  9.27k|               original_jpg_size(0),
  179|  9.27k|               error(JPEG_OK) {}
_ZN7guetzli14JPEGQuantTableC2Ev:
   86|   181k|  JPEGQuantTable() : values(kDCTBlockSize), precision(0),
   87|   181k|                     index(0), is_last(true) {}
_ZN7guetzli15JPEGHuffmanCodeC2Ev:
  101|   222k|  JPEGHuffmanCode() : counts(kJpegHuffmanMaxBitLength + 1),
  102|   222k|                      values(kJpegHuffmanAlphabetSize + 1),
  103|   222k|                      slot_id(0),
  104|   222k|                      is_last(true) {}
_ZN7guetzli13JPEGComponentC2Ev:
  142|  20.6k|  JPEGComponent() : id(0),
  143|  20.6k|                    h_samp_factor(1),
  144|  20.6k|                    v_samp_factor(1),
  145|  20.6k|                    quant_idx(0),
  146|  20.6k|                    width_in_blocks(0),
  147|  20.6k|                    height_in_blocks(0) {}

_ZN7guetzli18HasYCbCrColorSpaceERKNS_8JPEGDataE:
   25|  5.16k|bool HasYCbCrColorSpace(const JPEGData& jpg) {
   26|  5.16k|  bool has_Adobe_marker = false;
   27|  5.16k|  uint8_t Adobe_transform = 0;
   28|   326k|  for (const std::string& app : jpg.app_data) {
  ------------------
  |  Branch (28:31): [True: 326k, False: 4.58k]
  ------------------
   29|   326k|    if (static_cast<uint8_t>(app[0]) == 0xe0) {
  ------------------
  |  Branch (29:9): [True: 578, False: 325k]
  ------------------
   30|    578|      return true;
   31|   325k|    } else if (static_cast<uint8_t>(app[0]) == 0xee && app.size() >= 15) {
  ------------------
  |  Branch (31:16): [True: 1.99k, False: 323k]
  |  Branch (31:56): [True: 1.42k, False: 570]
  ------------------
   32|  1.42k|      has_Adobe_marker = true;
   33|  1.42k|      Adobe_transform = app[14];
   34|  1.42k|    }
   35|   326k|  }
   36|  4.58k|  if (has_Adobe_marker) {
  ------------------
  |  Branch (36:7): [True: 57, False: 4.53k]
  ------------------
   37|     57|    return (Adobe_transform != 0);
   38|     57|  }
   39|  4.53k|  const int cid0 = jpg.components[0].id;
   40|  4.53k|  const int cid1 = jpg.components[1].id;
   41|  4.53k|  const int cid2 = jpg.components[2].id;
   42|  4.53k|  return (cid0 != 'R' || cid1 != 'G' || cid2 != 'B');
  ------------------
  |  Branch (42:11): [True: 4.50k, False: 24]
  |  Branch (42:26): [True: 6, False: 18]
  |  Branch (42:41): [True: 16, False: 2]
  ------------------
   43|  4.58k|}
_ZN7guetzli15DecodeJpegToRGBERKNS_8JPEGDataE:
   45|  2.67k|std::vector<uint8_t> DecodeJpegToRGB(const JPEGData& jpg) {
   46|  2.67k|  if (jpg.components.size() == 1 ||
  ------------------
  |  Branch (46:7): [True: 79, False: 2.59k]
  ------------------
   47|  2.59k|      (jpg.components.size() == 3 &&
  ------------------
  |  Branch (47:8): [True: 2.59k, False: 2]
  ------------------
   48|  2.65k|       HasYCbCrColorSpace(jpg) && (jpg.Is420() || jpg.Is444()))) {
  ------------------
  |  Branch (48:8): [True: 2.58k, False: 7]
  |  Branch (48:36): [True: 1.80k, False: 779]
  |  Branch (48:51): [True: 767, False: 12]
  ------------------
   49|  2.65k|    OutputImage img(jpg.width, jpg.height);
   50|  2.65k|    img.CopyFromJpegData(jpg);
   51|  2.65k|    return img.ToSRGB();
   52|  2.65k|  }
   53|     21|  return std::vector<uint8_t>();
   54|  2.67k|}

_ZN7guetzli8ReadJpegEPKhmNS_12JpegReadModeEPNS_8JPEGDataE:
  932|  9.27k|              JPEGData* jpg) {
  933|  9.27k|  size_t pos = 0;
  934|       |  // Check SOI marker.
  935|  9.27k|  EXPECT_MARKER();
  ------------------
  |  |   57|  9.27k|  if (pos + 2 > len || data[pos] != 0xff) {                             \
  |  |  ------------------
  |  |  |  Branch (57:7): [True: 1, False: 9.27k]
  |  |  |  Branch (57:24): [True: 14, False: 9.26k]
  |  |  ------------------
  |  |   58|     15|    fprintf(stderr, "Marker byte (0xff) expected, found: %d "           \
  |  |   59|     15|            "pos=%d len=%d\n",                                          \
  |  |   60|     15|            (pos < len ? data[pos] : 0), static_cast<int>(pos),         \
  |  |  ------------------
  |  |  |  Branch (60:14): [True: 15, False: 0]
  |  |  ------------------
  |  |   61|     15|            static_cast<int>(len));                                     \
  |  |   62|     15|    jpg->error = JPEG_MARKER_BYTE_NOT_FOUND;                            \
  |  |   63|     15|    return false;                                                       \
  |  |   64|     15|  }
  ------------------
  936|  9.26k|  int marker = data[pos + 1];
  937|  9.26k|  pos += 2;
  938|  9.26k|  if (marker != 0xd8) {
  ------------------
  |  Branch (938:7): [True: 11, False: 9.25k]
  ------------------
  939|     11|    fprintf(stderr, "Did not find expected SOI marker, actual=%d\n", marker);
  940|     11|    jpg->error = JPEG_SOI_NOT_FOUND;
  941|     11|    return false;
  942|     11|  }
  943|  9.25k|  int lut_size = kMaxHuffmanTables * kJpegHuffmanLutSize;
  944|  9.25k|  std::vector<HuffmanTableEntry> dc_huff_lut(lut_size);
  945|  9.25k|  std::vector<HuffmanTableEntry> ac_huff_lut(lut_size);
  946|  9.25k|  bool found_sof = false;
  947|  9.25k|  uint16_t scan_progression[kMaxComponents][kDCTBlockSize] = { { 0 } };
  948|       |
  949|  9.25k|  bool is_progressive = false;   // default
  950|  7.11M|  do {
  951|       |    // Read next marker.
  952|  7.11M|    size_t num_skipped = FindNextMarker(data, len, pos);
  953|  7.11M|    if (num_skipped > 0) {
  ------------------
  |  Branch (953:9): [True: 6.69M, False: 421k]
  ------------------
  954|       |      // Add a fake marker to indicate arbitrary in-between-markers data.
  955|  6.69M|      jpg->marker_order.push_back(0xff);
  956|  6.69M|      jpg->inter_marker_data.push_back(
  957|  6.69M|          std::string(reinterpret_cast<const char*>(&data[pos]),
  958|  6.69M|                                      num_skipped));
  959|  6.69M|      pos += num_skipped;
  960|  6.69M|    }
  961|  7.11M|    EXPECT_MARKER();
  ------------------
  |  |   57|  7.11M|  if (pos + 2 > len || data[pos] != 0xff) {                             \
  |  |  ------------------
  |  |  |  Branch (57:7): [True: 540, False: 7.11M]
  |  |  |  Branch (57:24): [True: 0, False: 7.11M]
  |  |  ------------------
  |  |   58|    540|    fprintf(stderr, "Marker byte (0xff) expected, found: %d "           \
  |  |   59|    540|            "pos=%d len=%d\n",                                          \
  |  |   60|    540|            (pos < len ? data[pos] : 0), static_cast<int>(pos),         \
  |  |  ------------------
  |  |  |  Branch (60:14): [True: 252, False: 288]
  |  |  ------------------
  |  |   61|    540|            static_cast<int>(len));                                     \
  |  |   62|    540|    jpg->error = JPEG_MARKER_BYTE_NOT_FOUND;                            \
  |  |   63|    540|    return false;                                                       \
  |  |   64|    540|  }
  ------------------
  962|  7.11M|    marker = data[pos + 1];
  963|  7.11M|    pos += 2;
  964|  7.11M|    bool ok = true;
  965|  7.11M|    switch (marker) {
  966|  1.11k|      case 0xc0:
  ------------------
  |  Branch (966:7): [True: 1.11k, False: 7.11M]
  ------------------
  967|  2.55k|      case 0xc1:
  ------------------
  |  Branch (967:7): [True: 1.44k, False: 7.11M]
  ------------------
  968|  8.60k|      case 0xc2:
  ------------------
  |  Branch (968:7): [True: 6.05k, False: 7.10M]
  ------------------
  969|  8.60k|        is_progressive = (marker == 0xc2);
  970|  8.60k|        ok = ProcessSOF(data, len, mode, &pos, jpg);
  971|  8.60k|        found_sof = true;
  972|  8.60k|        break;
  973|  26.0k|      case 0xc4:
  ------------------
  |  Branch (973:7): [True: 26.0k, False: 7.08M]
  ------------------
  974|  26.0k|        ok = ProcessDHT(data, len, mode, &dc_huff_lut, &ac_huff_lut, &pos, jpg);
  975|  26.0k|        break;
  976|  3.84M|      case 0xd0:
  ------------------
  |  Branch (976:7): [True: 3.84M, False: 3.27M]
  ------------------
  977|  3.84M|      case 0xd1:
  ------------------
  |  Branch (977:7): [True: 7.80k, False: 7.10M]
  ------------------
  978|  3.85M|      case 0xd2:
  ------------------
  |  Branch (978:7): [True: 1.55k, False: 7.11M]
  ------------------
  979|  3.87M|      case 0xd3:
  ------------------
  |  Branch (979:7): [True: 18.8k, False: 7.09M]
  ------------------
  980|  3.87M|      case 0xd4:
  ------------------
  |  Branch (980:7): [True: 1.73k, False: 7.11M]
  ------------------
  981|  3.87M|      case 0xd5:
  ------------------
  |  Branch (981:7): [True: 885, False: 7.11M]
  ------------------
  982|  4.13M|      case 0xd6:
  ------------------
  |  Branch (982:7): [True: 266k, False: 6.84M]
  ------------------
  983|  4.84M|      case 0xd7:
  ------------------
  |  Branch (983:7): [True: 701k, False: 6.41M]
  ------------------
  984|       |        // RST markers do not have any data.
  985|  4.84M|        break;
  986|  2.70k|      case 0xd9:
  ------------------
  |  Branch (986:7): [True: 2.70k, False: 7.11M]
  ------------------
  987|       |        // Found end marker.
  988|  2.70k|        break;
  989|  6.74k|      case 0xda:
  ------------------
  |  Branch (989:7): [True: 6.74k, False: 7.10M]
  ------------------
  990|  6.74k|        if (mode == JPEG_READ_ALL) {
  ------------------
  |  Branch (990:13): [True: 6.41k, False: 332]
  ------------------
  991|  6.41k|          ok = ProcessScan(data, len, dc_huff_lut, ac_huff_lut,
  992|  6.41k|                           scan_progression, is_progressive, &pos, jpg);
  993|  6.41k|        }
  994|  6.74k|        break;
  995|  7.03k|      case 0xdb:
  ------------------
  |  Branch (995:7): [True: 7.03k, False: 7.10M]
  ------------------
  996|  7.03k|        ok = ProcessDQT(data, len, &pos, jpg);
  997|  7.03k|        break;
  998|    739|      case 0xdd:
  ------------------
  |  Branch (998:7): [True: 739, False: 7.11M]
  ------------------
  999|    739|        ok = ProcessDRI(data, len, &pos, jpg);
 1000|    739|        break;
 1001|   135k|      case 0xe0:
  ------------------
  |  Branch (1001:7): [True: 135k, False: 6.97M]
  ------------------
 1002|   736k|      case 0xe1:
  ------------------
  |  Branch (1002:7): [True: 600k, False: 6.51M]
  ------------------
 1003|   736k|      case 0xe2:
  ------------------
  |  Branch (1003:7): [True: 471, False: 7.11M]
  ------------------
 1004|   737k|      case 0xe3:
  ------------------
  |  Branch (1004:7): [True: 565, False: 7.11M]
  ------------------
 1005|   737k|      case 0xe4:
  ------------------
  |  Branch (1005:7): [True: 243, False: 7.11M]
  ------------------
 1006|   922k|      case 0xe5:
  ------------------
  |  Branch (1006:7): [True: 184k, False: 6.92M]
  ------------------
 1007|   922k|      case 0xe6:
  ------------------
  |  Branch (1007:7): [True: 236, False: 7.11M]
  ------------------
 1008|   922k|      case 0xe7:
  ------------------
  |  Branch (1008:7): [True: 299, False: 7.11M]
  ------------------
 1009|   923k|      case 0xe8:
  ------------------
  |  Branch (1009:7): [True: 667, False: 7.11M]
  ------------------
 1010|  1.26M|      case 0xe9:
  ------------------
  |  Branch (1010:7): [True: 343k, False: 6.76M]
  ------------------
 1011|  1.26M|      case 0xea:
  ------------------
  |  Branch (1011:7): [True: 468, False: 7.11M]
  ------------------
 1012|  1.26M|      case 0xeb:
  ------------------
  |  Branch (1012:7): [True: 457, False: 7.11M]
  ------------------
 1013|  1.26M|      case 0xec:
  ------------------
  |  Branch (1013:7): [True: 324, False: 7.11M]
  ------------------
 1014|  1.26M|      case 0xed:
  ------------------
  |  Branch (1014:7): [True: 304, False: 7.11M]
  ------------------
 1015|  1.27M|      case 0xee:
  ------------------
  |  Branch (1015:7): [True: 2.25k, False: 7.11M]
  ------------------
 1016|  1.79M|      case 0xef:
  ------------------
  |  Branch (1016:7): [True: 527k, False: 6.58M]
  ------------------
 1017|  1.79M|        if (mode != JPEG_READ_TABLES) {
  ------------------
  |  Branch (1017:13): [True: 1.79M, False: 0]
  ------------------
 1018|  1.79M|          ok = ProcessAPP(data, len, &pos, jpg);
 1019|  1.79M|        }
 1020|  1.79M|        break;
 1021|   421k|      case 0xfe:
  ------------------
  |  Branch (1021:7): [True: 421k, False: 6.69M]
  ------------------
 1022|   421k|        if (mode != JPEG_READ_TABLES) {
  ------------------
  |  Branch (1022:13): [True: 421k, False: 0]
  ------------------
 1023|   421k|          ok = ProcessCOM(data, len, &pos, jpg);
 1024|   421k|        }
 1025|   421k|        break;
 1026|      0|      default:
  ------------------
  |  Branch (1026:7): [True: 0, False: 7.11M]
  ------------------
 1027|      0|        fprintf(stderr, "Unsupported marker: %d pos=%d len=%d\n",
 1028|      0|                marker, static_cast<int>(pos), static_cast<int>(len));
 1029|      0|        jpg->error = JPEG_UNSUPPORTED_MARKER;
 1030|      0|        ok = false;
 1031|      0|        break;
 1032|  7.11M|    }
 1033|  7.11M|    if (!ok) {
  ------------------
  |  Branch (1033:9): [True: 1.73k, False: 7.11M]
  ------------------
 1034|  1.73k|      return false;
 1035|  1.73k|    }
 1036|  7.11M|    jpg->marker_order.push_back(marker);
 1037|  7.11M|    if (mode == JPEG_READ_HEADER && found_sof) {
  ------------------
  |  Branch (1037:9): [True: 3.82M, False: 3.29M]
  |  Branch (1037:37): [True: 4.27k, False: 3.81M]
  ------------------
 1038|  4.27k|      break;
 1039|  4.27k|    }
 1040|  7.11M|  } while (marker != 0xd9);
  ------------------
  |  Branch (1040:12): [True: 7.10M, False: 2.70k]
  ------------------
 1041|       |
 1042|  6.97k|  if (!found_sof) {
  ------------------
  |  Branch (1042:7): [True: 5, False: 6.97k]
  ------------------
 1043|      5|    fprintf(stderr, "Missing SOF marker.\n");
 1044|      5|    jpg->error = JPEG_SOF_NOT_FOUND;
 1045|      5|    return false;
 1046|      5|  }
 1047|       |
 1048|       |  // Supplemental checks.
 1049|  6.97k|  if (mode == JPEG_READ_ALL) {
  ------------------
  |  Branch (1049:7): [True: 2.70k, False: 4.27k]
  ------------------
 1050|  2.70k|    if (pos < len) {
  ------------------
  |  Branch (1050:9): [True: 310, False: 2.39k]
  ------------------
 1051|    310|      jpg->tail_data.assign(reinterpret_cast<const char*>(&data[pos]),
 1052|    310|                            len - pos);
 1053|    310|    }
 1054|  2.70k|    if (!FixupIndexes(jpg)) {
  ------------------
  |  Branch (1054:9): [True: 13, False: 2.69k]
  ------------------
 1055|     13|      return false;
 1056|     13|    }
 1057|  2.69k|    if (jpg->huffman_code.size() == 0) {
  ------------------
  |  Branch (1057:9): [True: 7, False: 2.68k]
  ------------------
 1058|       |      // Section B.2.4.2: "If a table has never been defined for a particular
 1059|       |      // destination, then when this destination is specified in a scan header,
 1060|       |      // the results are unpredictable."
 1061|      7|      fprintf(stderr, "Need at least one Huffman code table.\n");
 1062|      7|      jpg->error = JPEG_HUFFMAN_TABLE_ERROR;
 1063|      7|      return false;
 1064|      7|    }
 1065|  2.68k|    if (jpg->huffman_code.size() >= kMaxDHTMarkers) {
  ------------------
  |  Branch (1065:9): [True: 2, False: 2.68k]
  ------------------
 1066|      2|      fprintf(stderr, "Too many Huffman tables.\n");
 1067|      2|      jpg->error = JPEG_HUFFMAN_TABLE_ERROR;
 1068|      2|      return false;
 1069|      2|    }
 1070|  2.68k|  }
 1071|  6.95k|  return true;
 1072|  6.97k|}
_ZN7guetzli8ReadJpegERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS_12JpegReadModeEPNS_8JPEGDataE:
 1075|  4.25k|              JPEGData* jpg) {
 1076|  4.25k|  return ReadJpeg(reinterpret_cast<const uint8_t*>(data.data()),
 1077|  4.25k|                  static_cast<const size_t>(data.size()),
 1078|  4.25k|                  mode, jpg);
 1079|  4.25k|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_114FindNextMarkerEPKhmm:
  911|  7.11M|size_t FindNextMarker(const uint8_t* data, const size_t len, size_t pos) {
  912|       |  // kIsValidMarker[i] == 1 means (0xc0 + i) is a valid marker.
  913|  7.11M|  static const uint8_t kIsValidMarker[] = {
  914|  7.11M|    1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  915|  7.11M|    1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0,
  916|  7.11M|    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  917|  7.11M|    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
  918|  7.11M|  };
  919|  7.11M|  size_t num_skipped = 0;
  920|  58.7M|  while (pos + 1 < len &&
  ------------------
  |  Branch (920:10): [True: 58.7M, False: 540]
  ------------------
  921|  58.7M|         (data[pos] != 0xff || data[pos + 1] < 0xc0 ||
  ------------------
  |  Branch (921:11): [True: 48.5M, False: 10.1M]
  |  Branch (921:32): [True: 390k, False: 9.75M]
  ------------------
  922|  51.6M|          !kIsValidMarker[data[pos + 1] - 0xc0])) {
  ------------------
  |  Branch (922:11): [True: 2.64M, False: 7.11M]
  ------------------
  923|  51.6M|    ++pos;
  924|  51.6M|    ++num_skipped;
  925|  51.6M|  }
  926|  7.11M|  return num_skipped;
  927|  7.11M|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_110ProcessSOFEPKhmNS_12JpegReadModeEPmPNS_8JPEGDataE:
   88|  8.60k|                JpegReadMode mode, size_t* pos, JPEGData* jpg) {
   89|  8.60k|  if (jpg->width != 0) {
  ------------------
  |  Branch (89:7): [True: 17, False: 8.59k]
  ------------------
   90|     17|    fprintf(stderr, "Duplicate SOF marker.\n");
   91|     17|    jpg->error = JPEG_DUPLICATE_SOF;
   92|     17|    return false;
   93|     17|  }
   94|  8.59k|  const size_t start_pos = *pos;
   95|  8.59k|  VERIFY_LEN(8);
  ------------------
  |  |   32|  8.59k|  if (*pos + (n) > len) {                                               \
  |  |  ------------------
  |  |  |  Branch (32:7): [True: 7, False: 8.58k]
  |  |  ------------------
  |  |   33|      7|    fprintf(stderr, "Unexpected end of input: pos=%d need=%d len=%d\n", \
  |  |   34|      7|            static_cast<int>(*pos), static_cast<int>(n),                \
  |  |   35|      7|            static_cast<int>(len));                                     \
  |  |   36|      7|    jpg->error = JPEG_UNEXPECTED_EOF;                                   \
  |  |   37|      7|    return false;                                                       \
  |  |   38|      7|  }
  ------------------
   96|  8.58k|  size_t marker_len = ReadUint16(data, pos);
   97|  8.58k|  int precision = ReadUint8(data, pos);
   98|  8.58k|  int height = ReadUint16(data, pos);
   99|  8.58k|  int width = ReadUint16(data, pos);
  100|  8.58k|  int num_components = ReadUint8(data, pos);
  101|  8.58k|  VERIFY_INPUT(precision, 8, 8, PRECISION);
  ------------------
  |  |   41|  8.58k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 4, False: 8.57k]
  |  |  |  Branch (41:20): [True: 9, False: 8.57k]
  |  |  ------------------
  |  |   42|     13|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|     13|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|     13|        return false;                                                   \
  |  |   45|     13|  }
  ------------------
  102|  8.57k|  VERIFY_INPUT(height, 1, 65535, HEIGHT);
  ------------------
  |  |   41|  8.57k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 1, False: 8.56k]
  |  |  |  Branch (41:20): [True: 0, False: 8.56k]
  |  |  ------------------
  |  |   42|      1|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|      1|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|      1|        return false;                                                   \
  |  |   45|      1|  }
  ------------------
  103|  8.56k|  VERIFY_INPUT(width, 1, 65535, WIDTH);
  ------------------
  |  |   41|  8.56k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 1, False: 8.56k]
  |  |  |  Branch (41:20): [True: 0, False: 8.56k]
  |  |  ------------------
  |  |   42|      1|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|      1|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|      1|        return false;                                                   \
  |  |   45|      1|  }
  ------------------
  104|  8.56k|  VERIFY_INPUT(num_components, 1, kMaxComponents, NUMCOMP);
  ------------------
  |  |   41|  8.56k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 2, False: 8.56k]
  |  |  |  Branch (41:20): [True: 11, False: 8.55k]
  |  |  ------------------
  |  |   42|     13|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|     13|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|     13|        return false;                                                   \
  |  |   45|     13|  }
  ------------------
  105|  8.55k|  VERIFY_LEN(3 * num_components);
  ------------------
  |  |   32|  8.55k|  if (*pos + (n) > len) {                                               \
  |  |  ------------------
  |  |  |  Branch (32:7): [True: 6, False: 8.54k]
  |  |  ------------------
  |  |   33|      6|    fprintf(stderr, "Unexpected end of input: pos=%d need=%d len=%d\n", \
  |  |   34|      6|            static_cast<int>(*pos), static_cast<int>(n),                \
  |  |   35|      6|            static_cast<int>(len));                                     \
  |  |   36|      6|    jpg->error = JPEG_UNEXPECTED_EOF;                                   \
  |  |   37|      6|    return false;                                                       \
  |  |   38|      6|  }
  ------------------
  106|  8.54k|  jpg->height = height;
  107|  8.54k|  jpg->width = width;
  108|  8.54k|  jpg->components.resize(num_components);
  109|       |
  110|       |  // Read sampling factors and quant table index for each component.
  111|  8.54k|  std::vector<bool> ids_seen(256, false);
  112|  29.2k|  for (size_t i = 0; i < jpg->components.size(); ++i) {
  ------------------
  |  Branch (112:22): [True: 20.6k, False: 8.54k]
  ------------------
  113|  20.6k|    const int id = ReadUint8(data, pos);
  114|  20.6k|    if (ids_seen[id]) {   // (cf. section B.2.2, syntax of Ci)
  ------------------
  |  Branch (114:9): [True: 1, False: 20.6k]
  ------------------
  115|      1|      fprintf(stderr, "Duplicate ID %d in SOF.\n", id);
  116|      1|      jpg->error = JPEG_DUPLICATE_COMPONENT_ID;
  117|      1|      return false;
  118|      1|    }
  119|  20.6k|    ids_seen[id] = true;
  120|  20.6k|    jpg->components[i].id = id;
  121|  20.6k|    int factor = ReadUint8(data, pos);
  122|  20.6k|    int h_samp_factor = factor >> 4;
  123|  20.6k|    int v_samp_factor = factor & 0xf;
  124|  20.6k|    VERIFY_INPUT(h_samp_factor, 1, 15, SAMP_FACTOR);
  ------------------
  |  |   41|  20.6k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 5, False: 20.6k]
  |  |  |  Branch (41:20): [True: 0, False: 20.6k]
  |  |  ------------------
  |  |   42|      5|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|      5|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|      5|        return false;                                                   \
  |  |   45|      5|  }
  ------------------
  125|  20.6k|    VERIFY_INPUT(v_samp_factor, 1, 15, SAMP_FACTOR);
  ------------------
  |  |   41|  20.6k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 1, False: 20.6k]
  |  |  |  Branch (41:20): [True: 0, False: 20.6k]
  |  |  ------------------
  |  |   42|      1|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|      1|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|      1|        return false;                                                   \
  |  |   45|      1|  }
  ------------------
  126|  20.6k|    jpg->components[i].h_samp_factor = h_samp_factor;
  127|  20.6k|    jpg->components[i].v_samp_factor = v_samp_factor;
  128|  20.6k|    jpg->components[i].quant_idx = ReadUint8(data, pos);
  129|  20.6k|    jpg->max_h_samp_factor = std::max(jpg->max_h_samp_factor, h_samp_factor);
  130|  20.6k|    jpg->max_v_samp_factor = std::max(jpg->max_v_samp_factor, v_samp_factor);
  131|  20.6k|  }
  132|       |
  133|       |  // We have checked above that none of the sampling factors are 0, so the max
  134|       |  // sampling factors can not be 0.
  135|  8.54k|  jpg->MCU_rows = DivCeil(jpg->height, jpg->max_v_samp_factor * 8);
  136|  8.54k|  jpg->MCU_cols = DivCeil(jpg->width, jpg->max_h_samp_factor * 8);
  137|       |  // Compute the block dimensions for each component.
  138|  8.54k|  if (mode == JPEG_READ_ALL) {
  ------------------
  |  Branch (138:7): [True: 4.24k, False: 4.29k]
  ------------------
  139|  14.4k|    for (size_t i = 0; i < jpg->components.size(); ++i) {
  ------------------
  |  Branch (139:24): [True: 10.2k, False: 4.22k]
  ------------------
  140|  10.2k|      JPEGComponent* c = &jpg->components[i];
  141|  10.2k|      if (jpg->max_h_samp_factor % c->h_samp_factor != 0 ||
  ------------------
  |  Branch (141:11): [True: 13, False: 10.2k]
  ------------------
  142|  10.2k|          jpg->max_v_samp_factor % c->v_samp_factor != 0) {
  ------------------
  |  Branch (142:11): [True: 8, False: 10.2k]
  ------------------
  143|     21|        fprintf(stderr, "Non-integral subsampling ratios.\n");
  144|     21|        jpg->error = JPEG_INVALID_SAMPLING_FACTORS;
  145|     21|        return false;
  146|     21|      }
  147|  10.2k|      c->width_in_blocks = jpg->MCU_cols * c->h_samp_factor;
  148|  10.2k|      c->height_in_blocks = jpg->MCU_rows * c->v_samp_factor;
  149|  10.2k|      const uint64_t num_blocks =
  150|  10.2k|          static_cast<uint64_t>(c->width_in_blocks) * c->height_in_blocks;
  151|  10.2k|      if (num_blocks > (1ull << 21)) {
  ------------------
  |  Branch (151:11): [True: 0, False: 10.2k]
  ------------------
  152|       |        // Refuse to allocate more than 1 GB of memory for the coefficients,
  153|       |        // that is 2M blocks x 64 coeffs x 2 bytes per coeff x max 4 components.
  154|       |        // TODO(user) Add this limit to a GuetzliParams struct.
  155|      0|        fprintf(stderr, "Image too large.\n");
  156|      0|        jpg->error = JPEG_IMAGE_TOO_LARGE;
  157|      0|        return false;
  158|      0|      }
  159|  10.2k|      c->num_blocks = static_cast<int>(num_blocks);
  160|  10.2k|      c->coeffs.resize(c->num_blocks * kDCTBlockSize);
  161|  10.2k|    }
  162|  4.24k|  }
  163|  8.52k|  VERIFY_MARKER_END();
  ------------------
  |  |   48|  8.52k|  if (start_pos + marker_len != *pos) {                                 \
  |  |  ------------------
  |  |  |  Branch (48:7): [True: 25, False: 8.49k]
  |  |  ------------------
  |  |   49|     25|    fprintf(stderr, "Invalid marker length: declared=%d actual=%d\n",   \
  |  |   50|     25|            static_cast<int>(marker_len),                               \
  |  |   51|     25|            static_cast<int>(*pos - start_pos));                        \
  |  |   52|     25|    jpg->error = JPEG_WRONG_MARKER_SIZE;                                \
  |  |   53|     25|    return false;                                                       \
  |  |   54|     25|  }
  ------------------
  164|  8.49k|  return true;
  165|  8.52k|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_110ReadUint16EPKhPm:
   79|  2.29M|inline int ReadUint16(const uint8_t* data, size_t* pos) {
   80|  2.29M|  int v = (data[*pos] << 8) + data[*pos + 1];
   81|  2.29M|  *pos += 2;
   82|  2.29M|  return v;
   83|  2.29M|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_19ReadUint8EPKhPm:
   75|  4.68M|inline int ReadUint8(const uint8_t* data, size_t* pos) {
   76|  4.68M|  return data[(*pos)++];
   77|  4.68M|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_17DivCeilEii:
   71|  28.1k|inline int DivCeil(int a, int b) {
   72|  28.1k|  return (a + b - 1) / b;
   73|  28.1k|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_110ProcessDHTEPKhmNS_12JpegReadModeEPNSt3__16vectorINS_17HuffmanTableEntryENS4_9allocatorIS6_EEEESA_PmPNS_8JPEGDataE:
  256|  26.0k|                JPEGData* jpg) {
  257|  26.0k|  const size_t start_pos = *pos;
  258|  26.0k|  VERIFY_LEN(2);
  ------------------
  |  |   32|  26.0k|  if (*pos + (n) > len) {                                               \
  |  |  ------------------
  |  |  |  Branch (32:7): [True: 14, False: 25.9k]
  |  |  ------------------
  |  |   33|     14|    fprintf(stderr, "Unexpected end of input: pos=%d need=%d len=%d\n", \
  |  |   34|     14|            static_cast<int>(*pos), static_cast<int>(n),                \
  |  |   35|     14|            static_cast<int>(len));                                     \
  |  |   36|     14|    jpg->error = JPEG_UNEXPECTED_EOF;                                   \
  |  |   37|     14|    return false;                                                       \
  |  |   38|     14|  }
  ------------------
  259|  25.9k|  size_t marker_len = ReadUint16(data, pos);
  260|  25.9k|  if (marker_len == 2) {
  ------------------
  |  Branch (260:7): [True: 1, False: 25.9k]
  ------------------
  261|      1|    fprintf(stderr, "DHT marker: no Huffman table found\n");
  262|      1|    jpg->error = JPEG_EMPTY_DHT;
  263|      1|    return false;
  264|      1|  }
  265|   248k|  while (*pos < start_pos + marker_len) {
  ------------------
  |  Branch (265:10): [True: 222k, False: 25.6k]
  ------------------
  266|   222k|    VERIFY_LEN(1 + kJpegHuffmanMaxBitLength);
  ------------------
  |  |   32|   222k|  if (*pos + (n) > len) {                                               \
  |  |  ------------------
  |  |  |  Branch (32:7): [True: 192, False: 222k]
  |  |  ------------------
  |  |   33|    192|    fprintf(stderr, "Unexpected end of input: pos=%d need=%d len=%d\n", \
  |  |   34|    192|            static_cast<int>(*pos), static_cast<int>(n),                \
  |  |   35|    192|            static_cast<int>(len));                                     \
  |  |   36|    192|    jpg->error = JPEG_UNEXPECTED_EOF;                                   \
  |  |   37|    192|    return false;                                                       \
  |  |   38|    192|  }
  ------------------
  267|   222k|    JPEGHuffmanCode huff;
  268|   222k|    huff.slot_id = ReadUint8(data, pos);
  269|   222k|    int huffman_index = huff.slot_id;
  270|   222k|    int is_ac_table = (huff.slot_id & 0x10) != 0;
  271|   222k|    HuffmanTableEntry* huff_lut;
  272|   222k|    if (is_ac_table) {
  ------------------
  |  Branch (272:9): [True: 21.2k, False: 201k]
  ------------------
  273|  21.2k|      huffman_index -= 0x10;
  274|  21.2k|      VERIFY_INPUT(huffman_index, 0, 3, HUFFMAN_INDEX);
  ------------------
  |  |   41|  21.2k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 0, False: 21.2k]
  |  |  |  Branch (41:20): [True: 4, False: 21.2k]
  |  |  ------------------
  |  |   42|      4|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|      4|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|      4|        return false;                                                   \
  |  |   45|      4|  }
  ------------------
  275|  21.2k|      huff_lut = &(*ac_huff_lut)[huffman_index * kJpegHuffmanLutSize];
  276|   201k|    } else {
  277|   201k|      VERIFY_INPUT(huffman_index, 0, 3, HUFFMAN_INDEX);
  ------------------
  |  |   41|   201k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 0, False: 201k]
  |  |  |  Branch (41:20): [True: 8, False: 201k]
  |  |  ------------------
  |  |   42|      8|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|      8|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|      8|        return false;                                                   \
  |  |   45|      8|  }
  ------------------
  278|   201k|      huff_lut = &(*dc_huff_lut)[huffman_index * kJpegHuffmanLutSize];
  279|   201k|    }
  280|   222k|    huff.counts[0] = 0;
  281|   222k|    int total_count = 0;
  282|   222k|    int space = 1 << kJpegHuffmanMaxBitLength;
  283|   222k|    int max_depth = 1;
  284|  3.78M|    for (int i = 1; i <= kJpegHuffmanMaxBitLength; ++i) {
  ------------------
  |  Branch (284:21): [True: 3.56M, False: 222k]
  ------------------
  285|  3.56M|      int count = ReadUint8(data, pos);
  286|  3.56M|      if (count != 0) {
  ------------------
  |  Branch (286:11): [True: 109k, False: 3.45M]
  ------------------
  287|   109k|        max_depth = i;
  288|   109k|      }
  289|  3.56M|      huff.counts[i] = count;
  290|  3.56M|      total_count += count;
  291|  3.56M|      space -= count * (1 << (kJpegHuffmanMaxBitLength - i));
  292|  3.56M|    }
  293|   222k|    if (is_ac_table) {
  ------------------
  |  Branch (293:9): [True: 21.2k, False: 201k]
  ------------------
  294|  21.2k|      VERIFY_INPUT(total_count, 0, kJpegHuffmanAlphabetSize, HUFFMAN_CODE);
  ------------------
  |  |   41|  21.2k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 0, False: 21.2k]
  |  |  |  Branch (41:20): [True: 16, False: 21.2k]
  |  |  ------------------
  |  |   42|     16|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|     16|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|     16|        return false;                                                   \
  |  |   45|     16|  }
  ------------------
  295|   201k|    } else {
  296|   201k|      VERIFY_INPUT(total_count, 0, kJpegDCAlphabetSize, HUFFMAN_CODE);
  ------------------
  |  |   41|   201k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 0, False: 201k]
  |  |  |  Branch (41:20): [True: 35, False: 201k]
  |  |  ------------------
  |  |   42|     35|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|     35|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|     35|        return false;                                                   \
  |  |   45|     35|  }
  ------------------
  297|   201k|    }
  298|   222k|    VERIFY_LEN(total_count);
  ------------------
  |  |   32|   222k|  if (*pos + (n) > len) {                                               \
  |  |  ------------------
  |  |  |  Branch (32:7): [True: 21, False: 222k]
  |  |  ------------------
  |  |   33|     21|    fprintf(stderr, "Unexpected end of input: pos=%d need=%d len=%d\n", \
  |  |   34|     21|            static_cast<int>(*pos), static_cast<int>(n),                \
  |  |   35|     21|            static_cast<int>(len));                                     \
  |  |   36|     21|    jpg->error = JPEG_UNEXPECTED_EOF;                                   \
  |  |   37|     21|    return false;                                                       \
  |  |   38|     21|  }
  ------------------
  299|   222k|    std::vector<bool> values_seen(256, false);
  300|   554k|    for (int i = 0; i < total_count; ++i) {
  ------------------
  |  Branch (300:21): [True: 332k, False: 222k]
  ------------------
  301|   332k|      uint8_t value = ReadUint8(data, pos);
  302|   332k|      if (!is_ac_table) {
  ------------------
  |  Branch (302:11): [True: 59.7k, False: 272k]
  ------------------
  303|  59.7k|        VERIFY_INPUT(value, 0, kJpegDCAlphabetSize - 1, HUFFMAN_CODE);
  ------------------
  |  |   41|  59.7k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 0, False: 59.7k]
  |  |  |  Branch (41:20): [True: 7, False: 59.7k]
  |  |  ------------------
  |  |   42|      7|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|      7|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|      7|        return false;                                                   \
  |  |   45|      7|  }
  ------------------
  304|  59.7k|      }
  305|   332k|      if (values_seen[value]) {
  ------------------
  |  Branch (305:11): [True: 12, False: 332k]
  ------------------
  306|     12|        fprintf(stderr, "Duplicate Huffman code value %d\n", value);
  307|     12|        jpg->error = JPEG_INVALID_HUFFMAN_CODE;
  308|     12|        return false;
  309|     12|      }
  310|   332k|      values_seen[value] = true;
  311|   332k|      huff.values[i] = value;
  312|   332k|    }
  313|       |    // Add an invalid symbol that will have the all 1 code.
  314|   222k|    ++huff.counts[max_depth];
  315|   222k|    huff.values[total_count] = kJpegHuffmanAlphabetSize;
  316|   222k|    space -= (1 << (kJpegHuffmanMaxBitLength - max_depth));
  317|   222k|    if (space < 0) {
  ------------------
  |  Branch (317:9): [True: 20, False: 222k]
  ------------------
  318|     20|      fprintf(stderr, "Invalid Huffman code lengths.\n");
  319|     20|      jpg->error = JPEG_INVALID_HUFFMAN_CODE;
  320|     20|      return false;
  321|   222k|    } else if (space > 0 && huff_lut[0].value != 0xffff) {
  ------------------
  |  Branch (321:16): [True: 213k, False: 8.55k]
  |  Branch (321:29): [True: 111k, False: 102k]
  ------------------
  322|       |      // Re-initialize the values to an invalid symbol so that we can recognize
  323|       |      // it when reading the bit stream using a Huffman code with space > 0.
  324|  84.8M|      for (int i = 0; i < kJpegHuffmanLutSize; ++i) {
  ------------------
  |  Branch (324:23): [True: 84.7M, False: 111k]
  ------------------
  325|  84.7M|        huff_lut[i].bits = 0;
  326|  84.7M|        huff_lut[i].value = 0xffff;
  327|  84.7M|      }
  328|   111k|    }
  329|   222k|    huff.is_last = (*pos == start_pos + marker_len);
  330|   222k|    if (mode == JPEG_READ_ALL &&
  ------------------
  |  Branch (330:9): [True: 122k, False: 100k]
  ------------------
  331|   122k|        !BuildJpegHuffmanTable(&huff.counts[0], &huff.values[0], huff_lut)) {
  ------------------
  |  Branch (331:9): [True: 0, False: 122k]
  ------------------
  332|      0|      fprintf(stderr, "Failed to build Huffman table.\n");
  333|      0|      jpg->error = JPEG_INVALID_HUFFMAN_CODE;
  334|      0|      return false;
  335|      0|    }
  336|   222k|    jpg->huffman_code.push_back(huff);
  337|   222k|  }
  338|  25.6k|  VERIFY_MARKER_END();
  ------------------
  |  |   48|  25.6k|  if (start_pos + marker_len != *pos) {                                 \
  |  |  ------------------
  |  |  |  Branch (48:7): [True: 49, False: 25.6k]
  |  |  ------------------
  |  |   49|     49|    fprintf(stderr, "Invalid marker length: declared=%d actual=%d\n",   \
  |  |   50|     49|            static_cast<int>(marker_len),                               \
  |  |   51|     49|            static_cast<int>(*pos - start_pos));                        \
  |  |   52|     49|    jpg->error = JPEG_WRONG_MARKER_SIZE;                                \
  |  |   53|     49|    return false;                                                       \
  |  |   54|     49|  }
  ------------------
  339|  25.6k|  return true;
  340|  25.6k|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_111ProcessScanEPKhmRKNSt3__16vectorINS_17HuffmanTableEntryENS3_9allocatorIS5_EEEESA_PA64_tbPmPNS_8JPEGDataE:
  761|  6.41k|                 JPEGData* jpg) {
  762|  6.41k|  if (!ProcessSOS(data, len, pos, jpg)) {
  ------------------
  |  Branch (762:7): [True: 156, False: 6.25k]
  ------------------
  763|    156|    return false;
  764|    156|  }
  765|  6.25k|  JPEGScanInfo* scan_info = &jpg->scan_info.back();
  766|  6.25k|  bool is_interleaved = (scan_info->components.size() > 1);
  767|  6.25k|  int MCUs_per_row;
  768|  6.25k|  int MCU_rows;
  769|  6.25k|  if (is_interleaved) {
  ------------------
  |  Branch (769:7): [True: 731, False: 5.52k]
  ------------------
  770|    731|    MCUs_per_row = jpg->MCU_cols;
  771|    731|    MCU_rows = jpg->MCU_rows;
  772|  5.52k|  } else {
  773|  5.52k|    const JPEGComponent& c = jpg->components[scan_info->components[0].comp_idx];
  774|  5.52k|    MCUs_per_row =
  775|  5.52k|        DivCeil(jpg->width * c.h_samp_factor, 8 * jpg->max_h_samp_factor);
  776|  5.52k|    MCU_rows =
  777|  5.52k|        DivCeil(jpg->height * c.v_samp_factor, 8 * jpg->max_v_samp_factor);
  778|  5.52k|  }
  779|  6.25k|  coeff_t last_dc_coeff[kMaxComponents] = {0};
  780|  6.25k|  BitReaderState br(data, len, *pos);
  781|  6.25k|  int restarts_to_go = jpg->restart_interval;
  782|  6.25k|  int next_restart_marker = 0;
  783|  6.25k|  int eobrun = -1;
  784|  6.25k|  int block_scan_index = 0;
  785|  6.25k|  const int Al = is_progressive ? scan_info->Al : 0;
  ------------------
  |  Branch (785:18): [True: 5.66k, False: 595]
  ------------------
  786|  6.25k|  const int Ah = is_progressive ? scan_info->Ah : 0;
  ------------------
  |  Branch (786:18): [True: 5.66k, False: 595]
  ------------------
  787|  6.25k|  const int Ss = is_progressive ? scan_info->Ss : 0;
  ------------------
  |  Branch (787:18): [True: 5.66k, False: 595]
  ------------------
  788|  6.25k|  const int Se = is_progressive ? scan_info->Se : 63;
  ------------------
  |  Branch (788:18): [True: 5.66k, False: 595]
  ------------------
  789|  6.25k|  const uint16_t scan_bitmask = Ah == 0 ? (0xffff << Al) : (1u << Al);
  ------------------
  |  Branch (789:33): [True: 4.11k, False: 2.14k]
  ------------------
  790|  6.25k|  const uint16_t refinement_bitmask = (1 << Al) - 1;
  791|  13.8k|  for (size_t i = 0; i < scan_info->components.size(); ++i) {
  ------------------
  |  Branch (791:22): [True: 7.66k, False: 6.19k]
  ------------------
  792|  7.66k|    int comp_idx = scan_info->components[i].comp_idx;
  793|   191k|    for (int k = Ss; k <= Se; ++k) {
  ------------------
  |  Branch (793:22): [True: 183k, False: 7.60k]
  ------------------
  794|   183k|      if (scan_progression[comp_idx][k] & scan_bitmask) {
  ------------------
  |  Branch (794:11): [True: 49, False: 183k]
  ------------------
  795|     49|        fprintf(stderr, "Overlapping scans: component=%d k=%d prev_mask=%d "
  796|     49|                "cur_mask=%d\n", comp_idx, k, scan_progression[i][k],
  797|     49|                scan_bitmask);
  798|     49|        jpg->error = JPEG_OVERLAPPING_SCANS;
  799|     49|        return false;
  800|     49|      }
  801|   183k|      if (scan_progression[comp_idx][k] & refinement_bitmask) {
  ------------------
  |  Branch (801:11): [True: 13, False: 183k]
  ------------------
  802|     13|        fprintf(stderr, "Invalid scan order, a more refined scan was already "
  803|     13|                "done: component=%d k=%d prev_mask=%d cur_mask=%d\n", comp_idx,
  804|     13|                k, scan_progression[i][k], scan_bitmask);
  805|     13|        jpg->error = JPEG_INVALID_SCAN_ORDER;
  806|     13|        return false;
  807|     13|      }
  808|   183k|      scan_progression[comp_idx][k] |= scan_bitmask;
  809|   183k|    }
  810|  7.66k|  }
  811|  6.19k|  if (Al > 10) {
  ------------------
  |  Branch (811:7): [True: 4, False: 6.19k]
  ------------------
  812|      4|    fprintf(stderr, "Scan parameter Al=%d is not supported in guetzli.\n", Al);
  813|      4|    jpg->error = JPEG_NON_REPRESENTABLE_AC_COEFF;
  814|      4|    return false;
  815|      4|  }
  816|  98.6k|  for (int mcu_y = 0; mcu_y < MCU_rows; ++mcu_y) {
  ------------------
  |  Branch (816:23): [True: 92.8k, False: 5.84k]
  ------------------
  817|   280k|    for (int mcu_x = 0; mcu_x < MCUs_per_row; ++mcu_x) {
  ------------------
  |  Branch (817:25): [True: 188k, False: 92.4k]
  ------------------
  818|       |      // Handle the restart intervals.
  819|   188k|      if (jpg->restart_interval > 0) {
  ------------------
  |  Branch (819:11): [True: 10.6k, False: 177k]
  ------------------
  820|  10.6k|        if (restarts_to_go == 0) {
  ------------------
  |  Branch (820:13): [True: 167, False: 10.4k]
  ------------------
  821|    167|          if (ProcessRestart(data, len,
  ------------------
  |  Branch (821:15): [True: 72, False: 95]
  ------------------
  822|    167|                             &next_restart_marker, &br, jpg)) {
  823|     72|            restarts_to_go = jpg->restart_interval;
  824|     72|            memset(last_dc_coeff, 0, sizeof(last_dc_coeff));
  825|     72|            if (eobrun > 0) {
  ------------------
  |  Branch (825:17): [True: 4, False: 68]
  ------------------
  826|      4|              fprintf(stderr, "End-of-block run too long.\n");
  827|      4|              jpg->error = JPEG_EOB_RUN_TOO_LONG;
  828|      4|              return false;
  829|      4|            }
  830|     68|            eobrun = -1;   // fresh start
  831|     95|          } else {
  832|     95|            return false;
  833|     95|          }
  834|    167|        }
  835|  10.5k|        --restarts_to_go;
  836|  10.5k|      }
  837|       |      // Decode one MCU.
  838|   420k|      for (size_t i = 0; i < scan_info->components.size(); ++i) {
  ------------------
  |  Branch (838:26): [True: 232k, False: 187k]
  ------------------
  839|   232k|        JPEGComponentScanInfo* si = &scan_info->components[i];
  840|   232k|        JPEGComponent* c = &jpg->components[si->comp_idx];
  841|   232k|        const HuffmanTableEntry* dc_lut =
  842|   232k|            &dc_huff_lut[si->dc_tbl_idx * kJpegHuffmanLutSize];
  843|   232k|        const HuffmanTableEntry* ac_lut =
  844|   232k|            &ac_huff_lut[si->ac_tbl_idx * kJpegHuffmanLutSize];
  845|   232k|        int nblocks_y = is_interleaved ? c->v_samp_factor : 1;
  ------------------
  |  Branch (845:25): [True: 71.9k, False: 161k]
  ------------------
  846|   232k|        int nblocks_x = is_interleaved ? c->h_samp_factor : 1;
  ------------------
  |  Branch (846:25): [True: 71.9k, False: 161k]
  ------------------
  847|   666k|        for (int iy = 0; iy < nblocks_y; ++iy) {
  ------------------
  |  Branch (847:26): [True: 433k, False: 232k]
  ------------------
  848|  1.12M|          for (int ix = 0; ix < nblocks_x; ++ix) {
  ------------------
  |  Branch (848:28): [True: 690k, False: 433k]
  ------------------
  849|   690k|            int block_y = mcu_y * nblocks_y + iy;
  850|   690k|            int block_x = mcu_x * nblocks_x + ix;
  851|   690k|            int block_idx = block_y * c->width_in_blocks + block_x;
  852|   690k|            coeff_t* coeffs = &c->coeffs[block_idx * kDCTBlockSize];
  853|   690k|            if (Ah == 0) {
  ------------------
  |  Branch (853:17): [True: 327k, False: 363k]
  ------------------
  854|   327k|              if (!DecodeDCTBlock(dc_lut, ac_lut, Ss, Se, Al, &eobrun, &br, jpg,
  ------------------
  |  Branch (854:19): [True: 125, False: 327k]
  ------------------
  855|   327k|                                  &last_dc_coeff[si->comp_idx], coeffs)) {
  856|    125|                return false;
  857|    125|              }
  858|   363k|            } else {
  859|   363k|              if (!RefineDCTBlock(ac_lut, Ss, Se, Al,
  ------------------
  |  Branch (859:19): [True: 118, False: 363k]
  ------------------
  860|   363k|                                  &eobrun, &br, jpg, coeffs)) {
  861|    118|                return false;
  862|    118|              }
  863|   363k|            }
  864|   690k|            ++block_scan_index;
  865|   690k|          }
  866|   433k|        }
  867|   232k|      }
  868|   188k|    }
  869|  92.8k|  }
  870|  5.84k|  if (eobrun > 0) {
  ------------------
  |  Branch (870:7): [True: 84, False: 5.76k]
  ------------------
  871|     84|    fprintf(stderr, "End-of-block run too long.\n");
  872|     84|    jpg->error = JPEG_EOB_RUN_TOO_LONG;
  873|     84|    return false;
  874|     84|  }
  875|  5.76k|  if (!br.FinishStream(pos)) {
  ------------------
  |  Branch (875:7): [True: 284, False: 5.48k]
  ------------------
  876|    284|    jpg->error = JPEG_INVALID_SCAN;
  877|    284|    return false;
  878|    284|  }
  879|  5.48k|  if (*pos > len) {
  ------------------
  |  Branch (879:7): [True: 0, False: 5.48k]
  ------------------
  880|      0|    fprintf(stderr, "Unexpected end of file during scan. pos=%d len=%d\n",
  881|      0|            static_cast<int>(*pos), static_cast<int>(len));
  882|      0|    jpg->error = JPEG_UNEXPECTED_EOF;
  883|      0|    return false;
  884|      0|  }
  885|  5.48k|  return true;
  886|  5.48k|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_110ProcessSOSEPKhmPmPNS_8JPEGDataE:
  170|  6.41k|                JPEGData* jpg) {
  171|  6.41k|  const size_t start_pos = *pos;
  172|  6.41k|  VERIFY_LEN(3);
  ------------------
  |  |   32|  6.41k|  if (*pos + (n) > len) {                                               \
  |  |  ------------------
  |  |  |  Branch (32:7): [True: 14, False: 6.39k]
  |  |  ------------------
  |  |   33|     14|    fprintf(stderr, "Unexpected end of input: pos=%d need=%d len=%d\n", \
  |  |   34|     14|            static_cast<int>(*pos), static_cast<int>(n),                \
  |  |   35|     14|            static_cast<int>(len));                                     \
  |  |   36|     14|    jpg->error = JPEG_UNEXPECTED_EOF;                                   \
  |  |   37|     14|    return false;                                                       \
  |  |   38|     14|  }
  ------------------
  173|  6.39k|  size_t marker_len = ReadUint16(data, pos);
  174|  6.39k|  int comps_in_scan = ReadUint8(data, pos);
  175|  6.39k|  VERIFY_INPUT(comps_in_scan, 1, static_cast<int>(jpg->components.size()),
  ------------------
  |  |   41|  6.39k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 4, False: 6.39k]
  |  |  |  Branch (41:20): [True: 14, False: 6.38k]
  |  |  ------------------
  |  |   42|     18|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|     18|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|     18|        return false;                                                   \
  |  |   45|     18|  }
  ------------------
  176|  6.39k|               COMPS_IN_SCAN);
  177|       |
  178|  6.38k|  JPEGScanInfo scan_info;
  179|  6.38k|  scan_info.components.resize(comps_in_scan);
  180|  6.38k|  VERIFY_LEN(2 * comps_in_scan);
  ------------------
  |  |   32|  6.38k|  if (*pos + (n) > len) {                                               \
  |  |  ------------------
  |  |  |  Branch (32:7): [True: 14, False: 6.36k]
  |  |  ------------------
  |  |   33|     14|    fprintf(stderr, "Unexpected end of input: pos=%d need=%d len=%d\n", \
  |  |   34|     14|            static_cast<int>(*pos), static_cast<int>(n),                \
  |  |   35|     14|            static_cast<int>(len));                                     \
  |  |   36|     14|    jpg->error = JPEG_UNEXPECTED_EOF;                                   \
  |  |   37|     14|    return false;                                                       \
  |  |   38|     14|  }
  ------------------
  181|  6.36k|  std::vector<bool> ids_seen(256, false);
  182|  14.1k|  for (int i = 0; i < comps_in_scan; ++i) {
  ------------------
  |  Branch (182:19): [True: 7.84k, False: 6.34k]
  ------------------
  183|  7.84k|    int id = ReadUint8(data, pos);
  184|  7.84k|    if (ids_seen[id]) {   // (cf. section B.2.3, regarding CSj)
  ------------------
  |  Branch (184:9): [True: 2, False: 7.84k]
  ------------------
  185|      2|      fprintf(stderr, "Duplicate ID %d in SOS.\n", id);
  186|      2|      jpg->error = JPEG_DUPLICATE_COMPONENT_ID;
  187|      2|      return false;
  188|      2|    }
  189|  7.84k|    ids_seen[id] = true;
  190|  7.84k|    bool found_index = false;
  191|  29.1k|    for (size_t j = 0; j < jpg->components.size(); ++j) {
  ------------------
  |  Branch (191:24): [True: 21.2k, False: 7.84k]
  ------------------
  192|  21.2k|      if (jpg->components[j].id == id) {
  ------------------
  |  Branch (192:11): [True: 7.83k, False: 13.4k]
  ------------------
  193|  7.83k|        scan_info.components[i].comp_idx = j;
  194|  7.83k|        found_index = true;
  195|  7.83k|      }
  196|  21.2k|    }
  197|  7.84k|    if (!found_index) {
  ------------------
  |  Branch (197:9): [True: 12, False: 7.83k]
  ------------------
  198|     12|      fprintf(stderr, "SOS marker: Could not find component with id %d\n", id);
  199|     12|      jpg->error = JPEG_COMPONENT_NOT_FOUND;
  200|     12|      return false;
  201|     12|    }
  202|  7.83k|    int c = ReadUint8(data, pos);
  203|  7.83k|    int dc_tbl_idx = c >> 4;
  204|  7.83k|    int ac_tbl_idx = c & 0xf;
  205|  7.83k|    VERIFY_INPUT(dc_tbl_idx, 0, 3, HUFFMAN_INDEX);
  ------------------
  |  |   41|  7.83k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 0, False: 7.83k]
  |  |  |  Branch (41:20): [True: 5, False: 7.82k]
  |  |  ------------------
  |  |   42|      5|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|      5|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|      5|        return false;                                                   \
  |  |   45|      5|  }
  ------------------
  206|  7.82k|    VERIFY_INPUT(ac_tbl_idx, 0, 3, HUFFMAN_INDEX);
  ------------------
  |  |   41|  7.82k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 0, False: 7.82k]
  |  |  |  Branch (41:20): [True: 5, False: 7.82k]
  |  |  ------------------
  |  |   42|      5|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|      5|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|      5|        return false;                                                   \
  |  |   45|      5|  }
  ------------------
  207|  7.82k|    scan_info.components[i].dc_tbl_idx = dc_tbl_idx;
  208|  7.82k|    scan_info.components[i].ac_tbl_idx = ac_tbl_idx;
  209|  7.82k|  }
  210|  6.34k|  VERIFY_LEN(3);
  ------------------
  |  |   32|  6.34k|  if (*pos + (n) > len) {                                               \
  |  |  ------------------
  |  |  |  Branch (32:7): [True: 15, False: 6.32k]
  |  |  ------------------
  |  |   33|     15|    fprintf(stderr, "Unexpected end of input: pos=%d need=%d len=%d\n", \
  |  |   34|     15|            static_cast<int>(*pos), static_cast<int>(n),                \
  |  |   35|     15|            static_cast<int>(len));                                     \
  |  |   36|     15|    jpg->error = JPEG_UNEXPECTED_EOF;                                   \
  |  |   37|     15|    return false;                                                       \
  |  |   38|     15|  }
  ------------------
  211|  6.32k|  scan_info.Ss = ReadUint8(data, pos);
  212|  6.32k|  scan_info.Se = ReadUint8(data, pos);
  213|  6.32k|  VERIFY_INPUT(scan_info.Ss, 0, 63, START_OF_SCAN);
  ------------------
  |  |   41|  6.32k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 0, False: 6.32k]
  |  |  |  Branch (41:20): [True: 6, False: 6.32k]
  |  |  ------------------
  |  |   42|      6|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|      6|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|      6|        return false;                                                   \
  |  |   45|      6|  }
  ------------------
  214|  6.32k|  VERIFY_INPUT(scan_info.Se, scan_info.Ss, 63, END_OF_SCAN);
  ------------------
  |  |   41|  6.32k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 4, False: 6.31k]
  |  |  |  Branch (41:20): [True: 5, False: 6.31k]
  |  |  ------------------
  |  |   42|      9|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|      9|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|      9|        return false;                                                   \
  |  |   45|      9|  }
  ------------------
  215|  6.31k|  int c = ReadUint8(data, pos);
  216|  6.31k|  scan_info.Ah = c >> 4;
  217|  6.31k|  scan_info.Al = c & 0xf;
  218|       |  // Check that all the Huffman tables needed for this scan are defined.
  219|  14.0k|  for (int i = 0; i < comps_in_scan; ++i) {
  ------------------
  |  Branch (219:19): [True: 7.76k, False: 6.29k]
  ------------------
  220|  7.76k|    bool found_dc_table = false;
  221|  7.76k|    bool found_ac_table = false;
  222|   139k|    for (size_t j = 0; j < jpg->huffman_code.size(); ++j) {
  ------------------
  |  Branch (222:24): [True: 132k, False: 7.76k]
  ------------------
  223|   132k|      int slot_id = jpg->huffman_code[j].slot_id;
  224|   132k|      if (slot_id == scan_info.components[i].dc_tbl_idx) {
  ------------------
  |  Branch (224:11): [True: 35.1k, False: 96.8k]
  ------------------
  225|  35.1k|        found_dc_table = true;
  226|  96.8k|      } else if (slot_id == scan_info.components[i].ac_tbl_idx + 16) {
  ------------------
  |  Branch (226:18): [True: 54.8k, False: 42.0k]
  ------------------
  227|  54.8k|        found_ac_table = true;
  228|  54.8k|      }
  229|   132k|    }
  230|  7.76k|    if (scan_info.Ss == 0 && !found_dc_table) {
  ------------------
  |  Branch (230:9): [True: 2.63k, False: 5.12k]
  |  Branch (230:30): [True: 11, False: 2.62k]
  ------------------
  231|     11|      fprintf(stderr, "SOS marker: Could not find DC Huffman table with index "
  232|     11|              "%d\n", scan_info.components[i].dc_tbl_idx);
  233|     11|      jpg->error = JPEG_HUFFMAN_TABLE_NOT_FOUND;
  234|     11|      return false;
  235|     11|    }
  236|  7.75k|    if (scan_info.Se > 0 && !found_ac_table) {
  ------------------
  |  Branch (236:9): [True: 6.41k, False: 1.33k]
  |  Branch (236:29): [True: 10, False: 6.40k]
  ------------------
  237|     10|      fprintf(stderr, "SOS marker: Could not find AC Huffman table with index "
  238|     10|              "%d\n", scan_info.components[i].ac_tbl_idx);
  239|     10|      jpg->error = JPEG_HUFFMAN_TABLE_NOT_FOUND;
  240|     10|      return false;
  241|     10|    }
  242|  7.75k|  }
  243|  6.29k|  jpg->scan_info.push_back(scan_info);
  244|  6.29k|  VERIFY_MARKER_END();
  ------------------
  |  |   48|  6.29k|  if (start_pos + marker_len != *pos) {                                 \
  |  |  ------------------
  |  |  |  Branch (48:7): [True: 35, False: 6.25k]
  |  |  ------------------
  |  |   49|     35|    fprintf(stderr, "Invalid marker length: declared=%d actual=%d\n",   \
  |  |   50|     35|            static_cast<int>(marker_len),                               \
  |  |   51|     35|            static_cast<int>(*pos - start_pos));                        \
  |  |   52|     35|    jpg->error = JPEG_WRONG_MARKER_SIZE;                                \
  |  |   53|     35|    return false;                                                       \
  |  |   54|     35|  }
  ------------------
  245|  6.25k|  return true;
  246|  6.29k|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_114BitReaderStateC2EPKhmm:
  427|  6.25k|      : data_(data), len_(len) {
  428|  6.25k|    Reset(pos);
  429|  6.25k|  }
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_114BitReaderState5ResetEm:
  431|  6.32k|  void Reset(size_t pos) {
  432|  6.32k|    pos_ = pos;
  433|  6.32k|    val_ = 0;
  434|  6.32k|    bits_left_ = 0;
  435|  6.32k|    next_marker_pos_ = len_ - 2;
  436|  6.32k|    FillBitWindow();
  437|  6.32k|  }
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_114BitReaderState13FillBitWindowEv:
  459|  34.3M|  void FillBitWindow() {
  460|  34.3M|    if (bits_left_ <= 16) {
  ------------------
  |  Branch (460:9): [True: 4.37M, False: 29.9M]
  ------------------
  461|  31.3M|      while (bits_left_ <= 56) {
  ------------------
  |  Branch (461:14): [True: 26.9M, False: 4.37M]
  ------------------
  462|  26.9M|        val_ <<= 8;
  463|  26.9M|        val_ |= (uint64_t)GetNextByte();
  464|  26.9M|        bits_left_ += 8;
  465|  26.9M|      }
  466|  4.37M|    }
  467|  34.3M|  }
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_114BitReaderState11GetNextByteEv:
  440|  26.9M|  uint8_t GetNextByte() {
  441|  26.9M|    if (pos_ >= next_marker_pos_) {
  ------------------
  |  Branch (441:9): [True: 26.1M, False: 823k]
  ------------------
  442|  26.1M|      ++pos_;
  443|  26.1M|      return 0;
  444|  26.1M|    }
  445|   823k|    uint8_t c = data_[pos_++];
  446|   823k|    if (c == 0xff) {
  ------------------
  |  Branch (446:9): [True: 5.62k, False: 817k]
  ------------------
  447|  5.62k|      uint8_t escape = data_[pos_];
  448|  5.62k|      if (escape == 0) {
  ------------------
  |  Branch (448:11): [True: 2.91k, False: 2.71k]
  ------------------
  449|  2.91k|        ++pos_;
  450|  2.91k|      } else {
  451|       |        // 0xff was followed by a non-zero byte, which means that we found the
  452|       |        // start of the next marker segment.
  453|  2.71k|        next_marker_pos_ = pos_ - 1;
  454|  2.71k|      }
  455|  5.62k|    }
  456|   823k|    return c;
  457|  26.9M|  }
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_114ProcessRestartEPKhmPiPNS0_14BitReaderStateEPNS_8JPEGDataE:
  734|    167|                    JPEGData* jpg) {
  735|    167|  size_t pos = 0;
  736|    167|  if (!br->FinishStream(&pos)) {
  ------------------
  |  Branch (736:7): [True: 33, False: 134]
  ------------------
  737|     33|    jpg->error = JPEG_INVALID_SCAN;
  738|     33|    return false;
  739|     33|  }
  740|    134|  int expected_marker = 0xd0 + *next_restart_marker;
  741|    134|  EXPECT_MARKER();
  ------------------
  |  |   57|    134|  if (pos + 2 > len || data[pos] != 0xff) {                             \
  |  |  ------------------
  |  |  |  Branch (57:7): [True: 0, False: 134]
  |  |  |  Branch (57:24): [True: 41, False: 93]
  |  |  ------------------
  |  |   58|     41|    fprintf(stderr, "Marker byte (0xff) expected, found: %d "           \
  |  |   59|     41|            "pos=%d len=%d\n",                                          \
  |  |   60|     41|            (pos < len ? data[pos] : 0), static_cast<int>(pos),         \
  |  |  ------------------
  |  |  |  Branch (60:14): [True: 41, False: 0]
  |  |  ------------------
  |  |   61|     41|            static_cast<int>(len));                                     \
  |  |   62|     41|    jpg->error = JPEG_MARKER_BYTE_NOT_FOUND;                            \
  |  |   63|     41|    return false;                                                       \
  |  |   64|     41|  }
  ------------------
  742|     93|  int marker = data[pos + 1];
  743|     93|  if (marker != expected_marker) {
  ------------------
  |  Branch (743:7): [True: 21, False: 72]
  ------------------
  744|     21|    fprintf(stderr, "Did not find expected restart marker %d actual=%d\n",
  745|     21|            expected_marker, marker);
  746|     21|    jpg->error = JPEG_WRONG_RESTART_MARKER;
  747|     21|    return false;
  748|     21|  }
  749|     72|  br->Reset(pos + 2);
  750|     72|  *next_restart_marker += 1;
  751|     72|  *next_restart_marker &= 0x7;
  752|     72|  return true;
  753|     93|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_114DecodeDCTBlockEPKNS_17HuffmanTableEntryES3_iiiPiPNS0_14BitReaderStateEPNS_8JPEGDataEPsS9_:
  538|   327k|                    coeff_t* coeffs) {
  539|   327k|  int s;
  540|   327k|  int r;
  541|   327k|  bool eobrun_allowed = Ss > 0;
  542|   327k|  if (Ss == 0) {
  ------------------
  |  Branch (542:7): [True: 82.3k, False: 245k]
  ------------------
  543|  82.3k|    s = ReadSymbol(dc_huff, br);
  544|  82.3k|    if (s >= kJpegDCAlphabetSize) {
  ------------------
  |  Branch (544:9): [True: 49, False: 82.2k]
  ------------------
  545|     49|      fprintf(stderr, "Invalid Huffman symbol %d for DC coefficient.\n", s);
  546|     49|      jpg->error = JPEG_INVALID_SYMBOL;
  547|     49|      return false;
  548|     49|    }
  549|  82.2k|    if (s > 0) {
  ------------------
  |  Branch (549:9): [True: 35.8k, False: 46.4k]
  ------------------
  550|  35.8k|      r = br->ReadBits(s);
  551|  35.8k|      s = HuffExtend(r, s);
  552|  35.8k|    }
  553|  82.2k|    s += *last_dc_coeff;
  554|  82.2k|    const int dc_coeff = SignedLeftshift(s, Al);
  555|  82.2k|    coeffs[0] = dc_coeff;
  556|  82.2k|    if (dc_coeff != coeffs[0]) {
  ------------------
  |  Branch (556:9): [True: 26, False: 82.2k]
  ------------------
  557|     26|      fprintf(stderr, "Invalid DC coefficient %d\n", dc_coeff);
  558|     26|      jpg->error = JPEG_NON_REPRESENTABLE_DC_COEFF;
  559|     26|      return false;
  560|     26|    }
  561|  82.2k|    *last_dc_coeff = s;
  562|  82.2k|    ++Ss;
  563|  82.2k|  }
  564|   327k|  if (Ss > Se) {
  ------------------
  |  Branch (564:7): [True: 13.9k, False: 313k]
  ------------------
  565|  13.9k|    return true;
  566|  13.9k|  }
  567|   313k|  if (*eobrun > 0) {
  ------------------
  |  Branch (567:7): [True: 40.5k, False: 273k]
  ------------------
  568|  40.5k|    --(*eobrun);
  569|  40.5k|    return true;
  570|  40.5k|  }
  571|  9.71M|  for (int k = Ss; k <= Se; k++) {
  ------------------
  |  Branch (571:20): [True: 9.51M, False: 201k]
  ------------------
  572|  9.51M|    s = ReadSymbol(ac_huff, br);
  573|  9.51M|    if (s >= kJpegHuffmanAlphabetSize) {
  ------------------
  |  Branch (573:9): [True: 34, False: 9.51M]
  ------------------
  574|     34|      fprintf(stderr, "Invalid Huffman symbol %d for AC coefficient %d\n",
  575|     34|              s, k);
  576|     34|      jpg->error = JPEG_INVALID_SYMBOL;
  577|     34|      return false;
  578|     34|    }
  579|  9.51M|    r = s >> 4;
  580|  9.51M|    s &= 15;
  581|  9.51M|    if (s > 0) {
  ------------------
  |  Branch (581:9): [True: 9.44M, False: 77.3k]
  ------------------
  582|  9.44M|      k += r;
  583|  9.44M|      if (k > Se) {
  ------------------
  |  Branch (583:11): [True: 13, False: 9.44M]
  ------------------
  584|     13|        fprintf(stderr, "Out-of-band coefficient %d band was %d-%d\n",
  585|     13|                k, Ss, Se);
  586|     13|        jpg->error = JPEG_OUT_OF_BAND_COEFF;
  587|     13|        return false;
  588|     13|      }
  589|  9.44M|      if (s + Al >= kJpegDCAlphabetSize) {
  ------------------
  |  Branch (589:11): [True: 2, False: 9.44M]
  ------------------
  590|      2|        fprintf(stderr, "Out of range AC coefficient value: s=%d Al=%d k=%d\n",
  591|      2|                s, Al, k);
  592|      2|        jpg->error = JPEG_NON_REPRESENTABLE_AC_COEFF;
  593|      2|        return false;
  594|      2|      }
  595|  9.44M|      r = br->ReadBits(s);
  596|  9.44M|      s = HuffExtend(r, s);
  597|  9.44M|      coeffs[kJPEGNaturalOrder[k]] = SignedLeftshift(s, Al);
  598|  9.44M|    } else if (r == 15) {
  ------------------
  |  Branch (598:16): [True: 6.08k, False: 71.2k]
  ------------------
  599|  6.08k|      k += 15;
  600|  71.2k|    } else {
  601|  71.2k|      *eobrun = 1 << r;
  602|  71.2k|      if (r > 0) {
  ------------------
  |  Branch (602:11): [True: 17.9k, False: 53.3k]
  ------------------
  603|  17.9k|        if (!eobrun_allowed) {
  ------------------
  |  Branch (603:13): [True: 1, False: 17.9k]
  ------------------
  604|      1|          fprintf(stderr, "End-of-block run crossing DC coeff.\n");
  605|      1|          jpg->error = JPEG_EOB_RUN_TOO_LONG;
  606|      1|          return false;
  607|      1|        }
  608|  17.9k|        *eobrun += br->ReadBits(r);
  609|  17.9k|      }
  610|  71.2k|      break;
  611|  71.2k|    }
  612|  9.51M|  }
  613|   273k|  --(*eobrun);
  614|   273k|  return true;
  615|   273k|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_110ReadSymbolEPKNS_17HuffmanTableEntryEPNS0_14BitReaderStateE:
  508|  17.1M|int ReadSymbol(const HuffmanTableEntry* table, BitReaderState* br) {
  509|  17.1M|  int nbits;
  510|  17.1M|  br->FillBitWindow();
  511|  17.1M|  int val = (br->val_ >> (br->bits_left_ - 8)) & 0xff;
  512|  17.1M|  table += val;
  513|  17.1M|  nbits = table->bits - 8;
  514|  17.1M|  if (nbits > 0) {
  ------------------
  |  Branch (514:7): [True: 11.6M, False: 5.47M]
  ------------------
  515|  11.6M|    br->bits_left_ -= 8;
  516|  11.6M|    table += table->value;
  517|  11.6M|    val = (br->val_ >> (br->bits_left_ - nbits)) & ((1 << nbits) - 1);
  518|  11.6M|    table += val;
  519|  11.6M|  }
  520|  17.1M|  br->bits_left_ -= table->bits;
  521|  17.1M|  return table->value;
  522|  17.1M|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_114BitReaderState8ReadBitsEi:
  469|  17.1M|  int ReadBits(int nbits) {
  470|  17.1M|    FillBitWindow();
  471|  17.1M|    uint64_t val = (val_ >> (bits_left_ - nbits)) & ((1ULL << nbits) - 1);
  472|  17.1M|    bits_left_ -= nbits;
  473|  17.1M|    return val;
  474|  17.1M|  }
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_110HuffExtendEii:
  526|  9.47M|int HuffExtend(int x, int s) {
  527|  9.47M|  return (x < (1 << (s - 1)) ? x - (1 << s) + 1 : x);
  ------------------
  |  Branch (527:11): [True: 9.21M, False: 261k]
  ------------------
  528|  9.47M|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_115SignedLeftshiftEii:
   66|  9.52M|inline int SignedLeftshift(int v, int s) {
   67|  9.52M|  return (v >= 0) ? (v << s) : -((-v) << s);
  ------------------
  |  Branch (67:10): [True: 283k, False: 9.23M]
  ------------------
   68|  9.52M|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_114RefineDCTBlockEPKNS_17HuffmanTableEntryEiiiPiPNS0_14BitReaderStateEPNS_8JPEGDataEPs:
  622|   363k|                    coeff_t* coeffs) {
  623|   363k|  bool eobrun_allowed = Ss > 0;
  624|   363k|  if (Ss == 0) {
  ------------------
  |  Branch (624:7): [True: 72.8k, False: 290k]
  ------------------
  625|  72.8k|    int s = br->ReadBits(1);
  626|  72.8k|    coeff_t dc_coeff = coeffs[0];
  627|  72.8k|    dc_coeff |= s << Al;
  628|  72.8k|    coeffs[0] = dc_coeff;
  629|  72.8k|    ++Ss;
  630|  72.8k|  }
  631|   363k|  if (Ss > Se) {
  ------------------
  |  Branch (631:7): [True: 60.9k, False: 302k]
  ------------------
  632|  60.9k|    return true;
  633|  60.9k|  }
  634|   302k|  int p1 = 1 << Al;
  635|   302k|  int m1 = -(1 << Al);
  636|   302k|  int k = Ss;
  637|   302k|  int r;
  638|   302k|  int s;
  639|   302k|  bool in_zero_run = false;
  640|   302k|  if (*eobrun <= 0) {
  ------------------
  |  Branch (640:7): [True: 246k, False: 55.6k]
  ------------------
  641|  7.76M|    for (; k <= Se; k++) {
  ------------------
  |  Branch (641:12): [True: 7.55M, False: 202k]
  ------------------
  642|  7.55M|      s = ReadSymbol(ac_huff, br);
  643|  7.55M|      if (s >= kJpegHuffmanAlphabetSize) {
  ------------------
  |  Branch (643:11): [True: 77, False: 7.55M]
  ------------------
  644|     77|        fprintf(stderr, "Invalid Huffman symbol %d for AC coefficient %d\n",
  645|     77|                s, k);
  646|     77|        jpg->error = JPEG_INVALID_SYMBOL;
  647|     77|        return false;
  648|     77|      }
  649|  7.55M|      r = s >> 4;
  650|  7.55M|      s &= 15;
  651|  7.55M|      if (s) {
  ------------------
  |  Branch (651:11): [True: 7.51M, False: 44.5k]
  ------------------
  652|  7.51M|        if (s != 1) {
  ------------------
  |  Branch (652:13): [True: 10, False: 7.51M]
  ------------------
  653|     10|          fprintf(stderr, "Invalid Huffman symbol %d for AC coefficient %d\n",
  654|     10|                  s, k);
  655|     10|          jpg->error = JPEG_INVALID_SYMBOL;
  656|     10|          return false;
  657|     10|        }
  658|  7.51M|        s = br->ReadBits(1) ? p1 : m1;
  ------------------
  |  Branch (658:13): [True: 28.4k, False: 7.48M]
  ------------------
  659|  7.51M|        in_zero_run = false;
  660|  7.51M|      } else {
  661|  44.5k|        if (r != 15) {
  ------------------
  |  Branch (661:13): [True: 44.2k, False: 304]
  ------------------
  662|  44.2k|          *eobrun = 1 << r;
  663|  44.2k|          if (r > 0) {
  ------------------
  |  Branch (663:15): [True: 24.0k, False: 20.2k]
  ------------------
  664|  24.0k|            if (!eobrun_allowed) {
  ------------------
  |  Branch (664:17): [True: 2, False: 24.0k]
  ------------------
  665|      2|              fprintf(stderr, "End-of-block run crossing DC coeff.\n");
  666|      2|              jpg->error = JPEG_EOB_RUN_TOO_LONG;
  667|      2|              return false;
  668|      2|            }
  669|  24.0k|            *eobrun += br->ReadBits(r);
  670|  24.0k|          }
  671|  44.2k|          break;
  672|  44.2k|        }
  673|    304|        in_zero_run = true;
  674|    304|      }
  675|  8.01M|      do {
  676|  8.01M|        coeff_t thiscoef = coeffs[kJPEGNaturalOrder[k]];
  677|  8.01M|        if (thiscoef != 0) {
  ------------------
  |  Branch (677:13): [True: 19.2k, False: 7.99M]
  ------------------
  678|  19.2k|          if (br->ReadBits(1)) {
  ------------------
  |  Branch (678:15): [True: 1.68k, False: 17.5k]
  ------------------
  679|  1.68k|            if ((thiscoef & p1) == 0) {
  ------------------
  |  Branch (679:17): [True: 1.68k, False: 0]
  ------------------
  680|  1.68k|              if (thiscoef >= 0) {
  ------------------
  |  Branch (680:19): [True: 499, False: 1.18k]
  ------------------
  681|    499|                thiscoef += p1;
  682|  1.18k|              } else {
  683|  1.18k|                thiscoef += m1;
  684|  1.18k|              }
  685|  1.68k|            }
  686|  1.68k|          }
  687|  19.2k|          coeffs[kJPEGNaturalOrder[k]] = thiscoef;
  688|  7.99M|        } else {
  689|  7.99M|          if (--r < 0) {
  ------------------
  |  Branch (689:15): [True: 7.51M, False: 479k]
  ------------------
  690|  7.51M|            break;
  691|  7.51M|          }
  692|  7.99M|        }
  693|   498k|        k++;
  694|   498k|      } while (k <= Se);
  ------------------
  |  Branch (694:16): [True: 498k, False: 25]
  ------------------
  695|  7.51M|      if (s) {
  ------------------
  |  Branch (695:11): [True: 7.51M, False: 304]
  ------------------
  696|  7.51M|        if (k > Se) {
  ------------------
  |  Branch (696:13): [True: 15, False: 7.51M]
  ------------------
  697|     15|          fprintf(stderr, "Out-of-band coefficient %d band was %d-%d\n",
  698|     15|                  k, Ss, Se);
  699|     15|          jpg->error = JPEG_OUT_OF_BAND_COEFF;
  700|     15|          return false;
  701|     15|        }
  702|  7.51M|        coeffs[kJPEGNaturalOrder[k]] = s;
  703|  7.51M|      }
  704|  7.51M|    }
  705|   246k|  }
  706|   302k|  if (in_zero_run) {
  ------------------
  |  Branch (706:7): [True: 14, False: 302k]
  ------------------
  707|     14|    fprintf(stderr, "Extra zero run before end-of-block.\n");
  708|     14|    jpg->error = JPEG_EXTRA_ZERO_RUN;
  709|     14|    return false;
  710|     14|  }
  711|   302k|  if (*eobrun > 0) {
  ------------------
  |  Branch (711:7): [True: 99.9k, False: 202k]
  ------------------
  712|  4.00M|    for (; k <= Se; k++) {
  ------------------
  |  Branch (712:12): [True: 3.90M, False: 99.9k]
  ------------------
  713|  3.90M|      coeff_t thiscoef = coeffs[kJPEGNaturalOrder[k]];
  714|  3.90M|      if (thiscoef != 0) {
  ------------------
  |  Branch (714:11): [True: 45.1k, False: 3.86M]
  ------------------
  715|  45.1k|        if (br->ReadBits(1)) {
  ------------------
  |  Branch (715:13): [True: 7.77k, False: 37.3k]
  ------------------
  716|  7.77k|          if ((thiscoef & p1) == 0) {
  ------------------
  |  Branch (716:15): [True: 7.77k, False: 0]
  ------------------
  717|  7.77k|            if (thiscoef >= 0) {
  ------------------
  |  Branch (717:17): [True: 380, False: 7.39k]
  ------------------
  718|    380|              thiscoef += p1;
  719|  7.39k|            } else {
  720|  7.39k|              thiscoef += m1;
  721|  7.39k|            }
  722|  7.77k|          }
  723|  7.77k|        }
  724|  45.1k|        coeffs[kJPEGNaturalOrder[k]] = thiscoef;
  725|  45.1k|      }
  726|  3.90M|    }
  727|  99.9k|  }
  728|   302k|  --(*eobrun);
  729|   302k|  return true;
  730|   302k|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_114BitReaderState12FinishStreamEPm:
  478|  5.93k|  bool FinishStream(size_t* pos) {
  479|       |    // Give back some bytes that we did not use.
  480|  5.93k|    int unused_bytes_left = bits_left_ >> 3;
  481|  39.0k|    while (unused_bytes_left-- > 0) {
  ------------------
  |  Branch (481:12): [True: 33.1k, False: 5.93k]
  ------------------
  482|  33.1k|      --pos_;
  483|       |      // If we give back a 0 byte, we need to check if it was a 0xff/0x00 escape
  484|       |      // sequence, and if yes, we need to give back one more byte.
  485|  33.1k|      if (pos_ < next_marker_pos_ &&
  ------------------
  |  Branch (485:11): [True: 10.4k, False: 22.6k]
  ------------------
  486|  10.4k|          data_[pos_] == 0 && data_[pos_ - 1] == 0xff) {
  ------------------
  |  Branch (486:11): [True: 4.64k, False: 5.82k]
  |  Branch (486:31): [True: 180, False: 4.46k]
  ------------------
  487|    180|        --pos_;
  488|    180|      }
  489|  33.1k|    }
  490|  5.93k|    if (pos_ > next_marker_pos_) {
  ------------------
  |  Branch (490:9): [True: 317, False: 5.61k]
  ------------------
  491|       |      // Data ran out before the scan was complete.
  492|    317|      fprintf(stderr, "Unexpected end of scan.\n");
  493|    317|      return false;
  494|    317|    }
  495|  5.61k|    *pos = pos_;
  496|  5.61k|    return true;
  497|  5.93k|  }
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_110ProcessDQTEPKhmPmPNS_8JPEGDataE:
  345|  7.03k|                JPEGData* jpg) {
  346|  7.03k|  const size_t start_pos = *pos;
  347|  7.03k|  VERIFY_LEN(2);
  ------------------
  |  |   32|  7.03k|  if (*pos + (n) > len) {                                               \
  |  |  ------------------
  |  |  |  Branch (32:7): [True: 3, False: 7.02k]
  |  |  ------------------
  |  |   33|      3|    fprintf(stderr, "Unexpected end of input: pos=%d need=%d len=%d\n", \
  |  |   34|      3|            static_cast<int>(*pos), static_cast<int>(n),                \
  |  |   35|      3|            static_cast<int>(len));                                     \
  |  |   36|      3|    jpg->error = JPEG_UNEXPECTED_EOF;                                   \
  |  |   37|      3|    return false;                                                       \
  |  |   38|      3|  }
  ------------------
  348|  7.02k|  size_t marker_len = ReadUint16(data, pos);
  349|  7.02k|  if (marker_len == 2) {
  ------------------
  |  Branch (349:7): [True: 1, False: 7.02k]
  ------------------
  350|      1|    fprintf(stderr, "DQT marker: no quantization table found\n");
  351|      1|    jpg->error = JPEG_EMPTY_DQT;
  352|      1|    return false;
  353|      1|  }
  354|  14.0k|  while (*pos < start_pos + marker_len && jpg->quant.size() < kMaxQuantTables) {
  ------------------
  |  Branch (354:10): [True: 7.10k, False: 6.93k]
  |  Branch (354:43): [True: 7.07k, False: 24]
  ------------------
  355|  7.07k|    VERIFY_LEN(1);
  ------------------
  |  |   32|  7.07k|  if (*pos + (n) > len) {                                               \
  |  |  ------------------
  |  |  |  Branch (32:7): [True: 17, False: 7.05k]
  |  |  ------------------
  |  |   33|     17|    fprintf(stderr, "Unexpected end of input: pos=%d need=%d len=%d\n", \
  |  |   34|     17|            static_cast<int>(*pos), static_cast<int>(n),                \
  |  |   35|     17|            static_cast<int>(len));                                     \
  |  |   36|     17|    jpg->error = JPEG_UNEXPECTED_EOF;                                   \
  |  |   37|     17|    return false;                                                       \
  |  |   38|     17|  }
  ------------------
  356|  7.05k|    int quant_table_index = ReadUint8(data, pos);
  357|  7.05k|    int quant_table_precision = quant_table_index >> 4;
  358|  7.05k|    quant_table_index &= 0xf;
  359|  7.05k|    VERIFY_INPUT(quant_table_index, 0, 3, QUANT_TBL_INDEX);
  ------------------
  |  |   41|  7.05k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 0, False: 7.05k]
  |  |  |  Branch (41:20): [True: 4, False: 7.05k]
  |  |  ------------------
  |  |   42|      4|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|      4|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|      4|        return false;                                                   \
  |  |   45|      4|  }
  ------------------
  360|  7.05k|    VERIFY_LEN((quant_table_precision ? 2 : 1) * kDCTBlockSize);
  ------------------
  |  |   32|  14.1k|  if (*pos + (n) > len) {                                               \
  |  |  ------------------
  |  |  |  Branch (32:7): [True: 29, False: 7.02k]
  |  |  |  Branch (32:15): [True: 191, False: 6.86k]
  |  |  ------------------
  |  |   33|     29|    fprintf(stderr, "Unexpected end of input: pos=%d need=%d len=%d\n", \
  |  |   34|     58|            static_cast<int>(*pos), static_cast<int>(n),                \
  |  |  ------------------
  |  |  |  Branch (34:54): [True: 12, False: 17]
  |  |  ------------------
  |  |   35|     29|            static_cast<int>(len));                                     \
  |  |   36|     29|    jpg->error = JPEG_UNEXPECTED_EOF;                                   \
  |  |   37|     29|    return false;                                                       \
  |  |   38|     29|  }
  ------------------
  361|  7.02k|    JPEGQuantTable table;
  362|  7.02k|    table.index = quant_table_index;
  363|  7.02k|    table.precision = quant_table_precision;
  364|   455k|    for (int i = 0; i < kDCTBlockSize; ++i) {
  ------------------
  |  Branch (364:21): [True: 448k, False: 7.00k]
  ------------------
  365|   448k|      int quant_val = quant_table_precision ?
  ------------------
  |  Branch (365:23): [True: 11.0k, False: 437k]
  ------------------
  366|  11.0k|          ReadUint16(data, pos) :
  367|   448k|          ReadUint8(data, pos);
  368|   448k|      VERIFY_INPUT(quant_val, 1, 65535, QUANT_VAL);
  ------------------
  |  |   41|   448k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 19, False: 448k]
  |  |  |  Branch (41:20): [True: 0, False: 448k]
  |  |  ------------------
  |  |   42|     19|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|     19|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|     19|        return false;                                                   \
  |  |   45|     19|  }
  ------------------
  369|   448k|      table.values[kJPEGNaturalOrder[i]] = quant_val;
  370|   448k|    }
  371|  7.00k|    table.is_last = (*pos == start_pos + marker_len);
  372|  7.00k|    jpg->quant.push_back(table);
  373|  7.00k|  }
  374|  6.95k|  VERIFY_MARKER_END();
  ------------------
  |  |   48|  6.95k|  if (start_pos + marker_len != *pos) {                                 \
  |  |  ------------------
  |  |  |  Branch (48:7): [True: 39, False: 6.91k]
  |  |  ------------------
  |  |   49|     39|    fprintf(stderr, "Invalid marker length: declared=%d actual=%d\n",   \
  |  |   50|     39|            static_cast<int>(marker_len),                               \
  |  |   51|     39|            static_cast<int>(*pos - start_pos));                        \
  |  |   52|     39|    jpg->error = JPEG_WRONG_MARKER_SIZE;                                \
  |  |   53|     39|    return false;                                                       \
  |  |   54|     39|  }
  ------------------
  375|  6.91k|  return true;
  376|  6.95k|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_110ProcessDRIEPKhmPmPNS_8JPEGDataE:
  380|    739|                JPEGData* jpg) {
  381|    739|  if (jpg->restart_interval > 0) {
  ------------------
  |  Branch (381:7): [True: 15, False: 724]
  ------------------
  382|     15|    fprintf(stderr, "Duplicate DRI marker.\n");
  383|     15|    jpg->error = JPEG_DUPLICATE_DRI;
  384|     15|    return false;
  385|     15|  }
  386|    724|  const size_t start_pos = *pos;
  387|    724|  VERIFY_LEN(4);
  ------------------
  |  |   32|    724|  if (*pos + (n) > len) {                                               \
  |  |  ------------------
  |  |  |  Branch (32:7): [True: 8, False: 716]
  |  |  ------------------
  |  |   33|      8|    fprintf(stderr, "Unexpected end of input: pos=%d need=%d len=%d\n", \
  |  |   34|      8|            static_cast<int>(*pos), static_cast<int>(n),                \
  |  |   35|      8|            static_cast<int>(len));                                     \
  |  |   36|      8|    jpg->error = JPEG_UNEXPECTED_EOF;                                   \
  |  |   37|      8|    return false;                                                       \
  |  |   38|      8|  }
  ------------------
  388|    716|  size_t marker_len = ReadUint16(data, pos);
  389|    716|  int restart_interval = ReadUint16(data, pos);
  390|    716|  jpg->restart_interval = restart_interval;
  391|    716|  VERIFY_MARKER_END();
  ------------------
  |  |   48|    716|  if (start_pos + marker_len != *pos) {                                 \
  |  |  ------------------
  |  |  |  Branch (48:7): [True: 11, False: 705]
  |  |  ------------------
  |  |   49|     11|    fprintf(stderr, "Invalid marker length: declared=%d actual=%d\n",   \
  |  |   50|     11|            static_cast<int>(marker_len),                               \
  |  |   51|     11|            static_cast<int>(*pos - start_pos));                        \
  |  |   52|     11|    jpg->error = JPEG_WRONG_MARKER_SIZE;                                \
  |  |   53|     11|    return false;                                                       \
  |  |   54|     11|  }
  ------------------
  392|    705|  return true;
  393|    716|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_110ProcessAPPEPKhmPmPNS_8JPEGDataE:
  397|  1.79M|                JPEGData* jpg) {
  398|  1.79M|  VERIFY_LEN(2);
  ------------------
  |  |   32|  1.79M|  if (*pos + (n) > len) {                                               \
  |  |  ------------------
  |  |  |  Branch (32:7): [True: 80, False: 1.79M]
  |  |  ------------------
  |  |   33|     80|    fprintf(stderr, "Unexpected end of input: pos=%d need=%d len=%d\n", \
  |  |   34|     80|            static_cast<int>(*pos), static_cast<int>(n),                \
  |  |   35|     80|            static_cast<int>(len));                                     \
  |  |   36|     80|    jpg->error = JPEG_UNEXPECTED_EOF;                                   \
  |  |   37|     80|    return false;                                                       \
  |  |   38|     80|  }
  ------------------
  399|  1.79M|  size_t marker_len = ReadUint16(data, pos);
  400|  1.79M|  VERIFY_INPUT(marker_len, 2, 65535, MARKER_LEN);
  ------------------
  |  |   41|  1.79M|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 4, False: 1.79M]
  |  |  |  Branch (41:20): [True: 0, False: 1.79M]
  |  |  ------------------
  |  |   42|      4|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|      4|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|      4|        return false;                                                   \
  |  |   45|      4|  }
  ------------------
  401|  1.79M|  VERIFY_LEN(marker_len - 2);
  ------------------
  |  |   32|  1.79M|  if (*pos + (n) > len) {                                               \
  |  |  ------------------
  |  |  |  Branch (32:7): [True: 33, False: 1.79M]
  |  |  ------------------
  |  |   33|     33|    fprintf(stderr, "Unexpected end of input: pos=%d need=%d len=%d\n", \
  |  |   34|     33|            static_cast<int>(*pos), static_cast<int>(n),                \
  |  |   35|     33|            static_cast<int>(len));                                     \
  |  |   36|     33|    jpg->error = JPEG_UNEXPECTED_EOF;                                   \
  |  |   37|     33|    return false;                                                       \
  |  |   38|     33|  }
  ------------------
  402|       |  // Save the marker type together with the app data.
  403|  1.79M|  std::string app_str(reinterpret_cast<const char*>(
  404|  1.79M|      &data[*pos - 3]), marker_len + 1);
  405|  1.79M|  *pos += marker_len - 2;
  406|  1.79M|  jpg->app_data.push_back(app_str);
  407|  1.79M|  return true;
  408|  1.79M|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_110ProcessCOMEPKhmPmPNS_8JPEGDataE:
  412|   421k|                JPEGData* jpg) {
  413|   421k|  VERIFY_LEN(2);
  ------------------
  |  |   32|   421k|  if (*pos + (n) > len) {                                               \
  |  |  ------------------
  |  |  |  Branch (32:7): [True: 4, False: 421k]
  |  |  ------------------
  |  |   33|      4|    fprintf(stderr, "Unexpected end of input: pos=%d need=%d len=%d\n", \
  |  |   34|      4|            static_cast<int>(*pos), static_cast<int>(n),                \
  |  |   35|      4|            static_cast<int>(len));                                     \
  |  |   36|      4|    jpg->error = JPEG_UNEXPECTED_EOF;                                   \
  |  |   37|      4|    return false;                                                       \
  |  |   38|      4|  }
  ------------------
  414|   421k|  size_t marker_len = ReadUint16(data, pos);
  415|   421k|  VERIFY_INPUT(marker_len, 2, 65535, MARKER_LEN);
  ------------------
  |  |   41|   421k|  if (var < low || var > high) {                                        \
  |  |  ------------------
  |  |  |  Branch (41:7): [True: 4, False: 421k]
  |  |  |  Branch (41:20): [True: 0, False: 421k]
  |  |  ------------------
  |  |   42|      4|    fprintf(stderr, "Invalid %s: %d\n", #var, static_cast<int>(var));   \
  |  |   43|      4|    jpg->error = JPEG_INVALID_ ## code;                                 \
  |  |   44|      4|        return false;                                                   \
  |  |   45|      4|  }
  ------------------
  416|   421k|  VERIFY_LEN(marker_len - 2);
  ------------------
  |  |   32|   421k|  if (*pos + (n) > len) {                                               \
  |  |  ------------------
  |  |  |  Branch (32:7): [True: 39, False: 421k]
  |  |  ------------------
  |  |   33|     39|    fprintf(stderr, "Unexpected end of input: pos=%d need=%d len=%d\n", \
  |  |   34|     39|            static_cast<int>(*pos), static_cast<int>(n),                \
  |  |   35|     39|            static_cast<int>(len));                                     \
  |  |   36|     39|    jpg->error = JPEG_UNEXPECTED_EOF;                                   \
  |  |   37|     39|    return false;                                                       \
  |  |   38|     39|  }
  ------------------
  417|   421k|  std::string com_str(reinterpret_cast<const char*>(
  418|   421k|      &data[*pos - 2]), marker_len);
  419|   421k|  *pos += marker_len - 2;
  420|   421k|  jpg->com_data.push_back(com_str);
  421|   421k|  return true;
  422|   421k|}
jpeg_data_reader.cc:_ZN7guetzli12_GLOBAL__N_112FixupIndexesEPNS_8JPEGDataE:
  890|  2.70k|bool FixupIndexes(JPEGData* jpg) {
  891|  10.6k|  for (size_t i = 0; i < jpg->components.size(); ++i) {
  ------------------
  |  Branch (891:22): [True: 7.93k, False: 2.69k]
  ------------------
  892|  7.93k|    JPEGComponent* c = &jpg->components[i];
  893|  7.93k|    bool found_index = false;
  894|  9.07k|    for (size_t j = 0; j < jpg->quant.size(); ++j) {
  ------------------
  |  Branch (894:24): [True: 9.06k, False: 13]
  ------------------
  895|  9.06k|      if (jpg->quant[j].index == c->quant_idx) {
  ------------------
  |  Branch (895:11): [True: 7.92k, False: 1.14k]
  ------------------
  896|  7.92k|        c->quant_idx = j;
  897|  7.92k|        found_index = true;
  898|  7.92k|        break;
  899|  7.92k|      }
  900|  9.06k|    }
  901|  7.93k|    if (!found_index) {
  ------------------
  |  Branch (901:9): [True: 13, False: 7.92k]
  ------------------
  902|     13|      fprintf(stderr, "Quantization table with index %zd not found\n",
  903|     13|              c->quant_idx);
  904|     13|      jpg->error = JPEG_QUANT_TABLE_NOT_FOUND;
  905|     13|      return false;
  906|     13|    }
  907|  7.93k|  }
  908|  2.69k|  return true;
  909|  2.70k|}

_ZN7guetzli28UpdateACHistogramForDCTBlockEPKsPNS_13JpegHistogramE:
  189|  12.6M|                                  JpegHistogram* ac_histogram) {
  190|  12.6M|  int r = 0;
  191|   812M|  for (int k = 1; k < 64; ++k) {
  ------------------
  |  Branch (191:19): [True: 799M, False: 12.6M]
  ------------------
  192|   799M|    coeff_t coeff = coeffs[kJPEGNaturalOrder[k]];
  193|   799M|    if (coeff == 0) {
  ------------------
  |  Branch (193:9): [True: 667M, False: 132M]
  ------------------
  194|   667M|      r++;
  195|   667M|      continue;
  196|   667M|    }
  197|   135M|    while (r > 15) {
  ------------------
  |  Branch (197:12): [True: 3.12M, False: 132M]
  ------------------
  198|  3.12M|      ac_histogram->Add(0xf0);
  199|  3.12M|      r -= 16;
  200|  3.12M|    }
  201|   132M|    int nbits = Log2FloorNonZero(std::abs(coeff)) + 1;
  202|   132M|    int symbol = (r << 4) + nbits;
  203|   132M|    ac_histogram->Add(symbol);
  204|   132M|    r = 0;
  205|   132M|  }
  206|  12.6M|  if (r > 0) {
  ------------------
  |  Branch (206:7): [True: 11.3M, False: 1.34M]
  ------------------
  207|  11.3M|    ac_histogram->Add(0);
  208|  11.3M|  }
  209|  12.6M|}
_ZN7guetzli19HistogramHeaderCostERKNS_13JpegHistogramE:
  211|  2.59M|size_t HistogramHeaderCost(const JpegHistogram& histo) {
  212|  2.59M|  size_t header_bits = 17 * 8;
  213|   665M|  for (int i = 0; i + 1 < JpegHistogram::kSize; ++i) {
  ------------------
  |  Branch (213:19): [True: 663M, False: 2.59M]
  ------------------
  214|   663M|    if (histo.counts[i] > 0) {
  ------------------
  |  Branch (214:9): [True: 30.5M, False: 632M]
  ------------------
  215|  30.5M|      header_bits += 8;
  216|  30.5M|    }
  217|   663M|  }
  218|  2.59M|  return header_bits;
  219|  2.59M|}
_ZN7guetzli20HistogramEntropyCostERKNS_13JpegHistogramEPKh:
  222|  7.15M|                            const uint8_t depths[256]) {
  223|  7.15M|  size_t bits = 0;
  224|  1.83G|  for (int i = 0; i + 1 < JpegHistogram::kSize; ++i) {
  ------------------
  |  Branch (224:19): [True: 1.83G, False: 7.15M]
  ------------------
  225|       |    // JpegHistogram::Add() counts every symbol twice, so we have to divide by
  226|       |    // two here.
  227|  1.83G|    bits += (histo.counts[i] / 2) * (depths[i] + (i & 0xf));
  228|  1.83G|  }
  229|       |  // Estimate escape byte rate to be 0.75/256.
  230|  7.15M|  bits += (bits * 3 + 512) >> 10;
  231|  7.15M|  return bits;
  232|  7.15M|}
_ZN7guetzli17BuildDCHistogramsERKNS_8JPEGDataEPNS_13JpegHistogramE:
  234|   147k|void BuildDCHistograms(const JPEGData& jpg, JpegHistogram* histo) {
  235|   524k|  for (size_t i = 0; i < jpg.components.size(); ++i) {
  ------------------
  |  Branch (235:22): [True: 376k, False: 147k]
  ------------------
  236|   376k|    const JPEGComponent& c = jpg.components[i];
  237|   376k|    JpegHistogram* dc_histogram = &histo[i];
  238|   376k|    coeff_t last_dc_coeff = 0;
  239|  2.25M|    for (int mcu_y = 0; mcu_y < jpg.MCU_rows; ++mcu_y) {
  ------------------
  |  Branch (239:25): [True: 1.87M, False: 376k]
  ------------------
  240|  12.2M|      for (int mcu_x = 0; mcu_x < jpg.MCU_cols; ++mcu_x) {
  ------------------
  |  Branch (240:27): [True: 10.3M, False: 1.87M]
  ------------------
  241|  21.5M|        for (int iy = 0; iy < c.v_samp_factor; ++iy) {
  ------------------
  |  Branch (241:26): [True: 11.1M, False: 10.3M]
  ------------------
  242|  23.8M|          for (int ix = 0; ix < c.h_samp_factor; ++ix) {
  ------------------
  |  Branch (242:28): [True: 12.6M, False: 11.1M]
  ------------------
  243|  12.6M|            int block_y = mcu_y * c.v_samp_factor + iy;
  244|  12.6M|            int block_x = mcu_x * c.h_samp_factor + ix;
  245|  12.6M|            int block_idx = block_y * c.width_in_blocks + block_x;
  246|  12.6M|            coeff_t dc_coeff = c.coeffs[block_idx << 6];
  247|  12.6M|            int diff = std::abs(dc_coeff - last_dc_coeff);
  248|  12.6M|            int nbits = Log2Floor(diff) + 1;
  249|  12.6M|            dc_histogram->Add(nbits);
  250|  12.6M|            last_dc_coeff = dc_coeff;
  251|  12.6M|          }
  252|  11.1M|        }
  253|  10.3M|      }
  254|  1.87M|    }
  255|   376k|  }
  256|   147k|}
_ZN7guetzli17BuildACHistogramsERKNS_8JPEGDataEPNS_13JpegHistogramE:
  258|   147k|void BuildACHistograms(const JPEGData& jpg, JpegHistogram* histo) {
  259|   524k|  for (size_t i = 0; i < jpg.components.size(); ++i) {
  ------------------
  |  Branch (259:22): [True: 376k, False: 147k]
  ------------------
  260|   376k|    const JPEGComponent& c = jpg.components[i];
  261|   376k|    JpegHistogram* ac_histogram = &histo[i];
  262|  13.0M|    for (size_t j = 0; j < c.coeffs.size(); j += kDCTBlockSize) {
  ------------------
  |  Branch (262:24): [True: 12.6M, False: 376k]
  ------------------
  263|  12.6M|      UpdateACHistogramForDCTBlock(&c.coeffs[j], ac_histogram);
  264|  12.6M|    }
  265|   376k|  }
  266|   147k|}
_ZN7guetzli14JpegHeaderSizeERKNS_8JPEGDataEb:
  269|  3.56k|size_t JpegHeaderSize(const JPEGData& jpg, bool strip_metadata) {
  270|  3.56k|  size_t num_bytes = 0;
  271|  3.56k|  num_bytes += 2;  // SOI
  272|  3.56k|  if (strip_metadata) {
  ------------------
  |  Branch (272:7): [True: 3.56k, False: 0]
  ------------------
  273|  3.56k|    num_bytes += 18;  // APP0
  274|  3.56k|  } else {
  275|      0|    for (size_t i = 0; i < jpg.app_data.size(); ++i) {
  ------------------
  |  Branch (275:24): [True: 0, False: 0]
  ------------------
  276|      0|      num_bytes += 1 + jpg.app_data[i].size();
  277|      0|    }
  278|      0|    for (size_t i = 0; i < jpg.com_data.size(); ++i) {
  ------------------
  |  Branch (278:24): [True: 0, False: 0]
  ------------------
  279|      0|      num_bytes += 2 + jpg.com_data[i].size();
  280|      0|    }
  281|      0|  }
  282|       |  // DQT
  283|  3.56k|  num_bytes += 4;
  284|  7.51k|  for (size_t i = 0; i < jpg.quant.size(); ++i) {
  ------------------
  |  Branch (284:22): [True: 3.95k, False: 3.56k]
  ------------------
  285|  3.95k|    num_bytes += 1 + (jpg.quant[i].precision ? 2 : 1) * kDCTBlockSize;
  ------------------
  |  Branch (285:23): [True: 11, False: 3.94k]
  ------------------
  286|  3.95k|  }
  287|  3.56k|  num_bytes += 10 + 3 * jpg.components.size();  // SOF
  288|  3.56k|  num_bytes += 4;  // DHT (w/o actual Huffman code data)
  289|  3.56k|  num_bytes += 8 + 2 * jpg.components.size();  // SOS
  290|  3.56k|  num_bytes += 2;  // EOI
  291|  3.56k|  num_bytes += jpg.tail_data.size();
  292|  3.56k|  return num_bytes;
  293|  3.56k|}
_ZN7guetzli17ClusterHistogramsEPNS_13JpegHistogramEPmPiPh:
  296|   530k|                         int* histo_indexes, uint8_t* depth) {
  297|   530k|  memset(depth, 0, *num * JpegHistogram::kSize);
  298|   530k|  size_t costs[kMaxComponents];
  299|  1.93M|  for (size_t i = 0; i < *num; ++i) {
  ------------------
  |  Branch (299:22): [True: 1.40M, False: 530k]
  ------------------
  300|  1.40M|    histo_indexes[i] = i;
  301|  1.40M|    std::vector<HuffmanTree> tree(2 * JpegHistogram::kSize + 1);
  302|  1.40M|    CreateHuffmanTree(histo[i].counts, JpegHistogram::kSize,
  303|  1.40M|                      kJpegHuffmanMaxBitLength, &tree[0],
  304|  1.40M|                      &depth[i * JpegHistogram::kSize]);
  305|  1.40M|    costs[i] = (HistogramHeaderCost(histo[i]) +
  306|  1.40M|                HistogramEntropyCost(histo[i],
  307|  1.40M|                                     &depth[i * JpegHistogram::kSize]));
  308|  1.40M|  }
  309|   530k|  const size_t orig_num = *num;
  310|  1.30M|  while (*num > 1) {
  ------------------
  |  Branch (310:10): [True: 870k, False: 436k]
  ------------------
  311|   870k|    size_t last = *num - 1;
  312|   870k|    size_t second_last = *num - 2;
  313|   870k|    JpegHistogram combined(histo[last]);
  314|   870k|    combined.AddHistogram(histo[second_last]);
  315|   870k|    std::vector<HuffmanTree> tree(2 * JpegHistogram::kSize + 1);
  316|   870k|    uint8_t depth_combined[JpegHistogram::kSize] = { 0 };
  317|   870k|    CreateHuffmanTree(combined.counts, JpegHistogram::kSize,
  318|   870k|                      kJpegHuffmanMaxBitLength, &tree[0], depth_combined);
  319|   870k|    size_t cost_combined = (HistogramHeaderCost(combined) +
  320|   870k|                            HistogramEntropyCost(combined, depth_combined));
  321|   870k|    if (cost_combined < costs[last] + costs[second_last]) {
  ------------------
  |  Branch (321:9): [True: 776k, False: 94.2k]
  ------------------
  322|   776k|      histo[second_last] = combined;
  323|   776k|      histo[last] = JpegHistogram();
  324|   776k|      costs[second_last] = cost_combined;
  325|   776k|      memcpy(&depth[second_last * JpegHistogram::kSize], depth_combined,
  326|   776k|             sizeof(depth_combined));
  327|  3.10M|      for (size_t i = 0; i < orig_num; ++i) {
  ------------------
  |  Branch (327:26): [True: 2.32M, False: 776k]
  ------------------
  328|  2.32M|        if (histo_indexes[i] == last) {
  ------------------
  |  Branch (328:13): [True: 1.12M, False: 1.20M]
  ------------------
  329|  1.12M|          histo_indexes[i] = second_last;
  330|  1.12M|        }
  331|  2.32M|      }
  332|   776k|      --(*num);
  333|   776k|    } else {
  334|  94.2k|      break;
  335|  94.2k|    }
  336|   870k|  }
  337|   530k|  size_t total_cost = 0;
  338|  1.16M|  for (size_t i = 0; i < *num; ++i) {
  ------------------
  |  Branch (338:22): [True: 631k, False: 530k]
  ------------------
  339|   631k|    total_cost += costs[i];
  340|   631k|  }
  341|   530k|  return (total_cost + 7) / 8;
  342|   530k|}
_ZN7guetzli9WriteJpegERKNS_8JPEGDataEbNS_10JPEGOutputE:
  540|   143k|bool WriteJpeg(const JPEGData& jpg, bool strip_metadata, JPEGOutput out) {
  541|   143k|  static const uint8_t kSOIMarker[2] = { 0xff, 0xd8 };
  542|   143k|  static const uint8_t kEOIMarker[2] = { 0xff, 0xd9 };
  543|   143k|  std::vector<HuffmanCodeTable> dc_codes;
  544|   143k|  std::vector<HuffmanCodeTable> ac_codes;
  545|   143k|  return (JPEGWrite(out, kSOIMarker, sizeof(kSOIMarker)) &&
  ------------------
  |  Branch (545:11): [True: 143k, False: 0]
  ------------------
  546|   143k|          EncodeMetadata(jpg, strip_metadata, out) &&
  ------------------
  |  Branch (546:11): [True: 143k, False: 0]
  ------------------
  547|   143k|          EncodeDQT(jpg.quant, out) &&
  ------------------
  |  Branch (547:11): [True: 143k, False: 0]
  ------------------
  548|   143k|          EncodeSOF(jpg, out) &&
  ------------------
  |  Branch (548:11): [True: 143k, False: 0]
  ------------------
  549|   143k|          BuildAndEncodeHuffmanCodes(jpg, out, &dc_codes, &ac_codes) &&
  ------------------
  |  Branch (549:11): [True: 143k, False: 0]
  ------------------
  550|   143k|          EncodeScan(jpg, dc_codes, ac_codes, out) &&
  ------------------
  |  Branch (550:11): [True: 143k, False: 0]
  ------------------
  551|   143k|          JPEGWrite(out, kEOIMarker, sizeof(kEOIMarker)) &&
  ------------------
  |  Branch (551:11): [True: 143k, False: 0]
  ------------------
  552|   143k|          (strip_metadata || JPEGWrite(out, jpg.tail_data)));
  ------------------
  |  Branch (552:12): [True: 143k, False: 0]
  |  Branch (552:30): [True: 0, False: 0]
  ------------------
  553|   143k|}
jpeg_data_writer.cc:_ZN7guetzli12_GLOBAL__N_19JPEGWriteENS_10JPEGOutputEPKhm:
   34|  1.00M|inline bool JPEGWrite(JPEGOutput out, const uint8_t* buf, size_t len) {
   35|  1.00M|  static const size_t kBlockSize = 1u << 30;
   36|  1.00M|  size_t pos = 0;
   37|  1.00M|  while (len - pos > kBlockSize) {
  ------------------
  |  Branch (37:10): [True: 0, False: 1.00M]
  ------------------
   38|      0|    if (!out.Write(buf + pos, kBlockSize)) {
  ------------------
  |  Branch (38:9): [True: 0, False: 0]
  ------------------
   39|      0|      return false;
   40|      0|    }
   41|      0|    pos += kBlockSize;
   42|      0|  }
   43|  1.00M|  return out.Write(buf + pos, len - pos);
   44|  1.00M|}
jpeg_data_writer.cc:_ZN7guetzli12_GLOBAL__N_114EncodeMetadataERKNS_8JPEGDataEbNS_10JPEGOutputE:
   52|   143k|bool EncodeMetadata(const JPEGData& jpg, bool strip_metadata, JPEGOutput out) {
   53|   143k|  if (strip_metadata) {
  ------------------
  |  Branch (53:7): [True: 143k, False: 0]
  ------------------
   54|   143k|    const uint8_t kApp0Data[] = {
   55|   143k|      0xff, 0xe0, 0x00, 0x10,        // APP0
   56|   143k|      0x4a, 0x46, 0x49, 0x46, 0x00,  // 'JFIF'
   57|   143k|      0x01, 0x01,                    // v1.01
   58|   143k|      0x00, 0x00, 0x01, 0x00, 0x01,  // aspect ratio = 1:1
   59|   143k|      0x00, 0x00                     // thumbnail width/height
   60|   143k|    };
   61|   143k|    return JPEGWrite(out, kApp0Data, sizeof(kApp0Data));
   62|   143k|  }
   63|      0|  bool ok = true;
   64|      0|  for (size_t i = 0; i < jpg.app_data.size(); ++i) {
  ------------------
  |  Branch (64:22): [True: 0, False: 0]
  ------------------
   65|      0|    uint8_t data[1] = { 0xff };
   66|      0|    ok = ok && JPEGWrite(out, data, sizeof(data));
  ------------------
  |  Branch (66:10): [True: 0, False: 0]
  |  Branch (66:16): [True: 0, False: 0]
  ------------------
   67|      0|    ok = ok && JPEGWrite(out, jpg.app_data[i]);
  ------------------
  |  Branch (67:10): [True: 0, False: 0]
  |  Branch (67:16): [True: 0, False: 0]
  ------------------
   68|      0|  }
   69|      0|  for (size_t i = 0; i < jpg.com_data.size(); ++i) {
  ------------------
  |  Branch (69:22): [True: 0, False: 0]
  ------------------
   70|      0|    uint8_t data[2] = { 0xff, 0xfe };
   71|      0|    ok = ok && JPEGWrite(out, data, sizeof(data));
  ------------------
  |  Branch (71:10): [True: 0, False: 0]
  |  Branch (71:16): [True: 0, False: 0]
  ------------------
   72|      0|    ok = ok && JPEGWrite(out, jpg.com_data[i]);
  ------------------
  |  Branch (72:10): [True: 0, False: 0]
  |  Branch (72:16): [True: 0, False: 0]
  ------------------
   73|      0|  }
   74|      0|  return ok;
   75|   143k|}
jpeg_data_writer.cc:_ZN7guetzli12_GLOBAL__N_19EncodeDQTERKNSt3__16vectorINS_14JPEGQuantTableENS1_9allocatorIS3_EEEENS_10JPEGOutputE:
   77|   143k|bool EncodeDQT(const std::vector<JPEGQuantTable>& quant, JPEGOutput out) {
   78|   143k|  int marker_len = 2;
   79|   310k|  for (size_t i = 0; i < quant.size(); ++i) {
  ------------------
  |  Branch (79:22): [True: 166k, False: 143k]
  ------------------
   80|   166k|    marker_len += 1 + (quant[i].precision ? 2 : 1) * kDCTBlockSize;
  ------------------
  |  Branch (80:24): [True: 110, False: 166k]
  ------------------
   81|   166k|  }
   82|   143k|  std::vector<uint8_t> data(marker_len + 2);
   83|   143k|  size_t pos = 0;
   84|   143k|  data[pos++] = 0xff;
   85|   143k|  data[pos++] = 0xdb;
   86|   143k|  data[pos++] = marker_len >> 8;
   87|   143k|  data[pos++] = marker_len & 0xff;
   88|   310k|  for (size_t i = 0; i < quant.size(); ++i) {
  ------------------
  |  Branch (88:22): [True: 166k, False: 143k]
  ------------------
   89|   166k|    const JPEGQuantTable& table = quant[i];
   90|   166k|    data[pos++] = (table.precision << 4) + table.index;
   91|  10.8M|    for (int k = 0; k < kDCTBlockSize; ++k) {
  ------------------
  |  Branch (91:21): [True: 10.6M, False: 166k]
  ------------------
   92|  10.6M|      int val = table.values[kJPEGNaturalOrder[k]];
   93|  10.6M|      if (table.precision) {
  ------------------
  |  Branch (93:11): [True: 7.04k, False: 10.6M]
  ------------------
   94|  7.04k|        data[pos++] = val >> 8;
   95|  7.04k|      }
   96|  10.6M|      data[pos++] = val & 0xff;
   97|  10.6M|    }
   98|   166k|  }
   99|   143k|  return JPEGWrite(out, &data[0], pos);
  100|   143k|}
jpeg_data_writer.cc:_ZN7guetzli12_GLOBAL__N_19EncodeSOFERKNS_8JPEGDataENS_10JPEGOutputE:
  102|   143k|bool EncodeSOF(const JPEGData& jpg, JPEGOutput out) {
  103|   143k|  const size_t ncomps = jpg.components.size();
  104|   143k|  const size_t marker_len = 8 + 3 * ncomps;
  105|   143k|  std::vector<uint8_t> data(marker_len + 2);
  106|   143k|  size_t pos = 0;
  107|   143k|  data[pos++] = 0xff;
  108|   143k|  data[pos++] = 0xc1;
  109|   143k|  data[pos++] = static_cast<uint8_t>(marker_len >> 8);
  110|   143k|  data[pos++] = marker_len & 0xff;
  111|   143k|  data[pos++] = kJpegPrecision;
  112|   143k|  data[pos++] = jpg.height >> 8;
  113|   143k|  data[pos++] = jpg.height & 0xff;
  114|   143k|  data[pos++] = jpg.width >> 8;
  115|   143k|  data[pos++] = jpg.width & 0xff;
  116|   143k|  data[pos++] = static_cast<uint8_t>(ncomps);
  117|   511k|  for (size_t i = 0; i < ncomps; ++i) {
  ------------------
  |  Branch (117:22): [True: 368k, False: 143k]
  ------------------
  118|   368k|    data[pos++] = jpg.components[i].id;
  119|   368k|    data[pos++] = ((jpg.components[i].h_samp_factor << 4) |
  120|   368k|                      (jpg.components[i].v_samp_factor));
  121|   368k|    const size_t quant_idx = jpg.components[i].quant_idx;
  122|   368k|    if (quant_idx >= jpg.quant.size()) {
  ------------------
  |  Branch (122:9): [True: 0, False: 368k]
  ------------------
  123|      0|      return false;
  124|      0|    }
  125|   368k|    data[pos++] = jpg.quant[quant_idx].index;
  126|   368k|  }
  127|   143k|  return JPEGWrite(out, &data[0], pos);
  128|   143k|}
jpeg_data_writer.cc:_ZN7guetzli12_GLOBAL__N_126BuildAndEncodeHuffmanCodesERKNS_8JPEGDataENS_10JPEGOutputEPNSt3__16vectorINS_16HuffmanCodeTableENS5_9allocatorIS7_EEEESB_:
  363|   143k|                                std::vector<HuffmanCodeTable>* ac_huff_tables) {
  364|   143k|  const int ncomps = jpg.components.size();
  365|   143k|  dc_huff_tables->resize(ncomps);
  366|   143k|  ac_huff_tables->resize(ncomps);
  367|       |
  368|       |  // Build separate DC histograms for each component.
  369|   143k|  std::vector<JpegHistogram> histograms(ncomps);
  370|   143k|  BuildDCHistograms(jpg, &histograms[0]);
  371|       |
  372|       |  // Cluster DC histograms.
  373|   143k|  size_t num_dc_histo = ncomps;
  374|   143k|  int dc_histo_indexes[kMaxComponents];
  375|   143k|  std::vector<uint8_t> depths(ncomps * JpegHistogram::kSize);
  376|   143k|  ClusterHistograms(&histograms[0], &num_dc_histo, dc_histo_indexes,
  377|   143k|                    &depths[0]);
  378|       |
  379|       |  // Build separate AC histograms for each component.
  380|   143k|  histograms.resize(num_dc_histo + ncomps);
  381|   143k|  depths.resize((num_dc_histo + ncomps) * JpegHistogram::kSize);
  382|   143k|  BuildACHistograms(jpg, &histograms[num_dc_histo]);
  383|       |
  384|       |  // Cluster AC histograms.
  385|   143k|  size_t num_ac_histo = ncomps;
  386|   143k|  int ac_histo_indexes[kMaxComponents];
  387|   143k|  ClusterHistograms(&histograms[num_dc_histo], &num_ac_histo, ac_histo_indexes,
  388|   143k|                    &depths[num_dc_histo * JpegHistogram::kSize]);
  389|       |
  390|       |  // Compute DHT and SOS marker data sizes and start emitting DHT marker.
  391|   143k|  int num_histo = num_dc_histo + num_ac_histo;
  392|   143k|  histograms.resize(num_histo);
  393|   143k|  int total_count = 0;
  394|   459k|  for (size_t i = 0; i < histograms.size(); ++i) {
  ------------------
  |  Branch (394:22): [True: 316k, False: 143k]
  ------------------
  395|   316k|    total_count += histograms[i].NumSymbols();
  396|   316k|  }
  397|   143k|  const size_t dht_marker_len =
  398|   143k|      2 + num_histo * (kJpegHuffmanMaxBitLength + 1) + total_count;
  399|   143k|  const size_t sos_marker_len = 6 + 2 * ncomps;
  400|   143k|  std::vector<uint8_t> data(dht_marker_len + sos_marker_len + 4);
  401|   143k|  size_t pos = 0;
  402|   143k|  data[pos++] = 0xff;
  403|   143k|  data[pos++] = 0xc4;
  404|   143k|  data[pos++] = static_cast<uint8_t>(dht_marker_len >> 8);
  405|   143k|  data[pos++] = dht_marker_len & 0xff;
  406|       |
  407|       |  // Compute Huffman codes for each histograms.
  408|   459k|  for (int i = 0; i < num_histo; ++i) {
  ------------------
  |  Branch (408:19): [True: 316k, False: 143k]
  ------------------
  409|   316k|    const bool is_dc = static_cast<size_t>(i) < num_dc_histo;
  410|   316k|    const int idx = is_dc ? i : i - num_dc_histo;
  ------------------
  |  Branch (410:21): [True: 144k, False: 171k]
  ------------------
  411|   316k|    int counts[kJpegHuffmanMaxBitLength + 1] = { 0 };
  412|   316k|    int values[JpegHistogram::kSize] = { 0 };
  413|   316k|    BuildHuffmanCode(&depths[i * JpegHistogram::kSize], counts, values);
  414|   316k|    HuffmanCodeTable table;
  415|  81.2M|    for (int j = 0; j < 256; ++j) table.depth[j] = 255;
  ------------------
  |  Branch (415:21): [True: 80.9M, False: 316k]
  ------------------
  416|   316k|    BuildHuffmanCodeTable(counts, values, &table);
  417|  1.13M|    for (int c = 0; c < ncomps; ++c) {
  ------------------
  |  Branch (417:21): [True: 821k, False: 316k]
  ------------------
  418|   821k|      if (is_dc) {
  ------------------
  |  Branch (418:11): [True: 370k, False: 450k]
  ------------------
  419|   370k|        if (dc_histo_indexes[c] == idx) (*dc_huff_tables)[c] = table;
  ------------------
  |  Branch (419:13): [True: 368k, False: 2.73k]
  ------------------
  420|   450k|      } else {
  421|   450k|        if (ac_histo_indexes[c] == idx) (*ac_huff_tables)[c] = table;
  ------------------
  |  Branch (421:13): [True: 368k, False: 82.9k]
  ------------------
  422|   450k|      }
  423|   821k|    }
  424|   316k|    int max_length = kJpegHuffmanMaxBitLength;
  425|  3.74M|    while (max_length > 0 && counts[max_length] == 0) --max_length;
  ------------------
  |  Branch (425:12): [True: 3.74M, False: 0]
  |  Branch (425:30): [True: 3.43M, False: 316k]
  ------------------
  426|   316k|    --counts[max_length];
  427|   316k|    int total_count = 0;
  428|  2.25M|    for (int j = 0; j <= max_length; ++j) total_count += counts[j];
  ------------------
  |  Branch (428:21): [True: 1.93M, False: 316k]
  ------------------
  429|   316k|    data[pos++] = is_dc ? i : static_cast<uint8_t>(i - num_dc_histo + 0x10);
  ------------------
  |  Branch (429:19): [True: 144k, False: 171k]
  ------------------
  430|  5.37M|    for (size_t j = 1; j <= kJpegHuffmanMaxBitLength; ++j) {
  ------------------
  |  Branch (430:24): [True: 5.05M, False: 316k]
  ------------------
  431|  5.05M|      data[pos++] = counts[j];
  432|  5.05M|    }
  433|  3.45M|    for (int j = 0; j < total_count; ++j) {
  ------------------
  |  Branch (433:21): [True: 3.13M, False: 316k]
  ------------------
  434|  3.13M|      data[pos++] = values[j];
  435|  3.13M|    }
  436|   316k|  }
  437|       |
  438|       |  // Emit SOS marker data.
  439|   143k|  data[pos++] = 0xff;
  440|   143k|  data[pos++] = 0xda;
  441|   143k|  data[pos++] = static_cast<uint8_t>(sos_marker_len >> 8);
  442|   143k|  data[pos++] = sos_marker_len & 0xff;
  443|   143k|  data[pos++] = ncomps;
  444|   511k|  for (int i = 0; i < ncomps; ++i) {
  ------------------
  |  Branch (444:19): [True: 368k, False: 143k]
  ------------------
  445|   368k|    data[pos++] = jpg.components[i].id;
  446|   368k|    data[pos++] = (dc_histo_indexes[i] << 4) | ac_histo_indexes[i];
  447|   368k|  }
  448|   143k|  data[pos++] = 0;
  449|   143k|  data[pos++] = 63;
  450|   143k|  data[pos++] = 0;
  451|   143k|  assert(pos == data.size());
  ------------------
  |  Branch (451:3): [True: 143k, False: 0]
  ------------------
  452|   143k|  return JPEGWrite(out, &data[0], data.size());
  453|   143k|}
jpeg_data_writer.cc:_ZN7guetzli12_GLOBAL__N_116BuildHuffmanCodeEPhPiS2_:
  131|   316k|void BuildHuffmanCode(uint8_t* depth, int* counts, int* values) {
  132|  81.5M|  for (int i = 0; i < JpegHistogram::kSize; ++i) {
  ------------------
  |  Branch (132:19): [True: 81.2M, False: 316k]
  ------------------
  133|  81.2M|    if (depth[i] > 0) {
  ------------------
  |  Branch (133:9): [True: 3.45M, False: 77.7M]
  ------------------
  134|  3.45M|      ++counts[depth[i]];
  135|  3.45M|    }
  136|  81.2M|  }
  137|   316k|  int offset[kJpegHuffmanMaxBitLength + 1] = { 0 };
  138|  5.37M|  for (int i = 1; i <= kJpegHuffmanMaxBitLength; ++i) {
  ------------------
  |  Branch (138:19): [True: 5.05M, False: 316k]
  ------------------
  139|  5.05M|    offset[i] = offset[i - 1] + counts[i - 1];
  140|  5.05M|  }
  141|  81.5M|  for (int i = 0; i < JpegHistogram::kSize; ++i) {
  ------------------
  |  Branch (141:19): [True: 81.2M, False: 316k]
  ------------------
  142|  81.2M|    if (depth[i] > 0) {
  ------------------
  |  Branch (142:9): [True: 3.45M, False: 77.7M]
  ------------------
  143|  3.45M|      values[offset[depth[i]]++] = i;
  144|  3.45M|    }
  145|  81.2M|  }
  146|   316k|}
jpeg_data_writer.cc:_ZN7guetzli12_GLOBAL__N_121BuildHuffmanCodeTableEPKiS2_PNS_16HuffmanCodeTableE:
  149|   316k|                           HuffmanCodeTable* table) {
  150|   316k|  int huffcode[256];
  151|   316k|  int huffsize[256];
  152|   316k|  int p = 0;
  153|  5.37M|  for (int l = 1; l <= kJpegHuffmanMaxBitLength; ++l) {
  ------------------
  |  Branch (153:19): [True: 5.05M, False: 316k]
  ------------------
  154|  5.05M|    int i = counts[l];
  155|  8.51M|    while (i--) huffsize[p++] = l;
  ------------------
  |  Branch (155:12): [True: 3.45M, False: 5.05M]
  ------------------
  156|  5.05M|  }
  157|       |
  158|   316k|  if (p == 0)
  ------------------
  |  Branch (158:7): [True: 0, False: 316k]
  ------------------
  159|      0|    return;
  160|       |
  161|   316k|  huffsize[p - 1] = 0;
  162|   316k|  int lastp = p - 1;
  163|       |
  164|   316k|  int code = 0;
  165|   316k|  int si = huffsize[0];
  166|   316k|  p = 0;
  167|  1.88M|  while (huffsize[p]) {
  ------------------
  |  Branch (167:10): [True: 1.57M, False: 316k]
  ------------------
  168|  4.70M|    while ((huffsize[p]) == si) {
  ------------------
  |  Branch (168:12): [True: 3.13M, False: 1.57M]
  ------------------
  169|  3.13M|      huffcode[p++] = code;
  170|  3.13M|      code++;
  171|  3.13M|    }
  172|  1.57M|    code <<= 1;
  173|  1.57M|    si++;
  174|  1.57M|  }
  175|  3.45M|  for (p = 0; p < lastp; p++) {
  ------------------
  |  Branch (175:15): [True: 3.13M, False: 316k]
  ------------------
  176|  3.13M|    int i = values[p];
  177|  3.13M|    table->depth[i] = huffsize[p];
  178|  3.13M|    table->code[i] = huffcode[p];
  179|  3.13M|  }
  180|   316k|}
jpeg_data_writer.cc:_ZN7guetzli12_GLOBAL__N_110EncodeScanERKNS_8JPEGDataERKNSt3__16vectorINS_16HuffmanCodeTableENS4_9allocatorIS6_EEEESB_NS_10JPEGOutputE:
  505|   143k|                JPEGOutput out) {
  506|   143k|  coeff_t last_dc_coeff[kMaxComponents] = { 0 };
  507|   143k|  BitWriter bw(1 << 17);
  508|   888k|  for (int mcu_y = 0; mcu_y < jpg.MCU_rows; ++mcu_y) {
  ------------------
  |  Branch (508:23): [True: 745k, False: 143k]
  ------------------
  509|  4.85M|    for (int mcu_x = 0; mcu_x < jpg.MCU_cols; ++mcu_x) {
  ------------------
  |  Branch (509:25): [True: 4.10M, False: 745k]
  ------------------
  510|       |      // Encode one MCU
  511|  14.2M|      for (size_t i = 0; i < jpg.components.size(); ++i) {
  ------------------
  |  Branch (511:26): [True: 10.1M, False: 4.10M]
  ------------------
  512|  10.1M|        const JPEGComponent& c = jpg.components[i];
  513|  10.1M|        int nblocks_y = c.v_samp_factor;
  514|  10.1M|        int nblocks_x = c.h_samp_factor;
  515|  21.0M|        for (int iy = 0; iy < nblocks_y; ++iy) {
  ------------------
  |  Branch (515:26): [True: 10.9M, False: 10.1M]
  ------------------
  516|  23.3M|          for (int ix = 0; ix < nblocks_x; ++ix) {
  ------------------
  |  Branch (516:28): [True: 12.4M, False: 10.9M]
  ------------------
  517|  12.4M|            int block_y = mcu_y * nblocks_y + iy;
  518|  12.4M|            int block_x = mcu_x * nblocks_x + ix;
  519|  12.4M|            int block_idx = block_y * c.width_in_blocks + block_x;
  520|  12.4M|            const coeff_t* coeffs = &c.coeffs[block_idx << 6];
  521|  12.4M|            EncodeDCTBlockSequential(coeffs, dc_huff_table[i], ac_huff_table[i],
  522|  12.4M|                                     &last_dc_coeff[i], &bw);
  523|  12.4M|          }
  524|  10.9M|        }
  525|  10.1M|      }
  526|  4.10M|      if (bw.pos > (1 << 16)) {
  ------------------
  |  Branch (526:11): [True: 0, False: 4.10M]
  ------------------
  527|      0|        if (!JPEGWrite(out, bw.data.get(), bw.pos)) {
  ------------------
  |  Branch (527:13): [True: 0, False: 0]
  ------------------
  528|      0|          return false;
  529|      0|        }
  530|      0|        bw.pos = 0;
  531|      0|      }
  532|  4.10M|    }
  533|   745k|  }
  534|   143k|  bw.JumpToByteBoundary();
  535|   143k|  return !bw.overflow && JPEGWrite(out, bw.data.get(), bw.pos);
  ------------------
  |  Branch (535:10): [True: 143k, False: 0]
  |  Branch (535:26): [True: 143k, False: 0]
  ------------------
  536|   143k|}
jpeg_data_writer.cc:_ZN7guetzli12_GLOBAL__N_124EncodeDCTBlockSequentialEPKsRKNS_16HuffmanCodeTableES5_PsPNS_9BitWriterE:
  459|  12.4M|                              BitWriter* bw) {
  460|  12.4M|  coeff_t temp2;
  461|  12.4M|  coeff_t temp;
  462|  12.4M|  temp2 = coeffs[0];
  463|  12.4M|  temp = temp2 - *last_dc_coeff;
  464|  12.4M|  *last_dc_coeff = temp2;
  465|  12.4M|  temp2 = temp;
  466|  12.4M|  if (temp < 0) {
  ------------------
  |  Branch (466:7): [True: 1.21M, False: 11.2M]
  ------------------
  467|  1.21M|    temp = -temp;
  468|  1.21M|    temp2--;
  469|  1.21M|  }
  470|  12.4M|  int nbits = Log2Floor(temp) + 1;
  471|  12.4M|  bw->WriteBits(dc_huff.depth[nbits], dc_huff.code[nbits]);
  472|  12.4M|  if (nbits > 0) {
  ------------------
  |  Branch (472:7): [True: 1.90M, False: 10.5M]
  ------------------
  473|  1.90M|    bw->WriteBits(nbits, temp2 & ((1 << nbits) - 1));
  474|  1.90M|  }
  475|  12.4M|  int r = 0;
  476|   794M|  for (int k = 1; k < 64; ++k) {
  ------------------
  |  Branch (476:19): [True: 782M, False: 12.4M]
  ------------------
  477|   782M|    if ((temp = coeffs[kJPEGNaturalOrder[k]]) == 0) {
  ------------------
  |  Branch (477:9): [True: 652M, False: 129M]
  ------------------
  478|   652M|      r++;
  479|   652M|      continue;
  480|   652M|    }
  481|   129M|    if (temp < 0) {
  ------------------
  |  Branch (481:9): [True: 110M, False: 19.0M]
  ------------------
  482|   110M|      temp = -temp;
  483|   110M|      temp2 = ~temp;
  484|   110M|    } else {
  485|  19.0M|      temp2 = temp;
  486|  19.0M|    }
  487|   132M|    while (r > 15) {
  ------------------
  |  Branch (487:12): [True: 3.07M, False: 129M]
  ------------------
  488|  3.07M|      bw->WriteBits(ac_huff.depth[0xf0], ac_huff.code[0xf0]);
  489|  3.07M|      r -= 16;
  490|  3.07M|    }
  491|   129M|    int nbits = Log2FloorNonZero(temp) + 1;
  492|   129M|    int symbol = (r << 4) + nbits;
  493|   129M|    bw->WriteBits(ac_huff.depth[symbol], ac_huff.code[symbol]);
  494|   129M|    bw->WriteBits(nbits, temp2 & ((1 << nbits) - 1));
  495|   129M|    r = 0;
  496|   129M|  }
  497|  12.4M|  if (r > 0) {
  ------------------
  |  Branch (497:7): [True: 11.0M, False: 1.31M]
  ------------------
  498|  11.0M|    bw->WriteBits(ac_huff.depth[0], ac_huff.code[0]);
  499|  11.0M|  }
  500|  12.4M|}

_ZN7guetzli10JPEGOutputC2EPFiPvPKhmES1_:
   36|   143k|  JPEGOutput(JPEGOutputHook cb, void* data) : cb(cb), data(data) {}
_ZN7guetzli13JpegHistogramC2Ev:
   59|  1.30M|  JpegHistogram() { Clear(); }
_ZN7guetzli13JpegHistogram5ClearEv:
   60|  1.30M|  void Clear() {
   61|  1.30M|    memset(counts, 0, sizeof(counts));
   62|  1.30M|    counts[kSize - 1] = 1;
   63|  1.30M|  }
_ZN7guetzli13JpegHistogram3AddEii:
   67|  99.6M|  void Add(int symbol, int weight) {
   68|  99.6M|    counts[symbol] += 2 * weight;
   69|  99.6M|  }
_ZNK7guetzli10JPEGOutput5WriteEPKhm:
   37|  1.00M|  bool Write(const uint8_t* buf, size_t len) const {
   38|  1.00M|    return (len == 0) || (cb(data, buf, len) == len);
  ------------------
  |  Branch (38:12): [True: 0, False: 1.00M]
  |  Branch (38:26): [True: 1.00M, False: 0]
  ------------------
   39|  1.00M|  }
_ZN7guetzli13JpegHistogram3AddEi:
   64|   159M|  void Add(int symbol) {
   65|   159M|    counts[symbol] += 2;
   66|   159M|  }
_ZN7guetzli13JpegHistogram12AddHistogramERKS0_:
   70|   870k|  void AddHistogram(const JpegHistogram& other) {
   71|   223M|    for (int i = 0; i + 1 < kSize; ++i) {
  ------------------
  |  Branch (71:21): [True: 222M, False: 870k]
  ------------------
   72|   222M|      counts[i] += other.counts[i];
   73|   222M|    }
   74|   870k|    counts[kSize - 1] = 1;
   75|   870k|  }
_ZNK7guetzli13JpegHistogram10NumSymbolsEv:
   76|   316k|  int NumSymbols() const {
   77|   316k|    int n = 0;
   78|  81.2M|    for (int i = 0; i + 1 < kSize; ++i) {
  ------------------
  |  Branch (78:21): [True: 80.9M, False: 316k]
  ------------------
   79|  80.9M|      n += (counts[i] > 0 ? 1 : 0);
  ------------------
  |  Branch (79:13): [True: 3.13M, False: 77.7M]
  ------------------
   80|  80.9M|    }
   81|   316k|    return n;
   82|   316k|  }

_ZN7guetzli21BuildJpegHuffmanTableEPKiS1_PNS_17HuffmanTableEntryE:
   43|   122k|                          HuffmanTableEntry* lut) {
   44|   122k|  HuffmanTableEntry code;    // current table entry
   45|   122k|  HuffmanTableEntry* table;  // next available space in table
   46|   122k|  int len;         // current code length
   47|   122k|  int idx;         // symbol index
   48|   122k|  int key;         // prefix code
   49|   122k|  int reps;        // number of replicate key values in current table
   50|   122k|  int low;         // low bits for current root entry
   51|   122k|  int table_bits;  // key length of current table
   52|   122k|  int table_size;  // size of current table
   53|   122k|  int total_size;  // sum of root table size and 2nd level table sizes
   54|       |
   55|       |  // Make a local copy of the input bit length histogram.
   56|   122k|  int count[kJpegHuffmanMaxBitLength + 1] = { 0 };
   57|   122k|  int total_count = 0;
   58|  2.07M|  for (len = 1; len <= kJpegHuffmanMaxBitLength; ++len) {
  ------------------
  |  Branch (58:17): [True: 1.95M, False: 122k]
  ------------------
   59|  1.95M|    count[len] = count_in[len];
   60|  1.95M|    total_count += count[len];
   61|  1.95M|  }
   62|       |
   63|   122k|  table = lut;
   64|   122k|  table_bits = kJpegHuffmanRootTableBits;
   65|   122k|  table_size = 1 << table_bits;
   66|   122k|  total_size = table_size;
   67|       |
   68|       |  // Special case code with only one value.
   69|   122k|  if (total_count == 1) {
  ------------------
  |  Branch (69:7): [True: 79.9k, False: 42.2k]
  ------------------
   70|  79.9k|    code.bits = 0;
   71|  79.9k|    code.value = symbols[0];
   72|  20.5M|    for (key = 0; key < total_size; ++key) {
  ------------------
  |  Branch (72:19): [True: 20.4M, False: 79.9k]
  ------------------
   73|  20.4M|      table[key] = code;
   74|  20.4M|    }
   75|  79.9k|    return total_size;
   76|  79.9k|  }
   77|       |
   78|       |  // Fill in root table.
   79|  42.2k|  key = 0;
   80|  42.2k|  idx = 0;
   81|   379k|  for (len = 1; len <= kJpegHuffmanRootTableBits; ++len) {
  ------------------
  |  Branch (81:17): [True: 337k, False: 42.2k]
  ------------------
   82|   491k|    for (; count[len] > 0; --count[len]) {
  ------------------
  |  Branch (82:12): [True: 154k, False: 337k]
  ------------------
   83|   154k|      code.bits = len;
   84|   154k|      code.value = symbols[idx++];
   85|   154k|      reps = 1 << (kJpegHuffmanRootTableBits - len);
   86|  3.17M|      while (reps--) {
  ------------------
  |  Branch (86:14): [True: 3.01M, False: 154k]
  ------------------
   87|  3.01M|        table[key++] = code;
   88|  3.01M|      }
   89|   154k|    }
   90|   337k|  }
   91|       |
   92|       |  // Fill in 2nd level tables and add pointers to root table.
   93|  42.2k|  table += table_size;
   94|  42.2k|  table_size = 0;
   95|  42.2k|  low = 0;
   96|  42.2k|  for (len = kJpegHuffmanRootTableBits + 1;
   97|   379k|       len <= kJpegHuffmanMaxBitLength; ++len) {
  ------------------
  |  Branch (97:8): [True: 337k, False: 42.2k]
  ------------------
   98|   436k|    for (; count[len] > 0; --count[len]) {
  ------------------
  |  Branch (98:12): [True: 98.8k, False: 337k]
  ------------------
   99|       |      // Start a new sub-table if the previous one is full.
  100|  98.8k|      if (low >= table_size) {
  ------------------
  |  Branch (100:11): [True: 29.4k, False: 69.3k]
  ------------------
  101|  29.4k|        table += table_size;
  102|  29.4k|        table_bits = NextTableBitSize(count, len);
  103|  29.4k|        table_size = 1 << table_bits;
  104|  29.4k|        total_size += table_size;
  105|  29.4k|        low = 0;
  106|  29.4k|        lut[key].bits = table_bits + kJpegHuffmanRootTableBits;
  107|  29.4k|        lut[key].value = (table - lut) - key;
  108|  29.4k|        ++key;
  109|  29.4k|      }
  110|  98.8k|      code.bits = len - kJpegHuffmanRootTableBits;
  111|  98.8k|      code.value = symbols[idx++];
  112|  98.8k|      reps = 1 << (table_bits - code.bits);
  113|  1.15M|      while (reps--) {
  ------------------
  |  Branch (113:14): [True: 1.05M, False: 98.8k]
  ------------------
  114|  1.05M|        table[low++] = code;
  115|  1.05M|      }
  116|  98.8k|    }
  117|   337k|  }
  118|       |
  119|  42.2k|  return total_size;
  120|   122k|}
jpeg_huffman_decode.cc:_ZN7guetzliL16NextTableBitSizeEPKii:
   31|  29.4k|static inline int NextTableBitSize(const int* count, int len) {
   32|  29.4k|  int left = 1 << (len - kJpegHuffmanRootTableBits);
   33|  98.8k|  while (len < kJpegHuffmanMaxBitLength) {
  ------------------
  |  Branch (33:10): [True: 81.3k, False: 17.5k]
  ------------------
   34|  81.3k|    left -= count[len];
   35|  81.3k|    if (left <= 0) break;
  ------------------
  |  Branch (35:9): [True: 11.9k, False: 69.4k]
  ------------------
   36|  69.4k|    ++len;
   37|  69.4k|    left <<= 1;
   38|  69.4k|  }
   39|  29.4k|  return len - kJpegHuffmanRootTableBits;
   40|  29.4k|}

_ZN7guetzli17HuffmanTableEntryC2Ev:
   36|  56.2M|  HuffmanTableEntry() : bits(0), value(0xffff) {}

_ZN7guetzli20OutputImageComponentC2Eii:
   36|  7.63k|    : width_(w), height_(h) {
   37|  7.63k|  Reset(1, 1);
   38|  7.63k|}
_ZN7guetzli20OutputImageComponent5ResetEii:
   40|   123k|void OutputImageComponent::Reset(int factor_x, int factor_y) {
   41|   123k|  factor_x_ = factor_x;
   42|   123k|  factor_y_ = factor_y;
   43|   123k|  width_in_blocks_ = (width_ + 8 * factor_x_ - 1) / (8 * factor_x_);
   44|   123k|  height_in_blocks_ = (height_ + 8 * factor_y_ - 1) / (8 * factor_y_);
   45|   123k|  num_blocks_ = width_in_blocks_ * height_in_blocks_;
   46|   123k|  coeffs_ = std::vector<coeff_t>(num_blocks_ * kDCTBlockSize);
   47|   123k|  pixels_ = std::vector<uint16_t>(width_ * height_, 128 << 4);
   48|  7.99M|  for (int i = 0; i < kDCTBlockSize; ++i) quant_[i] = 1;
  ------------------
  |  Branch (48:19): [True: 7.87M, False: 123k]
  ------------------
   49|   123k|}
_ZNK7guetzli20OutputImageComponent9IsAllZeroEv:
   51|   183k|bool OutputImageComponent::IsAllZero() const {
   52|   183k|  int numcoeffs = num_blocks_ * kDCTBlockSize;
   53|  70.0M|  for (int i = 0; i < numcoeffs; ++i) {
  ------------------
  |  Branch (53:19): [True: 69.9M, False: 70.5k]
  ------------------
   54|  69.9M|    if (coeffs_[i] != 0) return false;
  ------------------
  |  Branch (54:9): [True: 113k, False: 69.8M]
  ------------------
   55|  69.9M|  }
   56|  70.5k|  return true;
   57|   183k|}
_ZNK7guetzli20OutputImageComponent13GetCoeffBlockEiiPs:
   60|  5.02M|                                         coeff_t block[kDCTBlockSize]) const {
   61|  5.02M|  assert(block_x < width_in_blocks_);
  ------------------
  |  Branch (61:3): [True: 5.02M, False: 0]
  ------------------
   62|  5.02M|  assert(block_y < height_in_blocks_);
  ------------------
  |  Branch (62:3): [True: 5.02M, False: 0]
  ------------------
   63|  5.02M|  int offset = (block_y * width_in_blocks_ + block_x) * kDCTBlockSize;
   64|  5.02M|  memcpy(block, &coeffs_[offset], kDCTBlockSize * sizeof(coeffs_[0]));
   65|  5.02M|}
_ZNK7guetzli20OutputImageComponent8ToPixelsEiiiiPhi:
   68|  18.4M|                                    uint8_t* out, int stride) const {
   69|  18.4M|  assert(xmin >= 0);
  ------------------
  |  Branch (69:3): [True: 18.4M, False: 0]
  ------------------
   70|  18.4M|  assert(ymin >= 0);
  ------------------
  |  Branch (70:3): [True: 18.4M, False: 0]
  ------------------
   71|  18.4M|  assert(xmin < width_);
  ------------------
  |  Branch (71:3): [True: 18.4M, False: 0]
  ------------------
   72|  18.4M|  assert(ymin < height_);
  ------------------
  |  Branch (72:3): [True: 18.4M, False: 0]
  ------------------
   73|  18.4M|  const int yend1 = ymin + ysize;
   74|  18.4M|  const int yend0 = std::min(yend1, height_);
   75|  18.4M|  int y = ymin;
   76|   179M|  for (; y < yend0; ++y) {
  ------------------
  |  Branch (76:10): [True: 160M, False: 18.4M]
  ------------------
   77|   160M|    const int xend1 = xmin + xsize;
   78|   160M|    const int xend0 = std::min(xend1, width_);
   79|   160M|    int x = xmin;
   80|   160M|    int px = y * width_ + xmin;
   81|  2.24G|    for (; x < xend0; ++x, ++px, out += stride) {
  ------------------
  |  Branch (81:12): [True: 2.08G, False: 160M]
  ------------------
   82|  2.08G|      *out = static_cast<uint8_t>((pixels_[px] + 8 - (x & 1)) >> 4);
   83|  2.08G|    }
   84|   160M|    const int offset = -stride;
   85|   226M|    for (; x < xend1; ++x) {
  ------------------
  |  Branch (85:12): [True: 65.6M, False: 160M]
  ------------------
   86|  65.6M|      *out = out[offset];
   87|  65.6M|      out += stride;
   88|  65.6M|    }
   89|   160M|  }
   90|  22.2M|  for (; y < yend1; ++y) {
  ------------------
  |  Branch (90:10): [True: 3.76M, False: 18.4M]
  ------------------
   91|  3.76M|    const int offset = -stride * xsize;
   92|  33.8M|    for (int x = 0; x < xsize; ++x) {
  ------------------
  |  Branch (92:21): [True: 30.0M, False: 3.76M]
  ------------------
   93|  30.0M|      *out = out[offset];
   94|  30.0M|      out += stride;
   95|  30.0M|    }
   96|  3.76M|  }
   97|  18.4M|}
_ZN7guetzli20OutputImageComponent13SetCoeffBlockEiiPKs:
  124|  22.6M|                                         const coeff_t block[kDCTBlockSize]) {
  125|  22.6M|  assert(block_x < width_in_blocks_);
  ------------------
  |  Branch (125:3): [True: 22.6M, False: 0]
  ------------------
  126|  22.6M|  assert(block_y < height_in_blocks_);
  ------------------
  |  Branch (126:3): [True: 22.6M, False: 0]
  ------------------
  127|  22.6M|  int offset = (block_y * width_in_blocks_ + block_x) * kDCTBlockSize;
  128|  22.6M|  memcpy(&coeffs_[offset], block, kDCTBlockSize * sizeof(coeffs_[0]));
  129|  22.6M|  uint8_t idct[kDCTBlockSize];
  130|  22.6M|  ComputeBlockIDCT(&coeffs_[offset], idct);
  131|  22.6M|  UpdatePixelsForBlock(block_x, block_y, idct);
  132|  22.6M|}
_ZN7guetzli20OutputImageComponent20UpdatePixelsForBlockEiiPKh:
  135|  22.6M|    int block_x, int block_y, const uint8_t idct[kDCTBlockSize]) {
  136|  22.6M|  if (factor_x_ == 1 && factor_y_ == 1) {
  ------------------
  |  Branch (136:7): [True: 21.0M, False: 1.54M]
  |  Branch (136:25): [True: 21.0M, False: 0]
  ------------------
  137|   189M|    for (int iy = 0; iy < 8; ++iy) {
  ------------------
  |  Branch (137:22): [True: 168M, False: 21.0M]
  ------------------
  138|  1.51G|      for (int ix = 0; ix < 8; ++ix) {
  ------------------
  |  Branch (138:24): [True: 1.35G, False: 168M]
  ------------------
  139|  1.35G|        int x = 8 * block_x + ix;
  140|  1.35G|        int y = 8 * block_y + iy;
  141|  1.35G|        if (x >= width_ || y >= height_) continue;
  ------------------
  |  Branch (141:13): [True: 83.1M, False: 1.26G]
  |  Branch (141:28): [True: 26.8M, False: 1.24G]
  ------------------
  142|  1.24G|        int p = y * width_ + x;
  143|  1.24G|        pixels_[p] = idct[8 * iy + ix] << 4;
  144|  1.24G|      }
  145|   168M|    }
  146|  21.0M|  } else if (factor_x_ == 2 && factor_y_ == 2) {
  ------------------
  |  Branch (146:14): [True: 1.54M, False: 0]
  |  Branch (146:32): [True: 1.54M, False: 0]
  ------------------
  147|       |    // Fill in the 10x10 pixel area in the subsampled image that will be the
  148|       |    // basis of the upsampling. This area is enough to hold the 3x3 kernel of
  149|       |    // the fancy upsampler around each pixel.
  150|  1.54M|    static const int kSubsampledEdgeSize = 10;
  151|  1.54M|    uint16_t subsampled[kSubsampledEdgeSize * kSubsampledEdgeSize];
  152|  16.9M|    for (int j = 0; j < kSubsampledEdgeSize; ++j) {
  ------------------
  |  Branch (152:21): [True: 15.4M, False: 1.54M]
  ------------------
  153|       |      // The order we fill in the rows is:
  154|       |      //   8 rows intersecting the block, row below, row above
  155|  15.4M|      const int y0 = block_y * 16 + (j < 9 ? j * 2 : -2);
  ------------------
  |  Branch (155:38): [True: 13.8M, False: 1.54M]
  ------------------
  156|   169M|      for (int i = 0; i < kSubsampledEdgeSize; ++i) {
  ------------------
  |  Branch (156:23): [True: 154M, False: 15.4M]
  ------------------
  157|       |        // The order we fill in each row is:
  158|       |        //   8 pixels within the block, left edge, right edge
  159|   154M|        const int ix = ((j < 9 ? (j + 1) * kSubsampledEdgeSize : 0) +
  ------------------
  |  Branch (159:26): [True: 138M, False: 15.4M]
  ------------------
  160|   154M|                        (i < 9 ? i + 1 : 0));
  ------------------
  |  Branch (160:26): [True: 138M, False: 15.4M]
  ------------------
  161|   154M|        const int x0 = block_x * 16 + (i < 9 ? i * 2 : -2);
  ------------------
  |  Branch (161:40): [True: 138M, False: 15.4M]
  ------------------
  162|   154M|        if (x0 < 0) {
  ------------------
  |  Branch (162:13): [True: 3.87M, False: 150M]
  ------------------
  163|  3.87M|          subsampled[ix] = subsampled[ix + 1];
  164|   150M|        } else if (y0 < 0) {
  ------------------
  |  Branch (164:20): [True: 4.64M, False: 145M]
  ------------------
  165|  4.64M|          subsampled[ix] = subsampled[ix + kSubsampledEdgeSize];
  166|   145M|        } else if (x0 >= width_) {
  ------------------
  |  Branch (166:20): [True: 18.9M, False: 126M]
  ------------------
  167|  18.9M|          subsampled[ix] = subsampled[ix - 1];
  168|   126M|        } else if (y0 >= height_) {
  ------------------
  |  Branch (168:20): [True: 17.5M, False: 108M]
  ------------------
  169|  17.5M|          subsampled[ix] = subsampled[ix - kSubsampledEdgeSize];
  170|   108M|        } else if (i < 8 && j < 8) {
  ------------------
  |  Branch (170:20): [True: 89.8M, False: 19.1M]
  |  Branch (170:29): [True: 74.3M, False: 15.5M]
  ------------------
  171|  74.3M|          subsampled[ix] = idct[j * 8 + i] << 4;
  172|  74.3M|        } else {
  173|       |          // Reconstruct the subsampled pixels around the edge of the current
  174|       |          // block by computing the inverse of the fancy upsampler.
  175|  34.6M|          const int y1 = std::max(y0 - 1, 0);
  176|  34.6M|          const int x1 = std::max(x0 - 1, 0);
  177|  34.6M|          subsampled[ix] = (pixels_[y0 * width_ + x0] * 9 +
  178|  34.6M|                            pixels_[y1 * width_ + x1] +
  179|  34.6M|                            pixels_[y0 * width_ + x1] * -3 +
  180|  34.6M|                            pixels_[y1 * width_ + x0] * -3) >> 2;
  181|  34.6M|        }
  182|   154M|      }
  183|  15.4M|    }
  184|       |
  185|       |    // Determine area to update.
  186|  1.54M|    int xmin = std::max(block_x * 16 - 1, 0);
  187|  1.54M|    int xmax = std::min(block_x * 16 + 16, width_ - 1);
  188|  1.54M|    int ymin = std::max(block_y * 16 - 1, 0);
  189|  1.54M|    int ymax = std::min(block_y * 16 + 16, height_ - 1);
  190|       |
  191|       |    // Apply the fancy upsampler on the subsampled block.
  192|  24.8M|    for (int y = ymin; y <= ymax; ++y) {
  ------------------
  |  Branch (192:24): [True: 23.2M, False: 1.54M]
  ------------------
  193|  23.2M|      const int y0 = ((y & ~1) / 2 - block_y * 8 + 1) * kSubsampledEdgeSize;
  194|  23.2M|      const int dy = ((y & 1) * 2 - 1) * kSubsampledEdgeSize;
  195|  23.2M|      uint16_t* rowptr = &pixels_[y * width_];
  196|   380M|      for (int x = xmin; x <= xmax; ++x) {
  ------------------
  |  Branch (196:26): [True: 357M, False: 23.2M]
  ------------------
  197|   357M|        const int x0 = (x & ~1) / 2 - block_x * 8 + 1;
  198|   357M|        const int dx = (x & 1) * 2 - 1;
  199|   357M|        const int ix = x0 + y0;
  200|   357M|        rowptr[x] = (subsampled[ix] * 9 + subsampled[ix + dy] * 3 +
  201|   357M|                     subsampled[ix + dx] * 3 + subsampled[ix + dx + dy]) >> 4;
  202|   357M|      }
  203|  23.2M|    }
  204|  1.54M|  } else {
  205|      0|    printf("Sampling ratio not supported: factor_x = %d factor_y = %d\n",
  206|      0|           factor_x_, factor_y_);
  207|      0|    exit(1);
  208|      0|  }
  209|  22.6M|}
_ZN7guetzli20OutputImageComponent21CopyFromJpegComponentERKNS_13JPEGComponentEiiPKi:
  213|   115k|                                                 const int* quant) {
  214|   115k|  Reset(factor_x, factor_y);
  215|   115k|  assert(width_in_blocks_ <= comp.width_in_blocks);
  ------------------
  |  Branch (215:3): [True: 115k, False: 0]
  ------------------
  216|   115k|  assert(height_in_blocks_ <= comp.height_in_blocks);
  ------------------
  |  Branch (216:3): [True: 115k, False: 0]
  ------------------
  217|   115k|  const size_t src_row_size = comp.width_in_blocks * kDCTBlockSize;
  218|   757k|  for (int block_y = 0; block_y < height_in_blocks_; ++block_y) {
  ------------------
  |  Branch (218:25): [True: 641k, False: 115k]
  ------------------
  219|   641k|    const coeff_t* src_coeffs = &comp.coeffs[block_y * src_row_size];
  220|  4.15M|    for (int block_x = 0; block_x < width_in_blocks_; ++block_x) {
  ------------------
  |  Branch (220:27): [True: 3.51M, False: 641k]
  ------------------
  221|  3.51M|      coeff_t block[kDCTBlockSize];
  222|   228M|      for (int i = 0; i < kDCTBlockSize; ++i) {
  ------------------
  |  Branch (222:23): [True: 225M, False: 3.51M]
  ------------------
  223|   225M|        block[i] = src_coeffs[i] * quant[i];
  224|   225M|      }
  225|  3.51M|      SetCoeffBlock(block_x, block_y, block);
  226|  3.51M|      src_coeffs += kDCTBlockSize;
  227|  3.51M|    }
  228|   641k|  }
  229|   115k|  memcpy(quant_, quant, sizeof(quant_));
  230|   115k|}
_ZN7guetzli20OutputImageComponent23ApplyGlobalQuantizationEPKi:
  232|   116k|void OutputImageComponent::ApplyGlobalQuantization(const int q[kDCTBlockSize]) {
  233|   716k|  for (int block_y = 0; block_y < height_in_blocks_; ++block_y) {
  ------------------
  |  Branch (233:25): [True: 599k, False: 116k]
  ------------------
  234|  3.68M|    for (int block_x = 0; block_x < width_in_blocks_; ++block_x) {
  ------------------
  |  Branch (234:27): [True: 3.08M, False: 599k]
  ------------------
  235|  3.08M|      coeff_t block[kDCTBlockSize];
  236|  3.08M|      GetCoeffBlock(block_x, block_y, block);
  237|  3.08M|      if (QuantizeBlock(block, q)) {
  ------------------
  |  Branch (237:11): [True: 1.11M, False: 1.97M]
  ------------------
  238|  1.11M|        SetCoeffBlock(block_x, block_y, block);
  239|  1.11M|      }
  240|  3.08M|    }
  241|   599k|  }
  242|   116k|  memcpy(quant_, q, sizeof(quant_));
  243|   116k|}
_ZN7guetzli11OutputImageC2Eii:
  246|  7.63k|    : width_(w),
  247|  7.63k|      height_(h),
  248|  7.63k|      components_(3, OutputImageComponent(w, h)) {}
_ZN7guetzli11OutputImage16CopyFromJpegDataERKNS_8JPEGDataE:
  250|  46.5k|void OutputImage::CopyFromJpegData(const JPEGData& jpg) {
  251|   161k|  for (size_t i = 0; i < jpg.components.size(); ++i) {
  ------------------
  |  Branch (251:22): [True: 115k, False: 46.5k]
  ------------------
  252|   115k|    const JPEGComponent& comp = jpg.components[i];
  253|   115k|    assert(jpg.max_h_samp_factor % comp.h_samp_factor == 0);
  ------------------
  |  Branch (253:5): [True: 115k, False: 0]
  ------------------
  254|   115k|    assert(jpg.max_v_samp_factor % comp.v_samp_factor == 0);
  ------------------
  |  Branch (254:5): [True: 115k, False: 0]
  ------------------
  255|   115k|    int factor_x = jpg.max_h_samp_factor / comp.h_samp_factor;
  256|   115k|    int factor_y = jpg.max_v_samp_factor / comp.v_samp_factor;
  257|   115k|    assert(comp.quant_idx < jpg.quant.size());
  ------------------
  |  Branch (257:5): [True: 115k, False: 0]
  ------------------
  258|   115k|    components_[i].CopyFromJpegComponent(comp, factor_x, factor_y,
  259|   115k|                                         &jpg.quant[comp.quant_idx].values[0]);
  260|   115k|  }
  261|  46.5k|}
_ZN7guetzli11OutputImage23ApplyGlobalQuantizationEPA64_Ki:
  342|  38.9k|void OutputImage::ApplyGlobalQuantization(const int q[3][kDCTBlockSize]) {
  343|   155k|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (343:19): [True: 116k, False: 38.9k]
  ------------------
  344|   116k|    components_[c].ApplyGlobalQuantization(&q[c][0]);
  345|   116k|  }
  346|  38.9k|}
_ZNK7guetzli11OutputImage14SaveToJpegDataEPNS_8JPEGDataE:
  348|   146k|void OutputImage::SaveToJpegData(JPEGData* jpg) const {
  349|   146k|  assert(components_[0].factor_x() == 1);
  ------------------
  |  Branch (349:3): [True: 146k, False: 0]
  ------------------
  350|   146k|  assert(components_[0].factor_y() == 1);
  ------------------
  |  Branch (350:3): [True: 146k, False: 0]
  ------------------
  351|   146k|  jpg->width = width_;
  352|   146k|  jpg->height = height_;
  353|   146k|  jpg->max_h_samp_factor = 1;
  354|   146k|  jpg->max_v_samp_factor = 1;
  355|   146k|  jpg->MCU_cols = components_[0].width_in_blocks();
  356|   146k|  jpg->MCU_rows = components_[0].height_in_blocks();
  357|   146k|  int ncomp = components_[1].IsAllZero() && components_[2].IsAllZero() ? 1 : 3;
  ------------------
  |  Branch (357:15): [True: 37.3k, False: 109k]
  |  Branch (357:45): [True: 33.1k, False: 4.19k]
  ------------------
  358|   373k|  for (int i = 1; i < ncomp; ++i) {
  ------------------
  |  Branch (358:19): [True: 226k, False: 146k]
  ------------------
  359|   226k|    jpg->max_h_samp_factor = std::max(jpg->max_h_samp_factor,
  360|   226k|                                      components_[i].factor_x());
  361|   226k|    jpg->max_v_samp_factor = std::max(jpg->max_h_samp_factor,
  362|   226k|                                      components_[i].factor_y());
  363|   226k|    jpg->MCU_cols = std::min(jpg->MCU_cols, components_[i].width_in_blocks());
  364|   226k|    jpg->MCU_rows = std::min(jpg->MCU_rows, components_[i].height_in_blocks());
  365|   226k|  }
  366|   146k|  jpg->components.resize(ncomp);
  367|   146k|  int q[3][kDCTBlockSize];
  368|   585k|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (368:19): [True: 439k, False: 146k]
  ------------------
  369|   439k|    memcpy(&q[c][0], components_[c].quant(), kDCTBlockSize * sizeof(q[0][0]));
  370|   439k|  }
  371|   519k|  for (int c = 0; c < ncomp; ++c) {
  ------------------
  |  Branch (371:19): [True: 373k, False: 146k]
  ------------------
  372|   373k|    JPEGComponent* comp = &jpg->components[c];
  373|   373k|    assert(jpg->max_h_samp_factor % components_[c].factor_x() == 0);
  ------------------
  |  Branch (373:5): [True: 373k, False: 0]
  ------------------
  374|   373k|    assert(jpg->max_v_samp_factor % components_[c].factor_y() == 0);
  ------------------
  |  Branch (374:5): [True: 373k, False: 0]
  ------------------
  375|   373k|    comp->id = c;
  376|   373k|    comp->h_samp_factor = jpg->max_h_samp_factor / components_[c].factor_x();
  377|   373k|    comp->v_samp_factor = jpg->max_v_samp_factor / components_[c].factor_y();
  378|   373k|    comp->width_in_blocks = jpg->MCU_cols * comp->h_samp_factor;
  379|   373k|    comp->height_in_blocks = jpg->MCU_rows * comp->v_samp_factor;
  380|   373k|    comp->num_blocks = comp->width_in_blocks * comp->height_in_blocks;
  381|   373k|    comp->coeffs.resize(kDCTBlockSize * comp->num_blocks);
  382|       |
  383|   373k|    int last_dc = 0;
  384|   373k|    const coeff_t* src_coeffs = components_[c].coeffs();
  385|   373k|    coeff_t* dest_coeffs = &comp->coeffs[0];
  386|  2.36M|    for (int block_y = 0; block_y < comp->height_in_blocks; ++block_y) {
  ------------------
  |  Branch (386:27): [True: 1.99M, False: 373k]
  ------------------
  387|  14.5M|      for (int block_x = 0; block_x < comp->width_in_blocks; ++block_x) {
  ------------------
  |  Branch (387:29): [True: 12.5M, False: 1.99M]
  ------------------
  388|  12.5M|        if (block_y >= components_[c].height_in_blocks() ||
  ------------------
  |  Branch (388:13): [True: 352k, False: 12.1M]
  ------------------
  389|  12.1M|            block_x >= components_[c].width_in_blocks()) {
  ------------------
  |  Branch (389:13): [True: 164k, False: 12.0M]
  ------------------
  390|   516k|          dest_coeffs[0] = last_dc;
  391|  33.0M|          for (int k = 1; k < kDCTBlockSize; ++k) {
  ------------------
  |  Branch (391:27): [True: 32.5M, False: 516k]
  ------------------
  392|  32.5M|            dest_coeffs[k] = 0;
  393|  32.5M|          }
  394|  12.0M|        } else {
  395|   781M|          for (int k = 0; k < kDCTBlockSize; ++k) {
  ------------------
  |  Branch (395:27): [True: 769M, False: 12.0M]
  ------------------
  396|   769M|            const int quant = q[c][k];
  397|   769M|            int coeff = src_coeffs[k];
  398|   769M|            assert(coeff % quant == 0);
  ------------------
  |  Branch (398:13): [True: 769M, False: 0]
  ------------------
  399|   769M|            dest_coeffs[k] = coeff / quant;
  400|   769M|          }
  401|  12.0M|          src_coeffs += kDCTBlockSize;
  402|  12.0M|        }
  403|  12.5M|        last_dc = dest_coeffs[0];
  404|  12.5M|        dest_coeffs += kDCTBlockSize;
  405|  12.5M|      }
  406|  1.99M|    }
  407|   373k|  }
  408|   146k|  SaveQuantTables(q, jpg);
  409|   146k|}
_ZNK7guetzli11OutputImage6ToSRGBEiiii:
  412|  6.15M|                                         int xsize, int ysize) const {
  413|  6.15M|  std::vector<uint8_t> rgb(xsize * ysize * 3);
  414|  24.6M|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (414:19): [True: 18.4M, False: 6.15M]
  ------------------
  415|  18.4M|    components_[c].ToPixels(xmin, ymin, xsize, ysize, &rgb[c], 3);
  416|  18.4M|  }
  417|   733M|  for (size_t p = 0; p < rgb.size(); p += 3) {
  ------------------
  |  Branch (417:22): [True: 727M, False: 6.15M]
  ------------------
  418|   727M|    ColorTransformYCbCrToRGB(&rgb[p]);
  419|   727M|  }
  420|  6.15M|  return rgb;
  421|  6.15M|}
_ZNK7guetzli11OutputImage6ToSRGBEv:
  423|  2.65k|std::vector<uint8_t> OutputImage::ToSRGB() const {
  424|  2.65k|  return ToSRGB(0, 0, width_, height_);
  425|  2.65k|}
_ZNK7guetzli11OutputImage11ToLinearRGBEiiiiPNSt3__16vectorINS2_IfNS1_9allocatorIfEEEENS3_IS5_EEEE:
  428|  6.15M|                              std::vector<std::vector<float> >* rgb) const {
  429|  6.15M|  const double* lut = Srgb8ToLinearTable();
  430|  6.15M|  std::vector<uint8_t> rgb_pixels = ToSRGB(xmin, ymin, xsize, ysize);
  431|   726M|  for (int p = 0; p < xsize * ysize; ++p) {
  ------------------
  |  Branch (431:19): [True: 720M, False: 6.15M]
  ------------------
  432|  2.88G|    for (int i = 0; i < 3; ++i) {
  ------------------
  |  Branch (432:21): [True: 2.16G, False: 720M]
  ------------------
  433|  2.16G|      (*rgb)[i][p] = static_cast<float>(lut[rgb_pixels[3 * p + i]]);
  434|  2.16G|    }
  435|   720M|  }
  436|  6.15M|}
_ZNK7guetzli11OutputImage11ToLinearRGBEPNSt3__16vectorINS2_IfNS1_9allocatorIfEEEENS3_IS5_EEEE:
  438|   143k|void OutputImage::ToLinearRGB(std::vector<std::vector<float> >* rgb) const {
  439|   143k|  ToLinearRGB(0, 0, width_, height_, rgb);
  440|   143k|}
_ZNK7guetzli11OutputImage12FrameTypeStrEv:
  442|   177k|std::string OutputImage::FrameTypeStr() const {
  443|   177k|  char buf[128];
  444|   177k|  int len = snprintf(buf, sizeof(buf), "f%d%d%d%d%d%d",
  445|   177k|                     component(0).factor_x(), component(0).factor_y(),
  446|   177k|                     component(1).factor_x(), component(1).factor_y(),
  447|   177k|                     component(2).factor_x(), component(2).factor_y());
  448|   177k|  return std::string(buf, len);
  449|   177k|}

_ZNK7guetzli20OutputImageComponent8factor_xEv:
   35|  1.85M|  int factor_x() const { return factor_x_; }
_ZNK7guetzli20OutputImageComponent8factor_yEv:
   36|  1.85M|  int factor_y() const { return factor_y_; }
_ZNK7guetzli20OutputImageComponent15width_in_blocksEv:
   37|  12.5M|  int width_in_blocks() const { return width_in_blocks_; }
_ZNK7guetzli20OutputImageComponent16height_in_blocksEv:
   38|  12.9M|  int height_in_blocks() const { return height_in_blocks_; }
_ZNK7guetzli20OutputImageComponent6coeffsEv:
   39|   373k|  const coeff_t* coeffs() const { return &coeffs_[0]; }
_ZNK7guetzli20OutputImageComponent5quantEv:
   40|  2.17M|  const int* quant() const { return &quant_[0]; }
_ZNK7guetzli11OutputImage5widthEv:
   98|  6.15M|  int width() const { return width_; }
_ZNK7guetzli11OutputImage6heightEv:
   99|  6.08M|  int height() const { return height_; }
_ZN7guetzli11OutputImage9componentEi:
  101|  22.0M|  OutputImageComponent& component(int c) { return components_[c]; }
_ZNK7guetzli11OutputImage9componentEi:
  102|  1.06M|  const OutputImageComponent& component(int c) const { return components_[c]; }

_ZN7guetzli16GuetzliStringOutEPvPKhm:
  123|  1.00M|int GuetzliStringOut(void* data, const uint8_t* buf, size_t count) {
  124|  1.00M|  std::string* sink =
  125|  1.00M|      reinterpret_cast<std::string*>(data);
  126|  1.00M|  sink->append(reinterpret_cast<const char*>(buf), count);
  127|  1.00M|  return count;
  128|  1.00M|}
_ZN7guetzli20CompareQuantMatricesEPKiS1_:
  161|   278k|int CompareQuantMatrices(const int* a, const int* b) {
  162|   278k|  int i = 0;
  163|  1.36M|  while (i < kBlockSize && a[i] == b[i]) ++i;
  ------------------
  |  Branch (163:10): [True: 1.36M, False: 2.33k]
  |  Branch (163:28): [True: 1.08M, False: 276k]
  ------------------
  164|   278k|  if (i == kBlockSize) {
  ------------------
  |  Branch (164:7): [True: 2.33k, False: 276k]
  ------------------
  165|  2.33k|    return 0;
  166|  2.33k|  }
  167|   276k|  if (a[i] < b[i]) {
  ------------------
  |  Branch (167:7): [True: 72.7k, False: 203k]
  ------------------
  168|  13.5M|    for (++i; i < kBlockSize; ++i) {
  ------------------
  |  Branch (168:15): [True: 13.4M, False: 72.7k]
  ------------------
  169|  13.4M|      if (a[i] > b[i]) return 2;
  ------------------
  |  Branch (169:11): [True: 0, False: 13.4M]
  ------------------
  170|  13.4M|    }
  171|  72.7k|    return -1;
  172|   203k|  } else {
  173|  38.9M|    for (++i; i < kBlockSize; ++i) {
  ------------------
  |  Branch (173:15): [True: 38.7M, False: 203k]
  ------------------
  174|  38.7M|      if (a[i] < b[i]) return 2;
  ------------------
  |  Branch (174:11): [True: 0, False: 38.7M]
  ------------------
  175|  38.7M|    }
  176|   203k|    return 1;
  177|   203k|  }
  178|   276k|}
_ZN7guetzli19ContrastSensitivityEi:
  180|  17.9M|double ContrastSensitivity(int k) {
  181|  17.9M|  return 1.0 / (1.0 + kJPEGZigZagOrder[k] / 2.0);
  182|  17.9M|}
_ZN7guetzli25QuantMatrixHeuristicScoreEPA64_Ki:
  184|  70.3k|double QuantMatrixHeuristicScore(const int q[3][kDCTBlockSize]) {
  185|  70.3k|  double score = 0.0;
  186|   281k|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (186:19): [True: 211k, False: 70.3k]
  ------------------
  187|  13.7M|    for (int k = 0; k < kDCTBlockSize; ++k) {
  ------------------
  |  Branch (187:21): [True: 13.5M, False: 211k]
  ------------------
  188|  13.5M|      score += 0.5 * (q[c][k] - 1.0) * ContrastSensitivity(k);
  189|  13.5M|    }
  190|   211k|  }
  191|  70.3k|  return score;
  192|  70.3k|}
_ZN7guetzli15ProcessJpegDataERKNS_6ParamsERKNS_8JPEGDataEPNS_10ComparatorEPNS_13GuetzliOutputEPNS_12ProcessStatsE:
  885|  2.65k|                     ProcessStats* stats) {
  886|  2.65k|  Processor processor;
  887|  2.65k|  return processor.ProcessJpegData(params, jpg_in, comparator, out, stats);
  888|  2.65k|}
_ZN7guetzli7ProcessERKNS_6ParamsEPNS_12ProcessStatsERKNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEPSB_:
  892|  4.25k|             std::string* jpg_out) {
  893|  4.25k|  JPEGData jpg;
  894|  4.25k|  if (!ReadJpeg(data, JPEG_READ_ALL, &jpg)) {
  ------------------
  |  Branch (894:7): [True: 1.56k, False: 2.68k]
  ------------------
  895|  1.56k|    fprintf(stderr, "Can't read jpg data from input file\n");
  896|  1.56k|    return false;
  897|  1.56k|  }
  898|  2.68k|  if (!CheckJpegSanity(jpg)) {
  ------------------
  |  Branch (898:7): [True: 9, False: 2.67k]
  ------------------
  899|      9|    fprintf(stderr, "Unsupported input JPEG (unexpectedly large coefficient "
  900|      9|            "values).\n");
  901|      9|    return false;
  902|      9|  }
  903|  2.67k|  std::vector<uint8_t> rgb = DecodeJpegToRGB(jpg);
  904|  2.67k|  if (rgb.empty()) {
  ------------------
  |  Branch (904:7): [True: 21, False: 2.65k]
  ------------------
  905|     21|    fprintf(stderr, "Unsupported input JPEG file (e.g. unsupported "
  906|     21|            "downsampling mode).\nPlease provide the input image as "
  907|     21|            "a PNG file.\n");
  908|     21|    return false;
  909|     21|  }
  910|  2.65k|  GuetzliOutput out;
  911|  2.65k|  ProcessStats dummy_stats;
  912|  2.65k|  if (stats == nullptr) {
  ------------------
  |  Branch (912:7): [True: 2.65k, False: 0]
  ------------------
  913|  2.65k|    stats = &dummy_stats;
  914|  2.65k|  }
  915|  2.65k|  std::unique_ptr<ButteraugliComparator> comparator;
  916|  2.65k|  if (jpg.width >= 32 && jpg.height >= 32) {
  ------------------
  |  Branch (916:7): [True: 2.58k, False: 69]
  |  Branch (916:26): [True: 2.54k, False: 42]
  ------------------
  917|  2.54k|    comparator.reset(
  918|  2.54k|        new ButteraugliComparator(jpg.width, jpg.height, &rgb,
  919|  2.54k|                                  params.butteraugli_target, stats));
  920|  2.54k|  }
  921|  2.65k|  bool ok = ProcessJpegData(params, jpg, comparator.get(), &out, stats);
  922|  2.65k|  *jpg_out = out.jpeg_data;
  923|  2.65k|  return ok;
  924|  2.67k|}
processor.cc:_ZN7guetzli12_GLOBAL__N_19Processor15ProcessJpegDataERKNS_6ParamsERKNS_8JPEGDataEPNS_10ComparatorEPNS_13GuetzliOutputEPNS_12ProcessStatsE:
  794|  2.65k|                                ProcessStats* stats) {
  795|  2.65k|  params_ = params;
  796|  2.65k|  comparator_ = comparator;
  797|  2.65k|  final_output_ = out;
  798|  2.65k|  stats_ = stats;
  799|       |
  800|  2.65k|  if (params.butteraugli_target > 2.0f) {
  ------------------
  |  Branch (800:7): [True: 0, False: 2.65k]
  ------------------
  801|      0|    fprintf(stderr,
  802|      0|            "Guetzli should be called with quality >= 84, otherwise the\n"
  803|      0|            "output will have noticeable artifacts. If you want to\n"
  804|      0|            "proceed anyway, please edit the source code.\n");
  805|      0|    return false;
  806|      0|  }
  807|  2.65k|  if (jpg_in.components.size() != 3 || !HasYCbCrColorSpace(jpg_in)) {
  ------------------
  |  Branch (807:7): [True: 79, False: 2.57k]
  |  Branch (807:40): [True: 0, False: 2.57k]
  ------------------
  808|     79|    fprintf(stderr, "Only YUV color space input jpeg is supported\n");
  809|     79|    return false;
  810|     79|  }
  811|  2.57k|  bool input_is_420;
  812|  2.57k|  if (jpg_in.Is444()) {
  ------------------
  |  Branch (812:7): [True: 767, False: 1.80k]
  ------------------
  813|    767|    input_is_420 = false;
  814|  1.80k|  } else if (jpg_in.Is420()) {
  ------------------
  |  Branch (814:14): [True: 1.80k, False: 0]
  ------------------
  815|  1.80k|    input_is_420 = true;
  816|  1.80k|  } else {
  817|      0|    fprintf(stderr, "Unsupported sampling factors:");
  818|      0|    for (size_t i = 0; i < jpg_in.components.size(); ++i) {
  ------------------
  |  Branch (818:24): [True: 0, False: 0]
  ------------------
  819|      0|      fprintf(stderr, " %dx%d", jpg_in.components[i].h_samp_factor,
  820|      0|              jpg_in.components[i].v_samp_factor);
  821|      0|    }
  822|      0|    fprintf(stderr, "\n");
  823|      0|    return false;
  824|      0|  }
  825|  2.57k|  int q_in[3][kDCTBlockSize];
  826|       |  // Output the original image, in case we do not manage to create anything
  827|       |  // with a good enough quality.
  828|  2.57k|  std::string encoded_jpg;
  829|  2.57k|  OutputJpeg(jpg_in, &encoded_jpg);
  830|  2.57k|  final_output_->score = -1;
  831|  2.57k|  GUETZLI_LOG(stats, "Original Out[%7zd]", encoded_jpg.size());
  ------------------
  |  |   29|  2.57k|  do {                                                             \
  |  |   30|  2.57k|    char debug_string[1024];                                       \
  |  |   31|  2.57k|    int res = snprintf(debug_string, sizeof(debug_string),         \
  |  |   32|  2.57k|                       __VA_ARGS__);                               \
  |  |   33|  2.57k|    assert(res > 0 && "expected successful printing");             \
  |  |   34|  2.57k|    (void)res;                                                     \
  |  |   35|  2.57k|    debug_string[sizeof(debug_string) - 1] = '\0';                 \
  |  |   36|  2.57k|    ::guetzli::PrintDebug(                      \
  |  |   37|  2.57k|         stats, std::string(debug_string));        \
  |  |   38|  2.57k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (38:12): [Folded, False: 2.57k]
  |  |  ------------------
  ------------------
  |  Branch (831:3): [True: 2.57k, False: 0]
  |  Branch (831:3): [True: 2.57k, Folded]
  |  Branch (831:3): [True: 2.57k, False: 0]
  ------------------
  832|  2.57k|  if (comparator_ == nullptr) {
  ------------------
  |  Branch (832:7): [True: 81, False: 2.49k]
  ------------------
  833|     81|    GUETZLI_LOG(stats, " <image too small for Butteraugli>\n");
  ------------------
  |  |   29|     81|  do {                                                             \
  |  |   30|     81|    char debug_string[1024];                                       \
  |  |   31|     81|    int res = snprintf(debug_string, sizeof(debug_string),         \
  |  |   32|     81|                       __VA_ARGS__);                               \
  |  |   33|     81|    assert(res > 0 && "expected successful printing");             \
  |  |   34|     81|    (void)res;                                                     \
  |  |   35|     81|    debug_string[sizeof(debug_string) - 1] = '\0';                 \
  |  |   36|     81|    ::guetzli::PrintDebug(                      \
  |  |   37|     81|         stats, std::string(debug_string));        \
  |  |   38|     81|  } while (0)
  |  |  ------------------
  |  |  |  Branch (38:12): [Folded, False: 81]
  |  |  ------------------
  ------------------
  |  Branch (833:5): [True: 81, False: 0]
  |  Branch (833:5): [True: 81, Folded]
  |  Branch (833:5): [True: 81, False: 0]
  ------------------
  834|     81|    final_output_->jpeg_data = encoded_jpg;
  835|     81|    final_output_->score = encoded_jpg.size();
  836|       |    // Butteraugli doesn't work with images this small.
  837|     81|    return true;
  838|     81|  }
  839|  2.49k|  {
  840|  2.49k|    JPEGData jpg = jpg_in;
  841|  2.49k|    RemoveOriginalQuantization(&jpg, q_in);
  842|  2.49k|    OutputImage img(jpg.width, jpg.height);
  843|  2.49k|    img.CopyFromJpegData(jpg);
  844|  2.49k|    comparator_->Compare(img);
  845|  2.49k|  }
  846|  2.49k|  MaybeOutput(encoded_jpg);
  847|  2.49k|  int try_420 = (input_is_420 || params_.force_420 ||
  ------------------
  |  Branch (847:18): [True: 1.74k, False: 750]
  |  Branch (847:34): [True: 0, False: 750]
  ------------------
  848|  1.74k|                 (params_.try_420 && !IsGrayscale(jpg_in))) ? 1 : 0;
  ------------------
  |  Branch (848:19): [True: 0, False: 750]
  |  Branch (848:38): [True: 0, False: 0]
  ------------------
  849|  2.49k|  int force_420 = (input_is_420 || params_.force_420) ? 1 : 0;
  ------------------
  |  Branch (849:20): [True: 1.74k, False: 750]
  |  Branch (849:36): [True: 0, False: 750]
  ------------------
  850|  4.98k|  for (int downsample = force_420; downsample <= try_420; ++downsample) {
  ------------------
  |  Branch (850:36): [True: 2.49k, False: 2.49k]
  ------------------
  851|  2.49k|    JPEGData jpg = jpg_in;
  852|  2.49k|    RemoveOriginalQuantization(&jpg, q_in);
  853|  2.49k|    OutputImage img(jpg.width, jpg.height);
  854|  2.49k|    img.CopyFromJpegData(jpg);
  855|  2.49k|    if (downsample) {
  ------------------
  |  Branch (855:9): [True: 1.74k, False: 750]
  ------------------
  856|  1.74k|      DownsampleImage(&img);
  857|  1.74k|      img.SaveToJpegData(&jpg);
  858|  1.74k|    }
  859|  2.49k|    int best_q[3][kDCTBlockSize];
  860|  2.49k|    memcpy(best_q, q_in, sizeof(best_q));
  861|  2.49k|    if (!SelectQuantMatrix(jpg, downsample != 0, best_q, &img)) {
  ------------------
  |  Branch (861:9): [True: 0, False: 2.49k]
  ------------------
  862|      0|      for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (862:23): [True: 0, False: 0]
  ------------------
  863|      0|        for (int i = 0; i < kDCTBlockSize; ++i) {
  ------------------
  |  Branch (863:25): [True: 0, False: 0]
  ------------------
  864|      0|          best_q[c][i] = 1;
  865|      0|        }
  866|      0|      }
  867|      0|    }
  868|  2.49k|    img.CopyFromJpegData(jpg);
  869|  2.49k|    img.ApplyGlobalQuantization(best_q);
  870|       |
  871|  2.49k|    if (!downsample) {
  ------------------
  |  Branch (871:9): [True: 750, False: 1.74k]
  ------------------
  872|    750|      SelectFrequencyMasking(jpg, &img, 7, 1.0, false);
  873|  1.74k|    } else {
  874|  1.74k|      const float ymul = jpg.components.size() == 1 ? 1.0f : 0.97f;
  ------------------
  |  Branch (874:26): [True: 673, False: 1.06k]
  ------------------
  875|  1.74k|      SelectFrequencyMasking(jpg, &img, 1, ymul, false);
  876|  1.74k|      SelectFrequencyMasking(jpg, &img, 6, 1.0, true);
  877|  1.74k|    }
  878|  2.49k|  }
  879|       |
  880|  2.49k|  return true;
  881|  2.57k|}
processor.cc:_ZN7guetzli12_GLOBAL__N_19Processor10OutputJpegERKNS_8JPEGDataEPNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEE:
  131|   143k|                           std::string* out) {
  132|   143k|  out->clear();
  133|   143k|  JPEGOutput output(GuetzliStringOut, out);
  134|   143k|  if (!WriteJpeg(jpg, params_.clear_metadata, output)) {
  ------------------
  |  Branch (134:7): [True: 0, False: 143k]
  ------------------
  135|       |    assert(0);
  ------------------
  |  Branch (135:5): [Folded, False: 0]
  ------------------
  136|      0|  }
  137|   143k|}
processor.cc:_ZN7guetzli12_GLOBAL__N_126RemoveOriginalQuantizationEPNS_8JPEGDataEPA64_i:
   82|  4.98k|void RemoveOriginalQuantization(JPEGData* jpg, int q_in[3][kDCTBlockSize]) {
   83|  19.9k|  for (int i = 0; i < 3; ++i) {
  ------------------
  |  Branch (83:19): [True: 14.9k, False: 4.98k]
  ------------------
   84|  14.9k|    JPEGComponent& c = jpg->components[i];
   85|  14.9k|    const int* q = &jpg->quant[c.quant_idx].values[0];
   86|  14.9k|    memcpy(&q_in[i][0], q, kDCTBlockSize * sizeof(q[0]));
   87|  30.0M|    for (size_t j = 0; j < c.coeffs.size(); ++j) {
  ------------------
  |  Branch (87:24): [True: 30.0M, False: 14.9k]
  ------------------
   88|  30.0M|      c.coeffs[j] *= q[j % kDCTBlockSize];
   89|  30.0M|    }
   90|  14.9k|  }
   91|  4.98k|  int q[3][kDCTBlockSize];
   92|  19.9k|  for (int i = 0; i < 3; ++i)
  ------------------
  |  Branch (92:19): [True: 14.9k, False: 4.98k]
  ------------------
   93|   971k|    for (int j = 0; j < kDCTBlockSize; ++j) q[i][j] = 1;
  ------------------
  |  Branch (93:21): [True: 956k, False: 14.9k]
  ------------------
   94|  4.98k|  SaveQuantTables(q, jpg);
   95|  4.98k|}
processor.cc:_ZN7guetzli12_GLOBAL__N_19Processor11MaybeOutputERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
  139|   143k|void Processor::MaybeOutput(const std::string& encoded_jpg) {
  140|   143k|  double score = comparator_->ScoreOutputSize(encoded_jpg.size());
  141|   143k|  GUETZLI_LOG(stats_, " Score[%.4f]", score);
  ------------------
  |  |   29|   143k|  do {                                                             \
  |  |   30|   143k|    char debug_string[1024];                                       \
  |  |   31|   143k|    int res = snprintf(debug_string, sizeof(debug_string),         \
  |  |   32|   143k|                       __VA_ARGS__);                               \
  |  |   33|   143k|    assert(res > 0 && "expected successful printing");             \
  |  |   34|   143k|    (void)res;                                                     \
  |  |   35|   143k|    debug_string[sizeof(debug_string) - 1] = '\0';                 \
  |  |   36|   143k|    ::guetzli::PrintDebug(                      \
  |  |   37|   143k|         stats, std::string(debug_string));        \
  |  |   38|   143k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (38:12): [Folded, False: 143k]
  |  |  ------------------
  ------------------
  |  Branch (141:3): [True: 143k, False: 0]
  |  Branch (141:3): [True: 143k, Folded]
  |  Branch (141:3): [True: 143k, False: 0]
  ------------------
  142|   143k|  if (score < final_output_->score || final_output_->score < 0) {
  ------------------
  |  Branch (142:7): [True: 4.93k, False: 138k]
  |  Branch (142:39): [True: 2.49k, False: 136k]
  ------------------
  143|  7.42k|    final_output_->jpeg_data = encoded_jpg;
  144|  7.42k|    final_output_->score = score;
  145|  7.42k|    GUETZLI_LOG(stats_, " (*)");
  ------------------
  |  |   29|  7.42k|  do {                                                             \
  |  |   30|  7.42k|    char debug_string[1024];                                       \
  |  |   31|  7.42k|    int res = snprintf(debug_string, sizeof(debug_string),         \
  |  |   32|  7.42k|                       __VA_ARGS__);                               \
  |  |   33|  7.42k|    assert(res > 0 && "expected successful printing");             \
  |  |   34|  7.42k|    (void)res;                                                     \
  |  |   35|  7.42k|    debug_string[sizeof(debug_string) - 1] = '\0';                 \
  |  |   36|  7.42k|    ::guetzli::PrintDebug(                      \
  |  |   37|  7.42k|         stats, std::string(debug_string));        \
  |  |   38|  7.42k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (38:12): [Folded, False: 7.42k]
  |  |  ------------------
  ------------------
  |  Branch (145:5): [True: 7.42k, False: 0]
  |  Branch (145:5): [True: 7.42k, Folded]
  |  Branch (145:5): [True: 7.42k, False: 0]
  ------------------
  146|  7.42k|  }
  147|   143k|  GUETZLI_LOG(stats_, "\n");
  ------------------
  |  |   29|   143k|  do {                                                             \
  |  |   30|   143k|    char debug_string[1024];                                       \
  |  |   31|   143k|    int res = snprintf(debug_string, sizeof(debug_string),         \
  |  |   32|   143k|                       __VA_ARGS__);                               \
  |  |   33|   143k|    assert(res > 0 && "expected successful printing");             \
  |  |   34|   143k|    (void)res;                                                     \
  |  |   35|   143k|    debug_string[sizeof(debug_string) - 1] = '\0';                 \
  |  |   36|   143k|    ::guetzli::PrintDebug(                      \
  |  |   37|   143k|         stats, std::string(debug_string));        \
  |  |   38|   143k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (38:12): [Folded, False: 143k]
  |  |  ------------------
  ------------------
  |  Branch (147:3): [True: 143k, False: 0]
  |  Branch (147:3): [True: 143k, Folded]
  |  Branch (147:3): [True: 143k, False: 0]
  ------------------
  148|   143k|}
processor.cc:_ZN7guetzli12_GLOBAL__N_19Processor15DownsampleImageEPNS_11OutputImageE:
   97|  1.74k|void Processor::DownsampleImage(OutputImage* img) {
   98|  1.74k|  if (img->component(1).factor_x() > 1 || img->component(1).factor_y() > 1) {
  ------------------
  |  Branch (98:7): [True: 1.74k, False: 0]
  |  Branch (98:43): [True: 0, False: 0]
  ------------------
   99|  1.74k|    return;
  100|  1.74k|  }
  101|      0|  OutputImage::DownsampleConfig cfg;
  102|      0|  cfg.use_silver_screen = params_.use_silver_screen;
  103|      0|  img->Downsample(cfg);
  104|      0|}
processor.cc:_ZN7guetzli12_GLOBAL__N_19Processor17SelectQuantMatrixERKNS_8JPEGDataEbPA64_iPNS_11OutputImageE:
  330|  2.49k|                                  OutputImage* img) {
  331|  2.49k|  QuantMatrixGenerator qgen(downsample, stats_);
  332|       |  // Don't try to go up to exactly the target distance when selecting a
  333|       |  // quantization matrix, since we will need some slack to do the frequency
  334|       |  // masking later.
  335|  2.49k|  const float target_mul_high = 0.97f;
  336|  2.49k|  const float target_mul_low = 0.95f;
  337|       |
  338|  2.49k|  QuantData best = TryQuantMatrix(jpg_in, target_mul_high, best_q, img);
  339|  36.2k|  for (;;) {
  340|  36.2k|    int q_next[3][kDCTBlockSize];
  341|  36.2k|    if (!qgen.GetNext(q_next)) {
  ------------------
  |  Branch (341:9): [True: 2.28k, False: 33.9k]
  ------------------
  342|  2.28k|      break;
  343|  2.28k|    }
  344|       |
  345|  33.9k|    QuantData data = TryQuantMatrix(jpg_in, target_mul_high, q_next, img);
  346|  33.9k|    qgen.Add(data);
  347|  33.9k|    if (CompareQuantData(data, best)) {
  ------------------
  |  Branch (347:9): [True: 2.48k, False: 31.4k]
  ------------------
  348|  2.48k|      best = data;
  349|  2.48k|      if (data.dist_ok && !comparator_->DistanceOK(target_mul_low)) {
  ------------------
  |  Branch (349:11): [True: 2.48k, False: 0]
  |  Branch (349:27): [True: 209, False: 2.27k]
  ------------------
  350|    209|        break;
  351|    209|      }
  352|  2.48k|    }
  353|  33.9k|  }
  354|       |
  355|  2.49k|  memcpy(&best_q[0][0], &best.q[0][0], kBlockSize * sizeof(best_q[0][0]));
  356|  2.49k|  GUETZLI_LOG(stats_, "\n%s selected quantization matrix:\n",
  ------------------
  |  |   29|  2.49k|  do {                                                             \
  |  |   30|  2.49k|    char debug_string[1024];                                       \
  |  |   31|  2.49k|    int res = snprintf(debug_string, sizeof(debug_string),         \
  |  |   32|  4.98k|                       __VA_ARGS__);                               \
  |  |  ------------------
  |  |  |  Branch (32:24): [True: 1.74k, False: 750]
  |  |  ------------------
  |  |   33|  2.49k|    assert(res > 0 && "expected successful printing");             \
  |  |   34|  2.49k|    (void)res;                                                     \
  |  |   35|  2.49k|    debug_string[sizeof(debug_string) - 1] = '\0';                 \
  |  |   36|  2.49k|    ::guetzli::PrintDebug(                      \
  |  |   37|  2.49k|         stats, std::string(debug_string));        \
  |  |   38|  2.49k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (38:12): [Folded, False: 2.49k]
  |  |  ------------------
  ------------------
  |  Branch (356:3): [True: 2.49k, False: 0]
  |  Branch (356:3): [True: 2.49k, Folded]
  |  Branch (356:3): [True: 2.49k, False: 0]
  ------------------
  357|  2.49k|              downsample ? "YUV420" : "YUV444");
  358|  2.49k|  GUETZLI_LOG_QUANT(stats_, best_q);
  ------------------
  |  |   40|  22.4k|  for (int y = 0; y < 8; ++y) {                        \
  |  |  ------------------
  |  |  |  Branch (40:19): [True: 19.9k, False: 2.49k]
  |  |  ------------------
  |  |   41|  79.7k|    for (int c = 0; c < 3; ++c) {                      \
  |  |  ------------------
  |  |  |  Branch (41:21): [True: 59.8k, False: 19.9k]
  |  |  ------------------
  |  |   42|   538k|      for (int x = 0; x < 8; ++x)                      \
  |  |  ------------------
  |  |  |  Branch (42:23): [True: 478k, False: 59.8k]
  |  |  ------------------
  |  |   43|   478k|        GUETZLI_LOG(stats, " %2d", (q)[c][8 * y + x]); \
  |  |  ------------------
  |  |  |  |   29|   478k|  do {                                                             \
  |  |  |  |   30|   478k|    char debug_string[1024];                                       \
  |  |  |  |   31|   478k|    int res = snprintf(debug_string, sizeof(debug_string),         \
  |  |  |  |   32|   478k|                       __VA_ARGS__);                               \
  |  |  |  |   33|   478k|    assert(res > 0 && "expected successful printing");             \
  |  |  |  |   34|   478k|    (void)res;                                                     \
  |  |  |  |   35|   478k|    debug_string[sizeof(debug_string) - 1] = '\0';                 \
  |  |  |  |   36|   478k|    ::guetzli::PrintDebug(                      \
  |  |  |  |   37|   478k|         stats, std::string(debug_string));        \
  |  |  |  |   38|   478k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (38:12): [Folded, False: 478k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   44|  59.8k|      GUETZLI_LOG(stats, "   ");                       \
  |  |  ------------------
  |  |  |  |   29|  59.8k|  do {                                                             \
  |  |  |  |   30|  59.8k|    char debug_string[1024];                                       \
  |  |  |  |   31|  59.8k|    int res = snprintf(debug_string, sizeof(debug_string),         \
  |  |  |  |   32|  59.8k|                       __VA_ARGS__);                               \
  |  |  |  |   33|  59.8k|    assert(res > 0 && "expected successful printing");             \
  |  |  |  |   34|  59.8k|    (void)res;                                                     \
  |  |  |  |   35|  59.8k|    debug_string[sizeof(debug_string) - 1] = '\0';                 \
  |  |  |  |   36|  59.8k|    ::guetzli::PrintDebug(                      \
  |  |  |  |   37|  59.8k|         stats, std::string(debug_string));        \
  |  |  |  |   38|  59.8k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (38:12): [Folded, False: 59.8k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   45|  59.8k|    }                                                  \
  |  |   46|  19.9k|    GUETZLI_LOG(stats, "\n");                          \
  |  |  ------------------
  |  |  |  |   29|  19.9k|  do {                                                             \
  |  |  |  |   30|  19.9k|    char debug_string[1024];                                       \
  |  |  |  |   31|  19.9k|    int res = snprintf(debug_string, sizeof(debug_string),         \
  |  |  |  |   32|  19.9k|                       __VA_ARGS__);                               \
  |  |  |  |   33|  19.9k|    assert(res > 0 && "expected successful printing");             \
  |  |  |  |   34|  19.9k|    (void)res;                                                     \
  |  |  |  |   35|  19.9k|    debug_string[sizeof(debug_string) - 1] = '\0';                 \
  |  |  |  |   36|  19.9k|    ::guetzli::PrintDebug(                      \
  |  |  |  |   37|  19.9k|         stats, std::string(debug_string));        \
  |  |  |  |   38|  19.9k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (38:12): [Folded, False: 19.9k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   47|  19.9k|  }
  ------------------
  |  Branch (358:3): [True: 478k, False: 0]
  |  Branch (358:3): [True: 478k, Folded]
  |  Branch (358:3): [True: 478k, False: 0]
  |  Branch (358:3): [True: 59.8k, False: 0]
  |  Branch (358:3): [True: 59.8k, Folded]
  |  Branch (358:3): [True: 59.8k, False: 0]
  |  Branch (358:3): [True: 19.9k, False: 0]
  |  Branch (358:3): [True: 19.9k, Folded]
  |  Branch (358:3): [True: 19.9k, False: 0]
  ------------------
  359|  2.49k|  return best.dist_ok;
  360|  2.49k|}
_ZN7guetzli20QuantMatrixGeneratorC2EbPNS_12ProcessStatsE:
  197|  2.49k|      : downsample_(downsample), hscore_a_(-1.0), hscore_b_(-1.0),
  198|  2.49k|        total_csf_(0.0), stats_(stats) {
  199|   161k|    for (int k = 0; k < kDCTBlockSize; ++k) {
  ------------------
  |  Branch (199:21): [True: 159k, False: 2.49k]
  ------------------
  200|   159k|      total_csf_ += 3.0 * ContrastSensitivity(k);
  201|   159k|    }
  202|  2.49k|  }
processor.cc:_ZN7guetzli12_GLOBAL__N_19Processor14TryQuantMatrixERKNS_8JPEGDataEfPA64_iPNS_11OutputImageE:
  301|  36.4k|                                    OutputImage* img) {
  302|  36.4k|  QuantData data;
  303|  36.4k|  memcpy(data.q, q, sizeof(data.q));
  304|  36.4k|  img->CopyFromJpegData(jpg_in);
  305|  36.4k|  img->ApplyGlobalQuantization(data.q);
  306|  36.4k|  std::string encoded_jpg;
  307|  36.4k|  {
  308|  36.4k|    JPEGData jpg_out = jpg_in;
  309|  36.4k|    img->SaveToJpegData(&jpg_out);
  310|  36.4k|    OutputJpeg(jpg_out, &encoded_jpg);
  311|  36.4k|  }
  312|  36.4k|  GUETZLI_LOG(stats_, "Iter %2d: %s quantization matrix:\n",
  ------------------
  |  |   29|  36.4k|  do {                                                             \
  |  |   30|  36.4k|    char debug_string[1024];                                       \
  |  |   31|  36.4k|    int res = snprintf(debug_string, sizeof(debug_string),         \
  |  |   32|  36.4k|                       __VA_ARGS__);                               \
  |  |   33|  36.4k|    assert(res > 0 && "expected successful printing");             \
  |  |   34|  36.4k|    (void)res;                                                     \
  |  |   35|  36.4k|    debug_string[sizeof(debug_string) - 1] = '\0';                 \
  |  |   36|  36.4k|    ::guetzli::PrintDebug(                      \
  |  |   37|  36.4k|         stats, std::string(debug_string));        \
  |  |   38|  36.4k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (38:12): [Folded, False: 36.4k]
  |  |  ------------------
  ------------------
  |  Branch (312:3): [True: 36.4k, False: 0]
  |  Branch (312:3): [True: 36.4k, Folded]
  |  Branch (312:3): [True: 36.4k, False: 0]
  ------------------
  313|  36.4k|              stats_->counters[kNumItersCnt] + 1,
  314|  36.4k|              img->FrameTypeStr().c_str());
  315|  36.4k|  GUETZLI_LOG_QUANT(stats_, q);
  ------------------
  |  |   40|   327k|  for (int y = 0; y < 8; ++y) {                        \
  |  |  ------------------
  |  |  |  Branch (40:19): [True: 291k, False: 36.4k]
  |  |  ------------------
  |  |   41|  1.16M|    for (int c = 0; c < 3; ++c) {                      \
  |  |  ------------------
  |  |  |  Branch (41:21): [True: 874k, False: 291k]
  |  |  ------------------
  |  |   42|  7.86M|      for (int x = 0; x < 8; ++x)                      \
  |  |  ------------------
  |  |  |  Branch (42:23): [True: 6.99M, False: 874k]
  |  |  ------------------
  |  |   43|  6.99M|        GUETZLI_LOG(stats, " %2d", (q)[c][8 * y + x]); \
  |  |  ------------------
  |  |  |  |   29|  6.99M|  do {                                                             \
  |  |  |  |   30|  6.99M|    char debug_string[1024];                                       \
  |  |  |  |   31|  6.99M|    int res = snprintf(debug_string, sizeof(debug_string),         \
  |  |  |  |   32|  6.99M|                       __VA_ARGS__);                               \
  |  |  |  |   33|  6.99M|    assert(res > 0 && "expected successful printing");             \
  |  |  |  |   34|  6.99M|    (void)res;                                                     \
  |  |  |  |   35|  6.99M|    debug_string[sizeof(debug_string) - 1] = '\0';                 \
  |  |  |  |   36|  6.99M|    ::guetzli::PrintDebug(                      \
  |  |  |  |   37|  6.99M|         stats, std::string(debug_string));        \
  |  |  |  |   38|  6.99M|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (38:12): [Folded, False: 6.99M]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   44|   874k|      GUETZLI_LOG(stats, "   ");                       \
  |  |  ------------------
  |  |  |  |   29|   874k|  do {                                                             \
  |  |  |  |   30|   874k|    char debug_string[1024];                                       \
  |  |  |  |   31|   874k|    int res = snprintf(debug_string, sizeof(debug_string),         \
  |  |  |  |   32|   874k|                       __VA_ARGS__);                               \
  |  |  |  |   33|   874k|    assert(res > 0 && "expected successful printing");             \
  |  |  |  |   34|   874k|    (void)res;                                                     \
  |  |  |  |   35|   874k|    debug_string[sizeof(debug_string) - 1] = '\0';                 \
  |  |  |  |   36|   874k|    ::guetzli::PrintDebug(                      \
  |  |  |  |   37|   874k|         stats, std::string(debug_string));        \
  |  |  |  |   38|   874k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (38:12): [Folded, False: 874k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   45|   874k|    }                                                  \
  |  |   46|   291k|    GUETZLI_LOG(stats, "\n");                          \
  |  |  ------------------
  |  |  |  |   29|   291k|  do {                                                             \
  |  |  |  |   30|   291k|    char debug_string[1024];                                       \
  |  |  |  |   31|   291k|    int res = snprintf(debug_string, sizeof(debug_string),         \
  |  |  |  |   32|   291k|                       __VA_ARGS__);                               \
  |  |  |  |   33|   291k|    assert(res > 0 && "expected successful printing");             \
  |  |  |  |   34|   291k|    (void)res;                                                     \
  |  |  |  |   35|   291k|    debug_string[sizeof(debug_string) - 1] = '\0';                 \
  |  |  |  |   36|   291k|    ::guetzli::PrintDebug(                      \
  |  |  |  |   37|   291k|         stats, std::string(debug_string));        \
  |  |  |  |   38|   291k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (38:12): [Folded, False: 291k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   47|   291k|  }
  ------------------
  |  Branch (315:3): [True: 6.99M, False: 0]
  |  Branch (315:3): [True: 6.99M, Folded]
  |  Branch (315:3): [True: 6.99M, False: 0]
  |  Branch (315:3): [True: 874k, False: 0]
  |  Branch (315:3): [True: 874k, Folded]
  |  Branch (315:3): [True: 874k, False: 0]
  |  Branch (315:3): [True: 291k, False: 0]
  |  Branch (315:3): [True: 291k, Folded]
  |  Branch (315:3): [True: 291k, False: 0]
  ------------------
  316|  36.4k|  GUETZLI_LOG(stats_, "Iter %2d: %s GQ[%5.2f] Out[%7zd]",
  ------------------
  |  |   29|  36.4k|  do {                                                             \
  |  |   30|  36.4k|    char debug_string[1024];                                       \
  |  |   31|  36.4k|    int res = snprintf(debug_string, sizeof(debug_string),         \
  |  |   32|  36.4k|                       __VA_ARGS__);                               \
  |  |   33|  36.4k|    assert(res > 0 && "expected successful printing");             \
  |  |   34|  36.4k|    (void)res;                                                     \
  |  |   35|  36.4k|    debug_string[sizeof(debug_string) - 1] = '\0';                 \
  |  |   36|  36.4k|    ::guetzli::PrintDebug(                      \
  |  |   37|  36.4k|         stats, std::string(debug_string));        \
  |  |   38|  36.4k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (38:12): [Folded, False: 36.4k]
  |  |  ------------------
  ------------------
  |  Branch (316:3): [True: 36.4k, False: 0]
  |  Branch (316:3): [True: 36.4k, Folded]
  |  Branch (316:3): [True: 36.4k, False: 0]
  ------------------
  317|  36.4k|              stats_->counters[kNumItersCnt] + 1,
  318|  36.4k|              img->FrameTypeStr().c_str(),
  319|  36.4k|              QuantMatrixHeuristicScore(q), encoded_jpg.size());
  320|  36.4k|  ++stats_->counters[kNumItersCnt];
  321|  36.4k|  comparator_->Compare(*img);
  322|  36.4k|  data.dist_ok = comparator_->DistanceOK(target_mul);
  323|  36.4k|  data.jpg_size = encoded_jpg.size();
  324|  36.4k|  MaybeOutput(encoded_jpg);
  325|  36.4k|  return data;
  326|  36.4k|}
_ZN7guetzli20QuantMatrixGenerator7GetNextEPA64_i:
  204|  36.2k|  bool GetNext(int q[3][kDCTBlockSize]) {
  205|       |    // This loop should terminate by return. This 1000 iteration limit is just a
  206|       |    // precaution.
  207|  37.1k|    for (int iter = 0; iter < 1000; iter++) {
  ------------------
  |  Branch (207:24): [True: 37.1k, False: 0]
  ------------------
  208|  37.1k|      double hscore;
  209|  37.1k|      if (hscore_b_ == -1.0) {
  ------------------
  |  Branch (209:11): [True: 20.7k, False: 16.4k]
  ------------------
  210|  20.7k|        if (hscore_a_ == -1.0) {
  ------------------
  |  Branch (210:13): [True: 2.49k, False: 18.2k]
  ------------------
  211|  2.49k|          hscore = downsample_ ? 0.0 : total_csf_;
  ------------------
  |  Branch (211:20): [True: 1.74k, False: 750]
  ------------------
  212|  18.2k|        } else {
  213|  18.2k|          if (hscore_a_ < 5.0 * total_csf_) {
  ------------------
  |  Branch (213:15): [True: 11.3k, False: 6.86k]
  ------------------
  214|  11.3k|            hscore = hscore_a_ + total_csf_;
  215|  11.3k|          } else {
  216|  6.86k|            hscore = 2 * (hscore_a_ + total_csf_);
  217|  6.86k|          }
  218|  18.2k|        }
  219|  20.7k|        if (hscore > 100 * total_csf_) {
  ------------------
  |  Branch (219:13): [True: 900, False: 19.8k]
  ------------------
  220|       |          // We could not find a quantization matrix that creates enough
  221|       |          // butteraugli error. This can happen if all dct coefficients are
  222|       |          // close to zero in the original image.
  223|    900|          return false;
  224|    900|        }
  225|  20.7k|      } else if (hscore_b_ == 0.0) {
  ------------------
  |  Branch (225:18): [True: 0, False: 16.4k]
  ------------------
  226|      0|        return false;
  227|  16.4k|      } else if (hscore_a_ == -1.0) {
  ------------------
  |  Branch (227:18): [True: 35, False: 16.3k]
  ------------------
  228|     35|        hscore = 0.0;
  229|  16.3k|      } else {
  230|  16.3k|        int lower_q[3][kDCTBlockSize];
  231|  16.3k|        int upper_q[3][kDCTBlockSize];
  232|  16.3k|        constexpr double kEps = 0.05;
  233|  16.3k|        GetQuantMatrixWithHeuristicScore(
  234|  16.3k|            (1 - kEps) * hscore_a_ + kEps * 0.5 * (hscore_a_ + hscore_b_),
  235|  16.3k|            lower_q);
  236|  16.3k|        GetQuantMatrixWithHeuristicScore(
  237|  16.3k|            (1 - kEps) * hscore_b_ + kEps * 0.5 * (hscore_a_ + hscore_b_),
  238|  16.3k|            upper_q);
  239|  16.3k|        if (CompareQuantMatrices(&lower_q[0][0], &upper_q[0][0]) == 0)
  ------------------
  |  Branch (239:13): [True: 1.38k, False: 14.9k]
  ------------------
  240|  1.38k|          return false;
  241|  14.9k|        hscore = (hscore_a_ + hscore_b_) * 0.5;
  242|  14.9k|      }
  243|  34.8k|      GetQuantMatrixWithHeuristicScore(hscore, q);
  244|  34.8k|      bool retry = false;
  245|   296k|      for (size_t i = 0; i < quants_.size(); ++i) {
  ------------------
  |  Branch (245:26): [True: 262k, False: 33.9k]
  ------------------
  246|   262k|        if (CompareQuantMatrices(&q[0][0], &quants_[i].q[0][0]) == 0) {
  ------------------
  |  Branch (246:13): [True: 948, False: 261k]
  ------------------
  247|    948|          if (quants_[i].dist_ok) {
  ------------------
  |  Branch (247:15): [True: 0, False: 948]
  ------------------
  248|      0|            hscore_a_ = hscore;
  249|    948|          } else {
  250|    948|            hscore_b_ = hscore;
  251|    948|          }
  252|    948|          retry = true;
  253|    948|          break;
  254|    948|        }
  255|   262k|      }
  256|  34.8k|      if (!retry) return true;
  ------------------
  |  Branch (256:11): [True: 33.9k, False: 948]
  ------------------
  257|  34.8k|    }
  258|      0|    return false;
  259|  36.2k|  }
_ZNK7guetzli20QuantMatrixGenerator32GetQuantMatrixWithHeuristicScoreEdPA64_i:
  273|  67.6k|                                        int q[3][kDCTBlockSize]) const {
  274|  67.6k|    int level = static_cast<int>(score / total_csf_);
  275|  67.6k|    score -= level * total_csf_;
  276|  4.39M|    for (int k = kDCTBlockSize - 1; k >= 0; --k) {
  ------------------
  |  Branch (276:37): [True: 4.32M, False: 67.6k]
  ------------------
  277|  17.3M|      for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (277:23): [True: 12.9M, False: 4.32M]
  ------------------
  278|  12.9M|        q[c][kJPEGNaturalOrder[k]] = 2 * level + (score > 0.0 ? 3 : 1);
  ------------------
  |  Branch (278:51): [True: 6.33M, False: 6.64M]
  ------------------
  279|  12.9M|      }
  280|  4.32M|      score -= 3.0 * ContrastSensitivity(kJPEGNaturalOrder[k]);
  281|  4.32M|    }
  282|  67.6k|  }
processor.cc:_ZN7guetzli20QuantMatrixGenerator3AddERKNS_12_GLOBAL__N_19QuantDataE:
  261|  33.9k|  void Add(const QuantData& data) {
  262|  33.9k|    quants_.push_back(data);
  263|  33.9k|    double hscore = QuantMatrixHeuristicScore(data.q);
  264|  33.9k|    if (data.dist_ok) {
  ------------------
  |  Branch (264:9): [True: 24.1k, False: 9.81k]
  ------------------
  265|  24.1k|      hscore_a_ = std::max(hscore_a_, hscore);
  266|  24.1k|    } else {
  267|  9.81k|      hscore_b_ = hscore_b_ == -1.0 ? hscore : std::min(hscore_b_, hscore);
  ------------------
  |  Branch (267:19): [True: 1.54k, False: 8.26k]
  ------------------
  268|  9.81k|    }
  269|  33.9k|  }
processor.cc:_ZN7guetzli16CompareQuantDataERKNS_12_GLOBAL__N_19QuantDataES3_:
  150|  33.9k|bool CompareQuantData(const QuantData& a, const QuantData& b) {
  151|  33.9k|  if (a.dist_ok && !b.dist_ok) return true;
  ------------------
  |  Branch (151:7): [True: 24.1k, False: 9.81k]
  |  Branch (151:20): [True: 0, False: 24.1k]
  ------------------
  152|  33.9k|  if (!a.dist_ok && b.dist_ok) return false;
  ------------------
  |  Branch (152:7): [True: 9.81k, False: 24.1k]
  |  Branch (152:21): [True: 9.81k, False: 0]
  ------------------
  153|  24.1k|  return a.jpg_size < b.jpg_size;
  154|  33.9k|}
processor.cc:_ZN7guetzli12_GLOBAL__N_19Processor22SelectFrequencyMaskingERKNS_8JPEGDataEPNS_11OutputImageEhdb:
  542|  4.23k|                                       bool stop_early) {
  543|  4.23k|  const int width = img->width();
  544|  4.23k|  const int height = img->height();
  545|  4.23k|  const int ncomp = jpg.components.size();
  546|  4.23k|  const int last_c = Log2FloorNonZero(comp_mask);
  547|  4.23k|  if (static_cast<size_t>(last_c) >= jpg.components.size()) return;
  ------------------
  |  Branch (547:7): [True: 673, False: 3.56k]
  ------------------
  548|  3.56k|  const int factor_x = img->component(last_c).factor_x();
  549|  3.56k|  const int factor_y = img->component(last_c).factor_y();
  550|  3.56k|  const int block_width = (width + 8 * factor_x - 1) / (8 * factor_x);
  551|  3.56k|  const int block_height = (height + 8 * factor_y - 1) / (8 * factor_y);
  552|  3.56k|  const int num_blocks = block_width * block_height;
  553|       |
  554|  3.56k|  std::vector<int> candidate_coeff_offsets(num_blocks + 1);
  555|  3.56k|  std::vector<uint8_t> candidate_coeffs;
  556|  3.56k|  std::vector<float> candidate_coeff_errors;
  557|  3.56k|  candidate_coeffs.reserve(60 * num_blocks);
  558|  3.56k|  candidate_coeff_errors.reserve(60 * num_blocks);
  559|  3.56k|  std::vector<CoeffData> block_order;
  560|  3.56k|  block_order.reserve(3 * kDCTBlockSize);
  561|  3.56k|  comparator_->StartBlockComparisons();
  562|  24.8k|  for (int block_y = 0, block_ix = 0; block_y < block_height; ++block_y) {
  ------------------
  |  Branch (562:39): [True: 21.3k, False: 3.56k]
  ------------------
  563|   146k|    for (int block_x = 0; block_x < block_width; ++block_x, ++block_ix) {
  ------------------
  |  Branch (563:27): [True: 125k, False: 21.3k]
  ------------------
  564|   125k|      coeff_t block[kBlockSize] = { 0 };
  565|   125k|      coeff_t orig_block[kBlockSize] = { 0 };
  566|   500k|      for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (566:23): [True: 375k, False: 125k]
  ------------------
  567|   375k|        if (comp_mask & (1 << c)) {
  ------------------
  |  Branch (567:13): [True: 201k, False: 174k]
  ------------------
  568|   201k|          assert(img->component(c).factor_x() == factor_x);
  ------------------
  |  Branch (568:11): [True: 201k, False: 0]
  ------------------
  569|   201k|          assert(img->component(c).factor_y() == factor_y);
  ------------------
  |  Branch (569:11): [True: 201k, False: 0]
  ------------------
  570|   201k|          img->component(c).GetCoeffBlock(block_x, block_y,
  571|   201k|                                          &block[c * kDCTBlockSize]);
  572|   201k|          const JPEGComponent& comp = jpg.components[c];
  573|   201k|          int jpg_block_ix = block_y * comp.width_in_blocks + block_x;
  574|   201k|          memcpy(&orig_block[c * kDCTBlockSize],
  575|   201k|                 &comp.coeffs[jpg_block_ix * kDCTBlockSize],
  576|   201k|                 kDCTBlockSize * sizeof(orig_block[0]));
  577|   201k|        }
  578|   375k|      }
  579|   125k|      block_order.clear();
  580|   125k|      ComputeBlockZeroingOrder(block, orig_block, block_x, block_y, factor_x,
  581|   125k|                               factor_y, comp_mask, img, &block_order);
  582|   125k|      candidate_coeff_offsets[block_ix] = candidate_coeffs.size();
  583|  1.44M|      for (size_t i = 0; i < block_order.size(); ++i) {
  ------------------
  |  Branch (583:26): [True: 1.31M, False: 125k]
  ------------------
  584|  1.31M|        candidate_coeffs.push_back(block_order[i].idx);
  585|  1.31M|        candidate_coeff_errors.push_back(block_order[i].block_err);
  586|  1.31M|      }
  587|   125k|    }
  588|  21.3k|  }
  589|  3.56k|  comparator_->FinishBlockComparisons();
  590|  3.56k|  candidate_coeff_offsets[num_blocks] = candidate_coeffs.size();
  591|       |
  592|  3.56k|  std::vector<JpegHistogram> ac_histograms(ncomp);
  593|  3.56k|  int jpg_header_size, dc_size;
  594|  3.56k|  {
  595|  3.56k|    JPEGData jpg_out = jpg;
  596|  3.56k|    img->SaveToJpegData(&jpg_out);
  597|  3.56k|    jpg_header_size = JpegHeaderSize(jpg_out, params_.clear_metadata);
  598|  3.56k|    dc_size = EstimateDCSize(jpg_out);
  599|  3.56k|    BuildACHistograms(jpg_out, &ac_histograms[0]);
  600|  3.56k|  }
  601|  3.56k|  std::vector<uint8_t> ac_depths;
  602|  3.56k|  int ac_histogram_size = ComputeEntropyCodes(ac_histograms, &ac_depths);
  603|  3.56k|  int base_size = jpg_header_size + dc_size + ac_histogram_size +
  604|  3.56k|      EntropyCodedDataSize(ac_histograms, ac_depths);
  605|  3.56k|  int prev_size = base_size;
  606|       |
  607|  3.56k|  std::vector<float> max_block_error(num_blocks);
  608|  3.56k|  std::vector<int> last_indexes(num_blocks);
  609|       |
  610|  3.56k|  bool first_up_iter = true;
  611|  7.12k|  for (int direction : {1, -1}) {
  ------------------
  |  Branch (611:22): [True: 7.12k, False: 3.56k]
  ------------------
  612|   111k|    for (;;) {
  613|   111k|      if (stop_early && direction == -1) {
  ------------------
  |  Branch (613:11): [True: 9.51k, False: 102k]
  |  Branch (613:25): [True: 7.42k, False: 2.09k]
  ------------------
  614|  7.42k|        if (prev_size > 1.01 * final_output_->jpeg_data.size()) {
  ------------------
  |  Branch (614:13): [True: 235, False: 7.18k]
  ------------------
  615|       |          // If we are down-adjusting the error, the output size will only keep
  616|       |          // increasing.
  617|       |          // TODO(user): Do this check always by comparing only the size
  618|       |          // of the currently processed components.
  619|    235|          break;
  620|    235|        }
  621|  7.42k|      }
  622|   111k|      std::vector<std::pair<int, float> > global_order;
  623|   111k|      int blocks_to_change;
  624|   111k|      std::vector<float> block_weight;
  625|   140k|      for (int rblock = 1; rblock <= 4; ++rblock) {
  ------------------
  |  Branch (625:28): [True: 133k, False: 6.88k]
  ------------------
  626|   133k|        block_weight = std::vector<float>(num_blocks);
  627|   133k|        std::vector<float> distmap(width * height);
  628|   133k|        if (!first_up_iter) {
  ------------------
  |  Branch (628:13): [True: 122k, False: 11.1k]
  ------------------
  629|   122k|          distmap = comparator_->distmap();
  630|   122k|        }
  631|   133k|        comparator_->ComputeBlockErrorAdjustmentWeights(
  632|   133k|            direction, rblock, target_mul, factor_x, factor_y, distmap,
  633|   133k|            &block_weight);
  634|   133k|        global_order.clear();
  635|   133k|        blocks_to_change = 0;
  636|   882k|        for (int block_y = 0, block_ix = 0; block_y < block_height; ++block_y) {
  ------------------
  |  Branch (636:45): [True: 748k, False: 133k]
  ------------------
  637|  5.79M|          for (int block_x = 0; block_x < block_width; ++block_x, ++block_ix) {
  ------------------
  |  Branch (637:33): [True: 5.04M, False: 748k]
  ------------------
  638|  5.04M|            const int last_index = last_indexes[block_ix];
  639|  5.04M|            const int offset = candidate_coeff_offsets[block_ix];
  640|  5.04M|            const int num_candidates =
  641|  5.04M|                candidate_coeff_offsets[block_ix + 1] - offset;
  642|  5.04M|            const float* candidate_errors = &candidate_coeff_errors[offset];
  643|  5.04M|            const float max_err = max_block_error[block_ix];
  644|  5.04M|            if (block_weight[block_ix] == 0) {
  ------------------
  |  Branch (644:17): [True: 1.75M, False: 3.28M]
  ------------------
  645|  1.75M|              continue;
  646|  1.75M|            }
  647|  3.28M|            if (direction > 0) {
  ------------------
  |  Branch (647:17): [True: 313k, False: 2.96M]
  ------------------
  648|  1.62M|              for (size_t i = last_index; i < num_candidates; ++i) {
  ------------------
  |  Branch (648:43): [True: 1.31M, False: 313k]
  ------------------
  649|  1.31M|                float val = ((candidate_errors[i] - max_err) /
  650|  1.31M|                             block_weight[block_ix]);
  651|  1.31M|                global_order.push_back(std::make_pair(block_ix, val));
  652|  1.31M|              }
  653|   313k|              blocks_to_change += (last_index < num_candidates ? 1 : 0);
  ------------------
  |  Branch (653:36): [True: 53.0k, False: 260k]
  ------------------
  654|  2.96M|            } else {
  655|  64.0M|              for (int i = last_index - 1; i >= 0; --i) {
  ------------------
  |  Branch (655:44): [True: 61.0M, False: 2.96M]
  ------------------
  656|  61.0M|                float val = ((max_err - candidate_errors[i]) /
  657|  61.0M|                             block_weight[block_ix]);
  658|  61.0M|                global_order.push_back(std::make_pair(block_ix, val));
  659|  61.0M|              }
  660|  2.96M|              blocks_to_change += (last_index > 0 ? 1 : 0);
  ------------------
  |  Branch (660:36): [True: 2.37M, False: 590k]
  ------------------
  661|  2.96M|            }
  662|  3.28M|          }
  663|   748k|        }
  664|   133k|        if (!global_order.empty()) {
  ------------------
  |  Branch (664:13): [True: 104k, False: 29.0k]
  ------------------
  665|       |          // If we found something to adjust with the current block adjustment
  666|       |          // radius, we can stop and adjust the blocks we have.
  667|   104k|          break;
  668|   104k|        }
  669|   133k|      }
  670|       |
  671|   111k|      if (global_order.empty()) {
  ------------------
  |  Branch (671:11): [True: 6.88k, False: 104k]
  ------------------
  672|  6.88k|        break;
  673|  6.88k|      }
  674|       |
  675|   104k|      std::sort(global_order.begin(), global_order.end(),
  676|   104k|                [](const std::pair<int, float>& a,
  677|   104k|                   const std::pair<int, float>& b) {
  678|   104k|                  return a.second < b.second; });
  679|       |
  680|   104k|      double rel_size_delta = direction > 0 ? 0.01 : 0.0005;
  ------------------
  |  Branch (680:31): [True: 2.57k, False: 102k]
  ------------------
  681|   104k|      if (direction > 0 && comparator_->DistanceOK(1.0)) {
  ------------------
  |  Branch (681:11): [True: 2.57k, False: 102k]
  |  Branch (681:28): [True: 2.09k, False: 486]
  ------------------
  682|  2.09k|        rel_size_delta = 0.05;
  683|  2.09k|      }
  684|   104k|      double min_size_delta = base_size * rel_size_delta;
  685|       |
  686|   104k|      float coeffs_to_change_per_block =
  687|   104k|          direction > 0 ? 2.0f : factor_x * factor_y * 0.2f;
  ------------------
  |  Branch (687:11): [True: 2.57k, False: 102k]
  ------------------
  688|   104k|      int min_coeffs_to_change = coeffs_to_change_per_block * blocks_to_change;
  689|       |
  690|   104k|      if (first_up_iter) {
  ------------------
  |  Branch (690:11): [True: 2.47k, False: 102k]
  ------------------
  691|  2.47k|        const float limit = 0.75f * comparator_->BlockErrorLimit();
  692|  2.47k|        auto it = std::partition_point(global_order.begin(), global_order.end(),
  693|  2.47k|                                       [=](const std::pair<int, float>& a) {
  694|  2.47k|                                         return a.second < limit; });
  695|  2.47k|        min_coeffs_to_change = std::max<int>(min_coeffs_to_change,
  696|  2.47k|                                             it - global_order.begin());
  697|  2.47k|        first_up_iter = false;
  698|  2.47k|      }
  699|       |
  700|   104k|      std::set<int> changed_blocks;
  701|   104k|      float val_threshold = 0.0;
  702|   104k|      int changed_coeffs = 0;
  703|   104k|      int est_jpg_size = prev_size;
  704|  1.73M|      for (size_t i = 0; i < global_order.size(); ++i) {
  ------------------
  |  Branch (704:26): [True: 1.73M, False: 1.22k]
  ------------------
  705|  1.73M|        const int block_ix = global_order[i].first;
  706|  1.73M|        const int block_x = block_ix % block_width;
  707|  1.73M|        const int block_y = block_ix / block_width;
  708|  1.73M|        const int last_idx = last_indexes[block_ix];
  709|  1.73M|        const int offset = candidate_coeff_offsets[block_ix];
  710|  1.73M|        const uint8_t* candidates = &candidate_coeffs[offset];
  711|  1.73M|        const int idx = candidates[last_idx + std::min(direction, 0)];
  712|  1.73M|        const int c = idx / kDCTBlockSize;
  713|  1.73M|        const int k = idx % kDCTBlockSize;
  714|  1.73M|        const int* quant = img->component(c).quant();
  715|  1.73M|        const JPEGComponent& comp = jpg.components[c];
  716|  1.73M|        const int jpg_block_ix = block_y * comp.width_in_blocks + block_x;
  717|  1.73M|        const int newval = direction > 0 ? 0 : Quantize(
  ------------------
  |  Branch (717:28): [True: 1.08M, False: 652k]
  ------------------
  718|   652k|            comp.coeffs[jpg_block_ix * kDCTBlockSize + k], quant[k]);
  719|  1.73M|        coeff_t block[kDCTBlockSize] = { 0 };
  720|  1.73M|        img->component(c).GetCoeffBlock(block_x, block_y, block);
  721|  1.73M|        UpdateACHistogram(-1, block, quant, &ac_histograms[c]);
  722|  1.73M|        double sum_of_hf = 0;
  723|   107M|        for (int ii = 3; ii < 64; ++ii) {
  ------------------
  |  Branch (723:26): [True: 105M, False: 1.73M]
  ------------------
  724|   105M|          if ((ii & 7) < 3 && ii < 3 * 8) continue;
  ------------------
  |  Branch (724:15): [True: 36.4M, False: 69.4M]
  |  Branch (724:31): [True: 10.4M, False: 26.0M]
  ------------------
  725|  95.5M|          sum_of_hf += std::abs(comp.coeffs[jpg_block_ix * kDCTBlockSize + ii]);
  726|  95.5M|        }
  727|  1.73M|        int limit = sum_of_hf < 60 ? 4 : 8;
  ------------------
  |  Branch (727:21): [True: 29.6k, False: 1.70M]
  ------------------
  728|  1.73M|        bool precious =
  729|  1.73M|            (k == 1 || k == 8) &&
  ------------------
  |  Branch (729:14): [True: 31.2k, False: 1.70M]
  |  Branch (729:24): [True: 23.4k, False: 1.68M]
  ------------------
  730|  54.7k|            std::abs(comp.coeffs[jpg_block_ix * kDCTBlockSize + k]) >= limit;
  ------------------
  |  Branch (730:13): [True: 30.5k, False: 24.2k]
  ------------------
  731|  1.73M|        if (!precious || newval != 0) {
  ------------------
  |  Branch (731:13): [True: 1.70M, False: 30.5k]
  |  Branch (731:26): [True: 9.65k, False: 20.8k]
  ------------------
  732|  1.71M|          block[k] = newval;
  733|  1.71M|        }
  734|  1.73M|        UpdateACHistogram(1, block, quant, &ac_histograms[c]);
  735|  1.73M|        img->component(c).SetCoeffBlock(block_x, block_y, block);
  736|  1.73M|        last_indexes[block_ix] += direction;
  737|  1.73M|        changed_blocks.insert(block_ix);
  738|  1.73M|        val_threshold = global_order[i].second;
  739|  1.73M|        ++changed_coeffs;
  740|  1.73M|        static const int kEntropyCodeUpdateFreq = 10;
  741|  1.73M|        if (i % kEntropyCodeUpdateFreq == 0) {
  ------------------
  |  Branch (741:13): [True: 235k, False: 1.50M]
  ------------------
  742|   235k|          ac_histogram_size = ComputeEntropyCodes(ac_histograms, &ac_depths);
  743|   235k|        }
  744|  1.73M|        est_jpg_size = jpg_header_size + dc_size + ac_histogram_size +
  745|  1.73M|            EntropyCodedDataSize(ac_histograms, ac_depths);
  746|  1.73M|        if (changed_coeffs > min_coeffs_to_change &&
  ------------------
  |  Branch (746:13): [True: 211k, False: 1.52M]
  ------------------
  747|   211k|            std::abs(est_jpg_size - prev_size) > min_size_delta) {
  ------------------
  |  Branch (747:13): [True: 103k, False: 108k]
  ------------------
  748|   103k|          break;
  749|   103k|        }
  750|  1.73M|      }
  751|   104k|      size_t global_order_size = global_order.size();
  752|   104k|      std::vector<std::pair<int, float>>().swap(global_order);
  753|       |
  754|  4.06M|      for (int i = 0; i < num_blocks; ++i) {
  ------------------
  |  Branch (754:23): [True: 3.95M, False: 104k]
  ------------------
  755|  3.95M|        max_block_error[i] += block_weight[i] * val_threshold * direction;
  756|  3.95M|      }
  757|       |
  758|   104k|      ++stats_->counters[kNumItersCnt];
  759|   104k|      ++stats_->counters[direction > 0 ? kNumItersUpCnt : kNumItersDownCnt];
  ------------------
  |  Branch (759:26): [True: 2.57k, False: 102k]
  ------------------
  760|   104k|      std::string encoded_jpg;
  761|   104k|      {
  762|   104k|        JPEGData jpg_out = jpg;
  763|   104k|        img->SaveToJpegData(&jpg_out);
  764|   104k|        OutputJpeg(jpg_out, &encoded_jpg);
  765|   104k|      }
  766|   104k|      GUETZLI_LOG(stats_,
  ------------------
  |  |   29|   104k|  do {                                                             \
  |  |   30|   104k|    char debug_string[1024];                                       \
  |  |   31|   104k|    int res = snprintf(debug_string, sizeof(debug_string),         \
  |  |   32|   209k|                       __VA_ARGS__);                               \
  |  |  ------------------
  |  |  |  Branch (32:24): [True: 2.57k, False: 102k]
  |  |  ------------------
  |  |   33|   104k|    assert(res > 0 && "expected successful printing");             \
  |  |   34|   104k|    (void)res;                                                     \
  |  |   35|   104k|    debug_string[sizeof(debug_string) - 1] = '\0';                 \
  |  |   36|   104k|    ::guetzli::PrintDebug(                      \
  |  |   37|   104k|         stats, std::string(debug_string));        \
  |  |   38|   104k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (38:12): [Folded, False: 104k]
  |  |  ------------------
  ------------------
  |  Branch (766:7): [True: 104k, False: 0]
  |  Branch (766:7): [True: 104k, Folded]
  |  Branch (766:7): [True: 104k, False: 0]
  ------------------
  767|   104k|                  "Iter %2d: %s(%d) %s Coeffs[%d/%zd] "
  768|   104k|                  "Blocks[%zd/%d/%d] ValThres[%.4f] Out[%7zd] EstErr[%.2f%%]",
  769|   104k|                  stats_->counters[kNumItersCnt], img->FrameTypeStr().c_str(),
  770|   104k|                  comp_mask, direction > 0 ? "up" : "down", changed_coeffs,
  771|   104k|                  global_order_size, changed_blocks.size(),
  772|   104k|                  blocks_to_change, num_blocks, val_threshold,
  773|   104k|                  encoded_jpg.size(),
  774|   104k|                  100.0 - (100.0 * est_jpg_size) / encoded_jpg.size());
  775|   104k|      comparator_->Compare(*img);
  776|   104k|      MaybeOutput(encoded_jpg);
  777|   104k|      prev_size = est_jpg_size;
  778|   104k|    }
  779|  7.12k|  }
  780|  3.56k|}
processor.cc:_ZN7guetzli12_GLOBAL__N_19Processor24ComputeBlockZeroingOrderEPKsS3_iiiihPNS_11OutputImageEPNSt3__16vectorINS0_9CoeffDataENS6_9allocatorIS8_EEEE:
  368|   125k|    std::vector<CoeffData>* output_order) {
  369|   125k|  static const uint8_t oldCsf[kDCTBlockSize] = {
  370|   125k|      10, 10, 20, 40, 60, 70, 80, 90,
  371|   125k|      10, 20, 30, 60, 70, 80, 90, 90,
  372|   125k|      20, 30, 60, 70, 80, 90, 90, 90,
  373|   125k|      40, 60, 70, 80, 90, 90, 90, 90,
  374|   125k|      60, 70, 80, 90, 90, 90, 90, 90,
  375|   125k|      70, 80, 90, 90, 90, 90, 90, 90,
  376|   125k|      80, 90, 90, 90, 90, 90, 90, 90,
  377|   125k|      90, 90, 90, 90, 90, 90, 90, 90,
  378|   125k|  };
  379|   125k|  static const double kWeight[3] = { 1.0, 0.22, 0.20 };
  380|   125k|#include "guetzli/order.inc"
  ------------------
  |  |    1|       |// Automatically generated by guetzli/order:update_c_code
  |  |    2|       |
  |  |    3|   125k|static const float csf[192] = {
  |  |    4|   125k|  0.0f,
  |  |    5|   125k|  1.71014f,
  |  |    6|   125k|  0.298711f,
  |  |    7|   125k|  0.233709f,
  |  |    8|   125k|  0.223126f,
  |  |    9|   125k|  0.207072f,
  |  |   10|   125k|  0.192775f,
  |  |   11|   125k|  0.161201f,
  |  |   12|   125k|  2.05807f,
  |  |   13|   125k|  0.222927f,
  |  |   14|   125k|  0.203406f,
  |  |   15|   125k|  0.188465f,
  |  |   16|   125k|  0.184668f,
  |  |   17|   125k|  0.169993f,
  |  |   18|   125k|  0.159142f,
  |  |   19|   125k|  0.130155f,
  |  |   20|   125k|  0.430518f,
  |  |   21|   125k|  0.204939f,
  |  |   22|   125k|  0.206655f,
  |  |   23|   125k|  0.192231f,
  |  |   24|   125k|  0.182941f,
  |  |   25|   125k|  0.169455f,
  |  |   26|   125k|  0.157599f,
  |  |   27|   125k|  0.127153f,
  |  |   28|   125k|  0.234757f,
  |  |   29|   125k|  0.191098f,
  |  |   30|   125k|  0.192698f,
  |  |   31|   125k|  0.17425f,
  |  |   32|   125k|  0.166503f,
  |  |   33|   125k|  0.142154f,
  |  |   34|   125k|  0.126182f,
  |  |   35|   125k|  0.104196f,
  |  |   36|   125k|  0.226117f,
  |  |   37|   125k|  0.185373f,
  |  |   38|   125k|  0.183825f,
  |  |   39|   125k|  0.166643f,
  |  |   40|   125k|  0.159414f,
  |  |   41|   125k|  0.12636f,
  |  |   42|   125k|  0.108696f,
  |  |   43|   125k|  0.0911974f,
  |  |   44|   125k|  0.207463f,
  |  |   45|   125k|  0.171517f,
  |  |   46|   125k|  0.170124f,
  |  |   47|   125k|  0.141582f,
  |  |   48|   125k|  0.126213f,
  |  |   49|   125k|  0.103627f,
  |  |   50|   125k|  0.0882436f,
  |  |   51|   125k|  0.0751848f,
  |  |   52|   125k|  0.196436f,
  |  |   53|   125k|  0.161947f,
  |  |   54|   125k|  0.159271f,
  |  |   55|   125k|  0.126938f,
  |  |   56|   125k|  0.109125f,
  |  |   57|   125k|  0.0878027f,
  |  |   58|   125k|  0.0749842f,
  |  |   59|   125k|  0.0633859f,
  |  |   60|   125k|  0.165232f,
  |  |   61|   125k|  0.132905f,
  |  |   62|   125k|  0.128679f,
  |  |   63|   125k|  0.105766f,
  |  |   64|   125k|  0.0906087f,
  |  |   65|   125k|  0.0751544f,
  |  |   66|   125k|  0.0641187f,
  |  |   67|   125k|  0.0529921f,
  |  |   68|   125k|  0.0f,
  |  |   69|   125k|  0.147235f,
  |  |   70|   125k|  0.11264f,
  |  |   71|   125k|  0.0757892f,
  |  |   72|   125k|  0.0493929f,
  |  |   73|   125k|  0.0280663f,
  |  |   74|   125k|  0.0075012f,
  |  |   75|   125k|  -0.000945567f,
  |  |   76|   125k|  0.149251f,
  |  |   77|   125k|  0.0964806f,
  |  |   78|   125k|  0.0786224f,
  |  |   79|   125k|  0.05206f,
  |  |   80|   125k|  0.0292758f,
  |  |   81|   125k|  0.00353094f,
  |  |   82|   125k|  -0.00277912f,
  |  |   83|   125k|  -0.00404481f,
  |  |   84|   125k|  0.115551f,
  |  |   85|   125k|  0.0793142f,
  |  |   86|   125k|  0.0623735f,
  |  |   87|   125k|  0.0405019f,
  |  |   88|   125k|  0.0152656f,
  |  |   89|   125k|  -0.00145742f,
  |  |   90|   125k|  -0.00370369f,
  |  |   91|   125k|  -0.00375106f,
  |  |   92|   125k|  0.0791547f,
  |  |   93|   125k|  0.0537506f,
  |  |   94|   125k|  0.0413634f,
  |  |   95|   125k|  0.0193486f,
  |  |   96|   125k|  0.000609066f,
  |  |   97|   125k|  -0.00510923f,
  |  |   98|   125k|  -0.0046452f,
  |  |   99|   125k|  -0.00385187f,
  |  |  100|   125k|  0.0544534f,
  |  |  101|   125k|  0.0334066f,
  |  |  102|   125k|  0.0153899f,
  |  |  103|   125k|  0.000539088f,
  |  |  104|   125k|  -0.00356085f,
  |  |  105|   125k|  -0.00535661f,
  |  |  106|   125k|  -0.00429145f,
  |  |  107|   125k|  -0.00343131f,
  |  |  108|   125k|  0.0356439f,
  |  |  109|   125k|  0.00865645f,
  |  |  110|   125k|  0.00165229f,
  |  |  111|   125k|  -0.00425931f,
  |  |  112|   125k|  -0.00507324f,
  |  |  113|   125k|  -0.00459083f,
  |  |  114|   125k|  -0.003703f,
  |  |  115|   125k|  -0.00310327f,
  |  |  116|   125k|  0.0121926f,
  |  |  117|   125k|  -0.0009259f,
  |  |  118|   125k|  -0.00330991f,
  |  |  119|   125k|  -0.00499378f,
  |  |  120|   125k|  -0.00437381f,
  |  |  121|   125k|  -0.00377427f,
  |  |  122|   125k|  -0.00311731f,
  |  |  123|   125k|  -0.00255125f,
  |  |  124|   125k|  -0.000320593f,
  |  |  125|   125k|  -0.00426043f,
  |  |  126|   125k|  -0.00416549f,
  |  |  127|   125k|  -0.00419364f,
  |  |  128|   125k|  -0.00365418f,
  |  |  129|   125k|  -0.00317499f,
  |  |  130|   125k|  -0.00255932f,
  |  |  131|   125k|  -0.00217917f,
  |  |  132|   125k|  0.0f,
  |  |  133|   125k|  0.143471f,
  |  |  134|   125k|  0.124336f,
  |  |  135|   125k|  0.0947465f,
  |  |  136|   125k|  0.0814066f,
  |  |  137|   125k|  0.0686776f,
  |  |  138|   125k|  0.0588122f,
  |  |  139|   125k|  0.0374415f,
  |  |  140|   125k|  0.146315f,
  |  |  141|   125k|  0.105334f,
  |  |  142|   125k|  0.0949415f,
  |  |  143|   125k|  0.0784241f,
  |  |  144|   125k|  0.0689064f,
  |  |  145|   125k|  0.0588304f,
  |  |  146|   125k|  0.0495961f,
  |  |  147|   125k|  0.0202342f,
  |  |  148|   125k|  0.123818f,
  |  |  149|   125k|  0.0952654f,
  |  |  150|   125k|  0.0860556f,
  |  |  151|   125k|  0.0724158f,
  |  |  152|   125k|  0.0628307f,
  |  |  153|   125k|  0.0529965f,
  |  |  154|   125k|  0.0353941f,
  |  |  155|   125k|  0.00815821f,
  |  |  156|   125k|  0.097054f,
  |  |  157|   125k|  0.080422f,
  |  |  158|   125k|  0.0731085f,
  |  |  159|   125k|  0.0636154f,
  |  |  160|   125k|  0.055606f,
  |  |  161|   125k|  0.0384127f,
  |  |  162|   125k|  0.0142879f,
  |  |  163|   125k|  0.00105195f,
  |  |  164|   125k|  0.0849312f,
  |  |  165|   125k|  0.071115f,
  |  |  166|   125k|  0.0631183f,
  |  |  167|   125k|  0.0552972f,
  |  |  168|   125k|  0.0369221f,
  |  |  169|   125k|  0.00798314f,
  |  |  170|   125k|  0.000716374f,
  |  |  171|   125k|  -0.00200948f,
  |  |  172|   125k|  0.0722298f,
  |  |  173|   125k|  0.0599559f,
  |  |  174|   125k|  0.054841f,
  |  |  175|   125k|  0.0387529f,
  |  |  176|   125k|  0.0107262f,
  |  |  177|   125k|  0.000355315f,
  |  |  178|   125k|  -0.00244803f,
  |  |  179|   125k|  -0.00335222f,
  |  |  180|   125k|  0.0635335f,
  |  |  181|   125k|  0.0514196f,
  |  |  182|   125k|  0.0406309f,
  |  |  183|   125k|  0.0125833f,
  |  |  184|   125k|  0.00151305f,
  |  |  185|   125k|  -0.00140269f,
  |  |  186|   125k|  -0.00362547f,
  |  |  187|   125k|  -0.00337649f,
  |  |  188|   125k|  0.0472024f,
  |  |  189|   125k|  0.0198725f,
  |  |  190|   125k|  0.0113437f,
  |  |  191|   125k|  0.00266305f,
  |  |  192|   125k|  -0.00137183f,
  |  |  193|   125k|  -0.00354158f,
  |  |  194|   125k|  -0.00341292f,
  |  |  195|   125k|  -0.00290074f
  |  |  196|   125k|};
  |  |  197|       |
  |  |  198|   125k|static const float bias[192] = {
  |  |  199|   125k|  0.0f,
  |  |  200|   125k|  0.0f,
  |  |  201|   125k|  0.0f,
  |  |  202|   125k|  0.0f,
  |  |  203|   125k|  0.0f,
  |  |  204|   125k|  0.0f,
  |  |  205|   125k|  0.0f,
  |  |  206|   125k|  0.0f,
  |  |  207|   125k|  0.0f,
  |  |  208|   125k|  0.0f,
  |  |  209|   125k|  0.0f,
  |  |  210|   125k|  0.0f,
  |  |  211|   125k|  0.0f,
  |  |  212|   125k|  0.0f,
  |  |  213|   125k|  0.0f,
  |  |  214|   125k|  0.0f,
  |  |  215|   125k|  0.0f,
  |  |  216|   125k|  0.0f,
  |  |  217|   125k|  0.0f,
  |  |  218|   125k|  0.0f,
  |  |  219|   125k|  0.0f,
  |  |  220|   125k|  0.0f,
  |  |  221|   125k|  0.0f,
  |  |  222|   125k|  0.0f,
  |  |  223|   125k|  0.0f,
  |  |  224|   125k|  0.0f,
  |  |  225|   125k|  0.0f,
  |  |  226|   125k|  0.0f,
  |  |  227|   125k|  0.0f,
  |  |  228|   125k|  0.0f,
  |  |  229|   125k|  0.0f,
  |  |  230|   125k|  0.0f,
  |  |  231|   125k|  0.0f,
  |  |  232|   125k|  0.0f,
  |  |  233|   125k|  0.0f,
  |  |  234|   125k|  0.0f,
  |  |  235|   125k|  0.0f,
  |  |  236|   125k|  0.0f,
  |  |  237|   125k|  0.0f,
  |  |  238|   125k|  0.0f,
  |  |  239|   125k|  0.0f,
  |  |  240|   125k|  0.0f,
  |  |  241|   125k|  0.0f,
  |  |  242|   125k|  0.0f,
  |  |  243|   125k|  0.0f,
  |  |  244|   125k|  0.0f,
  |  |  245|   125k|  0.0f,
  |  |  246|   125k|  0.0f,
  |  |  247|   125k|  0.0f,
  |  |  248|   125k|  0.0f,
  |  |  249|   125k|  0.0f,
  |  |  250|   125k|  0.0f,
  |  |  251|   125k|  0.0f,
  |  |  252|   125k|  0.0f,
  |  |  253|   125k|  0.0f,
  |  |  254|   125k|  0.0f,
  |  |  255|   125k|  0.0f,
  |  |  256|   125k|  0.0f,
  |  |  257|   125k|  0.0f,
  |  |  258|   125k|  0.0f,
  |  |  259|   125k|  0.0f,
  |  |  260|   125k|  0.0f,
  |  |  261|   125k|  0.0f,
  |  |  262|   125k|  0.0f,
  |  |  263|   125k|  0.0f,
  |  |  264|   125k|  0.0f,
  |  |  265|   125k|  0.0f,
  |  |  266|   125k|  0.0f,
  |  |  267|   125k|  0.0f,
  |  |  268|   125k|  0.0f,
  |  |  269|   125k|  0.0f,
  |  |  270|   125k|  0.0f,
  |  |  271|   125k|  0.0f,
  |  |  272|   125k|  0.0f,
  |  |  273|   125k|  0.0f,
  |  |  274|   125k|  0.0f,
  |  |  275|   125k|  0.0f,
  |  |  276|   125k|  0.0f,
  |  |  277|   125k|  0.0f,
  |  |  278|   125k|  0.0f,
  |  |  279|   125k|  0.0f,
  |  |  280|   125k|  0.0f,
  |  |  281|   125k|  0.0f,
  |  |  282|   125k|  0.0f,
  |  |  283|   125k|  0.0f,
  |  |  284|   125k|  0.0f,
  |  |  285|   125k|  0.0f,
  |  |  286|   125k|  0.0f,
  |  |  287|   125k|  0.0f,
  |  |  288|   125k|  0.0f,
  |  |  289|   125k|  0.0f,
  |  |  290|   125k|  0.0f,
  |  |  291|   125k|  0.0f,
  |  |  292|   125k|  0.0f,
  |  |  293|   125k|  0.0f,
  |  |  294|   125k|  0.0f,
  |  |  295|   125k|  0.0f,
  |  |  296|   125k|  0.0f,
  |  |  297|   125k|  0.0f,
  |  |  298|   125k|  0.0f,
  |  |  299|   125k|  0.0f,
  |  |  300|   125k|  0.0f,
  |  |  301|   125k|  0.0f,
  |  |  302|   125k|  0.0f,
  |  |  303|   125k|  0.0f,
  |  |  304|   125k|  0.0f,
  |  |  305|   125k|  0.0f,
  |  |  306|   125k|  0.0f,
  |  |  307|   125k|  0.0f,
  |  |  308|   125k|  0.0f,
  |  |  309|   125k|  0.0f,
  |  |  310|   125k|  0.0f,
  |  |  311|   125k|  0.0f,
  |  |  312|   125k|  0.0f,
  |  |  313|   125k|  0.0f,
  |  |  314|   125k|  0.0f,
  |  |  315|   125k|  0.0f,
  |  |  316|   125k|  0.0f,
  |  |  317|   125k|  0.0f,
  |  |  318|   125k|  0.0f,
  |  |  319|   125k|  0.0f,
  |  |  320|   125k|  0.0f,
  |  |  321|   125k|  0.0f,
  |  |  322|   125k|  0.0f,
  |  |  323|   125k|  0.0f,
  |  |  324|   125k|  0.0f,
  |  |  325|   125k|  0.0f,
  |  |  326|   125k|  0.0f,
  |  |  327|   125k|  0.0f,
  |  |  328|   125k|  0.0f,
  |  |  329|   125k|  0.0f,
  |  |  330|   125k|  0.0f,
  |  |  331|   125k|  0.0f,
  |  |  332|   125k|  0.0f,
  |  |  333|   125k|  0.0f,
  |  |  334|   125k|  0.0f,
  |  |  335|   125k|  0.0f,
  |  |  336|   125k|  0.0f,
  |  |  337|   125k|  0.0f,
  |  |  338|   125k|  0.0f,
  |  |  339|   125k|  0.0f,
  |  |  340|   125k|  0.0f,
  |  |  341|   125k|  0.0f,
  |  |  342|   125k|  0.0f,
  |  |  343|   125k|  0.0f,
  |  |  344|   125k|  0.0f,
  |  |  345|   125k|  0.0f,
  |  |  346|   125k|  0.0f,
  |  |  347|   125k|  0.0f,
  |  |  348|   125k|  0.0f,
  |  |  349|   125k|  0.0f,
  |  |  350|   125k|  0.0f,
  |  |  351|   125k|  0.0f,
  |  |  352|   125k|  0.0f,
  |  |  353|   125k|  0.0f,
  |  |  354|   125k|  0.0f,
  |  |  355|   125k|  0.0f,
  |  |  356|   125k|  0.0f,
  |  |  357|   125k|  0.0f,
  |  |  358|   125k|  0.0f,
  |  |  359|   125k|  0.0f,
  |  |  360|   125k|  0.0f,
  |  |  361|   125k|  0.0f,
  |  |  362|   125k|  0.0f,
  |  |  363|   125k|  0.0f,
  |  |  364|   125k|  0.0f,
  |  |  365|   125k|  0.0f,
  |  |  366|   125k|  0.0f,
  |  |  367|   125k|  0.0f,
  |  |  368|   125k|  0.0f,
  |  |  369|   125k|  0.0f,
  |  |  370|   125k|  0.0f,
  |  |  371|   125k|  0.0f,
  |  |  372|   125k|  0.0f,
  |  |  373|   125k|  0.0f,
  |  |  374|   125k|  0.0f,
  |  |  375|   125k|  0.0f,
  |  |  376|   125k|  0.0f,
  |  |  377|   125k|  0.0f,
  |  |  378|   125k|  0.0f,
  |  |  379|   125k|  0.0f,
  |  |  380|   125k|  0.0f,
  |  |  381|   125k|  0.0f,
  |  |  382|   125k|  0.0f,
  |  |  383|   125k|  0.0f,
  |  |  384|   125k|  0.0f,
  |  |  385|   125k|  0.0f,
  |  |  386|   125k|  0.0f,
  |  |  387|   125k|  0.0f,
  |  |  388|   125k|  0.0f,
  |  |  389|   125k|  0.0f,
  |  |  390|   125k|  0.0
  |  |  391|   125k|};
  ------------------
  381|   125k|  std::vector<std::pair<int, float> > input_order;
  382|   500k|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (382:19): [True: 375k, False: 125k]
  ------------------
  383|   375k|    if (!(comp_mask & (1 << c))) continue;
  ------------------
  |  Branch (383:9): [True: 174k, False: 201k]
  ------------------
  384|  12.8M|    for (int k = 1; k < kDCTBlockSize; ++k) {
  ------------------
  |  Branch (384:21): [True: 12.6M, False: 201k]
  ------------------
  385|  12.6M|      int idx = c * kDCTBlockSize + k;
  386|  12.6M|      if (block[idx] != 0) {
  ------------------
  |  Branch (386:11): [True: 1.87M, False: 10.8M]
  ------------------
  387|  1.87M|        float score;
  388|  1.87M|        if (params_.new_zeroing_model) {
  ------------------
  |  Branch (388:13): [True: 1.87M, False: 0]
  ------------------
  389|  1.87M|          score = std::abs(orig_block[idx]) * csf[idx] + bias[idx];
  390|  1.87M|        } else {
  391|      0|          score = static_cast<float>((std::abs(orig_block[idx]) - kJPEGZigZagOrder[k] / 64.0) *
  392|      0|                  kWeight[c] / oldCsf[k]);
  393|      0|        }
  394|  1.87M|        input_order.push_back(std::make_pair(idx, score));
  395|  1.87M|      }
  396|  12.6M|    }
  397|   201k|  }
  398|   125k|  std::sort(input_order.begin(), input_order.end(),
  399|   125k|            [](const std::pair<int, float>& a, const std::pair<int, float>& b) {
  400|   125k|              return a.second < b.second; });
  401|   125k|  coeff_t processed_block[kBlockSize];
  402|   125k|  memcpy(processed_block, block, sizeof(processed_block));
  403|   125k|  comparator_->SwitchBlock(block_x, block_y, factor_x, factor_y);
  404|  1.99M|  while (!input_order.empty()) {
  ------------------
  |  Branch (404:10): [True: 1.87M, False: 125k]
  ------------------
  405|  1.87M|    float best_err = 1e17f;
  406|  1.87M|    int best_i = 0;
  407|  7.32M|    for (size_t i = 0; i < std::min<size_t>(params_.zeroing_greedy_lookahead,
  ------------------
  |  Branch (407:24): [True: 5.45M, False: 1.87M]
  ------------------
  408|  7.32M|                                         input_order.size());
  409|  5.45M|         ++i) {
  410|  5.45M|      coeff_t candidate_block[kBlockSize];
  411|  5.45M|      memcpy(candidate_block, processed_block, sizeof(candidate_block));
  412|  5.45M|      const int idx = input_order[i].first;
  413|  5.45M|      candidate_block[idx] = 0;
  414|  21.8M|      for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (414:23): [True: 16.3M, False: 5.45M]
  ------------------
  415|  16.3M|        if (comp_mask & (1 << c)) {
  ------------------
  |  Branch (415:13): [True: 11.9M, False: 4.38M]
  ------------------
  416|  11.9M|          img->component(c).SetCoeffBlock(
  417|  11.9M|              block_x, block_y, &candidate_block[c * kDCTBlockSize]);
  418|  11.9M|        }
  419|  16.3M|      }
  420|  5.45M|      float max_err = 0;
  421|  11.1M|      for (int iy = 0; iy < factor_y; ++iy) {
  ------------------
  |  Branch (421:24): [True: 5.68M, False: 5.45M]
  ------------------
  422|  11.8M|        for (int ix = 0; ix < factor_x; ++ix) {
  ------------------
  |  Branch (422:26): [True: 6.15M, False: 5.68M]
  ------------------
  423|  6.15M|          int block_xx = block_x * factor_x + ix;
  424|  6.15M|          int block_yy = block_y * factor_y + iy;
  425|  6.15M|          if (8 * block_xx < img->width() && 8 * block_yy < img->height()) {
  ------------------
  |  Branch (425:15): [True: 6.08M, False: 68.4k]
  |  Branch (425:46): [True: 6.00M, False: 74.6k]
  ------------------
  426|  6.00M|            float err = static_cast<float>(comparator_->CompareBlock(*img, ix, iy));
  427|  6.00M|            max_err = std::max(max_err, err);
  428|  6.00M|          }
  429|  6.15M|        }
  430|  5.68M|      }
  431|  5.45M|      if (max_err < best_err) {
  ------------------
  |  Branch (431:11): [True: 3.93M, False: 1.51M]
  ------------------
  432|  3.93M|        best_err = max_err;
  433|  3.93M|        best_i = i;
  434|  3.93M|      }
  435|  5.45M|    }
  436|  1.87M|    int idx = input_order[best_i].first;
  437|  1.87M|    processed_block[idx] = 0;
  438|  1.87M|    input_order.erase(input_order.begin() + best_i);
  439|  1.87M|    output_order->push_back({idx, best_err});
  440|  7.49M|    for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (440:21): [True: 5.61M, False: 1.87M]
  ------------------
  441|  5.61M|      if (comp_mask & (1 << c)) {
  ------------------
  |  Branch (441:11): [True: 4.09M, False: 1.52M]
  ------------------
  442|  4.09M|        img->component(c).SetCoeffBlock(
  443|  4.09M|            block_x, block_y, &processed_block[c * kDCTBlockSize]);
  444|  4.09M|      }
  445|  5.61M|    }
  446|  1.87M|  }
  447|       |  // Make the block error values monotonic.
  448|   125k|  float min_err = 1e10;
  449|  1.99M|  for (int i = output_order->size() - 1; i >= 0; --i) {
  ------------------
  |  Branch (449:42): [True: 1.87M, False: 125k]
  ------------------
  450|  1.87M|    min_err = std::min(min_err, (*output_order)[i].block_err);
  451|  1.87M|    (*output_order)[i].block_err = min_err;
  452|  1.87M|  }
  453|       |  // Cut off at the block error limit.
  454|   125k|  size_t num = 0;
  455|  1.44M|  while (num < output_order->size() &&
  ------------------
  |  Branch (455:10): [True: 1.35M, False: 84.3k]
  ------------------
  456|  1.35M|         (*output_order)[num].block_err <= comparator_->BlockErrorLimit()) {
  ------------------
  |  Branch (456:10): [True: 1.31M, False: 40.8k]
  ------------------
  457|  1.31M|    ++num;
  458|  1.31M|  }
  459|   125k|  output_order->resize(num);
  460|       |  // Restore *img to the same state as it was at the start of this function.
  461|   500k|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (461:19): [True: 375k, False: 125k]
  ------------------
  462|   375k|    if (comp_mask & (1 << c)) {
  ------------------
  |  Branch (462:9): [True: 201k, False: 174k]
  ------------------
  463|   201k|      img->component(c).SetCoeffBlock(
  464|   201k|          block_x, block_y, &block[c * kDCTBlockSize]);
  465|   201k|    }
  466|   375k|  }
  467|   125k|}
processor.cc:_ZZN7guetzli12_GLOBAL__N_19Processor24ComputeBlockZeroingOrderEPKsS3_iiiihPNS_11OutputImageEPNSt3__16vectorINS0_9CoeffDataENS6_9allocatorIS8_EEEEENK3$_0clERKNS6_4pairIifEESH_:
  399|  13.4M|            [](const std::pair<int, float>& a, const std::pair<int, float>& b) {
  400|  13.4M|              return a.second < b.second; });
processor.cc:_ZN7guetzli12_GLOBAL__N_114EstimateDCSizeERKNS_8JPEGDataE:
  528|  3.56k|size_t EstimateDCSize(const JPEGData& jpg) {
  529|  3.56k|  std::vector<JpegHistogram> histograms(jpg.components.size());
  530|  3.56k|  BuildDCHistograms(jpg, &histograms[0]);
  531|  3.56k|  size_t num = histograms.size();
  532|  3.56k|  std::vector<int> indexes(num);
  533|  3.56k|  std::vector<uint8_t> depths(num * JpegHistogram::kSize);
  534|  3.56k|  return ClusterHistograms(&histograms[0], &num, &indexes[0], &depths[0]);
  535|  3.56k|}
processor.cc:_ZN7guetzli12_GLOBAL__N_119ComputeEntropyCodesERKNSt3__16vectorINS_13JpegHistogramENS1_9allocatorIS3_EEEEPNS2_IhNS4_IhEEEE:
  498|   239k|                           std::vector<uint8_t>* depths) {
  499|   239k|  std::vector<JpegHistogram> clustered = histograms;
  500|   239k|  size_t num = histograms.size();
  501|   239k|  std::vector<int> indexes(histograms.size());
  502|   239k|  std::vector<uint8_t> clustered_depths(
  503|   239k|      histograms.size() * JpegHistogram::kSize);
  504|   239k|  ClusterHistograms(&clustered[0], &num, &indexes[0], &clustered_depths[0]);
  505|   239k|  depths->resize(clustered_depths.size());
  506|   902k|  for (size_t i = 0; i < histograms.size(); ++i) {
  ------------------
  |  Branch (506:22): [True: 662k, False: 239k]
  ------------------
  507|   662k|    memcpy(&(*depths)[i * JpegHistogram::kSize],
  508|   662k|           &clustered_depths[indexes[i] * JpegHistogram::kSize],
  509|   662k|           JpegHistogram::kSize);
  510|   662k|  }
  511|   239k|  size_t histogram_size = 0;
  512|   550k|  for (size_t i = 0; i < num; ++i) {
  ------------------
  |  Branch (512:22): [True: 311k, False: 239k]
  ------------------
  513|   311k|    histogram_size += HistogramHeaderCost(clustered[i]) / 8;
  514|   311k|  }
  515|   239k|  return histogram_size;
  516|   239k|}
processor.cc:_ZN7guetzli12_GLOBAL__N_120EntropyCodedDataSizeERKNSt3__16vectorINS_13JpegHistogramENS1_9allocatorIS3_EEEERKNS2_IhNS4_IhEEEE:
  519|  1.74M|                            const std::vector<uint8_t>& depths) {
  520|  1.74M|  size_t numbits = 0;
  521|  6.61M|  for (size_t i = 0; i < histograms.size(); ++i) {
  ------------------
  |  Branch (521:22): [True: 4.87M, False: 1.74M]
  ------------------
  522|  4.87M|    numbits += HistogramEntropyCost(
  523|  4.87M|        histograms[i], &depths[i * JpegHistogram::kSize]);
  524|  4.87M|  }
  525|  1.74M|  return (numbits + 7) / 8;
  526|  1.74M|}
processor.cc:_ZZN7guetzli12_GLOBAL__N_19Processor22SelectFrequencyMaskingERKNS_8JPEGDataEPNS_11OutputImageEhdbENK3$_0clERKNSt3__14pairIifEESC_:
  677|   672M|                   const std::pair<int, float>& b) {
  678|   672M|                  return a.second < b.second; });
processor.cc:_ZZN7guetzli12_GLOBAL__N_19Processor22SelectFrequencyMaskingERKNS_8JPEGDataEPNS_11OutputImageEhdbENK3$_1clERKNSt3__14pairIifEE:
  693|  16.4k|                                       [=](const std::pair<int, float>& a) {
  694|  16.4k|                                         return a.second < limit; });
processor.cc:_ZN7guetzli12_GLOBAL__N_117UpdateACHistogramEiPKsPKiPNS_13JpegHistogramE:
  474|  3.47M|                       JpegHistogram* ac_histogram) {
  475|  3.47M|  int r = 0;
  476|   222M|  for (int k = 1; k < 64; ++k) {
  ------------------
  |  Branch (476:19): [True: 218M, False: 3.47M]
  ------------------
  477|   218M|    const int k_nat = kJPEGNaturalOrder[k];
  478|   218M|    coeff_t coeff = coeffs[k_nat];
  479|   218M|    if (coeff == 0) {
  ------------------
  |  Branch (479:9): [True: 123M, False: 95.2M]
  ------------------
  480|   123M|      r++;
  481|   123M|      continue;
  482|   123M|    }
  483|  97.0M|    while (r > 15) {
  ------------------
  |  Branch (483:12): [True: 1.75M, False: 95.2M]
  ------------------
  484|  1.75M|      ac_histogram->Add(0xf0, weight);
  485|  1.75M|      r -= 16;
  486|  1.75M|    }
  487|  95.2M|    int nbits = Log2FloorNonZero(std::abs(coeff / q[k_nat])) + 1;
  488|  95.2M|    int symbol = (r << 4) + nbits;
  489|  95.2M|    ac_histogram->Add(symbol, weight);
  490|  95.2M|    r = 0;
  491|  95.2M|  }
  492|  3.47M|  if (r > 0) {
  ------------------
  |  Branch (492:7): [True: 2.64M, False: 833k]
  ------------------
  493|  2.64M|    ac_histogram->Add(0, weight);
  494|  2.64M|  }
  495|  3.47M|}
processor.cc:_ZN7guetzli12_GLOBAL__N_115CheckJpegSanityERKNS_8JPEGDataE:
  106|  2.68k|bool CheckJpegSanity(const JPEGData& jpg) {
  107|  2.68k|  const int kMaxComponent = 1 << 12;
  108|  7.87k|  for (const JPEGComponent& comp : jpg.components) {
  ------------------
  |  Branch (108:34): [True: 7.87k, False: 2.67k]
  ------------------
  109|  7.87k|    const JPEGQuantTable& quant_table = jpg.quant[comp.quant_idx];
  110|  31.8M|    for (int i = 0; i < comp.coeffs.size(); i++) {
  ------------------
  |  Branch (110:21): [True: 31.8M, False: 7.86k]
  ------------------
  111|  31.8M|      coeff_t coeff = comp.coeffs[i];
  112|  31.8M|      int quant = quant_table.values[i % kDCTBlockSize];
  113|  31.8M|      if (std::abs(static_cast<int64_t>(coeff) * quant) > kMaxComponent) {
  ------------------
  |  Branch (113:11): [True: 9, False: 31.8M]
  ------------------
  114|      9|        return false;
  115|      9|      }
  116|  31.8M|    }
  117|  7.87k|  }
  118|  2.67k|  return true;
  119|  2.68k|}

_ZN7guetzli13QuantizeBlockEPsPKi:
   22|  3.08M|                   const int q[kDCTBlockSize]) {
   23|  3.08M|  bool changed = false;
   24|   200M|  for (int k = 0; k < kDCTBlockSize; ++k) {
  ------------------
  |  Branch (24:19): [True: 197M, False: 3.08M]
  ------------------
   25|   197M|    coeff_t coeff = Quantize(block[k], q[k]);
   26|   197M|    changed = changed || (coeff != block[k]);
  ------------------
  |  Branch (26:15): [True: 62.6M, False: 135M]
  |  Branch (26:26): [True: 1.11M, False: 133M]
  ------------------
   27|   197M|    block[k] = coeff;
   28|   197M|  }
   29|  3.08M|  return changed;
   30|  3.08M|}

_ZN7guetzli8QuantizeEsi:
   24|   198M|inline coeff_t Quantize(coeff_t raw_coeff, int quant) {
   25|   198M|  const int r = raw_coeff % quant;
   26|   198M|  const coeff_t delta =
   27|   198M|      2 * r > quant ? quant - r : (-2) * r > quant ? -quant - r : -r;
  ------------------
  |  Branch (27:7): [True: 1.60M, False: 196M]
  |  Branch (27:35): [True: 9.50M, False: 187M]
  ------------------
   28|   198M|  return raw_coeff + delta;
   29|   198M|}

_ZN7guetzli9ScoreJPEGEdid:
   24|   143k|                 double butteraugli_target) {
   25|   143k|  constexpr double kScale = 50;
   26|   143k|  constexpr double kMaxExponent = 10;
   27|   143k|  constexpr double kLargeSize = 1e30;
   28|       |  // TODO(user): The score should also depend on distance below target (and be
   29|       |  // smooth).
   30|   143k|  double diff = butteraugli_distance - butteraugli_target;
   31|   143k|  if (diff <= 0.0) {
  ------------------
  |  Branch (31:7): [True: 34.1k, False: 109k]
  ------------------
   32|  34.1k|    return size;
   33|   109k|  } else {
   34|   109k|    double exponent = kScale * diff;
   35|   109k|    if (exponent > kMaxExponent) {
  ------------------
  |  Branch (35:9): [True: 94.2k, False: 15.2k]
  ------------------
   36|  94.2k|      return kLargeSize * std::exp(kMaxExponent) * diff + size;
   37|  94.2k|    } else {
   38|  15.2k|      return std::exp(exponent) * size;
   39|  15.2k|    }
   40|   109k|  }
   41|   143k|}

_ZN7guetzli12ProcessStatsC2Ev:
   34|  2.65k|  ProcessStats() {}

_ZN11butteraugli12CacheAligned8AllocateEm:
   60|  86.0M|void *CacheAligned::Allocate(const size_t bytes) {
   61|  86.0M|  char *const allocated = static_cast<char *>(malloc(bytes + kCacheLineSize));
   62|  86.0M|  if (allocated == nullptr) {
  ------------------
  |  Branch (62:7): [True: 0, False: 86.0M]
  ------------------
   63|      0|    return nullptr;
   64|      0|  }
   65|  86.0M|  const uintptr_t misalignment =
   66|  86.0M|      reinterpret_cast<uintptr_t>(allocated) & (kCacheLineSize - 1);
   67|       |  // malloc is at least kPointerSize aligned, so we can store the "allocated"
   68|       |  // pointer immediately before the aligned memory.
   69|  86.0M|  assert(misalignment % kPointerSize == 0);
  ------------------
  |  Branch (69:3): [True: 86.0M, False: 0]
  ------------------
   70|  86.0M|  char *const aligned = allocated + kCacheLineSize - misalignment;
   71|  86.0M|  memcpy(aligned - kPointerSize, &allocated, kPointerSize);
   72|  86.0M|  return BUTTERAUGLI_ASSUME_ALIGNED(aligned, 64);
  ------------------
  |  |  137|  86.0M|#define BUTTERAUGLI_ASSUME_ALIGNED(ptr, align) __builtin_assume_aligned((ptr), (align))
  ------------------
   73|  86.0M|}
_ZN11butteraugli12CacheAligned4FreeEPv:
   75|  86.0M|void CacheAligned::Free(void *aligned_pointer) {
   76|  86.0M|  if (aligned_pointer == nullptr) {
  ------------------
  |  Branch (76:7): [True: 0, False: 86.0M]
  ------------------
   77|      0|    return;
   78|      0|  }
   79|  86.0M|  char *const aligned = static_cast<char *>(aligned_pointer);
   80|  86.0M|  assert(reinterpret_cast<uintptr_t>(aligned) % kCacheLineSize == 0);
  ------------------
  |  Branch (80:3): [True: 86.0M, False: 0]
  ------------------
   81|  86.0M|  char *allocated;
   82|  86.0M|  memcpy(&allocated, aligned - kPointerSize, kPointerSize);
   83|  86.0M|  assert(allocated <= aligned - kPointerSize);
  ------------------
  |  Branch (83:3): [True: 86.0M, False: 0]
  ------------------
   84|  86.0M|  assert(allocated >= aligned - kCacheLineSize);
  ------------------
  |  Branch (84:3): [True: 86.0M, False: 0]
  ------------------
   85|  86.0M|  free(allocated);
   86|  86.0M|}
_ZN11butteraugli13ComputeKernelEf:
  145|  21.3M|std::vector<float> ComputeKernel(float sigma) {
  146|  21.3M|  const float m = 2.25;  // Accuracy increases when m is increased.
  147|  21.3M|  const float scaler = -1.0 / (2 * sigma * sigma);
  148|  21.3M|  const int diff = std::max<int>(1, m * fabs(sigma));
  149|  21.3M|  std::vector<float> kernel(2 * diff + 1);
  150|   164M|  for (int i = -diff; i <= diff; ++i) {
  ------------------
  |  Branch (150:23): [True: 143M, False: 21.3M]
  ------------------
  151|   143M|    kernel[i + diff] = exp(scaler * i * i);
  152|   143M|  }
  153|  21.3M|  return kernel;
  154|  21.3M|}
_ZN11butteraugli20ConvolveBorderColumnERKNS_5ImageIfEERKNSt3__16vectorIfNS4_9allocatorIfEEEEffmPf:
  162|   243M|    float* const BUTTERAUGLI_RESTRICT row_out) {
  163|   243M|  const int offset = kernel.size() / 2;
  164|   243M|  int minx = x < offset ? 0 : x - offset;
  ------------------
  |  Branch (164:14): [True: 126M, False: 117M]
  ------------------
  165|   243M|  int maxx = std::min<int>(in.xsize() - 1, x + offset);
  166|   243M|  float weight = 0.0f;
  167|  2.84G|  for (int j = minx; j <= maxx; ++j) {
  ------------------
  |  Branch (167:22): [True: 2.59G, False: 243M]
  ------------------
  168|  2.59G|    weight += kernel[j - x + offset];
  169|  2.59G|  }
  170|       |  // Interpolate linearly between the no-border scaling and border scaling.
  171|   243M|  weight = (1.0f - border_ratio) * weight + border_ratio * weight_no_border;
  172|   243M|  float scale = 1.0f / weight;
  173|  5.98G|  for (size_t y = 0; y < in.ysize(); ++y) {
  ------------------
  |  Branch (173:22): [True: 5.74G, False: 243M]
  ------------------
  174|  5.74G|    const float* const BUTTERAUGLI_RESTRICT row_in = in.Row(y);
  175|  5.74G|    float sum = 0.0f;
  176|   109G|    for (int j = minx; j <= maxx; ++j) {
  ------------------
  |  Branch (176:24): [True: 104G, False: 5.74G]
  ------------------
  177|   104G|      sum += row_in[j] * kernel[j - x + offset];
  178|   104G|    }
  179|  5.74G|    row_out[y] = sum * scale;
  180|  5.74G|  }
  181|   243M|}
_ZN11butteraugli11ConvolutionERKNS_5ImageIfEERKNSt3__16vectorIfNS4_9allocatorIfEEEEf:
  186|  42.6M|                   const float border_ratio) {
  187|  42.6M|  ImageF out(in.ysize(), in.xsize());
  188|  42.6M|  const int len = kernel.size();
  189|  42.6M|  const int offset = kernel.size() / 2;
  190|  42.6M|  float weight_no_border = 0.0f;
  191|   328M|  for (int j = 0; j < len; ++j) {
  ------------------
  |  Branch (191:19): [True: 286M, False: 42.6M]
  ------------------
  192|   286M|    weight_no_border += kernel[j];
  193|   286M|  }
  194|  42.6M|  float scale_no_border = 1.0f / weight_no_border;
  195|  42.6M|  const int border1 = in.xsize() <= offset ? in.xsize() : offset;
  ------------------
  |  Branch (195:23): [True: 0, False: 42.6M]
  ------------------
  196|  42.6M|  const int border2 = in.xsize() - offset;
  197|  42.6M|  std::vector<float> scaled_kernel = kernel;
  198|   328M|  for (int i = 0; i < scaled_kernel.size(); ++i) {
  ------------------
  |  Branch (198:19): [True: 286M, False: 42.6M]
  ------------------
  199|   286M|    scaled_kernel[i] *= scale_no_border;
  200|   286M|  }
  201|       |  // left border
  202|   164M|  for (int x = 0; x < border1; ++x) {
  ------------------
  |  Branch (202:19): [True: 121M, False: 42.6M]
  ------------------
  203|   121M|    ConvolveBorderColumn(in, kernel, weight_no_border, border_ratio, x,
  204|   121M|                         out.Row(x));
  205|   121M|  }
  206|       |  // middle
  207|   604M|  for (size_t y = 0; y < in.ysize(); ++y) {
  ------------------
  |  Branch (207:22): [True: 562M, False: 42.6M]
  ------------------
  208|   562M|    const float* const BUTTERAUGLI_RESTRICT row_in = in.Row(y);
  209|  10.3G|    for (int x = border1; x < border2; ++x) {
  ------------------
  |  Branch (209:27): [True: 9.82G, False: 562M]
  ------------------
  210|  9.82G|      const int d = x - offset;
  211|  9.82G|      float* const BUTTERAUGLI_RESTRICT row_out = out.Row(x);
  212|  9.82G|      float sum = 0.0f;
  213|   122G|      for (int j = 0; j < len; ++j) {
  ------------------
  |  Branch (213:23): [True: 112G, False: 9.82G]
  ------------------
  214|   112G|        sum += row_in[d + j] * scaled_kernel[j];
  215|   112G|      }
  216|  9.82G|      row_out[y] = sum;
  217|  9.82G|    }
  218|   562M|  }
  219|       |  // right border
  220|   164M|  for (int x = border2; x < in.xsize(); ++x) {
  ------------------
  |  Branch (220:25): [True: 121M, False: 42.6M]
  ------------------
  221|   121M|    ConvolveBorderColumn(in, kernel, weight_no_border, border_ratio, x,
  222|   121M|                         out.Row(x));
  223|   121M|  }
  224|  42.6M|  return out;
  225|  42.6M|}
_ZN11butteraugli4BlurERKNS_5ImageIfEEff:
  229|  21.3M|ImageF Blur(const ImageF& in, float sigma, float border_ratio) {
  230|  21.3M|  std::vector<float> kernel = ComputeKernel(sigma);
  231|  21.3M|  return Convolution(Convolution(in, kernel, border_ratio),
  232|  21.3M|                     kernel, border_ratio);
  233|  21.3M|}
_ZN11butteraugli18OpsinDynamicsImageERKNSt3__16vectorINS_5ImageIfEENS0_9allocatorIS3_EEEE:
  324|  6.47M|std::vector<ImageF> OpsinDynamicsImage(const std::vector<ImageF>& rgb) {
  325|  6.47M|  PROFILER_FUNC;
  326|  6.47M|  std::vector<ImageF> xyb(3);
  327|  6.47M|  std::vector<ImageF> blurred(3);
  328|  6.47M|  const double kSigma = 1.2;
  329|  25.8M|  for (int i = 0; i < 3; ++i) {
  ------------------
  |  Branch (329:19): [True: 19.4M, False: 6.47M]
  ------------------
  330|  19.4M|    xyb[i] = ImageF(rgb[i].xsize(), rgb[i].ysize());
  331|  19.4M|    blurred[i] = Blur(rgb[i], kSigma, 0.0f);
  332|  19.4M|  }
  333|  69.3M|  for (size_t y = 0; y < rgb[0].ysize(); ++y) {
  ------------------
  |  Branch (333:22): [True: 62.9M, False: 6.47M]
  ------------------
  334|  62.9M|    const float* const BUTTERAUGLI_RESTRICT row_r = rgb[0].Row(y);
  335|  62.9M|    const float* const BUTTERAUGLI_RESTRICT row_g = rgb[1].Row(y);
  336|  62.9M|    const float* const BUTTERAUGLI_RESTRICT row_b = rgb[2].Row(y);
  337|  62.9M|    const float* const BUTTERAUGLI_RESTRICT row_blurred_r = blurred[0].Row(y);
  338|  62.9M|    const float* const BUTTERAUGLI_RESTRICT row_blurred_g = blurred[1].Row(y);
  339|  62.9M|    const float* const BUTTERAUGLI_RESTRICT row_blurred_b = blurred[2].Row(y);
  340|  62.9M|    float* const BUTTERAUGLI_RESTRICT row_out_x = xyb[0].Row(y);
  341|  62.9M|    float* const BUTTERAUGLI_RESTRICT row_out_y = xyb[1].Row(y);
  342|  62.9M|    float* const BUTTERAUGLI_RESTRICT row_out_b = xyb[2].Row(y);
  343|  1.14G|    for (size_t x = 0; x < rgb[0].xsize(); ++x) {
  ------------------
  |  Branch (343:24): [True: 1.08G, False: 62.9M]
  ------------------
  344|  1.08G|      float sensitivity[3];
  345|  1.08G|      {
  346|       |        // Calculate sensitivity based on the smoothed image gamma derivative.
  347|  1.08G|        float pre_mixed0, pre_mixed1, pre_mixed2;
  348|  1.08G|        OpsinAbsorbance(row_blurred_r[x], row_blurred_g[x], row_blurred_b[x],
  349|  1.08G|                        &pre_mixed0, &pre_mixed1, &pre_mixed2);
  350|       |        // TODO: use new polynomial to compute Gamma(x)/x derivative.
  351|  1.08G|        sensitivity[0] = Gamma(pre_mixed0) / pre_mixed0;
  352|  1.08G|        sensitivity[1] = Gamma(pre_mixed1) / pre_mixed1;
  353|  1.08G|        sensitivity[2] = Gamma(pre_mixed2) / pre_mixed2;
  354|  1.08G|      }
  355|  1.08G|      float cur_mixed0, cur_mixed1, cur_mixed2;
  356|  1.08G|      OpsinAbsorbance(row_r[x], row_g[x], row_b[x],
  357|  1.08G|                      &cur_mixed0, &cur_mixed1, &cur_mixed2);
  358|  1.08G|      cur_mixed0 *= sensitivity[0];
  359|  1.08G|      cur_mixed1 *= sensitivity[1];
  360|  1.08G|      cur_mixed2 *= sensitivity[2];
  361|  1.08G|      RgbToXyb(cur_mixed0, cur_mixed1, cur_mixed2,
  362|  1.08G|               &row_out_x[x], &row_out_y[x], &row_out_b[x]);
  363|  1.08G|    }
  364|  62.9M|  }
  365|  6.47M|  return xyb;
  366|  6.47M|}
_ZN11butteraugli16CalculateDiffmapERKNS_5ImageIfEE:
  718|   143k|ImageF CalculateDiffmap(const ImageF& diffmap_in) {
  719|   143k|  PROFILER_FUNC;
  720|       |  // Take square root.
  721|   143k|  ImageF diffmap(diffmap_in.xsize(), diffmap_in.ysize());
  722|   143k|  static const float kInitialSlope = 100.0f;
  723|  6.72M|  for (size_t y = 0; y < diffmap.ysize(); ++y) {
  ------------------
  |  Branch (723:22): [True: 6.57M, False: 143k]
  ------------------
  724|  6.57M|    const float* const BUTTERAUGLI_RESTRICT row_in = diffmap_in.Row(y);
  725|  6.57M|    float* const BUTTERAUGLI_RESTRICT row_out = diffmap.Row(y);
  726|   342M|    for (size_t x = 0; x < diffmap.xsize(); ++x) {
  ------------------
  |  Branch (726:24): [True: 335M, False: 6.57M]
  ------------------
  727|   335M|      const float orig_val = row_in[x];
  728|       |      // TODO(b/29974893): Until that is fixed do not call sqrt on very small
  729|       |      // numbers.
  730|   335M|      row_out[x] = (orig_val < (1.0f / (kInitialSlope * kInitialSlope))
  ------------------
  |  Branch (730:21): [True: 39.4M, False: 296M]
  ------------------
  731|   335M|                    ? kInitialSlope * orig_val
  732|   335M|                    : std::sqrt(orig_val));
  733|   335M|    }
  734|  6.57M|  }
  735|   143k|  {
  736|   143k|    static const double kSigma = 1.72547472444;
  737|   143k|    static const double mul1 = 0.458794906198;
  738|   143k|    static const float scale = 1.0f / (1.0f + mul1);
  739|   143k|    static const double border_ratio = 1.0; // 2.01209066992;
  740|   143k|    ImageF blurred = Blur(diffmap, kSigma, border_ratio);
  741|  6.72M|    for (int y = 0; y < diffmap.ysize(); ++y) {
  ------------------
  |  Branch (741:21): [True: 6.57M, False: 143k]
  ------------------
  742|  6.57M|      const float* const BUTTERAUGLI_RESTRICT row_blurred = blurred.Row(y);
  743|  6.57M|      float* const BUTTERAUGLI_RESTRICT row = diffmap.Row(y);
  744|   342M|      for (int x = 0; x < diffmap.xsize(); ++x) {
  ------------------
  |  Branch (744:23): [True: 335M, False: 6.57M]
  ------------------
  745|   335M|        row[x] += mul1 * row_blurred[x];
  746|   335M|        row[x] *= scale;
  747|   335M|      }
  748|  6.57M|    }
  749|   143k|  }
  750|   143k|  return diffmap;
  751|   143k|}
_ZN11butteraugli15MaskPsychoImageERKNS_11PsychoImageES2_mmPNSt3__16vectorINS_5ImageIfEENS3_9allocatorIS6_EEEESA_:
  756|   143k|                     std::vector<ImageF>* BUTTERAUGLI_RESTRICT mask_dc) {
  757|   143k|  std::vector<ImageF> mask_xyb0 = CreatePlanes<float>(xsize, ysize, 3);
  758|   143k|  std::vector<ImageF> mask_xyb1 = CreatePlanes<float>(xsize, ysize, 3);
  759|   143k|  static const double muls[4] = {
  760|   143k|    0,
  761|   143k|    1.64178305129,
  762|   143k|    0.831081703362,
  763|   143k|    3.23680933546,
  764|   143k|  };
  765|   431k|  for (int i = 0; i < 2; ++i) {
  ------------------
  |  Branch (765:19): [True: 287k, False: 143k]
  ------------------
  766|   287k|    double a = muls[2 * i];
  767|   287k|    double b = muls[2 * i + 1];
  768|  13.4M|    for (size_t y = 0; y < ysize; ++y) {
  ------------------
  |  Branch (768:24): [True: 13.1M, False: 287k]
  ------------------
  769|  13.1M|      const float* const BUTTERAUGLI_RESTRICT row_hf0 = pi0.hf[i].Row(y);
  770|  13.1M|      const float* const BUTTERAUGLI_RESTRICT row_hf1 = pi1.hf[i].Row(y);
  771|  13.1M|      const float* const BUTTERAUGLI_RESTRICT row_uhf0 = pi0.uhf[i].Row(y);
  772|  13.1M|      const float* const BUTTERAUGLI_RESTRICT row_uhf1 = pi1.uhf[i].Row(y);
  773|  13.1M|      float* const BUTTERAUGLI_RESTRICT row0 = mask_xyb0[i].Row(y);
  774|  13.1M|      float* const BUTTERAUGLI_RESTRICT row1 = mask_xyb1[i].Row(y);
  775|   684M|      for (size_t x = 0; x < xsize; ++x) {
  ------------------
  |  Branch (775:26): [True: 671M, False: 13.1M]
  ------------------
  776|   671M|        row0[x] = a * row_uhf0[x] + b * row_hf0[x];
  777|   671M|        row1[x] = a * row_uhf1[x] + b * row_hf1[x];
  778|   671M|      }
  779|  13.1M|    }
  780|   287k|  }
  781|   143k|  Mask(mask_xyb0, mask_xyb1, mask, mask_dc);
  782|   143k|}
_ZN11butteraugli21ButteraugliComparatorC2ERKNSt3__16vectorINS_5ImageIfEENS1_9allocatorIS4_EEEE:
  785|  2.54k|    : xsize_(rgb0[0].xsize()),
  786|  2.54k|      ysize_(rgb0[0].ysize()),
  787|  2.54k|      num_pixels_(xsize_ * ysize_) {
  788|  2.54k|  if (xsize_ < 8 || ysize_ < 8) return;
  ------------------
  |  Branch (788:7): [True: 0, False: 2.54k]
  |  Branch (788:21): [True: 0, False: 2.54k]
  ------------------
  789|  2.54k|  std::vector<ImageF> xyb0 = OpsinDynamicsImage(rgb0);
  790|  2.54k|  SeparateFrequencies(xsize_, ysize_, xyb0, pi0_);
  791|  2.54k|}
_ZNK11butteraugli21ButteraugliComparator7DiffmapERKNSt3__16vectorINS_5ImageIfEENS1_9allocatorIS4_EEEERS4_:
  800|   143k|                                    ImageF &result) const {
  801|   143k|  PROFILER_FUNC;
  802|   143k|  if (xsize_ < 8 || ysize_ < 8) return;
  ------------------
  |  Branch (802:7): [True: 0, False: 143k]
  |  Branch (802:21): [True: 0, False: 143k]
  ------------------
  803|   143k|  DiffmapOpsinDynamicsImage(OpsinDynamicsImage(rgb1), result);
  804|   143k|}
_ZNK11butteraugli21ButteraugliComparator25DiffmapOpsinDynamicsImageERKNSt3__16vectorINS_5ImageIfEENS1_9allocatorIS4_EEEERS4_:
  808|   143k|    ImageF &result) const {
  809|   143k|  PROFILER_FUNC;
  810|   143k|  if (xsize_ < 8 || ysize_ < 8) return;
  ------------------
  |  Branch (810:7): [True: 0, False: 143k]
  |  Branch (810:21): [True: 0, False: 143k]
  ------------------
  811|   143k|  PsychoImage pi1;
  812|   143k|  SeparateFrequencies(xsize_, ysize_, xyb1, pi1);
  813|   143k|  result = ImageF(xsize_, ysize_);
  814|   143k|  DiffmapPsychoImage(pi1, result);
  815|   143k|}
_ZNK11butteraugli21ButteraugliComparator18DiffmapPsychoImageERKNS_11PsychoImageERNS_5ImageIfEE:
  818|   143k|                                               ImageF& result) const {
  819|   143k|  PROFILER_FUNC;
  820|   143k|  const float hf_asymmetry_ = 0.8f;
  821|   143k|  if (xsize_ < 8 || ysize_ < 8) {
  ------------------
  |  Branch (821:7): [True: 0, False: 143k]
  |  Branch (821:21): [True: 0, False: 143k]
  ------------------
  822|      0|    return;
  823|      0|  }
  824|   143k|  std::vector<ImageF> block_diff_dc(3);
  825|   143k|  std::vector<ImageF> block_diff_ac(3);
  826|   574k|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (826:19): [True: 431k, False: 143k]
  ------------------
  827|   431k|    block_diff_dc[c] = ImageF(xsize_, ysize_, 0.0);
  828|   431k|    block_diff_ac[c] = ImageF(xsize_, ysize_, 0.0);
  829|   431k|  }
  830|       |
  831|   143k|  static const double wUhfMalta = 5.1409625726;
  832|   143k|  static const double norm1Uhf = 58.5001247061;
  833|   143k|  MaltaDiffMap(pi0_.uhf[1], pi1.uhf[1],
  834|   143k|               wUhfMalta * hf_asymmetry_,
  835|   143k|               wUhfMalta / hf_asymmetry_,
  836|   143k|               norm1Uhf,
  837|   143k|               &block_diff_ac[1]);
  838|       |
  839|   143k|  static const double wUhfMaltaX = 4.91743441556;
  840|   143k|  static const double norm1UhfX = 687196.39002;
  841|   143k|  MaltaDiffMap(pi0_.uhf[0], pi1.uhf[0],
  842|   143k|               wUhfMaltaX * hf_asymmetry_,
  843|   143k|               wUhfMaltaX / hf_asymmetry_,
  844|   143k|               norm1UhfX,
  845|   143k|               &block_diff_ac[0]);
  846|       |
  847|   143k|  static const double wHfMalta = 153.671655716;
  848|   143k|  static const double norm1Hf = 83150785.9592;
  849|   143k|  MaltaDiffMapLF(pi0_.hf[1], pi1.hf[1],
  850|   143k|                 wHfMalta * sqrt(hf_asymmetry_),
  851|   143k|                 wHfMalta / sqrt(hf_asymmetry_),
  852|   143k|                 norm1Hf,
  853|   143k|                 &block_diff_ac[1]);
  854|       |
  855|   143k|  static const double wHfMaltaX = 668.358918152;
  856|   143k|  static const double norm1HfX = 0.882954368025;
  857|   143k|  MaltaDiffMapLF(pi0_.hf[0], pi1.hf[0],
  858|   143k|                 wHfMaltaX * sqrt(hf_asymmetry_),
  859|   143k|                 wHfMaltaX / sqrt(hf_asymmetry_),
  860|   143k|                 norm1HfX,
  861|   143k|                 &block_diff_ac[0]);
  862|       |
  863|   143k|  static const double wMfMalta = 6841.81248144;
  864|   143k|  static const double norm1Mf = 0.0135134962487;
  865|   143k|  MaltaDiffMapLF(pi0_.mf[1], pi1.mf[1], wMfMalta, wMfMalta, norm1Mf,
  866|   143k|                 &block_diff_ac[1]);
  867|       |
  868|   143k|  static const double wMfMaltaX = 813.901703816;
  869|   143k|  static const double norm1MfX = 16792.9322251;
  870|   143k|  MaltaDiffMapLF(pi0_.mf[0], pi1.mf[0], wMfMaltaX, wMfMaltaX, norm1MfX,
  871|   143k|                 &block_diff_ac[0]);
  872|       |
  873|   143k|  static const double wmul[9] = {
  874|   143k|    0,
  875|   143k|    32.4449876135,
  876|   143k|    0,
  877|   143k|    0,
  878|   143k|    0,
  879|   143k|    0,
  880|   143k|    1.01370836411,
  881|   143k|    0,
  882|   143k|    1.74566011615,
  883|   143k|  };
  884|       |
  885|   143k|  static const double maxclamp = 85.7047444518;
  886|   143k|  static const double kSigmaHfX = 10.6666499623;
  887|   143k|  static const double w = 884.809801415;
  888|   143k|  SameNoiseLevels(pi0_.hf[1], pi1.hf[1], kSigmaHfX, w, maxclamp,
  889|   143k|                  &block_diff_ac[1]);
  890|       |
  891|   574k|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (891:19): [True: 431k, False: 143k]
  ------------------
  892|   431k|    if (c < 2) {
  ------------------
  |  Branch (892:9): [True: 287k, False: 143k]
  ------------------
  893|   287k|      L2DiffAsymmetric(pi0_.hf[c], pi1.hf[c],
  894|   287k|                       wmul[c] * hf_asymmetry_,
  895|   287k|                       wmul[c] / hf_asymmetry_,
  896|   287k|                       &block_diff_ac[c]);
  897|   287k|    }
  898|   431k|    L2Diff(pi0_.mf[c], pi1.mf[c], wmul[3 + c], &block_diff_ac[c]);
  899|   431k|    L2Diff(pi0_.lf[c], pi1.lf[c], wmul[6 + c], &block_diff_dc[c]);
  900|   431k|  }
  901|       |
  902|   143k|  std::vector<ImageF> mask_xyb;
  903|   143k|  std::vector<ImageF> mask_xyb_dc;
  904|   143k|  MaskPsychoImage(pi0_, pi1, xsize_, ysize_, &mask_xyb, &mask_xyb_dc);
  905|       |
  906|   143k|  result = CalculateDiffmap(
  907|   143k|      CombineChannels(mask_xyb, mask_xyb_dc, block_diff_dc, block_diff_ac));
  908|   143k|}
_ZNK11butteraugli21ButteraugliComparator12MaltaDiffMapERKNS_5ImageIfEES4_dddPS2_:
 1574|   287k|    const double norm1, ImageF* BUTTERAUGLI_RESTRICT block_diff_ac) const {
 1575|   287k|  PROFILER_FUNC;
 1576|   287k|  const double len = 3.75;
 1577|   287k|  static const double mulli = 0.354191303559;
 1578|   287k|  MaltaDiffMapImpl<MaltaTag>(lum0, lum1, xsize_, ysize_, w_0gt1, w_0lt1,
 1579|   287k|                             norm1, len,
 1580|   287k|                             mulli, block_diff_ac);
 1581|   287k|}
_ZNK11butteraugli21ButteraugliComparator14MaltaDiffMapLFERKNS_5ImageIfEES4_dddPS2_:
 1587|   574k|    const double norm1, ImageF* BUTTERAUGLI_RESTRICT block_diff_ac) const {
 1588|   574k|  PROFILER_FUNC;
 1589|   574k|  const double len = 3.75;
 1590|   574k|  static const double mulli = 0.405371989604;
 1591|   574k|  MaltaDiffMapImpl<MaltaTagLF>(lum0, lum1, xsize_, ysize_,
 1592|   574k|                               w_0gt1, w_0lt1,
 1593|   574k|                               norm1, len,
 1594|   574k|                               mulli, block_diff_ac);
 1595|   574k|}
_ZNK11butteraugli21ButteraugliComparator15CombineChannelsERKNSt3__16vectorINS_5ImageIfEENS1_9allocatorIS4_EEEES9_S9_S9_:
 1601|   143k|    const std::vector<ImageF>& block_diff_ac) const {
 1602|   143k|  PROFILER_FUNC;
 1603|   143k|  ImageF result(xsize_, ysize_);
 1604|  6.72M|  for (size_t y = 0; y < ysize_; ++y) {
  ------------------
  |  Branch (1604:22): [True: 6.57M, False: 143k]
  ------------------
 1605|  6.57M|    float* const BUTTERAUGLI_RESTRICT row_out = result.Row(y);
 1606|   342M|    for (size_t x = 0; x < xsize_; ++x) {
  ------------------
  |  Branch (1606:24): [True: 335M, False: 6.57M]
  ------------------
 1607|   335M|      float mask[3];
 1608|   335M|      float dc_mask[3];
 1609|   335M|      float diff_dc[3];
 1610|   335M|      float diff_ac[3];
 1611|  1.34G|      for (int i = 0; i < 3; ++i) {
  ------------------
  |  Branch (1611:23): [True: 1.00G, False: 335M]
  ------------------
 1612|  1.00G|        mask[i] = mask_xyb[i].Row(y)[x];
 1613|  1.00G|        dc_mask[i] = mask_xyb_dc[i].Row(y)[x];
 1614|  1.00G|        diff_dc[i] = block_diff_dc[i].Row(y)[x];
 1615|  1.00G|        diff_ac[i] = block_diff_ac[i].Row(y)[x];
 1616|  1.00G|      }
 1617|   335M|      row_out[x] = (DotProduct(diff_dc, dc_mask) + DotProduct(diff_ac, mask));
 1618|   335M|    }
 1619|  6.57M|  }
 1620|   143k|  return result;
 1621|   143k|}
_ZN11butteraugli27ButteraugliScoreFromDiffmapERKNS_5ImageIfEE:
 1623|   143k|double ButteraugliScoreFromDiffmap(const ImageF& diffmap) {
 1624|   143k|  PROFILER_FUNC;
 1625|   143k|  float retval = 0.0f;
 1626|  6.72M|  for (size_t y = 0; y < diffmap.ysize(); ++y) {
  ------------------
  |  Branch (1626:22): [True: 6.57M, False: 143k]
  ------------------
 1627|  6.57M|    const float * const BUTTERAUGLI_RESTRICT row = diffmap.Row(y);
 1628|   342M|    for (size_t x = 0; x < diffmap.xsize(); ++x) {
  ------------------
  |  Branch (1628:24): [True: 335M, False: 6.57M]
  ------------------
 1629|   335M|      retval = std::max(retval, row[x]);
 1630|   335M|    }
 1631|  6.57M|  }
 1632|   143k|  return retval;
 1633|   143k|}
_ZN11butteraugli5MaskXEd:
 1655|   344M|double MaskX(double delta) {
 1656|   344M|  static const double extmul = 2.59885507073;
 1657|   344M|  static const double extoff = 3.08805636789;
 1658|   344M|  static const double offset = 0.315424196682;
 1659|   344M|  static const double scaler = 16.2770141832;
 1660|   344M|  static const double mul = 5.62939030582;
 1661|   344M|  static const std::array<double, 512> lut =
 1662|   344M|                MakeMask(extmul, extoff, mul, offset, scaler);
 1663|   344M|  return InterpolateClampNegative(lut.data(), lut.size(), delta);
 1664|   344M|}
_ZN11butteraugli5MaskYEd:
 1666|   689M|double MaskY(double delta) {
 1667|   689M|  static const double extmul = 0.9613705131;
 1668|   689M|  static const double extoff = -0.581933100068;
 1669|   689M|  static const double offset = 1.00846207765;
 1670|   689M|  static const double scaler = 2.2342321176;
 1671|   689M|  static const double mul = 6.64307621174;
 1672|   689M|  static const std::array<double, 512> lut =
 1673|   689M|      MakeMask(extmul, extoff, mul, offset, scaler);
 1674|   689M|  return InterpolateClampNegative(lut.data(), lut.size(), delta);
 1675|   689M|}
_ZN11butteraugli7MaskDcXEd:
 1677|   344M|double MaskDcX(double delta) {
 1678|   344M|  static const double extmul = 10.0470705878;
 1679|   344M|  static const double extoff = 3.18472654033;
 1680|   344M|  static const double offset = 0.0551512255218;
 1681|   344M|  static const double scaler = 70.0;
 1682|   344M|  static const double mul = 0.373092999662;
 1683|   344M|  static const std::array<double, 512> lut =
 1684|   344M|      MakeMask(extmul, extoff, mul, offset, scaler);
 1685|   344M|  return InterpolateClampNegative(lut.data(), lut.size(), delta);
 1686|   344M|}
_ZN11butteraugli7MaskDcYEd:
 1688|   689M|double MaskDcY(double delta) {
 1689|   689M|  static const double extmul = 0.0115640939227;
 1690|   689M|  static const double extoff = 45.9483175519;
 1691|   689M|  static const double offset = 0.0142290066313;
 1692|   689M|  static const double scaler = 5.0;
 1693|   689M|  static const double mul = 2.52611324247;
 1694|   689M|  static const std::array<double, 512> lut =
 1695|   689M|      MakeMask(extmul, extoff, mul, offset, scaler);
 1696|   689M|  return InterpolateClampNegative(lut.data(), lut.size(), delta);
 1697|   689M|}
_ZN11butteraugli14DiffPrecomputeERKNS_5ImageIfEES3_:
 1699|   294k|ImageF DiffPrecompute(const ImageF& xyb0, const ImageF& xyb1) {
 1700|   294k|  PROFILER_FUNC;
 1701|   294k|  const size_t xsize = xyb0.xsize();
 1702|   294k|  const size_t ysize = xyb0.ysize();
 1703|   294k|  ImageF result(xsize, ysize);
 1704|   294k|  size_t x2, y2;
 1705|  13.8M|  for (size_t y = 0; y < ysize; ++y) {
  ------------------
  |  Branch (1705:22): [True: 13.5M, False: 294k]
  ------------------
 1706|  13.5M|    if (y + 1 < ysize) {
  ------------------
  |  Branch (1706:9): [True: 13.2M, False: 294k]
  ------------------
 1707|  13.2M|      y2 = y + 1;
 1708|  13.2M|    } else if (y > 0) {
  ------------------
  |  Branch (1708:16): [True: 294k, False: 0]
  ------------------
 1709|   294k|      y2 = y - 1;
 1710|   294k|    } else {
 1711|      0|      y2 = y;
 1712|      0|    }
 1713|  13.5M|    const float* const BUTTERAUGLI_RESTRICT row0_in = xyb0.Row(y);
 1714|  13.5M|    const float* const BUTTERAUGLI_RESTRICT row1_in = xyb1.Row(y);
 1715|  13.5M|    const float* const BUTTERAUGLI_RESTRICT row0_in2 = xyb0.Row(y2);
 1716|  13.5M|    const float* const BUTTERAUGLI_RESTRICT row1_in2 = xyb1.Row(y2);
 1717|  13.5M|    float* const BUTTERAUGLI_RESTRICT row_out = result.Row(y);
 1718|   702M|    for (size_t x = 0; x < xsize; ++x) {
  ------------------
  |  Branch (1718:24): [True: 689M, False: 13.5M]
  ------------------
 1719|   689M|      if (x + 1 < xsize) {
  ------------------
  |  Branch (1719:11): [True: 675M, False: 13.5M]
  ------------------
 1720|   675M|        x2 = x + 1;
 1721|   675M|      } else if (x > 0) {
  ------------------
  |  Branch (1721:18): [True: 13.5M, False: 0]
  ------------------
 1722|  13.5M|        x2 = x - 1;
 1723|  13.5M|      } else {
 1724|      0|        x2 = x;
 1725|      0|      }
 1726|   689M|      double sup0 = (fabs(row0_in[x] - row0_in[x2]) +
 1727|   689M|                     fabs(row0_in[x] - row0_in2[x]));
 1728|   689M|      double sup1 = (fabs(row1_in[x] - row1_in[x2]) +
 1729|   689M|                     fabs(row1_in[x] - row1_in2[x]));
 1730|   689M|      static const double mul0 = 0.918416534734;
 1731|   689M|      row_out[x] = mul0 * std::min(sup0, sup1);
 1732|   689M|      static const double cutoff = 55.0184555849;
 1733|   689M|      if (row_out[x] >= cutoff) {
  ------------------
  |  Branch (1733:11): [True: 114M, False: 575M]
  ------------------
 1734|   114M|        row_out[x] = cutoff;
 1735|   114M|      }
 1736|   689M|    }
 1737|  13.5M|  }
 1738|   294k|  return result;
 1739|   294k|}
_ZN11butteraugli4MaskERKNSt3__16vectorINS_5ImageIfEENS0_9allocatorIS3_EEEES8_PS6_S9_:
 1744|   147k|          std::vector<ImageF>* BUTTERAUGLI_RESTRICT mask_dc) {
 1745|   147k|  PROFILER_FUNC;
 1746|   147k|  const size_t xsize = xyb0[0].xsize();
 1747|   147k|  const size_t ysize = xyb0[0].ysize();
 1748|   147k|  mask->resize(3);
 1749|   147k|  *mask_dc = CreatePlanes<float>(xsize, ysize, 3);
 1750|   147k|  double muls[2] = {
 1751|   147k|    0.207017089891,
 1752|   147k|    0.267138152891,
 1753|   147k|  };
 1754|   147k|  double normalizer = {
 1755|   147k|    1.0 / (muls[0] + muls[1]),
 1756|   147k|  };
 1757|   147k|  static const double r0 = 2.3770330432;
 1758|   147k|  static const double r1 = 9.04353323561;
 1759|   147k|  static const double r2 = 9.24456601467;
 1760|   147k|  static const double border_ratio = -0.0724948220913;
 1761|       |
 1762|   147k|  {
 1763|       |    // X component
 1764|   147k|    ImageF diff = DiffPrecompute(xyb0[0], xyb1[0]);
 1765|   147k|    ImageF blurred = Blur(diff, r2, border_ratio);
 1766|   147k|    (*mask)[0] = ImageF(xsize, ysize);
 1767|  6.91M|    for (size_t y = 0; y < ysize; ++y) {
  ------------------
  |  Branch (1767:24): [True: 6.76M, False: 147k]
  ------------------
 1768|   351M|      for (size_t x = 0; x < xsize; ++x) {
  ------------------
  |  Branch (1768:26): [True: 344M, False: 6.76M]
  ------------------
 1769|   344M|        (*mask)[0].Row(y)[x] = blurred.Row(y)[x];
 1770|   344M|      }
 1771|  6.76M|    }
 1772|   147k|  }
 1773|   147k|  {
 1774|       |    // Y component
 1775|   147k|    (*mask)[1] = ImageF(xsize, ysize);
 1776|   147k|    ImageF diff = DiffPrecompute(xyb0[1], xyb1[1]);
 1777|   147k|    ImageF blurred1 = Blur(diff, r0, border_ratio);
 1778|   147k|    ImageF blurred2 = Blur(diff, r1, border_ratio);
 1779|  6.91M|    for (size_t y = 0; y < ysize; ++y) {
  ------------------
  |  Branch (1779:24): [True: 6.76M, False: 147k]
  ------------------
 1780|   351M|      for (size_t x = 0; x < xsize; ++x) {
  ------------------
  |  Branch (1780:26): [True: 344M, False: 6.76M]
  ------------------
 1781|   344M|        const double val = normalizer * (
 1782|   344M|            muls[0] * blurred1.Row(y)[x] +
 1783|   344M|            muls[1] * blurred2.Row(y)[x]);
 1784|   344M|        (*mask)[1].Row(y)[x] = val;
 1785|   344M|      }
 1786|  6.76M|    }
 1787|   147k|  }
 1788|       |  // B component
 1789|   147k|  (*mask)[2] = ImageF(xsize, ysize);
 1790|   147k|  static const double mul[2] = {
 1791|   147k|    16.6963293877,
 1792|   147k|    2.1364621982,
 1793|   147k|  };
 1794|   147k|  static const double w00 = 36.4671237619;
 1795|   147k|  static const double w11 = 2.1887170895;
 1796|   147k|  static const double w_ytob_hf = std::max<double>(
 1797|   147k|      0.086624184478,
 1798|   147k|      0.0);
 1799|   147k|  static const double w_ytob_lf = 21.6804277046;
 1800|   147k|  static const double p1_to_p0 = 0.0513061271723;
 1801|       |
 1802|  6.91M|  for (size_t y = 0; y < ysize; ++y) {
  ------------------
  |  Branch (1802:22): [True: 6.76M, False: 147k]
  ------------------
 1803|   351M|    for (size_t x = 0; x < xsize; ++x) {
  ------------------
  |  Branch (1803:24): [True: 344M, False: 6.76M]
  ------------------
 1804|   344M|      const double s0 = (*mask)[0].Row(y)[x];
 1805|   344M|      const double s1 = (*mask)[1].Row(y)[x];
 1806|   344M|      const double p1 = mul[1] * w11 * s1;
 1807|   344M|      const double p0 = mul[0] * w00 * s0 + p1_to_p0 * p1;
 1808|       |
 1809|   344M|      (*mask)[0].Row(y)[x] = MaskX(p0);
 1810|   344M|      (*mask)[1].Row(y)[x] = MaskY(p1);
 1811|   344M|      (*mask)[2].Row(y)[x] = w_ytob_hf * MaskY(p1);
 1812|   344M|      (*mask_dc)[0].Row(y)[x] = MaskDcX(p0);
 1813|   344M|      (*mask_dc)[1].Row(y)[x] = MaskDcY(p1);
 1814|   344M|      (*mask_dc)[2].Row(y)[x] = w_ytob_lf * MaskDcY(p1);
 1815|   344M|    }
 1816|  6.76M|  }
 1817|   147k|}
butteraugli.cc:_ZN11butteraugliL5GammaEd:
  319|  3.24G|static inline double Gamma(double v) {
  320|       |  //return SimpleGamma(v);
  321|  3.24G|  return GammaPolynomial(v);
  322|  3.24G|}
butteraugli.cc:_ZN11butteraugliL19SeparateFrequenciesEmmRKNSt3__16vectorINS_5ImageIfEENS0_9allocatorIS3_EEEERNS_11PsychoImageE:
  492|   146k|    PsychoImage &ps) {
  493|   146k|  PROFILER_FUNC;
  494|   146k|  ps.lf.resize(3);   // XYB
  495|   146k|  ps.mf.resize(3);   // XYB
  496|   146k|  ps.hf.resize(2);   // XY
  497|   146k|  ps.uhf.resize(2);  // XY
  498|       |  // Extract lf ...
  499|   146k|  static const double kSigmaLf = 7.46953768697;
  500|   146k|  static const double kSigmaHf = 3.734768843485;
  501|   146k|  static const double kSigmaUhf = 1.8673844217425;
  502|       |  // At borders we move some more of the energy to the high frequency
  503|       |  // parts, because there can be unfortunate continuations in tiling
  504|       |  // background color etc. So we want to represent the borders with
  505|       |  // some more accuracy.
  506|   146k|  static double border_lf = -0.00457628248637;
  507|   146k|  static double border_mf = -0.271277366628;
  508|   146k|  static double border_hf = 0.147068973249;
  509|   438k|  for (int i = 0; i < 3; ++i) {
  ------------------
  |  Branch (509:19): [True: 438k, False: 0]
  ------------------
  510|   438k|    ps.lf[i] = Blur(xyb[i], kSigmaLf, border_lf);
  511|       |    // ... and keep everything else in mf.
  512|   438k|    ps.mf[i] = ImageF(xsize, ysize);
  513|  20.5M|    for (size_t y = 0; y < ysize; ++y) {
  ------------------
  |  Branch (513:24): [True: 20.1M, False: 438k]
  ------------------
  514|  1.04G|      for (size_t x = 0; x < xsize; ++x) {
  ------------------
  |  Branch (514:26): [True: 1.02G, False: 20.1M]
  ------------------
  515|  1.02G|        ps.mf[i].Row(y)[x] = xyb[i].Row(y)[x] - ps.lf[i].Row(y)[x];
  516|  1.02G|      }
  517|  20.1M|    }
  518|   438k|    if (i == 2) {
  ------------------
  |  Branch (518:9): [True: 146k, False: 292k]
  ------------------
  519|   146k|      ps.mf[i] = Blur(ps.mf[i], kSigmaHf, border_mf);
  520|   146k|      break;
  521|   146k|    }
  522|       |    // Divide mf into mf and hf.
  523|   292k|    ps.hf[i] = ImageF(xsize, ysize);
  524|  13.7M|    for (size_t y = 0; y < ysize; ++y) {
  ------------------
  |  Branch (524:24): [True: 13.4M, False: 292k]
  ------------------
  525|  13.4M|      float* BUTTERAUGLI_RESTRICT const row_mf = ps.mf[i].Row(y);
  526|  13.4M|      float* BUTTERAUGLI_RESTRICT const row_hf = ps.hf[i].Row(y);
  527|   697M|      for (size_t x = 0; x < xsize; ++x) {
  ------------------
  |  Branch (527:26): [True: 684M, False: 13.4M]
  ------------------
  528|   684M|        row_hf[x] = row_mf[x];
  529|   684M|      }
  530|  13.4M|    }
  531|   292k|    ps.mf[i] = Blur(ps.mf[i], kSigmaHf, border_mf);
  532|   292k|    static const double w0 = 0.120079806822;
  533|   292k|    static const double w1 = 0.03430529365;
  534|   292k|    if (i == 0) {
  ------------------
  |  Branch (534:9): [True: 146k, False: 146k]
  ------------------
  535|  6.86M|      for (size_t y = 0; y < ysize; ++y) {
  ------------------
  |  Branch (535:26): [True: 6.71M, False: 146k]
  ------------------
  536|  6.71M|        float* BUTTERAUGLI_RESTRICT const row_mf = ps.mf[0].Row(y);
  537|  6.71M|        float* BUTTERAUGLI_RESTRICT const row_hf = ps.hf[0].Row(y);
  538|   348M|        for (size_t x = 0; x < xsize; ++x) {
  ------------------
  |  Branch (538:28): [True: 342M, False: 6.71M]
  ------------------
  539|   342M|          row_hf[x] -= row_mf[x];
  540|   342M|          row_mf[x] = RemoveRangeAroundZero(w0, row_mf[x]);
  541|   342M|        }
  542|  6.71M|      }
  543|   146k|    } else {
  544|  6.86M|      for (size_t y = 0; y < ysize; ++y) {
  ------------------
  |  Branch (544:26): [True: 6.71M, False: 146k]
  ------------------
  545|  6.71M|        float* BUTTERAUGLI_RESTRICT const row_mf = ps.mf[1].Row(y);
  546|  6.71M|        float* BUTTERAUGLI_RESTRICT const row_hf = ps.hf[1].Row(y);
  547|   348M|        for (size_t x = 0; x < xsize; ++x) {
  ------------------
  |  Branch (547:28): [True: 342M, False: 6.71M]
  ------------------
  548|   342M|          row_hf[x] -= row_mf[x];
  549|   342M|          row_mf[x] = AmplifyRangeAroundZero(w1, row_mf[x]);
  550|   342M|        }
  551|  6.71M|      }
  552|   146k|    }
  553|   292k|  }
  554|       |  // Suppress red-green by intensity change in the high freq channels.
  555|   146k|  static const double suppress = 2.96534974403;
  556|   146k|  ps.hf[0] = SuppressXByY(xsize, ysize, ps.hf[0], ps.hf[1], suppress);
  557|       |
  558|   438k|  for (int i = 0; i < 2; ++i) {
  ------------------
  |  Branch (558:19): [True: 292k, False: 146k]
  ------------------
  559|       |    // Divide hf into hf and uhf.
  560|   292k|    ps.uhf[i] = ImageF(xsize, ysize);
  561|  13.7M|    for (size_t y = 0; y < ysize; ++y) {
  ------------------
  |  Branch (561:24): [True: 13.4M, False: 292k]
  ------------------
  562|  13.4M|      float* BUTTERAUGLI_RESTRICT const row_uhf = ps.uhf[i].Row(y);
  563|  13.4M|      float* BUTTERAUGLI_RESTRICT const row_hf = ps.hf[i].Row(y);
  564|   697M|      for (size_t x = 0; x < xsize; ++x) {
  ------------------
  |  Branch (564:26): [True: 684M, False: 13.4M]
  ------------------
  565|   684M|        row_uhf[x] = row_hf[x];
  566|   684M|      }
  567|  13.4M|    }
  568|   292k|    ps.hf[i] = Blur(ps.hf[i], kSigmaUhf, border_hf);
  569|   292k|    static const double kRemoveHfRange = 0.0287615200377;
  570|   292k|    static const double kMaxclampHf = 78.8223237675;
  571|   292k|    static const double kMaxclampUhf = 5.8907152736;
  572|   292k|    static const float kMulSuppressHf = 1.10684769012;
  573|   292k|    static const float kMulRegHf = 0.478741530298;
  574|   292k|    static const float kRegHf = 2000 * kMulRegHf;
  575|   292k|    static const float kMulSuppressUhf = 1.76905001176;
  576|   292k|    static const float kMulRegUhf = 0.310148420674;
  577|   292k|    static const float kRegUhf = 2000 * kMulRegUhf;
  578|       |
  579|   292k|    if (i == 0) {
  ------------------
  |  Branch (579:9): [True: 146k, False: 146k]
  ------------------
  580|  6.86M|      for (size_t y = 0; y < ysize; ++y) {
  ------------------
  |  Branch (580:26): [True: 6.71M, False: 146k]
  ------------------
  581|  6.71M|        float* BUTTERAUGLI_RESTRICT const row_uhf = ps.uhf[0].Row(y);
  582|  6.71M|        float* BUTTERAUGLI_RESTRICT const row_hf = ps.hf[0].Row(y);
  583|   348M|        for (size_t x = 0; x < xsize; ++x) {
  ------------------
  |  Branch (583:28): [True: 342M, False: 6.71M]
  ------------------
  584|   342M|          row_uhf[x] -= row_hf[x];
  585|   342M|          row_hf[x] = RemoveRangeAroundZero(kRemoveHfRange, row_hf[x]);
  586|   342M|        }
  587|  6.71M|      }
  588|   146k|    } else {
  589|  6.86M|      for (size_t y = 0; y < ysize; ++y) {
  ------------------
  |  Branch (589:26): [True: 6.71M, False: 146k]
  ------------------
  590|  6.71M|        float* BUTTERAUGLI_RESTRICT const row_uhf = ps.uhf[1].Row(y);
  591|  6.71M|        float* BUTTERAUGLI_RESTRICT const row_hf = ps.hf[1].Row(y);
  592|  6.71M|        float* BUTTERAUGLI_RESTRICT const row_lf = ps.lf[1].Row(y);
  593|   348M|        for (size_t x = 0; x < xsize; ++x) {
  ------------------
  |  Branch (593:28): [True: 342M, False: 6.71M]
  ------------------
  594|   342M|          row_uhf[x] -= row_hf[x];
  595|   342M|          row_hf[x] = MaximumClamp(row_hf[x], kMaxclampHf);
  596|   342M|          row_uhf[x] = MaximumClamp(row_uhf[x], kMaxclampUhf);
  597|   342M|          row_uhf[x] = SuppressUhfInBrightAreas(row_uhf[x], row_lf[x],
  598|   342M|                                                kMulSuppressUhf, kRegUhf);
  599|   342M|          row_hf[x] = SuppressHfInBrightAreas(row_hf[x], row_lf[x],
  600|   342M|                                              kMulSuppressHf, kRegHf);
  601|       |
  602|   342M|        }
  603|  6.71M|      }
  604|   146k|    }
  605|   292k|  }
  606|       |  // Modify range around zero code only concerns the high frequency
  607|       |  // planes and only the X and Y channels.
  608|       |  // Convert low freq xyb to vals space so that we can do a simple squared sum
  609|       |  // diff on the low frequencies later.
  610|  6.86M|  for (size_t y = 0; y < ysize; ++y) {
  ------------------
  |  Branch (610:22): [True: 6.71M, False: 146k]
  ------------------
  611|  6.71M|    float* BUTTERAUGLI_RESTRICT const row_x = ps.lf[0].Row(y);
  612|  6.71M|    float* BUTTERAUGLI_RESTRICT const row_y = ps.lf[1].Row(y);
  613|  6.71M|    float* BUTTERAUGLI_RESTRICT const row_b = ps.lf[2].Row(y);
  614|   348M|    for (size_t x = 0; x < xsize; ++x) {
  ------------------
  |  Branch (614:24): [True: 342M, False: 6.71M]
  ------------------
  615|   342M|      float valx, valy, valb;
  616|   342M|      XybLowFreqToVals(row_x[x], row_y[x], row_b[x], &valx, &valy, &valb);
  617|   342M|      row_x[x] = valx;
  618|   342M|      row_y[x] = valy;
  619|   342M|      row_b[x] = valb;
  620|   342M|    }
  621|  6.71M|  }
  622|   146k|}
butteraugli.cc:_ZN11butteraugliL21RemoveRangeAroundZeroEff:
  369|   684M|static BUTTERAUGLI_INLINE float RemoveRangeAroundZero(float w, float x) {
  370|   684M|  return x > w ? x - w : x < -w ? x + w : 0.0f;
  ------------------
  |  Branch (370:10): [True: 117M, False: 566M]
  |  Branch (370:26): [True: 117M, False: 449M]
  ------------------
  371|   684M|}
butteraugli.cc:_ZN11butteraugliL22AmplifyRangeAroundZeroEff:
  374|   342M|static BUTTERAUGLI_INLINE float AmplifyRangeAroundZero(float w, float x) {
  375|   342M|  return x > w ? x + w : x < -w ? x - w : 2.0f * x;
  ------------------
  |  Branch (375:10): [True: 135M, False: 206M]
  |  Branch (375:26): [True: 189M, False: 16.7M]
  ------------------
  376|   342M|}
butteraugli.cc:_ZN11butteraugliL12SuppressXByYEmmRKNS_5ImageIfEES3_d:
  472|   146k|                           const double yw) {
  473|   146k|  static const double s = 0.745954517135;
  474|   146k|  ImageF inew(xsize, ysize);
  475|  6.86M|  for (size_t y = 0; y < ysize; ++y) {
  ------------------
  |  Branch (475:22): [True: 6.71M, False: 146k]
  ------------------
  476|  6.71M|    const float* const rowx = ix.Row(y);
  477|  6.71M|    const float* const rowy = iy.Row(y);
  478|  6.71M|    float* const rownew = inew.Row(y);
  479|   348M|    for (size_t x = 0; x < xsize; ++x) {
  ------------------
  |  Branch (479:24): [True: 342M, False: 6.71M]
  ------------------
  480|   342M|      const double xval = rowx[x];
  481|   342M|      const double yval = rowy[x];
  482|   342M|      const double scaler = s + (yw * (1.0 - s)) / (yw + yval * yval);
  483|   342M|      rownew[x] = scaler * xval;
  484|   342M|    }
  485|  6.71M|  }
  486|   146k|  return inew;
  487|   146k|}
butteraugli.cc:_ZN11butteraugliL12MaximumClampEff:
  432|   684M|static float MaximumClamp(float v, float maxval) {
  433|   684M|  static const double kMul = 0.688059627878;
  434|   684M|  if (v >= maxval) {
  ------------------
  |  Branch (434:7): [True: 88.2M, False: 596M]
  ------------------
  435|  88.2M|    v -= maxval;
  436|  88.2M|    v *= kMul;
  437|  88.2M|    v += maxval;
  438|   596M|  } else if (v < -maxval) {
  ------------------
  |  Branch (438:14): [True: 116M, False: 479M]
  ------------------
  439|   116M|    v += maxval;
  440|   116M|    v *= kMul;
  441|   116M|    v -= maxval;
  442|   116M|  }
  443|   684M|  return v;
  444|   684M|}
butteraugli.cc:_ZN11butteraugliL24SuppressUhfInBrightAreasEffff:
  427|   342M|                                      float mul, float reg) {
  428|   342M|  float scaler = mul * reg / (reg + brightness);
  429|   342M|  return scaler * hf;
  430|   342M|}
butteraugli.cc:_ZN11butteraugliL23SuppressHfInBrightAreasEffff:
  421|   342M|                                     float mul, float reg) {
  422|   342M|  float scaler = mul * reg / (reg + brightness);
  423|   342M|  return scaler * hf;
  424|   342M|}
_ZN11butteraugli16XybLowFreqToValsIfEEvRKT_S3_S3_PS1_S4_S4_:
  385|   342M|                                         V *BUTTERAUGLI_RESTRICT valb) {
  386|   342M|  static const double xmuli = 5.57547552483;
  387|   342M|  static const double ymuli = 1.20828034498;
  388|   342M|  static const double bmuli = 6.08319517575;
  389|   342M|  static const double y_to_b_muli = -0.628811683685;
  390|       |
  391|   342M|  const V xmul(xmuli);
  392|   342M|  const V ymul(ymuli);
  393|   342M|  const V bmul(bmuli);
  394|   342M|  const V y_to_b_mul(y_to_b_muli);
  395|   342M|  const V b = b_arg + y_to_b_mul * y;
  396|   342M|  *valb = b * bmul;
  397|   342M|  *valx = x * xmul;
  398|   342M|  *valy = y * ymul;
  399|   342M|}
butteraugli.cc:_ZN11butteraugliL15SameNoiseLevelsERKNS_5ImageIfEES3_dddPS1_:
  628|   143k|                            ImageF* BUTTERAUGLI_RESTRICT diffmap) {
  629|   143k|  ImageF blurred(i0.xsize(), i0.ysize());
  630|  6.72M|  for (size_t y = 0; y < i0.ysize(); ++y) {
  ------------------
  |  Branch (630:22): [True: 6.57M, False: 143k]
  ------------------
  631|  6.57M|    const float* BUTTERAUGLI_RESTRICT const row0 = i0.Row(y);
  632|  6.57M|    const float* BUTTERAUGLI_RESTRICT const row1 = i1.Row(y);
  633|  6.57M|    float* BUTTERAUGLI_RESTRICT const to = blurred.Row(y);
  634|   342M|    for (size_t x = 0; x < i0.xsize(); ++x) {
  ------------------
  |  Branch (634:24): [True: 335M, False: 6.57M]
  ------------------
  635|   335M|      double v0 = fabs(row0[x]);
  636|   335M|      double v1 = fabs(row1[x]);
  637|   335M|      if (v0 > maxclamp) v0 = maxclamp;
  ------------------
  |  Branch (637:11): [True: 0, False: 335M]
  ------------------
  638|   335M|      if (v1 > maxclamp) v1 = maxclamp;
  ------------------
  |  Branch (638:11): [True: 0, False: 335M]
  ------------------
  639|   335M|      to[x] = v0 - v1;
  640|   335M|    }
  641|       |
  642|  6.57M|  }
  643|   143k|  blurred = Blur(blurred, kSigma, 0.0);
  644|  6.72M|  for (size_t y = 0; y < i0.ysize(); ++y) {
  ------------------
  |  Branch (644:22): [True: 6.57M, False: 143k]
  ------------------
  645|  6.57M|    const float* BUTTERAUGLI_RESTRICT const row = blurred.Row(y);
  646|  6.57M|    float* BUTTERAUGLI_RESTRICT const row_diff = diffmap->Row(y);
  647|   342M|    for (size_t x = 0; x < i0.xsize(); ++x) {
  ------------------
  |  Branch (647:24): [True: 335M, False: 6.57M]
  ------------------
  648|   335M|      double diff = row[x];
  649|   335M|      row_diff[x] += w * diff * diff;
  650|   335M|    }
  651|  6.57M|  }
  652|   143k|}
butteraugli.cc:_ZN11butteraugliL16L2DiffAsymmetricERKNS_5ImageIfEES3_ddPS1_:
  675|   287k|                             ImageF* BUTTERAUGLI_RESTRICT diffmap) {
  676|   287k|  if (w_0gt1 == 0 && w_0lt1 == 0) {
  ------------------
  |  Branch (676:7): [True: 143k, False: 143k]
  |  Branch (676:22): [True: 143k, False: 0]
  ------------------
  677|   143k|    return;
  678|   143k|  }
  679|   143k|  w_0gt1 *= 0.8;
  680|   143k|  w_0lt1 *= 0.8;
  681|  6.72M|  for (size_t y = 0; y < i0.ysize(); ++y) {
  ------------------
  |  Branch (681:22): [True: 6.57M, False: 143k]
  ------------------
  682|  6.57M|    const float* BUTTERAUGLI_RESTRICT const row0 = i0.Row(y);
  683|  6.57M|    const float* BUTTERAUGLI_RESTRICT const row1 = i1.Row(y);
  684|  6.57M|    float* BUTTERAUGLI_RESTRICT const row_diff = diffmap->Row(y);
  685|   342M|    for (size_t x = 0; x < i0.xsize(); ++x) {
  ------------------
  |  Branch (685:24): [True: 335M, False: 6.57M]
  ------------------
  686|       |      // Primary symmetric quadratic objective.
  687|   335M|      double diff = row0[x] - row1[x];
  688|   335M|      row_diff[x] += w_0gt1 * diff * diff;
  689|       |
  690|       |      // Secondary half-open quadratic objectives.
  691|   335M|      const double fabs0 = fabs(row0[x]);
  692|   335M|      const double too_small = 0.4 * fabs0;
  693|   335M|      const double too_big = 1.0 * fabs0;
  694|       |
  695|   335M|      if (row0[x] < 0) {
  ------------------
  |  Branch (695:11): [True: 164M, False: 171M]
  ------------------
  696|   164M|        if (row1[x] > -too_small) {
  ------------------
  |  Branch (696:13): [True: 12.4M, False: 151M]
  ------------------
  697|  12.4M|          double v = row1[x] + too_small;
  698|  12.4M|          row_diff[x] += w_0lt1 * v * v;
  699|   151M|        } else if (row1[x] < -too_big) {
  ------------------
  |  Branch (699:20): [True: 70.8M, False: 80.9M]
  ------------------
  700|  70.8M|          double v = -row1[x] - too_big;
  701|  70.8M|          row_diff[x] += w_0lt1 * v * v;
  702|  70.8M|        }
  703|   171M|      } else {
  704|   171M|        if (row1[x] < too_small) {
  ------------------
  |  Branch (704:13): [True: 12.7M, False: 158M]
  ------------------
  705|  12.7M|          double v = too_small - row1[x];
  706|  12.7M|          row_diff[x] += w_0lt1 * v * v;
  707|   158M|        } else if (row1[x] > too_big) {
  ------------------
  |  Branch (707:20): [True: 71.5M, False: 87.1M]
  ------------------
  708|  71.5M|          double v = row1[x] - too_big;
  709|  71.5M|          row_diff[x] += w_0lt1 * v * v;
  710|  71.5M|        }
  711|   171M|      }
  712|   335M|    }
  713|  6.57M|  }
  714|   143k|}
butteraugli.cc:_ZN11butteraugliL6L2DiffERKNS_5ImageIfEES3_dPS1_:
  655|   862k|                   ImageF* BUTTERAUGLI_RESTRICT diffmap) {
  656|   862k|  if (w == 0) {
  ------------------
  |  Branch (656:7): [True: 574k, False: 287k]
  ------------------
  657|   574k|    return;
  658|   574k|  }
  659|  13.4M|  for (size_t y = 0; y < i0.ysize(); ++y) {
  ------------------
  |  Branch (659:22): [True: 13.1M, False: 287k]
  ------------------
  660|  13.1M|    const float* BUTTERAUGLI_RESTRICT const row0 = i0.Row(y);
  661|  13.1M|    const float* BUTTERAUGLI_RESTRICT const row1 = i1.Row(y);
  662|  13.1M|    float* BUTTERAUGLI_RESTRICT const row_diff = diffmap->Row(y);
  663|   684M|    for (size_t x = 0; x < i0.xsize(); ++x) {
  ------------------
  |  Branch (663:24): [True: 671M, False: 13.1M]
  ------------------
  664|   671M|      double diff = row0[x] - row1[x];
  665|   671M|      row_diff[x] += w * diff * diff;
  666|   671M|    }
  667|  13.1M|  }
  668|   287k|}
_ZN11butteraugli10DotProductEPKfS1_:
  141|   671M|inline float DotProduct(const float u[3], const float v[3]) {
  142|   671M|  return u[0] * v[0] + u[1] * v[1] + u[2] * v[2];
  143|   671M|}
butteraugli.cc:_ZN11butteraugliL8MakeMaskEddddd:
 1641|      4|    double scaler) {
 1642|      4|  std::array<double, 512> lut;
 1643|  2.05k|  for (int i = 0; i < lut.size(); ++i) {
  ------------------
  |  Branch (1643:19): [True: 2.04k, False: 4]
  ------------------
 1644|  2.04k|    const double c = mul / ((0.01 * scaler * i) + offset);
 1645|  2.04k|    lut[i] = kGlobalScale * (1.0 + extmul * (c + extoff));
 1646|  2.04k|    if (lut[i] < 1e-5) {
  ------------------
  |  Branch (1646:9): [True: 0, False: 2.04k]
  ------------------
 1647|      0|      lut[i] = 1e-5;
 1648|      0|    }
 1649|  2.04k|    assert(lut[i] >= 0.0);
  ------------------
  |  Branch (1649:5): [True: 2.04k, False: 0]
  ------------------
 1650|  2.04k|    lut[i] *= lut[i];
 1651|  2.04k|  }
 1652|      4|  return lut;
 1653|      4|}
_ZN11butteraugli24InterpolateClampNegativeEPKdid:
  237|  2.06G|                                       int size, double ix) {
  238|  2.06G|  if (ix < 0) {
  ------------------
  |  Branch (238:7): [True: 0, False: 2.06G]
  ------------------
  239|      0|    ix = 0;
  240|      0|  }
  241|  2.06G|  int baseix = static_cast<int>(ix);
  242|  2.06G|  double res;
  243|  2.06G|  if (baseix >= size - 1) {
  ------------------
  |  Branch (243:7): [True: 7.14M, False: 2.06G]
  ------------------
  244|  7.14M|    res = array[size - 1];
  245|  2.06G|  } else {
  246|  2.06G|    double mix = ix - baseix;
  247|  2.06G|    int nextix = baseix + 1;
  248|  2.06G|    res = array[baseix] + mix * (array[nextix] - array[baseix]);
  249|  2.06G|  }
  250|  2.06G|  return res;
  251|  2.06G|}
butteraugli.cc:_ZN11butteraugliL16MaltaDiffMapImplINS_8MaltaTagEEEvRKNS_5ImageIfEES5_mmdddddPS3_:
 1467|   287k|                             ImageF* block_diff_ac) {
 1468|   287k|  const float kWeight0 = 0.5;
 1469|   287k|  const float kWeight1 = 0.33;
 1470|       |
 1471|   287k|  const double w_pre0gt1 = mulli * sqrt(kWeight0 * w_0gt1) / (len * 2 + 1);
 1472|   287k|  const double w_pre0lt1 = mulli * sqrt(kWeight1 * w_0lt1) / (len * 2 + 1);
 1473|   287k|  const float norm2_0gt1 = w_pre0gt1 * norm1;
 1474|   287k|  const float norm2_0lt1 = w_pre0lt1 * norm1;
 1475|       |
 1476|   287k|  std::vector<float> diffs(ysize_ * xsize_);
 1477|  13.4M|  for (size_t y = 0, ix = 0; y < ysize_; ++y) {
  ------------------
  |  Branch (1477:30): [True: 13.1M, False: 287k]
  ------------------
 1478|  13.1M|    const float* BUTTERAUGLI_RESTRICT const row0 = lum0.Row(y);
 1479|  13.1M|    const float* BUTTERAUGLI_RESTRICT const row1 = lum1.Row(y);
 1480|   684M|    for (size_t x = 0; x < xsize_; ++x, ++ix) {
  ------------------
  |  Branch (1480:24): [True: 671M, False: 13.1M]
  ------------------
 1481|   671M|      const float absval = 0.5 * std::abs(row0[x]) + 0.5 * std::abs(row1[x]);
 1482|   671M|      const float diff = row0[x] - row1[x];
 1483|   671M|      const float scaler = norm2_0gt1 / (static_cast<float>(norm1) + absval);
 1484|       |
 1485|       |      // Primary symmetric quadratic objective.
 1486|   671M|      diffs[ix] = scaler * diff;
 1487|       |
 1488|   671M|      const float scaler2 = norm2_0lt1 / (static_cast<float>(norm1) + absval);
 1489|   671M|      const double fabs0 = fabs(row0[x]);
 1490|       |
 1491|       |      // Secondary half-open quadratic objectives.
 1492|   671M|      const double too_small = 0.55 * fabs0;
 1493|   671M|      const double too_big = 1.05 * fabs0;
 1494|       |
 1495|   671M|      if (row0[x] < 0) {
  ------------------
  |  Branch (1495:11): [True: 350M, False: 320M]
  ------------------
 1496|   350M|        if (row1[x] > -too_small) {
  ------------------
  |  Branch (1496:13): [True: 40.7M, False: 310M]
  ------------------
 1497|  40.7M|          double impact = scaler2 * (row1[x] + too_small);
 1498|  40.7M|          if (diff < 0) {
  ------------------
  |  Branch (1498:15): [True: 40.7M, False: 0]
  ------------------
 1499|  40.7M|            diffs[ix] -= impact;
 1500|  40.7M|          } else {
 1501|      0|            diffs[ix] += impact;
 1502|      0|          }
 1503|   310M|        } else if (row1[x] < -too_big) {
  ------------------
  |  Branch (1503:20): [True: 78.9M, False: 231M]
  ------------------
 1504|  78.9M|          double impact = scaler2 * (-row1[x] - too_big);
 1505|  78.9M|          if (diff < 0) {
  ------------------
  |  Branch (1505:15): [True: 0, False: 78.9M]
  ------------------
 1506|      0|            diffs[ix] -= impact;
 1507|  78.9M|          } else {
 1508|  78.9M|            diffs[ix] += impact;
 1509|  78.9M|          }
 1510|  78.9M|        }
 1511|   350M|      } else {
 1512|   320M|        if (row1[x] < too_small) {
  ------------------
  |  Branch (1512:13): [True: 40.0M, False: 280M]
  ------------------
 1513|  40.0M|          double impact = scaler2 * (too_small - row1[x]);
 1514|  40.0M|          if (diff < 0) {
  ------------------
  |  Branch (1514:15): [True: 0, False: 40.0M]
  ------------------
 1515|      0|            diffs[ix] -= impact;
 1516|  40.0M|          } else {
 1517|  40.0M|            diffs[ix] += impact;
 1518|  40.0M|          }
 1519|   280M|        } else if (row1[x] > too_big) {
  ------------------
  |  Branch (1519:20): [True: 74.4M, False: 206M]
  ------------------
 1520|  74.4M|          double impact = scaler2 * (row1[x] - too_big);
 1521|  74.4M|          if (diff < 0) {
  ------------------
  |  Branch (1521:15): [True: 74.4M, False: 0]
  ------------------
 1522|  74.4M|            diffs[ix] -= impact;
 1523|  74.4M|          } else {
 1524|      0|            diffs[ix] += impact;
 1525|      0|          }
 1526|  74.4M|        }
 1527|   320M|      }
 1528|   671M|    }
 1529|  13.1M|  }
 1530|       |
 1531|   287k|  size_t y0 = 0;
 1532|       |  // Top
 1533|  1.43M|  for (; y0 < 4; ++y0) {
  ------------------
  |  Branch (1533:10): [True: 1.14M, False: 287k]
  ------------------
 1534|  1.14M|    float* const BUTTERAUGLI_RESTRICT row_diff = block_diff_ac->Row(y0);
 1535|  58.2M|    for (size_t x0 = 0; x0 < xsize_; ++x0) {
  ------------------
  |  Branch (1535:25): [True: 57.1M, False: 1.14M]
  ------------------
 1536|  57.1M|      row_diff[x0] +=
 1537|  57.1M|          PaddedMaltaUnit<false, Tag>(&diffs[0], x0, y0, xsize_, ysize_);
 1538|  57.1M|    }
 1539|  1.14M|  }
 1540|       |
 1541|       |  // Middle
 1542|  11.1M|  for (; y0 < ysize_ - 4; ++y0) {
  ------------------
  |  Branch (1542:10): [True: 10.8M, False: 287k]
  ------------------
 1543|  10.8M|    float* const BUTTERAUGLI_RESTRICT row_diff = block_diff_ac->Row(y0);
 1544|  10.8M|    size_t x0 = 0;
 1545|  54.2M|    for (; x0 < 4; ++x0) {
  ------------------
  |  Branch (1545:12): [True: 43.4M, False: 10.8M]
  ------------------
 1546|  43.4M|      row_diff[x0] +=
 1547|  43.4M|          PaddedMaltaUnit<false, Tag>(&diffs[0], x0, y0, xsize_, ysize_);
 1548|  43.4M|    }
 1549|   481M|    for (; x0 < xsize_ - 4; ++x0) {
  ------------------
  |  Branch (1549:12): [True: 470M, False: 10.8M]
  ------------------
 1550|   470M|      row_diff[x0] +=
 1551|   470M|          PaddedMaltaUnit<true, Tag>(&diffs[0], x0, y0, xsize_, ysize_);
 1552|   470M|    }
 1553|       |
 1554|  54.2M|    for (; x0 < xsize_; ++x0) {
  ------------------
  |  Branch (1554:12): [True: 43.4M, False: 10.8M]
  ------------------
 1555|  43.4M|      row_diff[x0] +=
 1556|  43.4M|          PaddedMaltaUnit<false, Tag>(&diffs[0], x0, y0, xsize_, ysize_);
 1557|  43.4M|    }
 1558|  10.8M|  }
 1559|       |
 1560|       |  // Bottom
 1561|  1.43M|  for (; y0 < ysize_; ++y0) {
  ------------------
  |  Branch (1561:10): [True: 1.14M, False: 287k]
  ------------------
 1562|  1.14M|    float* const BUTTERAUGLI_RESTRICT row_diff = block_diff_ac->Row(y0);
 1563|  58.2M|    for (size_t x0 = 0; x0 < xsize_; ++x0) {
  ------------------
  |  Branch (1563:25): [True: 57.1M, False: 1.14M]
  ------------------
 1564|  57.1M|      row_diff[x0] +=
 1565|  57.1M|          PaddedMaltaUnit<false, Tag>(&diffs[0], x0, y0, xsize_, ysize_);
 1566|  57.1M|    }
 1567|  1.14M|  }
 1568|   287k|}
butteraugli.cc:_ZN11butteraugliL15PaddedMaltaUnitILb0ENS_8MaltaTagEEEfPfmmmm:
 1431|   201M|    const size_t xsize_, const size_t ysize_) {
 1432|   201M|  int ix0 = y0 * xsize_ + x0;
 1433|   201M|  const float* BUTTERAUGLI_RESTRICT d = &diffs[ix0];
 1434|   201M|  if (fastMode ||
  ------------------
  |  Branch (1434:7): [Folded, False: 201M]
  ------------------
 1435|   201M|      (x0 >= 4 && y0 >= 4 && x0 < (xsize_ - 4) && y0 < (ysize_ - 4))) {
  ------------------
  |  Branch (1435:8): [True: 148M, False: 52.6M]
  |  Branch (1435:19): [True: 95.9M, False: 52.5M]
  |  Branch (1435:30): [True: 47.9M, False: 48.0M]
  |  Branch (1435:51): [True: 0, False: 47.9M]
  ------------------
 1436|      0|    return MaltaUnit(Tag(), d, xsize_);
 1437|      0|  }
 1438|       |
 1439|   201M|  float borderimage[9 * 9];
 1440|  2.01G|  for (int dy = 0; dy < 9; ++dy) {
  ------------------
  |  Branch (1440:20): [True: 1.80G, False: 201M]
  ------------------
 1441|  1.80G|    int y = y0 + dy - 4;
 1442|  1.80G|    if (y < 0 || y >= ysize_) {
  ------------------
  |  Branch (1442:9): [True: 142M, False: 1.66G]
  |  Branch (1442:18): [True: 142M, False: 1.52G]
  ------------------
 1443|  2.85G|      for (int dx = 0; dx < 9; ++dx) {
  ------------------
  |  Branch (1443:24): [True: 2.57G, False: 285M]
  ------------------
 1444|  2.57G|        borderimage[dy * 9 + dx] = 0.0f;
 1445|  2.57G|      }
 1446|  1.52G|    } else {
 1447|  15.2G|      for (int dx = 0; dx < 9; ++dx) {
  ------------------
  |  Branch (1447:24): [True: 13.7G, False: 1.52G]
  ------------------
 1448|  13.7G|        int x = x0 + dx - 4;
 1449|  13.7G|        if (x < 0 || x >= xsize_) {
  ------------------
  |  Branch (1449:13): [True: 1.12G, False: 12.5G]
  |  Branch (1449:22): [True: 1.12G, False: 11.4G]
  ------------------
 1450|  2.25G|          borderimage[dy * 9 + dx] = 0.0f;
 1451|  11.4G|        } else {
 1452|  11.4G|          borderimage[dy * 9 + dx] = diffs[y * xsize_ + x];
 1453|  11.4G|        }
 1454|  13.7G|      }
 1455|  1.52G|    }
 1456|  1.80G|  }
 1457|   201M|  return MaltaUnit(Tag(), &borderimage[4 * 9 + 4], 9);
 1458|   201M|}
butteraugli.cc:_ZN11butteraugliL9MaltaUnitENS_8MaltaTagEPKfi:
 1147|   671M|                       const int xs) {
 1148|   671M|  const int xs3 = 3 * xs;
 1149|   671M|  float retval = 0;
 1150|   671M|  {
 1151|       |    // x grows, y constant
 1152|   671M|    float sum =
 1153|   671M|        d[-4] +
 1154|   671M|        d[-3] +
 1155|   671M|        d[-2] +
 1156|   671M|        d[-1] +
 1157|   671M|        d[0] +
 1158|   671M|        d[1] +
 1159|   671M|        d[2] +
 1160|   671M|        d[3] +
 1161|   671M|        d[4];
 1162|   671M|    retval += sum * sum;
 1163|   671M|  }
 1164|   671M|  {
 1165|       |    // y grows, x constant
 1166|   671M|    float sum =
 1167|   671M|        d[-xs3 - xs] +
 1168|   671M|        d[-xs3] +
 1169|   671M|        d[-xs - xs] +
 1170|   671M|        d[-xs] +
 1171|   671M|        d[0] +
 1172|   671M|        d[xs] +
 1173|   671M|        d[xs + xs] +
 1174|   671M|        d[xs3] +
 1175|   671M|        d[xs3 + xs];
 1176|   671M|    retval += sum * sum;
 1177|   671M|  }
 1178|   671M|  {
 1179|       |    // both grow
 1180|   671M|    float sum =
 1181|   671M|        d[-xs3 - 3] +
 1182|   671M|        d[-xs - xs - 2] +
 1183|   671M|        d[-xs - 1] +
 1184|   671M|        d[0] +
 1185|   671M|        d[xs + 1] +
 1186|   671M|        d[xs + xs + 2] +
 1187|   671M|        d[xs3 + 3];
 1188|   671M|    retval += sum * sum;
 1189|   671M|  }
 1190|   671M|  {
 1191|       |    // y grows, x shrinks
 1192|   671M|    float sum =
 1193|   671M|        d[-xs3 + 3] +
 1194|   671M|        d[-xs - xs + 2] +
 1195|   671M|        d[-xs + 1] +
 1196|   671M|        d[0] +
 1197|   671M|        d[xs - 1] +
 1198|   671M|        d[xs + xs - 2] +
 1199|   671M|        d[xs3 - 3];
 1200|   671M|    retval += sum * sum;
 1201|   671M|  }
 1202|   671M|  {
 1203|       |    // y grows -4 to 4, x shrinks 1 -> -1
 1204|   671M|    float sum =
 1205|   671M|        d[-xs3 - xs + 1] +
 1206|   671M|        d[-xs3 + 1] +
 1207|   671M|        d[-xs - xs + 1] +
 1208|   671M|        d[-xs] +
 1209|   671M|        d[0] +
 1210|   671M|        d[xs] +
 1211|   671M|        d[xs + xs - 1] +
 1212|   671M|        d[xs3 - 1] +
 1213|   671M|        d[xs3 + xs - 1];
 1214|   671M|    retval += sum * sum;
 1215|   671M|  }
 1216|   671M|  {
 1217|       |    //  y grows -4 to 4, x grows -1 -> 1
 1218|   671M|    float sum =
 1219|   671M|        d[-xs3 - xs - 1] +
 1220|   671M|        d[-xs3 - 1] +
 1221|   671M|        d[-xs - xs - 1] +
 1222|   671M|        d[-xs] +
 1223|   671M|        d[0] +
 1224|   671M|        d[xs] +
 1225|   671M|        d[xs + xs + 1] +
 1226|   671M|        d[xs3 + 1] +
 1227|   671M|        d[xs3 + xs + 1];
 1228|   671M|    retval += sum * sum;
 1229|   671M|  }
 1230|   671M|  {
 1231|       |    // x grows -4 to 4, y grows -1 to 1
 1232|   671M|    float sum =
 1233|   671M|        d[-4 - xs] +
 1234|   671M|        d[-3 - xs] +
 1235|   671M|        d[-2 - xs] +
 1236|   671M|        d[-1] +
 1237|   671M|        d[0] +
 1238|   671M|        d[1] +
 1239|   671M|        d[2 + xs] +
 1240|   671M|        d[3 + xs] +
 1241|   671M|        d[4 + xs];
 1242|   671M|    retval += sum * sum;
 1243|   671M|  }
 1244|   671M|  {
 1245|       |    // x grows -4 to 4, y shrinks 1 to -1
 1246|   671M|    float sum =
 1247|   671M|        d[-4 + xs] +
 1248|   671M|        d[-3 + xs] +
 1249|   671M|        d[-2 + xs] +
 1250|   671M|        d[-1] +
 1251|   671M|        d[0] +
 1252|   671M|        d[1] +
 1253|   671M|        d[2 - xs] +
 1254|   671M|        d[3 - xs] +
 1255|   671M|        d[4 - xs];
 1256|   671M|    retval += sum * sum;
 1257|   671M|  }
 1258|   671M|  {
 1259|       |    /* 0_________
 1260|       |       1__*______
 1261|       |       2___*_____
 1262|       |       3___*_____
 1263|       |       4____0____
 1264|       |       5_____*___
 1265|       |       6_____*___
 1266|       |       7______*__
 1267|       |       8_________ */
 1268|   671M|    float sum =
 1269|   671M|        d[-xs3 - 2] +
 1270|   671M|        d[-xs - xs - 1] +
 1271|   671M|        d[-xs - 1] +
 1272|   671M|        d[0] +
 1273|   671M|        d[xs + 1] +
 1274|   671M|        d[xs + xs + 1] +
 1275|   671M|        d[xs3 + 2];
 1276|   671M|    retval += sum * sum;
 1277|   671M|  }
 1278|   671M|  {
 1279|       |    /* 0_________
 1280|       |       1______*__
 1281|       |       2_____*___
 1282|       |       3_____*___
 1283|       |       4____0____
 1284|       |       5___*_____
 1285|       |       6___*_____
 1286|       |       7__*______
 1287|       |       8_________ */
 1288|   671M|    float sum =
 1289|   671M|        d[-xs3 + 2] +
 1290|   671M|        d[-xs - xs + 1] +
 1291|   671M|        d[-xs + 1] +
 1292|   671M|        d[0] +
 1293|   671M|        d[xs - 1] +
 1294|   671M|        d[xs + xs - 1] +
 1295|   671M|        d[xs3 - 2];
 1296|   671M|    retval += sum * sum;
 1297|   671M|  }
 1298|   671M|  {
 1299|       |    /* 0_________
 1300|       |       1_________
 1301|       |       2_*_______
 1302|       |       3__**_____
 1303|       |       4____0____
 1304|       |       5_____**__
 1305|       |       6_______*_
 1306|       |       7_________
 1307|       |       8_________ */
 1308|   671M|    float sum =
 1309|   671M|        d[-xs - xs - 3] +
 1310|   671M|        d[-xs - 2] +
 1311|   671M|        d[-xs - 1] +
 1312|   671M|        d[0] +
 1313|   671M|        d[xs + 1] +
 1314|   671M|        d[xs + 2] +
 1315|   671M|        d[xs + xs + 3];
 1316|   671M|    retval += sum * sum;
 1317|   671M|  }
 1318|   671M|  {
 1319|       |    /* 0_________
 1320|       |       1_________
 1321|       |       2_______*_
 1322|       |       3_____**__
 1323|       |       4____0____
 1324|       |       5__**_____
 1325|       |       6_*_______
 1326|       |       7_________
 1327|       |       8_________ */
 1328|   671M|    float sum =
 1329|   671M|        d[-xs - xs + 3] +
 1330|   671M|        d[-xs + 2] +
 1331|   671M|        d[-xs + 1] +
 1332|   671M|        d[0] +
 1333|   671M|        d[xs - 1] +
 1334|   671M|        d[xs - 2] +
 1335|   671M|        d[xs + xs - 3];
 1336|   671M|    retval += sum * sum;
 1337|   671M|  }
 1338|   671M|  {
 1339|       |    /* 0_________
 1340|       |       1_________
 1341|       |       2_________
 1342|       |       3______**_
 1343|       |       4____0*___
 1344|       |       5__**_____
 1345|       |       6**_______
 1346|       |       7_________
 1347|       |       8_________ */
 1348|       |
 1349|   671M|    float sum =
 1350|   671M|        d[xs + xs - 4] +
 1351|   671M|        d[xs + xs - 3] +
 1352|   671M|        d[xs - 2] +
 1353|   671M|        d[xs - 1] +
 1354|   671M|        d[0] +
 1355|   671M|        d[1] +
 1356|   671M|        d[-xs + 2] +
 1357|   671M|        d[-xs + 3];
 1358|   671M|    retval += sum * sum;
 1359|   671M|  }
 1360|   671M|  {
 1361|       |    /* 0_________
 1362|       |       1_________
 1363|       |       2**_______
 1364|       |       3__**_____
 1365|       |       4____0*___
 1366|       |       5______**_
 1367|       |       6_________
 1368|       |       7_________
 1369|       |       8_________ */
 1370|   671M|    float sum =
 1371|   671M|        d[-xs - xs - 4] +
 1372|   671M|        d[-xs - xs - 3] +
 1373|   671M|        d[-xs - 2] +
 1374|   671M|        d[-xs - 1] +
 1375|   671M|        d[0] +
 1376|   671M|        d[1] +
 1377|   671M|        d[xs + 2] +
 1378|   671M|        d[xs + 3];
 1379|   671M|    retval += sum * sum;
 1380|   671M|  }
 1381|   671M|  {
 1382|       |    /* 0__*______
 1383|       |       1__*______
 1384|       |       2___*_____
 1385|       |       3___*_____
 1386|       |       4____0____
 1387|       |       5____*____
 1388|       |       6_____*___
 1389|       |       7_____*___
 1390|       |       8_________ */
 1391|   671M|    float sum =
 1392|   671M|        d[-xs3 - xs - 2] +
 1393|   671M|        d[-xs3 - 2] +
 1394|   671M|        d[-xs - xs - 1] +
 1395|   671M|        d[-xs - 1] +
 1396|   671M|        d[0] +
 1397|   671M|        d[xs] +
 1398|   671M|        d[xs + xs + 1] +
 1399|   671M|        d[xs3 + 1];
 1400|   671M|    retval += sum * sum;
 1401|   671M|  }
 1402|   671M|  {
 1403|       |    /* 0______*__
 1404|       |       1______*__
 1405|       |       2_____*___
 1406|       |       3_____*___
 1407|       |       4____0____
 1408|       |       5____*____
 1409|       |       6___*_____
 1410|       |       7___*_____
 1411|       |       8_________ */
 1412|   671M|    float sum =
 1413|   671M|        d[-xs3 - xs + 2] +
 1414|   671M|        d[-xs3 + 2] +
 1415|   671M|        d[-xs - xs + 1] +
 1416|   671M|        d[-xs + 1] +
 1417|   671M|        d[0] +
 1418|   671M|        d[xs] +
 1419|   671M|        d[xs + xs - 1] +
 1420|   671M|        d[xs3 - 1];
 1421|   671M|    retval += sum * sum;
 1422|   671M|  }
 1423|   671M|  return retval;
 1424|   671M|}
butteraugli.cc:_ZN11butteraugliL15PaddedMaltaUnitILb1ENS_8MaltaTagEEEfPfmmmm:
 1431|   470M|    const size_t xsize_, const size_t ysize_) {
 1432|   470M|  int ix0 = y0 * xsize_ + x0;
 1433|   470M|  const float* BUTTERAUGLI_RESTRICT d = &diffs[ix0];
 1434|   470M|  if (fastMode ||
  ------------------
  |  Branch (1434:7): [True: 470M, Folded]
  ------------------
 1435|   470M|      (x0 >= 4 && y0 >= 4 && x0 < (xsize_ - 4) && y0 < (ysize_ - 4))) {
  ------------------
  |  Branch (1435:8): [True: 0, False: 0]
  |  Branch (1435:19): [True: 0, False: 0]
  |  Branch (1435:30): [True: 0, False: 0]
  |  Branch (1435:51): [True: 0, False: 0]
  ------------------
 1436|   470M|    return MaltaUnit(Tag(), d, xsize_);
 1437|   470M|  }
 1438|       |
 1439|      0|  float borderimage[9 * 9];
 1440|      0|  for (int dy = 0; dy < 9; ++dy) {
  ------------------
  |  Branch (1440:20): [True: 0, False: 0]
  ------------------
 1441|      0|    int y = y0 + dy - 4;
 1442|      0|    if (y < 0 || y >= ysize_) {
  ------------------
  |  Branch (1442:9): [True: 0, False: 0]
  |  Branch (1442:18): [True: 0, False: 0]
  ------------------
 1443|      0|      for (int dx = 0; dx < 9; ++dx) {
  ------------------
  |  Branch (1443:24): [True: 0, False: 0]
  ------------------
 1444|      0|        borderimage[dy * 9 + dx] = 0.0f;
 1445|      0|      }
 1446|      0|    } else {
 1447|      0|      for (int dx = 0; dx < 9; ++dx) {
  ------------------
  |  Branch (1447:24): [True: 0, False: 0]
  ------------------
 1448|      0|        int x = x0 + dx - 4;
 1449|      0|        if (x < 0 || x >= xsize_) {
  ------------------
  |  Branch (1449:13): [True: 0, False: 0]
  |  Branch (1449:22): [True: 0, False: 0]
  ------------------
 1450|      0|          borderimage[dy * 9 + dx] = 0.0f;
 1451|      0|        } else {
 1452|      0|          borderimage[dy * 9 + dx] = diffs[y * xsize_ + x];
 1453|      0|        }
 1454|      0|      }
 1455|      0|    }
 1456|      0|  }
 1457|      0|  return MaltaUnit(Tag(), &borderimage[4 * 9 + 4], 9);
 1458|   470M|}
butteraugli.cc:_ZN11butteraugliL16MaltaDiffMapImplINS_10MaltaTagLFEEEvRKNS_5ImageIfEES5_mmdddddPS3_:
 1467|   574k|                             ImageF* block_diff_ac) {
 1468|   574k|  const float kWeight0 = 0.5;
 1469|   574k|  const float kWeight1 = 0.33;
 1470|       |
 1471|   574k|  const double w_pre0gt1 = mulli * sqrt(kWeight0 * w_0gt1) / (len * 2 + 1);
 1472|   574k|  const double w_pre0lt1 = mulli * sqrt(kWeight1 * w_0lt1) / (len * 2 + 1);
 1473|   574k|  const float norm2_0gt1 = w_pre0gt1 * norm1;
 1474|   574k|  const float norm2_0lt1 = w_pre0lt1 * norm1;
 1475|       |
 1476|   574k|  std::vector<float> diffs(ysize_ * xsize_);
 1477|  26.8M|  for (size_t y = 0, ix = 0; y < ysize_; ++y) {
  ------------------
  |  Branch (1477:30): [True: 26.3M, False: 574k]
  ------------------
 1478|  26.3M|    const float* BUTTERAUGLI_RESTRICT const row0 = lum0.Row(y);
 1479|  26.3M|    const float* BUTTERAUGLI_RESTRICT const row1 = lum1.Row(y);
 1480|  1.36G|    for (size_t x = 0; x < xsize_; ++x, ++ix) {
  ------------------
  |  Branch (1480:24): [True: 1.34G, False: 26.3M]
  ------------------
 1481|  1.34G|      const float absval = 0.5 * std::abs(row0[x]) + 0.5 * std::abs(row1[x]);
 1482|  1.34G|      const float diff = row0[x] - row1[x];
 1483|  1.34G|      const float scaler = norm2_0gt1 / (static_cast<float>(norm1) + absval);
 1484|       |
 1485|       |      // Primary symmetric quadratic objective.
 1486|  1.34G|      diffs[ix] = scaler * diff;
 1487|       |
 1488|  1.34G|      const float scaler2 = norm2_0lt1 / (static_cast<float>(norm1) + absval);
 1489|  1.34G|      const double fabs0 = fabs(row0[x]);
 1490|       |
 1491|       |      // Secondary half-open quadratic objectives.
 1492|  1.34G|      const double too_small = 0.55 * fabs0;
 1493|  1.34G|      const double too_big = 1.05 * fabs0;
 1494|       |
 1495|  1.34G|      if (row0[x] < 0) {
  ------------------
  |  Branch (1495:11): [True: 476M, False: 866M]
  ------------------
 1496|   476M|        if (row1[x] > -too_small) {
  ------------------
  |  Branch (1496:13): [True: 42.4M, False: 433M]
  ------------------
 1497|  42.4M|          double impact = scaler2 * (row1[x] + too_small);
 1498|  42.4M|          if (diff < 0) {
  ------------------
  |  Branch (1498:15): [True: 42.4M, False: 0]
  ------------------
 1499|  42.4M|            diffs[ix] -= impact;
 1500|  42.4M|          } else {
 1501|      0|            diffs[ix] += impact;
 1502|      0|          }
 1503|   433M|        } else if (row1[x] < -too_big) {
  ------------------
  |  Branch (1503:20): [True: 109M, False: 324M]
  ------------------
 1504|   109M|          double impact = scaler2 * (-row1[x] - too_big);
 1505|   109M|          if (diff < 0) {
  ------------------
  |  Branch (1505:15): [True: 0, False: 109M]
  ------------------
 1506|      0|            diffs[ix] -= impact;
 1507|   109M|          } else {
 1508|   109M|            diffs[ix] += impact;
 1509|   109M|          }
 1510|   109M|        }
 1511|   866M|      } else {
 1512|   866M|        if (row1[x] < too_small) {
  ------------------
  |  Branch (1512:13): [True: 49.4M, False: 816M]
  ------------------
 1513|  49.4M|          double impact = scaler2 * (too_small - row1[x]);
 1514|  49.4M|          if (diff < 0) {
  ------------------
  |  Branch (1514:15): [True: 0, False: 49.4M]
  ------------------
 1515|      0|            diffs[ix] -= impact;
 1516|  49.4M|          } else {
 1517|  49.4M|            diffs[ix] += impact;
 1518|  49.4M|          }
 1519|   816M|        } else if (row1[x] > too_big) {
  ------------------
  |  Branch (1519:20): [True: 113M, False: 703M]
  ------------------
 1520|   113M|          double impact = scaler2 * (row1[x] - too_big);
 1521|   113M|          if (diff < 0) {
  ------------------
  |  Branch (1521:15): [True: 113M, False: 0]
  ------------------
 1522|   113M|            diffs[ix] -= impact;
 1523|   113M|          } else {
 1524|      0|            diffs[ix] += impact;
 1525|      0|          }
 1526|   113M|        }
 1527|   866M|      }
 1528|  1.34G|    }
 1529|  26.3M|  }
 1530|       |
 1531|   574k|  size_t y0 = 0;
 1532|       |  // Top
 1533|  2.87M|  for (; y0 < 4; ++y0) {
  ------------------
  |  Branch (1533:10): [True: 2.29M, False: 574k]
  ------------------
 1534|  2.29M|    float* const BUTTERAUGLI_RESTRICT row_diff = block_diff_ac->Row(y0);
 1535|   116M|    for (size_t x0 = 0; x0 < xsize_; ++x0) {
  ------------------
  |  Branch (1535:25): [True: 114M, False: 2.29M]
  ------------------
 1536|   114M|      row_diff[x0] +=
 1537|   114M|          PaddedMaltaUnit<false, Tag>(&diffs[0], x0, y0, xsize_, ysize_);
 1538|   114M|    }
 1539|  2.29M|  }
 1540|       |
 1541|       |  // Middle
 1542|  22.2M|  for (; y0 < ysize_ - 4; ++y0) {
  ------------------
  |  Branch (1542:10): [True: 21.7M, False: 574k]
  ------------------
 1543|  21.7M|    float* const BUTTERAUGLI_RESTRICT row_diff = block_diff_ac->Row(y0);
 1544|  21.7M|    size_t x0 = 0;
 1545|   108M|    for (; x0 < 4; ++x0) {
  ------------------
  |  Branch (1545:12): [True: 86.8M, False: 21.7M]
  ------------------
 1546|  86.8M|      row_diff[x0] +=
 1547|  86.8M|          PaddedMaltaUnit<false, Tag>(&diffs[0], x0, y0, xsize_, ysize_);
 1548|  86.8M|    }
 1549|   962M|    for (; x0 < xsize_ - 4; ++x0) {
  ------------------
  |  Branch (1549:12): [True: 940M, False: 21.7M]
  ------------------
 1550|   940M|      row_diff[x0] +=
 1551|   940M|          PaddedMaltaUnit<true, Tag>(&diffs[0], x0, y0, xsize_, ysize_);
 1552|   940M|    }
 1553|       |
 1554|   108M|    for (; x0 < xsize_; ++x0) {
  ------------------
  |  Branch (1554:12): [True: 86.8M, False: 21.7M]
  ------------------
 1555|  86.8M|      row_diff[x0] +=
 1556|  86.8M|          PaddedMaltaUnit<false, Tag>(&diffs[0], x0, y0, xsize_, ysize_);
 1557|  86.8M|    }
 1558|  21.7M|  }
 1559|       |
 1560|       |  // Bottom
 1561|  2.87M|  for (; y0 < ysize_; ++y0) {
  ------------------
  |  Branch (1561:10): [True: 2.29M, False: 574k]
  ------------------
 1562|  2.29M|    float* const BUTTERAUGLI_RESTRICT row_diff = block_diff_ac->Row(y0);
 1563|   116M|    for (size_t x0 = 0; x0 < xsize_; ++x0) {
  ------------------
  |  Branch (1563:25): [True: 114M, False: 2.29M]
  ------------------
 1564|   114M|      row_diff[x0] +=
 1565|   114M|          PaddedMaltaUnit<false, Tag>(&diffs[0], x0, y0, xsize_, ysize_);
 1566|   114M|    }
 1567|  2.29M|  }
 1568|   574k|}
butteraugli.cc:_ZN11butteraugliL15PaddedMaltaUnitILb0ENS_10MaltaTagLFEEEfPfmmmm:
 1431|   402M|    const size_t xsize_, const size_t ysize_) {
 1432|   402M|  int ix0 = y0 * xsize_ + x0;
 1433|   402M|  const float* BUTTERAUGLI_RESTRICT d = &diffs[ix0];
 1434|   402M|  if (fastMode ||
  ------------------
  |  Branch (1434:7): [Folded, False: 402M]
  ------------------
 1435|   402M|      (x0 >= 4 && y0 >= 4 && x0 < (xsize_ - 4) && y0 < (ysize_ - 4))) {
  ------------------
  |  Branch (1435:8): [True: 296M, False: 105M]
  |  Branch (1435:19): [True: 191M, False: 105M]
  |  Branch (1435:30): [True: 95.8M, False: 96.0M]
  |  Branch (1435:51): [True: 0, False: 95.8M]
  ------------------
 1436|      0|    return MaltaUnit(Tag(), d, xsize_);
 1437|      0|  }
 1438|       |
 1439|   402M|  float borderimage[9 * 9];
 1440|  4.02G|  for (int dy = 0; dy < 9; ++dy) {
  ------------------
  |  Branch (1440:20): [True: 3.61G, False: 402M]
  ------------------
 1441|  3.61G|    int y = y0 + dy - 4;
 1442|  3.61G|    if (y < 0 || y >= ysize_) {
  ------------------
  |  Branch (1442:9): [True: 285M, False: 3.33G]
  |  Branch (1442:18): [True: 285M, False: 3.04G]
  ------------------
 1443|  5.71G|      for (int dx = 0; dx < 9; ++dx) {
  ------------------
  |  Branch (1443:24): [True: 5.14G, False: 571M]
  ------------------
 1444|  5.14G|        borderimage[dy * 9 + dx] = 0.0f;
 1445|  5.14G|      }
 1446|  3.04G|    } else {
 1447|  30.4G|      for (int dx = 0; dx < 9; ++dx) {
  ------------------
  |  Branch (1447:24): [True: 27.4G, False: 3.04G]
  ------------------
 1448|  27.4G|        int x = x0 + dx - 4;
 1449|  27.4G|        if (x < 0 || x >= xsize_) {
  ------------------
  |  Branch (1449:13): [True: 2.25G, False: 25.1G]
  |  Branch (1449:22): [True: 2.25G, False: 22.9G]
  ------------------
 1450|  4.50G|          borderimage[dy * 9 + dx] = 0.0f;
 1451|  22.9G|        } else {
 1452|  22.9G|          borderimage[dy * 9 + dx] = diffs[y * xsize_ + x];
 1453|  22.9G|        }
 1454|  27.4G|      }
 1455|  3.04G|    }
 1456|  3.61G|  }
 1457|   402M|  return MaltaUnit(Tag(), &borderimage[4 * 9 + 4], 9);
 1458|   402M|}
butteraugli.cc:_ZN11butteraugliL9MaltaUnitENS_10MaltaTagLFEPKfi:
  915|  1.34G|                       const int xs) {
  916|  1.34G|  const int xs3 = 3 * xs;
  917|  1.34G|  float retval = 0;
  918|  1.34G|  {
  919|       |    // x grows, y constant
  920|  1.34G|    float sum =
  921|  1.34G|        d[-4] +
  922|  1.34G|        d[-2] +
  923|  1.34G|        d[0] +
  924|  1.34G|        d[2] +
  925|  1.34G|        d[4];
  926|  1.34G|    retval += sum * sum;
  927|  1.34G|  }
  928|  1.34G|  {
  929|       |    // y grows, x constant
  930|  1.34G|    float sum =
  931|  1.34G|        d[-xs3 - xs] +
  932|  1.34G|        d[-xs - xs] +
  933|  1.34G|        d[0] +
  934|  1.34G|        d[xs + xs] +
  935|  1.34G|        d[xs3 + xs];
  936|  1.34G|    retval += sum * sum;
  937|  1.34G|  }
  938|  1.34G|  {
  939|       |    // both grow
  940|  1.34G|    float sum =
  941|  1.34G|        d[-xs3 - 3] +
  942|  1.34G|        d[-xs - xs - 2] +
  943|  1.34G|        d[0] +
  944|  1.34G|        d[xs + xs + 2] +
  945|  1.34G|        d[xs3 + 3];
  946|  1.34G|    retval += sum * sum;
  947|  1.34G|  }
  948|  1.34G|  {
  949|       |    // y grows, x shrinks
  950|  1.34G|    float sum =
  951|  1.34G|        d[-xs3 + 3] +
  952|  1.34G|        d[-xs - xs + 2] +
  953|  1.34G|        d[0] +
  954|  1.34G|        d[xs + xs - 2] +
  955|  1.34G|        d[xs3 - 3];
  956|  1.34G|    retval += sum * sum;
  957|  1.34G|  }
  958|  1.34G|  {
  959|       |    // y grows -4 to 4, x shrinks 1 -> -1
  960|  1.34G|    float sum =
  961|  1.34G|        d[-xs3 - xs + 1] +
  962|  1.34G|        d[-xs - xs + 1] +
  963|  1.34G|        d[0] +
  964|  1.34G|        d[xs + xs - 1] +
  965|  1.34G|        d[xs3 + xs - 1];
  966|  1.34G|    retval += sum * sum;
  967|  1.34G|  }
  968|  1.34G|  {
  969|       |    //  y grows -4 to 4, x grows -1 -> 1
  970|  1.34G|    float sum =
  971|  1.34G|        d[-xs3 - xs - 1] +
  972|  1.34G|        d[-xs - xs - 1] +
  973|  1.34G|        d[0] +
  974|  1.34G|        d[xs + xs + 1] +
  975|  1.34G|        d[xs3 + xs + 1];
  976|  1.34G|    retval += sum * sum;
  977|  1.34G|  }
  978|  1.34G|  {
  979|       |    // x grows -4 to 4, y grows -1 to 1
  980|  1.34G|    float sum =
  981|  1.34G|        d[-4 - xs] +
  982|  1.34G|        d[-2 - xs] +
  983|  1.34G|        d[0] +
  984|  1.34G|        d[2 + xs] +
  985|  1.34G|        d[4 + xs];
  986|  1.34G|    retval += sum * sum;
  987|  1.34G|  }
  988|  1.34G|  {
  989|       |    // x grows -4 to 4, y shrinks 1 to -1
  990|  1.34G|    float sum =
  991|  1.34G|        d[-4 + xs] +
  992|  1.34G|        d[-2 + xs] +
  993|  1.34G|        d[0] +
  994|  1.34G|        d[2 - xs] +
  995|  1.34G|        d[4 - xs];
  996|  1.34G|    retval += sum * sum;
  997|  1.34G|  }
  998|  1.34G|  {
  999|       |    /* 0_________
 1000|       |       1__*______
 1001|       |       2___*_____
 1002|       |       3_________
 1003|       |       4____0____
 1004|       |       5_________
 1005|       |       6_____*___
 1006|       |       7______*__
 1007|       |       8_________ */
 1008|  1.34G|    float sum =
 1009|  1.34G|        d[-xs3 - 2] +
 1010|  1.34G|        d[-xs - xs - 1] +
 1011|  1.34G|        d[0] +
 1012|  1.34G|        d[xs + xs + 1] +
 1013|  1.34G|        d[xs3 + 2];
 1014|  1.34G|    retval += sum * sum;
 1015|  1.34G|  }
 1016|  1.34G|  {
 1017|       |    /* 0_________
 1018|       |       1______*__
 1019|       |       2_____*___
 1020|       |       3_________
 1021|       |       4____0____
 1022|       |       5_________
 1023|       |       6___*_____
 1024|       |       7__*______
 1025|       |       8_________ */
 1026|  1.34G|    float sum =
 1027|  1.34G|        d[-xs3 + 2] +
 1028|  1.34G|        d[-xs - xs + 1] +
 1029|  1.34G|        d[0] +
 1030|  1.34G|        d[xs + xs - 1] +
 1031|  1.34G|        d[xs3 - 2];
 1032|  1.34G|    retval += sum * sum;
 1033|  1.34G|  }
 1034|  1.34G|  {
 1035|       |    /* 0_________
 1036|       |       1_________
 1037|       |       2_*_______
 1038|       |       3__*______
 1039|       |       4____0____
 1040|       |       5______*__
 1041|       |       6_______*_
 1042|       |       7_________
 1043|       |       8_________ */
 1044|  1.34G|    float sum =
 1045|  1.34G|        d[-xs - xs - 3] +
 1046|  1.34G|        d[-xs - 2] +
 1047|  1.34G|        d[0] +
 1048|  1.34G|        d[xs + 2] +
 1049|  1.34G|        d[xs + xs + 3];
 1050|  1.34G|    retval += sum * sum;
 1051|  1.34G|  }
 1052|  1.34G|  {
 1053|       |    /* 0_________
 1054|       |       1_________
 1055|       |       2_______*_
 1056|       |       3______*__
 1057|       |       4____0____
 1058|       |       5__*______
 1059|       |       6_*_______
 1060|       |       7_________
 1061|       |       8_________ */
 1062|  1.34G|    float sum =
 1063|  1.34G|        d[-xs - xs + 3] +
 1064|  1.34G|        d[-xs + 2] +
 1065|  1.34G|        d[0] +
 1066|  1.34G|        d[xs - 2] +
 1067|  1.34G|        d[xs + xs - 3];
 1068|  1.34G|    retval += sum * sum;
 1069|  1.34G|  }
 1070|  1.34G|  {
 1071|       |    /* 0_________
 1072|       |       1_________
 1073|       |       2________*
 1074|       |       3______*__
 1075|       |       4____0____
 1076|       |       5__*______
 1077|       |       6*________
 1078|       |       7_________
 1079|       |       8_________ */
 1080|       |
 1081|  1.34G|    float sum =
 1082|  1.34G|        d[xs + xs - 4] +
 1083|  1.34G|        d[xs - 2] +
 1084|  1.34G|        d[0] +
 1085|  1.34G|        d[-xs + 2] +
 1086|  1.34G|        d[-xs - xs + 4];
 1087|  1.34G|    retval += sum * sum;
 1088|  1.34G|  }
 1089|  1.34G|  {
 1090|       |    /* 0_________
 1091|       |       1_________
 1092|       |       2*________
 1093|       |       3__*______
 1094|       |       4____0____
 1095|       |       5______*__
 1096|       |       6________*
 1097|       |       7_________
 1098|       |       8_________ */
 1099|  1.34G|    float sum =
 1100|  1.34G|        d[-xs - xs - 4] +
 1101|  1.34G|        d[-xs - 2] +
 1102|  1.34G|        d[0] +
 1103|  1.34G|        d[xs + 2] +
 1104|  1.34G|        d[xs + xs + 4];
 1105|  1.34G|    retval += sum * sum;
 1106|  1.34G|  }
 1107|  1.34G|  {
 1108|       |    /* 0__*______
 1109|       |       1_________
 1110|       |       2___*_____
 1111|       |       3_________
 1112|       |       4____0____
 1113|       |       5_________
 1114|       |       6_____*___
 1115|       |       7_________
 1116|       |       8______*__ */
 1117|  1.34G|    float sum =
 1118|  1.34G|        d[-xs3 - xs - 2] +
 1119|  1.34G|        d[-xs - xs - 1] +
 1120|  1.34G|        d[0] +
 1121|  1.34G|        d[xs + xs + 1] +
 1122|  1.34G|        d[xs3 + xs + 2];
 1123|  1.34G|    retval += sum * sum;
 1124|  1.34G|  }
 1125|  1.34G|  {
 1126|       |    /* 0______*__
 1127|       |       1_________
 1128|       |       2_____*___
 1129|       |       3_________
 1130|       |       4____0____
 1131|       |       5_________
 1132|       |       6___*_____
 1133|       |       7_________
 1134|       |       8__*______ */
 1135|  1.34G|    float sum =
 1136|  1.34G|        d[-xs3 - xs + 2] +
 1137|  1.34G|        d[-xs - xs + 1] +
 1138|  1.34G|        d[0] +
 1139|  1.34G|        d[xs + xs - 1] +
 1140|  1.34G|        d[xs3 + xs - 2];
 1141|  1.34G|    retval += sum * sum;
 1142|  1.34G|  }
 1143|  1.34G|  return retval;
 1144|  1.34G|}
butteraugli.cc:_ZN11butteraugliL15PaddedMaltaUnitILb1ENS_10MaltaTagLFEEEfPfmmmm:
 1431|   940M|    const size_t xsize_, const size_t ysize_) {
 1432|   940M|  int ix0 = y0 * xsize_ + x0;
 1433|   940M|  const float* BUTTERAUGLI_RESTRICT d = &diffs[ix0];
 1434|   940M|  if (fastMode ||
  ------------------
  |  Branch (1434:7): [True: 940M, Folded]
  ------------------
 1435|   940M|      (x0 >= 4 && y0 >= 4 && x0 < (xsize_ - 4) && y0 < (ysize_ - 4))) {
  ------------------
  |  Branch (1435:8): [True: 0, False: 0]
  |  Branch (1435:19): [True: 0, False: 0]
  |  Branch (1435:30): [True: 0, False: 0]
  |  Branch (1435:51): [True: 0, False: 0]
  ------------------
 1436|   940M|    return MaltaUnit(Tag(), d, xsize_);
 1437|   940M|  }
 1438|       |
 1439|      0|  float borderimage[9 * 9];
 1440|      0|  for (int dy = 0; dy < 9; ++dy) {
  ------------------
  |  Branch (1440:20): [True: 0, False: 0]
  ------------------
 1441|      0|    int y = y0 + dy - 4;
 1442|      0|    if (y < 0 || y >= ysize_) {
  ------------------
  |  Branch (1442:9): [True: 0, False: 0]
  |  Branch (1442:18): [True: 0, False: 0]
  ------------------
 1443|      0|      for (int dx = 0; dx < 9; ++dx) {
  ------------------
  |  Branch (1443:24): [True: 0, False: 0]
  ------------------
 1444|      0|        borderimage[dy * 9 + dx] = 0.0f;
 1445|      0|      }
 1446|      0|    } else {
 1447|      0|      for (int dx = 0; dx < 9; ++dx) {
  ------------------
  |  Branch (1447:24): [True: 0, False: 0]
  ------------------
 1448|      0|        int x = x0 + dx - 4;
 1449|      0|        if (x < 0 || x >= xsize_) {
  ------------------
  |  Branch (1449:13): [True: 0, False: 0]
  |  Branch (1449:22): [True: 0, False: 0]
  ------------------
 1450|      0|          borderimage[dy * 9 + dx] = 0.0f;
 1451|      0|        } else {
 1452|      0|          borderimage[dy * 9 + dx] = diffs[y * xsize_ + x];
 1453|      0|        }
 1454|      0|      }
 1455|      0|    }
 1456|      0|  }
 1457|      0|  return MaltaUnit(Tag(), &borderimage[4 * 9 + 4], 9);
 1458|   940M|}

_ZNK11butteraugli18RationalPolynomialclEd:
  581|  3.24G|  inline double operator()(const double x) const {
  582|       |    // First normalize to [0, 1].
  583|  3.24G|    const double x01 = (x - min_value) / (max_value - min_value);
  584|       |    // And then to [-1, 1] domain of Chebyshev polynomials.
  585|  3.24G|    const double xc = 2.0 * x01 - 1.0;
  586|       |
  587|  3.24G|    const double yp = EvaluatePolynomial(xc, p);
  588|  3.24G|    const double yq = EvaluatePolynomial(xc, q);
  589|  3.24G|    if (yq == 0.0) return 0.0;
  ------------------
  |  Branch (589:9): [True: 0, False: 3.24G]
  ------------------
  590|  3.24G|    return static_cast<float>(yp / yq);
  591|  3.24G|  }
_ZN11butteraugli18RationalPolynomial18EvaluatePolynomialILi6EEEddRAT__Kd:
  573|  6.49G|                                   const double (&coefficients)[N]) {
  574|  6.49G|    double b1 = 0.0;
  575|  6.49G|    double b2 = 0.0;
  576|  6.49G|    ClenshawRecursion<N - 1>(x, coefficients, &b1, &b2);
  577|  6.49G|    return b1;
  578|  6.49G|  }
butteraugli_comparator.cc:_ZN11butteraugliL12CreatePlanesIfEENSt3__16vectorINS_5ImageIT_EENS1_9allocatorIS5_EEEEmmm:
  328|   149k|                                                 const size_t num_planes) {
  329|   149k|  std::vector<Image<T>> planes;
  330|   149k|  planes.reserve(num_planes);
  331|   599k|  for (size_t i = 0; i < num_planes; ++i) {
  ------------------
  |  Branch (331:22): [True: 449k, False: 149k]
  ------------------
  332|   449k|    planes.emplace_back(xsize, ysize);
  333|   449k|  }
  334|   149k|  return planes;
  335|   149k|}
_ZN11butteraugli5ImageIfEC2EOS1_:
  250|  18.9M|      : xsize_(other.xsize_),
  251|  18.9M|        ysize_(other.ysize_),
  252|  18.9M|        bytes_per_row_(other.bytes_per_row_),
  253|  18.9M|        bytes_(std::move(other.bytes_)) {}
_ZN11butteraugli5ImageIfEC2Emm:
  222|  85.2M|      : xsize_(xsize),
  223|  85.2M|        ysize_(ysize),
  224|  85.2M|        bytes_per_row_(BytesPerRow(xsize)),
  225|  85.2M|        bytes_(Allocate(bytes_per_row_ * ysize)) {}
_ZN11butteraugli5ImageIfE11BytesPerRowEm:
  200|  86.0M|  static size_t BytesPerRow(const size_t xsize) {
  201|       |    // Allow reading one extra AVX-2 vector on the right margin.
  202|  86.0M|    const size_t row_size = xsize * sizeof(T) + 32;
  203|  86.0M|    const size_t align = CacheAligned::kCacheLineSize;
  204|  86.0M|    size_t bytes_per_row = (row_size + align - 1) & ~(align - 1);
  205|       |    // During the lengthy window before writes are committed to memory, CPUs
  206|       |    // guard against read after write hazards by checking the address, but
  207|       |    // only the lower 11 bits. We avoid a false dependency between writes to
  208|       |    // consecutive rows by ensuring their sizes are not multiples of 2 KiB.
  209|  86.0M|    if (bytes_per_row % 2048 == 0) {
  ------------------
  |  Branch (209:9): [True: 0, False: 86.0M]
  ------------------
  210|      0|      bytes_per_row += align;
  211|      0|    }
  212|  86.0M|    return bytes_per_row;
  213|  86.0M|  }
butteraugli_comparator.cc:_ZN11butteraugliL8AllocateIhEENSt3__110unique_ptrIA_T_PFvPvEEEm:
  159|  19.4M|static inline CacheAlignedUniquePtrT<T> Allocate(const size_t entries) {
  160|  19.4M|  return CacheAlignedUniquePtrT<T>(
  161|  19.4M|      static_cast<T * const BUTTERAUGLI_RESTRICT>(
  162|  19.4M|          CacheAligned::Allocate(entries * sizeof(T))),
  163|  19.4M|      CacheAligned::Free);
  164|  19.4M|}
_ZN11butteraugli5ImageIfE3RowEm:
  275|  17.4G|  T *const BUTTERAUGLI_RESTRICT Row(const size_t y) {
  276|  17.4G|#ifdef BUTTERAUGLI_ENABLE_CHECKS
  277|  17.4G|    if (y >= ysize_) {
  ------------------
  |  Branch (277:9): [True: 0, False: 17.4G]
  ------------------
  278|      0|      printf("Row %zu out of bounds (ysize=%zu)\n", y, ysize_);
  279|      0|      abort();
  280|      0|    }
  281|  17.4G|#endif
  282|  17.4G|    void *row = bytes_.get() + y * bytes_per_row_;
  283|  17.4G|    return reinterpret_cast<T *>(BUTTERAUGLI_ASSUME_ALIGNED(row, 64));
  ------------------
  |  |  137|  17.4G|#define BUTTERAUGLI_ASSUME_ALIGNED(ptr, align) __builtin_assume_aligned((ptr), (align))
  ------------------
  284|  17.4G|  }
butteraugli_comparator.cc:_ZN11butteraugliL16PlanesFromPackedIfEENSt3__16vectorINS_5ImageIT_EENS1_9allocatorIS5_EEEEmmRKNS2_INS2_IS4_NS6_IS4_EEEENS6_ISA_EEEE:
  394|  6.32M|    const std::vector<std::vector<T>> &packed) {
  395|  6.32M|  std::vector<Image<T>> planes;
  396|  6.32M|  planes.reserve(packed.size());
  397|  18.9M|  for (const std::vector<T> &p : packed) {
  ------------------
  |  Branch (397:32): [True: 18.9M, False: 6.32M]
  ------------------
  398|  18.9M|    planes.push_back(Image<T>(xsize, ysize));
  399|  18.9M|    CopyFromPacked(p, &planes.back());
  400|  18.9M|  }
  401|  6.32M|  return planes;
  402|  6.32M|}
butteraugli_comparator.cc:_ZN11butteraugliL14CopyFromPackedIfEEvRKNSt3__16vectorIT_NS1_9allocatorIS3_EEEEPNS_5ImageIS3_EE:
  379|  18.9M|static inline void CopyFromPacked(const std::vector<T> &from, Image<T> *to) {
  380|  18.9M|  const size_t xsize = to->xsize();
  381|  18.9M|  const size_t ysize = to->ysize();
  382|  18.9M|  assert(from.size() == xsize * ysize);
  ------------------
  |  Branch (382:3): [True: 18.9M, False: 0]
  ------------------
  383|   186M|  for (size_t y = 0; y < ysize; ++y) {
  ------------------
  |  Branch (383:22): [True: 167M, False: 18.9M]
  ------------------
  384|   167M|    const float* const BUTTERAUGLI_RESTRICT row_from =
  385|   167M|        from.data() + y * xsize;
  386|   167M|    float* const BUTTERAUGLI_RESTRICT row_to = to->Row(y);
  387|   167M|    memcpy(row_to, row_from, xsize * sizeof(T));
  388|   167M|  }
  389|  18.9M|}
_ZNK11butteraugli5ImageIfE5xsizeEv:
  272|  4.48G|  size_t xsize() const { return xsize_; }
_ZNK11butteraugli5ImageIfE5ysizeEv:
  273|  6.81G|  size_t ysize() const { return ysize_; }
_ZN11butteraugli5ImageIfEC2Ev:
  218|  41.7M|  Image() : xsize_(0), ysize_(0), bytes_per_row_(0),
  219|  41.7M|            bytes_(static_cast<uint8_t*>(nullptr), Ignore) {}
butteraugli_comparator.cc:_ZN11butteraugliL12CopyToPackedIfEEvRKNS_5ImageIT_EEPNSt3__16vectorIS2_NS6_9allocatorIS2_EEEE:
  361|  18.6M|static inline void CopyToPacked(const Image<T> &from, std::vector<T> *to) {
  362|  18.6M|  const size_t xsize = from.xsize();
  363|  18.6M|  const size_t ysize = from.ysize();
  364|       |#if BUTTERAUGLI_ENABLE_CHECKS
  365|       |  if (to->size() < xsize * ysize) {
  366|       |    printf("%zu x %zu exceeds %zu capacity\n", xsize, ysize, to->size());
  367|       |    abort();
  368|       |  }
  369|       |#endif
  370|   173M|  for (size_t y = 0; y < ysize; ++y) {
  ------------------
  |  Branch (370:22): [True: 154M, False: 18.6M]
  ------------------
  371|   154M|    const float* const BUTTERAUGLI_RESTRICT row_from = from.Row(y);
  372|   154M|    float* const BUTTERAUGLI_RESTRICT row_to = to->data() + y * xsize;
  373|   154M|    memcpy(row_to, row_from, xsize * sizeof(T));
  374|   154M|  }
  375|  18.6M|}
butteraugli_comparator.cc:_ZN11butteraugliL16PackedFromPlanesIfEENSt3__16vectorINS2_IT_NS1_9allocatorIS3_EEEENS4_IS6_EEEERKNS2_INS_5ImageIS3_EENS4_ISA_EEEE:
  406|  6.17M|    const std::vector<Image<T>> &planes) {
  407|  6.17M|  assert(!planes.empty());
  ------------------
  |  Branch (407:3): [True: 6.17M, False: 0]
  ------------------
  408|  6.17M|  const size_t num_pixels = planes[0].xsize() * planes[0].ysize();
  409|  6.17M|  std::vector<std::vector<T>> packed;
  410|  6.17M|  packed.reserve(planes.size());
  411|  18.5M|  for (const Image<T> &image : planes) {
  ------------------
  |  Branch (411:30): [True: 18.5M, False: 6.17M]
  ------------------
  412|  18.5M|    packed.push_back(std::vector<T>(num_pixels));
  413|  18.5M|    CopyToPacked(image, &packed.back());
  414|  18.5M|  }
  415|  6.17M|  return packed;
  416|  6.17M|}
_ZNK11butteraugli5ImageIfE3RowEm:
  286|  11.9G|  const T *const BUTTERAUGLI_RESTRICT Row(const size_t y) const {
  287|  11.9G|#ifdef BUTTERAUGLI_ENABLE_CHECKS
  288|  11.9G|    if (y >= ysize_) {
  ------------------
  |  Branch (288:9): [True: 0, False: 11.9G]
  ------------------
  289|      0|      printf("Const row %zu out of bounds (ysize=%zu)\n", y, ysize_);
  290|      0|      abort();
  291|      0|    }
  292|  11.9G|#endif
  293|  11.9G|    void *row = bytes_.get() + y * bytes_per_row_;
  294|  11.9G|    return reinterpret_cast<const T *>(BUTTERAUGLI_ASSUME_ALIGNED(row, 64));
  ------------------
  |  |  137|  11.9G|#define BUTTERAUGLI_ASSUME_ALIGNED(ptr, align) __builtin_assume_aligned((ptr), (align))
  ------------------
  295|  11.9G|  }
butteraugli.cc:_ZN11butteraugliL15GammaPolynomialEd:
  603|  3.24G|static inline double GammaPolynomial(double value) {
  604|  3.24G|  static const RationalPolynomial r = {
  605|  3.24G|    0.971783, 590.188894,
  606|  3.24G|    {
  607|  3.24G|      98.7821300963361, 164.273222212631, 92.948112871376,
  608|  3.24G|      33.8165311212688, 6.91626704983562, 0.556380877028234
  609|  3.24G|    },
  610|  3.24G|    {
  611|  3.24G|      1, 1.64339473427892, 0.89392405219969, 0.298947051776379,
  612|  3.24G|      0.0507146002577288, 0.00226495093949756
  613|  3.24G|    }};
  614|  3.24G|  return r(value);
  615|  3.24G|}
butteraugli.cc:_ZN11butteraugliL17ClenshawRecursionILi5EEEvdPKdPdS3_:
  550|  6.49G|                                     double *b1, double *b2) {
  551|  6.49G|  const double x_b1 = x * (*b1);
  552|  6.49G|  const double t = (x_b1 + x_b1) - (*b2) + coefficients[INDEX];
  553|  6.49G|  *b2 = *b1;
  554|  6.49G|  *b1 = t;
  555|       |
  556|  6.49G|  ClenshawRecursion<INDEX - 1>(x, coefficients, b1, b2);
  557|  6.49G|}
butteraugli.cc:_ZN11butteraugliL17ClenshawRecursionILi4EEEvdPKdPdS3_:
  550|  6.49G|                                     double *b1, double *b2) {
  551|  6.49G|  const double x_b1 = x * (*b1);
  552|  6.49G|  const double t = (x_b1 + x_b1) - (*b2) + coefficients[INDEX];
  553|  6.49G|  *b2 = *b1;
  554|  6.49G|  *b1 = t;
  555|       |
  556|  6.49G|  ClenshawRecursion<INDEX - 1>(x, coefficients, b1, b2);
  557|  6.49G|}
butteraugli.cc:_ZN11butteraugliL17ClenshawRecursionILi3EEEvdPKdPdS3_:
  550|  6.49G|                                     double *b1, double *b2) {
  551|  6.49G|  const double x_b1 = x * (*b1);
  552|  6.49G|  const double t = (x_b1 + x_b1) - (*b2) + coefficients[INDEX];
  553|  6.49G|  *b2 = *b1;
  554|  6.49G|  *b1 = t;
  555|       |
  556|  6.49G|  ClenshawRecursion<INDEX - 1>(x, coefficients, b1, b2);
  557|  6.49G|}
butteraugli.cc:_ZN11butteraugliL17ClenshawRecursionILi2EEEvdPKdPdS3_:
  550|  6.49G|                                     double *b1, double *b2) {
  551|  6.49G|  const double x_b1 = x * (*b1);
  552|  6.49G|  const double t = (x_b1 + x_b1) - (*b2) + coefficients[INDEX];
  553|  6.49G|  *b2 = *b1;
  554|  6.49G|  *b1 = t;
  555|       |
  556|  6.49G|  ClenshawRecursion<INDEX - 1>(x, coefficients, b1, b2);
  557|  6.49G|}
butteraugli.cc:_ZN11butteraugliL17ClenshawRecursionILi1EEEvdPKdPdS3_:
  550|  6.49G|                                     double *b1, double *b2) {
  551|  6.49G|  const double x_b1 = x * (*b1);
  552|  6.49G|  const double t = (x_b1 + x_b1) - (*b2) + coefficients[INDEX];
  553|  6.49G|  *b2 = *b1;
  554|  6.49G|  *b1 = t;
  555|       |
  556|  6.49G|  ClenshawRecursion<INDEX - 1>(x, coefficients, b1, b2);
  557|  6.49G|}
butteraugli.cc:_ZN11butteraugliL17ClenshawRecursionILi0EEEvdPKdPdS3_:
  562|  6.49G|                                 double *b1, double *b2) {
  563|  6.49G|  const double x_b1 = x * (*b1);
  564|       |  // The final iteration differs - no 2 * x_b1 here.
  565|  6.49G|  *b1 = x_b1 - (*b2) + coefficients[0];
  566|  6.49G|}
butteraugli.cc:_ZN11butteraugliL8AllocateIhEENSt3__110unique_ptrIA_T_PFvPvEEEm:
  159|  66.6M|static inline CacheAlignedUniquePtrT<T> Allocate(const size_t entries) {
  160|  66.6M|  return CacheAlignedUniquePtrT<T>(
  161|  66.6M|      static_cast<T * const BUTTERAUGLI_RESTRICT>(
  162|  66.6M|          CacheAligned::Allocate(entries * sizeof(T))),
  163|  66.6M|      CacheAligned::Free);
  164|  66.6M|}
_ZN11butteraugli5ImageIfEaSEOS1_:
  256|  42.9M|  Image &operator=(Image &&other) {
  257|  42.9M|    xsize_ = other.xsize_;
  258|  42.9M|    ysize_ = other.ysize_;
  259|  42.9M|    bytes_per_row_ = other.bytes_per_row_;
  260|  42.9M|    bytes_ = std::move(other.bytes_);
  261|  42.9M|    return *this;
  262|  42.9M|  }
_ZN11butteraugli15OpsinAbsorbanceIfEEvRKT_S3_S3_PS1_S4_S4_:
  503|  2.16G|                                        V *BUTTERAUGLI_RESTRICT out2) {
  504|       |  // https://en.wikipedia.org/wiki/Photopsin absorbance modeling.
  505|  2.16G|  static const double mixi0 = 0.254462330846;
  506|  2.16G|  static const double mixi1 = 0.488238255095;
  507|  2.16G|  static const double mixi2 = 0.0635278003854;
  508|  2.16G|  static const double mixi3 = 1.01681026909;
  509|  2.16G|  static const double mixi4 = 0.195214015766;
  510|  2.16G|  static const double mixi5 = 0.568019861857;
  511|  2.16G|  static const double mixi6 = 0.0860755536007;
  512|  2.16G|  static const double mixi7 = 1.1510118369;
  513|  2.16G|  static const double mixi8 = 0.07374607900105684;
  514|  2.16G|  static const double mixi9 = 0.06142425304154509;
  515|  2.16G|  static const double mixi10 = 0.24416850520714256;
  516|  2.16G|  static const double mixi11 = 1.20481945273;
  517|       |
  518|  2.16G|  const V mix0(mixi0);
  519|  2.16G|  const V mix1(mixi1);
  520|  2.16G|  const V mix2(mixi2);
  521|  2.16G|  const V mix3(mixi3);
  522|  2.16G|  const V mix4(mixi4);
  523|  2.16G|  const V mix5(mixi5);
  524|  2.16G|  const V mix6(mixi6);
  525|  2.16G|  const V mix7(mixi7);
  526|  2.16G|  const V mix8(mixi8);
  527|  2.16G|  const V mix9(mixi9);
  528|  2.16G|  const V mix10(mixi10);
  529|  2.16G|  const V mix11(mixi11);
  530|       |
  531|  2.16G|  *out0 = mix0 * in0 + mix1 * in1 + mix2 * in2 + mix3;
  532|  2.16G|  *out1 = mix4 * in0 + mix5 * in1 + mix6 * in2 + mix7;
  533|  2.16G|  *out2 = mix8 * in0 + mix9 * in1 + mix10 * in2 + mix11;
  534|  2.16G|}
_ZN11butteraugli8RgbToXybIfEEvRKT_S3_S3_PS1_S4_S4_:
  492|  1.08G|                                 V *BUTTERAUGLI_RESTRICT valb) {
  493|  1.08G|  *valx = r - g;
  494|  1.08G|  *valy = r + g;
  495|  1.08G|  *valb = b;
  496|  1.08G|}
butteraugli.cc:_ZN11butteraugliL12CreatePlanesIfEENSt3__16vectorINS_5ImageIT_EENS1_9allocatorIS5_EEEEmmm:
  328|   434k|                                                 const size_t num_planes) {
  329|   434k|  std::vector<Image<T>> planes;
  330|   434k|  planes.reserve(num_planes);
  331|  1.73M|  for (size_t i = 0; i < num_planes; ++i) {
  ------------------
  |  Branch (331:22): [True: 1.30M, False: 434k]
  ------------------
  332|  1.30M|    planes.emplace_back(xsize, ysize);
  333|  1.30M|  }
  334|   434k|  return planes;
  335|   434k|}
_ZN11butteraugli5ImageIfEC2Emmf:
  228|   862k|      : xsize_(xsize),
  229|   862k|        ysize_(ysize),
  230|   862k|        bytes_per_row_(BytesPerRow(xsize)),
  231|   862k|        bytes_(Allocate(bytes_per_row_ * ysize)) {
  232|  40.3M|    for (size_t y = 0; y < ysize_; ++y) {
  ------------------
  |  Branch (232:24): [True: 39.4M, False: 862k]
  ------------------
  233|  39.4M|      T* const BUTTERAUGLI_RESTRICT row = Row(y);
  234|  2.05G|      for (int x = 0; x < xsize_; ++x) {
  ------------------
  |  Branch (234:23): [True: 2.01G, False: 39.4M]
  ------------------
  235|  2.01G|        row[x] = val;
  236|  2.01G|      }
  237|  39.4M|    }
  238|   862k|  }

