_ZNK5draco28AttributeOctahedronTransform28CopyToAttributeTransformDataEPNS_22AttributeTransformDataE:
   36|    450|    AttributeTransformData* out_data) const {
   37|    450|  out_data->set_transform_type(ATTRIBUTE_OCTAHEDRON_TRANSFORM);
   38|    450|  out_data->AppendParameterValue(quantization_bits_);
   39|    450|}
_ZN5draco28AttributeOctahedronTransform25InverseTransformAttributeERKNS_14PointAttributeEPS1_:
   49|    434|    const PointAttribute& attribute, PointAttribute* target_attribute) {
   50|    434|  if (target_attribute->data_type() != DT_FLOAT32) {
  ------------------
  |  Branch (50:7): [True: 0, False: 434]
  ------------------
   51|      0|    return false;
   52|      0|  }
   53|       |
   54|    434|  const int num_points = target_attribute->size();
   55|    434|  const int num_components = target_attribute->num_components();
   56|    434|  if (num_components != 3) {
  ------------------
  |  Branch (56:7): [True: 0, False: 434]
  ------------------
   57|      0|    return false;
   58|      0|  }
   59|    434|  constexpr int kEntrySize = sizeof(float) * 3;
   60|    434|  float att_val[3];
   61|    434|  const int32_t* source_attribute_data = reinterpret_cast<const int32_t*>(
   62|    434|      attribute.GetAddress(AttributeValueIndex(0)));
   63|    434|  uint8_t* target_address =
   64|    434|      target_attribute->GetAddress(AttributeValueIndex(0));
   65|    434|  OctahedronToolBox octahedron_tool_box;
   66|    434|  if (!octahedron_tool_box.SetQuantizationBits(quantization_bits_)) {
  ------------------
  |  Branch (66:7): [True: 315, False: 119]
  ------------------
   67|    315|    return false;
   68|    315|  }
   69|  31.7M|  for (uint32_t i = 0; i < num_points; ++i) {
  ------------------
  |  Branch (69:24): [True: 31.7M, False: 119]
  ------------------
   70|  31.7M|    const int32_t s = *source_attribute_data++;
   71|  31.7M|    const int32_t t = *source_attribute_data++;
   72|  31.7M|    octahedron_tool_box.QuantizedOctahedralCoordsToUnitVector(s, t, att_val);
   73|       |
   74|       |    // Store the decoded floating point values into the attribute buffer.
   75|  31.7M|    std::memcpy(target_address, att_val, kEntrySize);
   76|  31.7M|    target_address += kEntrySize;
   77|  31.7M|  }
   78|    119|  return true;
   79|    434|}
_ZN5draco28AttributeOctahedronTransform16DecodeParametersERKNS_14PointAttributeEPNS_13DecoderBufferE:
   95|    860|    const PointAttribute& attribute, DecoderBuffer* decoder_buffer) {
   96|    860|  uint8_t quantization_bits;
   97|    860|  if (!decoder_buffer->Decode(&quantization_bits)) {
  ------------------
  |  Branch (97:7): [True: 410, False: 450]
  ------------------
   98|    410|    return false;
   99|    410|  }
  100|    450|  quantization_bits_ = quantization_bits;
  101|    450|  return true;
  102|    860|}

_ZN5draco28AttributeOctahedronTransformC2Ev:
   28|  1.11k|  AttributeOctahedronTransform() : quantization_bits_(-1) {}

_ZNK5draco30AttributeQuantizationTransform28CopyToAttributeTransformDataEPNS_22AttributeTransformDataE:
   49|    206|    AttributeTransformData* out_data) const {
   50|    206|  out_data->set_transform_type(ATTRIBUTE_QUANTIZATION_TRANSFORM);
   51|    206|  out_data->AppendParameterValue(quantization_bits_);
   52|  5.31k|  for (int i = 0; i < min_values_.size(); ++i) {
  ------------------
  |  Branch (52:19): [True: 5.10k, False: 206]
  ------------------
   53|  5.10k|    out_data->AppendParameterValue(min_values_[i]);
   54|  5.10k|  }
   55|    206|  out_data->AppendParameterValue(range_);
   56|    206|}
_ZN5draco30AttributeQuantizationTransform25InverseTransformAttributeERKNS_14PointAttributeEPS1_:
   72|     50|    const PointAttribute& attribute, PointAttribute* target_attribute) {
   73|     50|  if (target_attribute->data_type() != DT_FLOAT32) {
  ------------------
  |  Branch (73:7): [True: 0, False: 50]
  ------------------
   74|      0|    return false;
   75|      0|  }
   76|       |
   77|       |  // Convert all quantized values back to floats.
   78|     50|  const int32_t max_quantized_value =
   79|     50|      (1u << static_cast<uint32_t>(quantization_bits_)) - 1;
   80|     50|  const int num_components = target_attribute->num_components();
   81|     50|  const int entry_size = sizeof(float) * num_components;
   82|     50|  const std::unique_ptr<float[]> att_val(new float[num_components]);
   83|     50|  int quant_val_id = 0;
   84|     50|  int out_byte_pos = 0;
   85|     50|  Dequantizer dequantizer;
   86|     50|  if (!dequantizer.Init(range_, max_quantized_value)) {
  ------------------
  |  Branch (86:7): [True: 0, False: 50]
  ------------------
   87|      0|    return false;
   88|      0|  }
   89|     50|  const int32_t* const source_attribute_data = reinterpret_cast<const int32_t*>(
   90|     50|      attribute.GetAddress(AttributeValueIndex(0)));
   91|       |
   92|     50|  const int num_values = target_attribute->size();
   93|       |
   94|  18.4M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (94:24): [True: 18.4M, False: 50]
  ------------------
   95|  56.7M|    for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (95:21): [True: 38.3M, False: 18.4M]
  ------------------
   96|  38.3M|      float value =
   97|  38.3M|          dequantizer.DequantizeFloat(source_attribute_data[quant_val_id++]);
   98|  38.3M|      value = value + min_values_[c];
   99|  38.3M|      att_val[c] = value;
  100|  38.3M|    }
  101|       |    // Store the floating point value into the attribute buffer.
  102|  18.4M|    target_attribute->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
  103|  18.4M|    out_byte_pos += entry_size;
  104|  18.4M|  }
  105|     50|  return true;
  106|     50|}
_ZN5draco30AttributeQuantizationTransform19IsQuantizationValidEi:
  109|    230|    int quantization_bits) {
  110|       |  // Currently we allow only up to 30 bit quantization.
  111|    230|  return quantization_bits >= 1 && quantization_bits <= 30;
  ------------------
  |  Branch (111:10): [True: 218, False: 12]
  |  Branch (111:36): [True: 206, False: 12]
  ------------------
  112|    230|}
_ZN5draco30AttributeQuantizationTransform13SetParametersEiPKfif:
  117|    149|                                                   float range) {
  118|    149|  if (!IsQuantizationValid(quantization_bits)) {
  ------------------
  |  Branch (118:7): [True: 7, False: 142]
  ------------------
  119|      7|    return false;
  120|      7|  }
  121|    142|  quantization_bits_ = quantization_bits;
  122|    142|  min_values_.assign(min_values, min_values + num_components);
  123|    142|  range_ = range;
  124|    142|  return true;
  125|    149|}
_ZN5draco30AttributeQuantizationTransform16DecodeParametersERKNS_14PointAttributeEPNS_13DecoderBufferE:
  202|    135|    const PointAttribute& attribute, DecoderBuffer* decoder_buffer) {
  203|    135|  min_values_.resize(attribute.num_components());
  204|    135|  if (!decoder_buffer->Decode(&min_values_[0],
  ------------------
  |  Branch (204:7): [True: 44, False: 91]
  ------------------
  205|    135|                              sizeof(float) * min_values_.size())) {
  206|     44|    return false;
  207|     44|  }
  208|     91|  if (!decoder_buffer->Decode(&range_)) {
  ------------------
  |  Branch (208:7): [True: 7, False: 84]
  ------------------
  209|      7|    return false;
  210|      7|  }
  211|     84|  uint8_t quantization_bits;
  212|     84|  if (!decoder_buffer->Decode(&quantization_bits)) {
  ------------------
  |  Branch (212:7): [True: 3, False: 81]
  ------------------
  213|      3|    return false;
  214|      3|  }
  215|     81|  if (!IsQuantizationValid(quantization_bits)) {
  ------------------
  |  Branch (215:7): [True: 17, False: 64]
  ------------------
  216|     17|    return false;
  217|     17|  }
  218|     64|  quantization_bits_ = quantization_bits;
  219|     64|  return true;
  220|     81|}

_ZN5draco30AttributeQuantizationTransformC2Ev:
   29|    406|  AttributeQuantizationTransform() : quantization_bits_(-1), range_(0.f) {}
_ZNK5draco30AttributeQuantizationTransform17quantization_bitsEv:
   59|     62|  int32_t quantization_bits() const { return quantization_bits_; }
_ZNK5draco30AttributeQuantizationTransform5rangeEv:
   62|     62|  float range() const { return range_; }

_ZNK5draco18AttributeTransform19TransferToAttributeEPNS_14PointAttributeE:
   19|    656|bool AttributeTransform::TransferToAttribute(PointAttribute* attribute) const {
   20|    656|  std::unique_ptr<AttributeTransformData> transform_data(
   21|    656|      new AttributeTransformData());
   22|    656|  this->CopyToAttributeTransformData(transform_data.get());
   23|    656|  attribute->SetAttributeTransformData(std::move(transform_data));
   24|    656|  return true;
   25|    656|}

_ZN5draco18AttributeTransformD2Ev:
   29|  1.76k|  virtual ~AttributeTransform() = default;

_ZN5draco22AttributeTransformDataC2Ev:
   32|    656|  AttributeTransformData() : transform_type_(ATTRIBUTE_INVALID_TRANSFORM) {}
_ZN5draco22AttributeTransformData18set_transform_typeENS_22AttributeTransformTypeE:
   37|    656|  void set_transform_type(AttributeTransformType type) {
   38|    656|    transform_type_ = type;
   39|    656|  }
_ZN5draco22AttributeTransformDataC2ERKS0_:
   33|     47|  AttributeTransformData(const AttributeTransformData& data) = default;
_ZN5draco22AttributeTransformData20AppendParameterValueIiEEvRKT_:
   60|    656|  void AppendParameterValue(const DataTypeT& in_data) {
   61|    656|    SetParameterValue(static_cast<int>(buffer_.data_size()), in_data);
   62|    656|  }
_ZN5draco22AttributeTransformData17SetParameterValueIiEEviRKT_:
   51|    656|  void SetParameterValue(int byte_offset, const DataTypeT& in_data) {
   52|    656|    if (byte_offset + sizeof(DataTypeT) > buffer_.data_size()) {
  ------------------
  |  Branch (52:9): [True: 656, False: 0]
  ------------------
   53|    656|      buffer_.Resize(byte_offset + sizeof(DataTypeT));
   54|    656|    }
   55|    656|    buffer_.Write(byte_offset, &in_data, sizeof(DataTypeT));
   56|    656|  }
_ZN5draco22AttributeTransformData20AppendParameterValueIfEEvRKT_:
   60|  5.31k|  void AppendParameterValue(const DataTypeT& in_data) {
   61|  5.31k|    SetParameterValue(static_cast<int>(buffer_.data_size()), in_data);
   62|  5.31k|  }
_ZN5draco22AttributeTransformData17SetParameterValueIfEEviRKT_:
   51|  5.31k|  void SetParameterValue(int byte_offset, const DataTypeT& in_data) {
   52|  5.31k|    if (byte_offset + sizeof(DataTypeT) > buffer_.data_size()) {
  ------------------
  |  Branch (52:9): [True: 5.31k, False: 0]
  ------------------
   53|  5.31k|      buffer_.Resize(byte_offset + sizeof(DataTypeT));
   54|  5.31k|    }
   55|  5.31k|    buffer_.Write(byte_offset, &in_data, sizeof(DataTypeT));
   56|  5.31k|  }

_ZN5draco17GeometryAttributeC2Ev:
   20|  41.6k|    : buffer_(nullptr),
   21|  41.6k|      num_components_(1),
   22|  41.6k|      data_type_(DT_FLOAT32),
   23|  41.6k|      byte_stride_(0),
   24|  41.6k|      byte_offset_(0),
   25|  41.6k|      attribute_type_(INVALID),
   26|  41.6k|      unique_id_(0) {}
_ZN5draco17GeometryAttribute4InitENS0_4TypeEPNS_10DataBufferEhNS_8DataTypeEbll:
   31|  41.6k|                             int64_t byte_stride, int64_t byte_offset) {
   32|  41.6k|  buffer_ = buffer;
   33|  41.6k|  if (buffer) {
  ------------------
  |  Branch (33:7): [True: 0, False: 41.6k]
  ------------------
   34|      0|    buffer_descriptor_.buffer_id = buffer->buffer_id();
   35|      0|    buffer_descriptor_.buffer_update_count = buffer->update_count();
   36|      0|  }
   37|  41.6k|  num_components_ = num_components;
   38|  41.6k|  data_type_ = data_type;
   39|  41.6k|  normalized_ = normalized;
   40|  41.6k|  byte_stride_ = byte_stride;
   41|  41.6k|  byte_offset_ = byte_offset;
   42|  41.6k|  attribute_type_ = attribute_type;
   43|  41.6k|}
_ZN5draco17GeometryAttribute8CopyFromERKS0_:
   45|  1.24k|bool GeometryAttribute::CopyFrom(const GeometryAttribute& src_att) {
   46|  1.24k|  num_components_ = src_att.num_components_;
   47|  1.24k|  data_type_ = src_att.data_type_;
   48|  1.24k|  normalized_ = src_att.normalized_;
   49|  1.24k|  byte_stride_ = src_att.byte_stride_;
   50|  1.24k|  byte_offset_ = src_att.byte_offset_;
   51|  1.24k|  attribute_type_ = src_att.attribute_type_;
   52|  1.24k|  buffer_descriptor_ = src_att.buffer_descriptor_;
   53|  1.24k|  unique_id_ = src_att.unique_id_;
   54|  1.24k|  if (src_att.buffer_ == nullptr) {
  ------------------
  |  Branch (54:7): [True: 0, False: 1.24k]
  ------------------
   55|      0|    buffer_ = nullptr;
   56|  1.24k|  } else {
   57|  1.24k|    if (buffer_ == nullptr) {
  ------------------
  |  Branch (57:9): [True: 0, False: 1.24k]
  ------------------
   58|      0|      return false;
   59|      0|    }
   60|  1.24k|    buffer_->Update(src_att.buffer_->data(), src_att.buffer_->data_size());
   61|  1.24k|  }
   62|       |#ifdef DRACO_TRANSCODER_SUPPORTED
   63|       |  name_ = src_att.name_;
   64|       |#endif
   65|  1.24k|  return true;
   66|  1.24k|}
_ZN5draco17GeometryAttribute11ResetBufferEPNS_10DataBufferEll:
  102|  24.9k|                                    int64_t byte_offset) {
  103|  24.9k|  buffer_ = buffer;
  104|  24.9k|  buffer_descriptor_.buffer_id = buffer->buffer_id();
  105|  24.9k|  buffer_descriptor_.buffer_update_count = buffer->update_count();
  106|  24.9k|  byte_stride_ = byte_stride;
  107|  24.9k|  byte_offset_ = byte_offset;
  108|  24.9k|}

_ZNK5draco17GeometryAttribute10GetBytePosENS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEE:
  118|  19.1M|  inline int64_t GetBytePos(AttributeValueIndex att_index) const {
  119|  19.1M|    return byte_offset_ + byte_stride_ * att_index.value();
  120|  19.1M|  }
_ZNK5draco17GeometryAttribute10GetAddressENS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEE:
  122|  19.1M|  inline const uint8_t* GetAddress(AttributeValueIndex att_index) const {
  123|  19.1M|    const int64_t byte_pos = GetBytePos(att_index);
  124|  19.1M|    return buffer_->data() + byte_pos;
  125|  19.1M|  }
_ZN5draco17GeometryAttribute10GetAddressENS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEE:
  126|  11.7k|  inline uint8_t* GetAddress(AttributeValueIndex att_index) {
  127|  11.7k|    const int64_t byte_pos = GetBytePos(att_index);
  128|  11.7k|    return buffer_->data() + byte_pos;
  129|  11.7k|  }
_ZNK5draco17GeometryAttribute14IsAddressValidEPKh:
  130|  57.5M|  inline bool IsAddressValid(const uint8_t* address) const {
  131|  57.5M|    return ((buffer_->data() + buffer_->data_size()) > address);
  132|  57.5M|  }
_ZNK5draco17GeometryAttribute8GetValueENS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEEPv:
  136|  40.6M|  void GetValue(AttributeValueIndex att_index, void* out_data) const {
  137|  40.6M|    const int64_t byte_pos = byte_offset_ + byte_stride_ * att_index.value();
  138|  40.6M|    buffer_->Read(byte_pos, out_data, byte_stride_);
  139|  40.6M|  }
_ZN5draco17GeometryAttribute17SetAttributeValueENS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEEPKv:
  143|   425M|  void SetAttributeValue(AttributeValueIndex entry_index, const void* value) {
  144|   425M|    const int64_t byte_pos = entry_index.value() * byte_stride();
  145|   425M|    buffer_->Write(byte_pos, value, byte_stride());
  146|   425M|  }
_ZNK5draco17GeometryAttribute14attribute_typeEv:
  266|  79.3k|  Type attribute_type() const { return attribute_type_; }
_ZNK5draco17GeometryAttribute9data_typeEv:
  269|  47.1k|  DataType data_type() const { return data_type_; }
_ZNK5draco17GeometryAttribute14num_componentsEv:
  273|  81.4M|  uint8_t num_components() const { return num_components_; }
_ZNK5draco17GeometryAttribute11byte_strideEv:
  282|   850M|  int64_t byte_stride() const { return byte_stride_; }
_ZNK5draco17GeometryAttribute9unique_idEv:
  287|  9.52k|  uint32_t unique_id() const { return unique_id_; }
_ZN5draco17GeometryAttribute13set_unique_idEj:
  288|   104k|  void set_unique_id(uint32_t id) { unique_id_ = id; }
_ZNK5draco17GeometryAttribute12ConvertValueIlEEbNS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEEPT_:
  229|  19.1M|  bool ConvertValue(AttributeValueIndex att_index, OutT* out_value) const {
  230|  19.1M|    return ConvertValue<OutT>(att_index, num_components_, out_value);
  231|  19.1M|  }
_ZNK5draco17GeometryAttribute12ConvertValueIlEEbNS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEEaPT_:
  179|  19.1M|                    OutT* out_val) const {
  180|  19.1M|    if (out_val == nullptr) {
  ------------------
  |  Branch (180:9): [True: 0, False: 19.1M]
  ------------------
  181|      0|      return false;
  182|      0|    }
  183|  19.1M|    switch (data_type_) {
  184|      0|      case DT_INT8:
  ------------------
  |  Branch (184:7): [True: 0, False: 19.1M]
  ------------------
  185|      0|        return ConvertTypedValue<int8_t, OutT>(att_id, out_num_components,
  186|      0|                                               out_val);
  187|      0|      case DT_UINT8:
  ------------------
  |  Branch (187:7): [True: 0, False: 19.1M]
  ------------------
  188|      0|        return ConvertTypedValue<uint8_t, OutT>(att_id, out_num_components,
  189|      0|                                                out_val);
  190|      0|      case DT_INT16:
  ------------------
  |  Branch (190:7): [True: 0, False: 19.1M]
  ------------------
  191|      0|        return ConvertTypedValue<int16_t, OutT>(att_id, out_num_components,
  192|      0|                                                out_val);
  193|      0|      case DT_UINT16:
  ------------------
  |  Branch (193:7): [True: 0, False: 19.1M]
  ------------------
  194|      0|        return ConvertTypedValue<uint16_t, OutT>(att_id, out_num_components,
  195|      0|                                                 out_val);
  196|  19.1M|      case DT_INT32:
  ------------------
  |  Branch (196:7): [True: 19.1M, False: 0]
  ------------------
  197|  19.1M|        return ConvertTypedValue<int32_t, OutT>(att_id, out_num_components,
  198|  19.1M|                                                out_val);
  199|      0|      case DT_UINT32:
  ------------------
  |  Branch (199:7): [True: 0, False: 19.1M]
  ------------------
  200|      0|        return ConvertTypedValue<uint32_t, OutT>(att_id, out_num_components,
  201|      0|                                                 out_val);
  202|      0|      case DT_INT64:
  ------------------
  |  Branch (202:7): [True: 0, False: 19.1M]
  ------------------
  203|      0|        return ConvertTypedValue<int64_t, OutT>(att_id, out_num_components,
  204|      0|                                                out_val);
  205|      0|      case DT_UINT64:
  ------------------
  |  Branch (205:7): [True: 0, False: 19.1M]
  ------------------
  206|      0|        return ConvertTypedValue<uint64_t, OutT>(att_id, out_num_components,
  207|      0|                                                 out_val);
  208|      0|      case DT_FLOAT32:
  ------------------
  |  Branch (208:7): [True: 0, False: 19.1M]
  ------------------
  209|      0|        return ConvertTypedValue<float, OutT>(att_id, out_num_components,
  210|      0|                                              out_val);
  211|      0|      case DT_FLOAT64:
  ------------------
  |  Branch (211:7): [True: 0, False: 19.1M]
  ------------------
  212|      0|        return ConvertTypedValue<double, OutT>(att_id, out_num_components,
  213|      0|                                               out_val);
  214|      0|      case DT_BOOL:
  ------------------
  |  Branch (214:7): [True: 0, False: 19.1M]
  ------------------
  215|      0|        return ConvertTypedValue<bool, OutT>(att_id, out_num_components,
  216|      0|                                             out_val);
  217|      0|      default:
  ------------------
  |  Branch (217:7): [True: 0, False: 19.1M]
  ------------------
  218|       |        // Wrong attribute type.
  219|      0|        return false;
  220|  19.1M|    }
  221|  19.1M|  }
_ZNK5draco17GeometryAttribute17ConvertTypedValueIilEEbNS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEEhPT0_:
  306|  19.1M|                         OutT* out_value) const {
  307|  19.1M|    const uint8_t* src_address = GetAddress(att_id);
  308|       |
  309|       |    // Convert all components available in both the original and output formats.
  310|  76.6M|    for (int i = 0; i < std::min(num_components_, out_num_components); ++i) {
  ------------------
  |  Branch (310:21): [True: 57.4M, False: 19.1M]
  ------------------
  311|  57.4M|      if (!IsAddressValid(src_address)) {
  ------------------
  |  Branch (311:11): [True: 0, False: 57.4M]
  ------------------
  312|      0|        return false;
  313|      0|      }
  314|  57.4M|      const T in_value = *reinterpret_cast<const T*>(src_address);
  315|  57.4M|      if (!ConvertComponentValue<T, OutT>(in_value, normalized_,
  ------------------
  |  Branch (315:11): [True: 0, False: 57.4M]
  ------------------
  316|  57.4M|                                          out_value + i)) {
  317|      0|        return false;
  318|      0|      }
  319|  57.4M|      src_address += sizeof(T);
  320|  57.4M|    }
  321|       |    // Fill empty data for unused output components if needed.
  322|  19.1M|    for (int i = num_components_; i < out_num_components; ++i) {
  ------------------
  |  Branch (322:35): [True: 0, False: 19.1M]
  ------------------
  323|      0|      out_value[i] = static_cast<OutT>(0);
  324|      0|    }
  325|  19.1M|    return true;
  326|  19.1M|  }
_ZN5draco17GeometryAttribute21ConvertComponentValueIilEEbRKT_bPT0_:
  364|  57.4M|                                    OutT* out_value) {
  365|       |    // Make sure the |in_value| can be represented as an integral type OutT.
  366|  57.4M|#if __cplusplus >= 201703L
  367|  57.4M|    if constexpr (std::is_integral<OutT>::value) {
  368|       |#else
  369|       |    if (std::is_integral<OutT>::value) {
  370|       |#endif
  371|       |      // Make sure the |in_value| fits within the range of values that OutT
  372|       |      // is able to represent. Perform the check only for integral types.
  373|  57.4M|#if __cplusplus >= 201703L
  374|       |      if constexpr (!std::is_same<T, bool>::value &&
  375|  57.4M|                    std::is_integral<T>::value) {
  376|       |#else
  377|       |      if (!std::is_same<T, bool>::value && std::is_integral<T>::value) {
  378|       |#endif
  379|  57.4M|        static constexpr OutT kOutMin =
  380|  57.4M|            std::is_signed<T>::value ? std::numeric_limits<OutT>::min() : 0;
  ------------------
  |  Branch (380:13): [True: 0, Folded]
  ------------------
  381|  57.4M|        if (in_value < kOutMin || in_value > std::numeric_limits<OutT>::max()) {
  ------------------
  |  Branch (381:13): [True: 0, False: 57.4M]
  |  Branch (381:35): [True: 0, False: 57.4M]
  ------------------
  382|      0|          return false;
  383|      0|        }
  384|  57.4M|      }
  385|       |
  386|       |      // Check conversion of floating point |in_value| to integral value OutT.
  387|  57.4M|#if __cplusplus >= 201703L
  388|       |      if constexpr (std::is_floating_point<T>::value) {
  389|       |#else
  390|       |      if (std::is_floating_point<T>::value) {
  391|       |#endif
  392|       |        // Make sure the floating point |in_value| is not NaN and not Inf as
  393|       |        // integral type OutT is unable to represent these values.
  394|       |        if (sizeof(in_value) > sizeof(double)) {
  395|       |          if (std::isnan(static_cast<long double>(in_value)) ||
  396|       |              std::isinf(static_cast<long double>(in_value))) {
  397|       |            return false;
  398|       |          }
  399|       |        } else if (sizeof(in_value) > sizeof(float)) {
  400|       |          if (std::isnan(static_cast<double>(in_value)) ||
  401|       |              std::isinf(static_cast<double>(in_value))) {
  402|       |            return false;
  403|       |          }
  404|       |        } else {
  405|       |          if (std::isnan(static_cast<float>(in_value)) ||
  406|       |              std::isinf(static_cast<float>(in_value))) {
  407|       |            return false;
  408|       |          }
  409|       |        }
  410|       |
  411|       |        // Make sure the floating point |in_value| fits within the range of
  412|       |        // values that integral type OutT is able to represent.
  413|       |        if (in_value < std::numeric_limits<OutT>::min() ||
  414|       |            in_value >= std::numeric_limits<OutT>::max()) {
  415|       |          return false;
  416|       |        }
  417|       |      }
  418|  57.4M|    }
  419|       |
  420|  57.4M|    if (!normalized) {
  ------------------
  |  Branch (420:9): [True: 57.4M, False: 0]
  ------------------
  421|  57.4M|      *out_value = static_cast<OutT>(in_value);
  422|  57.4M|    } else {
  423|      0|#if __cplusplus >= 201703L
  424|       |      if constexpr (std::is_integral<T>::value &&
  425|       |                    std::is_floating_point<OutT>::value) {
  426|       |#else
  427|       |      if (std::is_integral<T>::value && std::is_floating_point<OutT>::value) {
  428|       |#endif
  429|       |        // When converting integer to floating point, normalize the value if
  430|       |        // necessary.
  431|       |        *out_value = static_cast<OutT>(in_value);
  432|       |        *out_value /= static_cast<OutT>(std::numeric_limits<T>::max());
  433|       |#if __cplusplus >= 201703L
  434|       |      } else if constexpr (std::is_floating_point<T>::value &&
  435|       |                           std::is_integral<OutT>::value) {
  436|       |#else
  437|       |      } else if (std::is_floating_point<T>::value &&
  438|       |                 std::is_integral<OutT>::value) {
  439|       |#endif
  440|       |        // Converting from floating point to a normalized integer.
  441|       |        if (in_value > 1 || in_value < 0) {
  442|       |          // Normalized float values need to be between 0 and 1.
  443|       |          return false;
  444|       |        }
  445|       |        // TODO(ostava): Consider allowing float to normalized integer
  446|       |        // conversion for 64-bit integer types. Currently it doesn't work
  447|       |        // because we don't have a floating point type that could store all 64
  448|       |        // bit integers.
  449|       |        if (sizeof(OutT) > 4) {
  450|       |          return false;
  451|       |        }
  452|       |        // Expand the float to the range of the output integer and round it to
  453|       |        // the nearest representable value. Use doubles for the math to ensure
  454|       |        // the integer values are represented properly during the conversion
  455|       |        // process.
  456|       |        *out_value = static_cast<OutT>(std::floor(
  457|       |            in_value * static_cast<double>(std::numeric_limits<OutT>::max()) +
  458|       |            0.5));
  459|      0|      } else {
  460|      0|        *out_value = static_cast<OutT>(in_value);
  461|      0|      }
  462|      0|    }
  463|       |
  464|       |    // TODO(ostava): Add handling of normalized attributes when converting
  465|       |    // between different integer representations. If the attribute is
  466|       |    // normalized, integer values should be converted as if they represent 0-1
  467|       |    // range. E.g. when we convert uint16 to uint8, the range <0, 2^16 - 1>
  468|       |    // should be converted to range <0, 2^8 - 1>.
  469|  57.4M|    return true;
  470|  57.4M|  }
_ZNK5draco17GeometryAttribute12ConvertValueIfEEbNS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEEPT_:
  229|  18.1k|  bool ConvertValue(AttributeValueIndex att_index, OutT* out_value) const {
  230|  18.1k|    return ConvertValue<OutT>(att_index, num_components_, out_value);
  231|  18.1k|  }
_ZNK5draco17GeometryAttribute12ConvertValueIfEEbNS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEEaPT_:
  179|  18.1k|                    OutT* out_val) const {
  180|  18.1k|    if (out_val == nullptr) {
  ------------------
  |  Branch (180:9): [True: 0, False: 18.1k]
  ------------------
  181|      0|      return false;
  182|      0|    }
  183|  18.1k|    switch (data_type_) {
  184|      0|      case DT_INT8:
  ------------------
  |  Branch (184:7): [True: 0, False: 18.1k]
  ------------------
  185|      0|        return ConvertTypedValue<int8_t, OutT>(att_id, out_num_components,
  186|      0|                                               out_val);
  187|      0|      case DT_UINT8:
  ------------------
  |  Branch (187:7): [True: 0, False: 18.1k]
  ------------------
  188|      0|        return ConvertTypedValue<uint8_t, OutT>(att_id, out_num_components,
  189|      0|                                                out_val);
  190|      0|      case DT_INT16:
  ------------------
  |  Branch (190:7): [True: 0, False: 18.1k]
  ------------------
  191|      0|        return ConvertTypedValue<int16_t, OutT>(att_id, out_num_components,
  192|      0|                                                out_val);
  193|      0|      case DT_UINT16:
  ------------------
  |  Branch (193:7): [True: 0, False: 18.1k]
  ------------------
  194|      0|        return ConvertTypedValue<uint16_t, OutT>(att_id, out_num_components,
  195|      0|                                                 out_val);
  196|  18.1k|      case DT_INT32:
  ------------------
  |  Branch (196:7): [True: 18.1k, False: 0]
  ------------------
  197|  18.1k|        return ConvertTypedValue<int32_t, OutT>(att_id, out_num_components,
  198|  18.1k|                                                out_val);
  199|      0|      case DT_UINT32:
  ------------------
  |  Branch (199:7): [True: 0, False: 18.1k]
  ------------------
  200|      0|        return ConvertTypedValue<uint32_t, OutT>(att_id, out_num_components,
  201|      0|                                                 out_val);
  202|      0|      case DT_INT64:
  ------------------
  |  Branch (202:7): [True: 0, False: 18.1k]
  ------------------
  203|      0|        return ConvertTypedValue<int64_t, OutT>(att_id, out_num_components,
  204|      0|                                                out_val);
  205|      0|      case DT_UINT64:
  ------------------
  |  Branch (205:7): [True: 0, False: 18.1k]
  ------------------
  206|      0|        return ConvertTypedValue<uint64_t, OutT>(att_id, out_num_components,
  207|      0|                                                 out_val);
  208|      0|      case DT_FLOAT32:
  ------------------
  |  Branch (208:7): [True: 0, False: 18.1k]
  ------------------
  209|      0|        return ConvertTypedValue<float, OutT>(att_id, out_num_components,
  210|      0|                                              out_val);
  211|      0|      case DT_FLOAT64:
  ------------------
  |  Branch (211:7): [True: 0, False: 18.1k]
  ------------------
  212|      0|        return ConvertTypedValue<double, OutT>(att_id, out_num_components,
  213|      0|                                               out_val);
  214|      0|      case DT_BOOL:
  ------------------
  |  Branch (214:7): [True: 0, False: 18.1k]
  ------------------
  215|      0|        return ConvertTypedValue<bool, OutT>(att_id, out_num_components,
  216|      0|                                             out_val);
  217|      0|      default:
  ------------------
  |  Branch (217:7): [True: 0, False: 18.1k]
  ------------------
  218|       |        // Wrong attribute type.
  219|      0|        return false;
  220|  18.1k|    }
  221|  18.1k|  }
_ZNK5draco17GeometryAttribute17ConvertTypedValueIifEEbNS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEEhPT0_:
  306|  18.1k|                         OutT* out_value) const {
  307|  18.1k|    const uint8_t* src_address = GetAddress(att_id);
  308|       |
  309|       |    // Convert all components available in both the original and output formats.
  310|  72.7k|    for (int i = 0; i < std::min(num_components_, out_num_components); ++i) {
  ------------------
  |  Branch (310:21): [True: 54.5k, False: 18.1k]
  ------------------
  311|  54.5k|      if (!IsAddressValid(src_address)) {
  ------------------
  |  Branch (311:11): [True: 0, False: 54.5k]
  ------------------
  312|      0|        return false;
  313|      0|      }
  314|  54.5k|      const T in_value = *reinterpret_cast<const T*>(src_address);
  315|  54.5k|      if (!ConvertComponentValue<T, OutT>(in_value, normalized_,
  ------------------
  |  Branch (315:11): [True: 0, False: 54.5k]
  ------------------
  316|  54.5k|                                          out_value + i)) {
  317|      0|        return false;
  318|      0|      }
  319|  54.5k|      src_address += sizeof(T);
  320|  54.5k|    }
  321|       |    // Fill empty data for unused output components if needed.
  322|  18.1k|    for (int i = num_components_; i < out_num_components; ++i) {
  ------------------
  |  Branch (322:35): [True: 0, False: 18.1k]
  ------------------
  323|      0|      out_value[i] = static_cast<OutT>(0);
  324|      0|    }
  325|  18.1k|    return true;
  326|  18.1k|  }
_ZN5draco17GeometryAttribute21ConvertComponentValueIifEEbRKT_bPT0_:
  364|  54.5k|                                    OutT* out_value) {
  365|       |    // Make sure the |in_value| can be represented as an integral type OutT.
  366|  54.5k|#if __cplusplus >= 201703L
  367|       |    if constexpr (std::is_integral<OutT>::value) {
  368|       |#else
  369|       |    if (std::is_integral<OutT>::value) {
  370|       |#endif
  371|       |      // Make sure the |in_value| fits within the range of values that OutT
  372|       |      // is able to represent. Perform the check only for integral types.
  373|       |#if __cplusplus >= 201703L
  374|       |      if constexpr (!std::is_same<T, bool>::value &&
  375|       |                    std::is_integral<T>::value) {
  376|       |#else
  377|       |      if (!std::is_same<T, bool>::value && std::is_integral<T>::value) {
  378|       |#endif
  379|       |        static constexpr OutT kOutMin =
  380|       |            std::is_signed<T>::value ? std::numeric_limits<OutT>::min() : 0;
  381|       |        if (in_value < kOutMin || in_value > std::numeric_limits<OutT>::max()) {
  382|       |          return false;
  383|       |        }
  384|       |      }
  385|       |
  386|       |      // Check conversion of floating point |in_value| to integral value OutT.
  387|       |#if __cplusplus >= 201703L
  388|       |      if constexpr (std::is_floating_point<T>::value) {
  389|       |#else
  390|       |      if (std::is_floating_point<T>::value) {
  391|       |#endif
  392|       |        // Make sure the floating point |in_value| is not NaN and not Inf as
  393|       |        // integral type OutT is unable to represent these values.
  394|       |        if (sizeof(in_value) > sizeof(double)) {
  395|       |          if (std::isnan(static_cast<long double>(in_value)) ||
  396|       |              std::isinf(static_cast<long double>(in_value))) {
  397|       |            return false;
  398|       |          }
  399|       |        } else if (sizeof(in_value) > sizeof(float)) {
  400|       |          if (std::isnan(static_cast<double>(in_value)) ||
  401|       |              std::isinf(static_cast<double>(in_value))) {
  402|       |            return false;
  403|       |          }
  404|       |        } else {
  405|       |          if (std::isnan(static_cast<float>(in_value)) ||
  406|       |              std::isinf(static_cast<float>(in_value))) {
  407|       |            return false;
  408|       |          }
  409|       |        }
  410|       |
  411|       |        // Make sure the floating point |in_value| fits within the range of
  412|       |        // values that integral type OutT is able to represent.
  413|       |        if (in_value < std::numeric_limits<OutT>::min() ||
  414|       |            in_value >= std::numeric_limits<OutT>::max()) {
  415|       |          return false;
  416|       |        }
  417|       |      }
  418|       |    }
  419|       |
  420|  54.5k|    if (!normalized) {
  ------------------
  |  Branch (420:9): [True: 54.5k, False: 0]
  ------------------
  421|  54.5k|      *out_value = static_cast<OutT>(in_value);
  422|  54.5k|    } else {
  423|      0|#if __cplusplus >= 201703L
  424|       |      if constexpr (std::is_integral<T>::value &&
  425|      0|                    std::is_floating_point<OutT>::value) {
  426|       |#else
  427|       |      if (std::is_integral<T>::value && std::is_floating_point<OutT>::value) {
  428|       |#endif
  429|       |        // When converting integer to floating point, normalize the value if
  430|       |        // necessary.
  431|      0|        *out_value = static_cast<OutT>(in_value);
  432|      0|        *out_value /= static_cast<OutT>(std::numeric_limits<T>::max());
  433|      0|#if __cplusplus >= 201703L
  434|       |      } else if constexpr (std::is_floating_point<T>::value &&
  435|       |                           std::is_integral<OutT>::value) {
  436|       |#else
  437|       |      } else if (std::is_floating_point<T>::value &&
  438|       |                 std::is_integral<OutT>::value) {
  439|       |#endif
  440|       |        // Converting from floating point to a normalized integer.
  441|       |        if (in_value > 1 || in_value < 0) {
  442|       |          // Normalized float values need to be between 0 and 1.
  443|       |          return false;
  444|       |        }
  445|       |        // TODO(ostava): Consider allowing float to normalized integer
  446|       |        // conversion for 64-bit integer types. Currently it doesn't work
  447|       |        // because we don't have a floating point type that could store all 64
  448|       |        // bit integers.
  449|       |        if (sizeof(OutT) > 4) {
  450|       |          return false;
  451|       |        }
  452|       |        // Expand the float to the range of the output integer and round it to
  453|       |        // the nearest representable value. Use doubles for the math to ensure
  454|       |        // the integer values are represented properly during the conversion
  455|       |        // process.
  456|       |        *out_value = static_cast<OutT>(std::floor(
  457|       |            in_value * static_cast<double>(std::numeric_limits<OutT>::max()) +
  458|       |            0.5));
  459|       |      } else {
  460|       |        *out_value = static_cast<OutT>(in_value);
  461|       |      }
  462|      0|    }
  463|       |
  464|       |    // TODO(ostava): Add handling of normalized attributes when converting
  465|       |    // between different integer representations. If the attribute is
  466|       |    // normalized, integer values should be converted as if they represent 0-1
  467|       |    // range. E.g. when we convert uint16 to uint8, the range <0, 2^16 - 1>
  468|       |    // should be converted to range <0, 2^8 - 1>.
  469|  54.5k|    return true;
  470|  54.5k|  }

_ZN5draco14PointAttributeC2ERKNS_17GeometryAttributeE:
   32|  41.5k|    : GeometryAttribute(att),
   33|  41.5k|      num_unique_entries_(0),
   34|  41.5k|      identity_mapping_(false) {}
_ZN5draco14PointAttribute8CopyFromERKS0_:
   47|  1.24k|void PointAttribute::CopyFrom(const PointAttribute& src_att) {
   48|  1.24k|  if (buffer() == nullptr) {
  ------------------
  |  Branch (48:7): [True: 0, False: 1.24k]
  ------------------
   49|       |    // If the destination attribute doesn't have a valid buffer, create it.
   50|      0|    attribute_buffer_ = std::unique_ptr<DataBuffer>(new DataBuffer());
   51|      0|    ResetBuffer(attribute_buffer_.get(), 0, 0);
   52|      0|  }
   53|  1.24k|  if (!GeometryAttribute::CopyFrom(src_att)) {
  ------------------
  |  Branch (53:7): [True: 0, False: 1.24k]
  ------------------
   54|      0|    return;
   55|      0|  }
   56|  1.24k|  identity_mapping_ = src_att.identity_mapping_;
   57|  1.24k|  num_unique_entries_ = src_att.num_unique_entries_;
   58|  1.24k|  indices_map_ = src_att.indices_map_;
   59|  1.24k|  if (src_att.attribute_transform_data_) {
  ------------------
  |  Branch (59:7): [True: 47, False: 1.20k]
  ------------------
   60|     47|    attribute_transform_data_ = std::unique_ptr<AttributeTransformData>(
   61|     47|        new AttributeTransformData(*src_att.attribute_transform_data_));
   62|  1.20k|  } else {
   63|  1.20k|    attribute_transform_data_ = nullptr;
   64|  1.20k|  }
   65|  1.24k|}
_ZN5draco14PointAttribute5ResetEm:
   67|  24.9k|bool PointAttribute::Reset(size_t num_attribute_values) {
   68|  24.9k|  if (attribute_buffer_ == nullptr) {
  ------------------
  |  Branch (68:7): [True: 24.9k, False: 0]
  ------------------
   69|  24.9k|    attribute_buffer_ = std::unique_ptr<DataBuffer>(new DataBuffer());
   70|  24.9k|  }
   71|  24.9k|  const int64_t entry_size = DataTypeLength(data_type()) * num_components();
   72|  24.9k|  if (!attribute_buffer_->Update(nullptr, num_attribute_values * entry_size)) {
  ------------------
  |  Branch (72:7): [True: 0, False: 24.9k]
  ------------------
   73|      0|    return false;
   74|      0|  }
   75|       |  // Assign the new buffer to the parent attribute.
   76|  24.9k|  ResetBuffer(attribute_buffer_.get(), entry_size, 0);
   77|  24.9k|  num_unique_entries_ = static_cast<uint32_t>(num_attribute_values);
   78|  24.9k|  return true;
   79|  24.9k|}

_ZNK5draco14PointAttribute4sizeEv:
   55|   425M|  size_t size() const { return num_unique_entries_; }
_ZNK5draco14PointAttribute12mapped_indexENS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   56|   440M|  AttributeValueIndex mapped_index(PointIndex point_index) const {
   57|   440M|    if (identity_mapping_) {
  ------------------
  |  Branch (57:9): [True: 384M, False: 55.7M]
  ------------------
   58|   384M|      return AttributeValueIndex(point_index.value());
   59|   384M|    }
   60|  55.7M|    return indices_map_[point_index];
   61|   440M|  }
_ZNK5draco14PointAttribute6bufferEv:
   62|   266M|  DataBuffer* buffer() const { return attribute_buffer_.get(); }
_ZNK5draco14PointAttribute19is_mapping_identityEv:
   63|  36.6M|  bool is_mapping_identity() const { return identity_mapping_; }
_ZNK5draco14PointAttribute16indices_map_sizeEv:
   64|  36.6M|  size_t indices_map_size() const {
   65|  36.6M|    if (is_mapping_identity()) {
  ------------------
  |  Branch (65:9): [True: 0, False: 36.6M]
  ------------------
   66|      0|      return 0;
   67|      0|    }
   68|  36.6M|    return indices_map_.size();
   69|  36.6M|  }
_ZN5draco14PointAttribute18SetIdentityMappingEv:
   88|  15.3k|  void SetIdentityMapping() {
   89|  15.3k|    identity_mapping_ = true;
   90|  15.3k|    indices_map_.clear();
   91|  15.3k|  }
_ZN5draco14PointAttribute18SetExplicitMappingEm:
   94|  22.5k|  void SetExplicitMapping(size_t num_points) {
   95|  22.5k|    identity_mapping_ = false;
   96|  22.5k|    indices_map_.resize(num_points, kInvalidAttributeValueIndex);
   97|  22.5k|  }
_ZN5draco14PointAttribute16SetPointMapEntryENS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_IjNS_29AttributeValueIndex_tag_type_EEE:
  101|  96.6M|                        AttributeValueIndex entry_index) {
  102|  96.6M|    DRACO_DCHECK(!identity_mapping_);
  103|  96.6M|    indices_map_[point_index] = entry_index;
  104|  96.6M|  }
_ZN5draco14PointAttribute25SetAttributeTransformDataENSt3__110unique_ptrINS_22AttributeTransformDataENS1_14default_deleteIS3_EEEE:
  129|    656|      std::unique_ptr<AttributeTransformData> transform_data) {
  130|    656|    attribute_transform_data_ = std::move(transform_data);
  131|    656|  }

_ZN5draco17AttributesDecoderC2Ev:
   22|  43.7k|    : point_cloud_decoder_(nullptr), point_cloud_(nullptr) {}
_ZN5draco17AttributesDecoder4InitEPNS_17PointCloudDecoderEPNS_10PointCloudE:
   24|  43.6k|bool AttributesDecoder::Init(PointCloudDecoder* decoder, PointCloud* pc) {
   25|  43.6k|  point_cloud_decoder_ = decoder;
   26|  43.6k|  point_cloud_ = pc;
   27|  43.6k|  return true;
   28|  43.6k|}
_ZN5draco17AttributesDecoder27DecodeAttributesDecoderDataEPNS_13DecoderBufferE:
   30|  11.3k|bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer* in_buffer) {
   31|       |  // Decode and create attributes.
   32|  11.3k|  uint32_t num_attributes;
   33|  11.3k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   34|  11.3k|  if (point_cloud_decoder_->bitstream_version() <
  ------------------
  |  Branch (34:7): [True: 84, False: 11.2k]
  ------------------
   35|  11.3k|      DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  11.3k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
   36|     84|    if (!in_buffer->Decode(&num_attributes)) {
  ------------------
  |  Branch (36:9): [True: 16, False: 68]
  ------------------
   37|     16|      return false;
   38|     16|    }
   39|     84|  } else
   40|  11.2k|#endif
   41|  11.2k|  {
   42|  11.2k|    if (!DecodeVarint(&num_attributes, in_buffer)) {
  ------------------
  |  Branch (42:9): [True: 83, False: 11.1k]
  ------------------
   43|     83|      return false;
   44|     83|    }
   45|  11.2k|  }
   46|       |
   47|       |  // Check that decoded number of attributes is valid.
   48|  11.2k|  if (num_attributes == 0) {
  ------------------
  |  Branch (48:7): [True: 19, False: 11.2k]
  ------------------
   49|     19|    return false;
   50|     19|  }
   51|  11.2k|  if (num_attributes > 5 * in_buffer->remaining_size()) {
  ------------------
  |  Branch (51:7): [True: 107, False: 11.1k]
  ------------------
   52|       |    // The decoded number of attributes is unreasonably high, because at least
   53|       |    // five bytes of attribute descriptor data per attribute are expected.
   54|    107|    return false;
   55|    107|  }
   56|       |
   57|       |  // Decode attribute descriptor data.
   58|  11.1k|  point_attribute_ids_.resize(num_attributes);
   59|  11.1k|  PointCloud* pc = point_cloud_;
   60|  42.8k|  for (uint32_t i = 0; i < num_attributes; ++i) {
  ------------------
  |  Branch (60:24): [True: 31.9k, False: 10.9k]
  ------------------
   61|       |    // Decode attribute descriptor data.
   62|  31.9k|    uint8_t att_type, data_type, num_components, normalized;
   63|  31.9k|    if (!in_buffer->Decode(&att_type)) {
  ------------------
  |  Branch (63:9): [True: 27, False: 31.8k]
  ------------------
   64|     27|      return false;
   65|     27|    }
   66|  31.8k|    if (!in_buffer->Decode(&data_type)) {
  ------------------
  |  Branch (66:9): [True: 24, False: 31.8k]
  ------------------
   67|     24|      return false;
   68|     24|    }
   69|  31.8k|    if (!in_buffer->Decode(&num_components)) {
  ------------------
  |  Branch (69:9): [True: 26, False: 31.8k]
  ------------------
   70|     26|      return false;
   71|     26|    }
   72|  31.8k|    if (!in_buffer->Decode(&normalized)) {
  ------------------
  |  Branch (72:9): [True: 11, False: 31.8k]
  ------------------
   73|     11|      return false;
   74|     11|    }
   75|  31.8k|    if (att_type >= GeometryAttribute::NAMED_ATTRIBUTES_COUNT) {
  ------------------
  |  Branch (75:9): [True: 36, False: 31.7k]
  ------------------
   76|     36|      return false;
   77|     36|    }
   78|  31.7k|    if (data_type == DT_INVALID || data_type >= DT_TYPES_COUNT) {
  ------------------
  |  Branch (78:9): [True: 5, False: 31.7k]
  |  Branch (78:36): [True: 10, False: 31.7k]
  ------------------
   79|     15|      return false;
   80|     15|    }
   81|       |
   82|       |    // Check decoded attribute descriptor data.
   83|  31.7k|    if (num_components == 0) {
  ------------------
  |  Branch (83:9): [True: 4, False: 31.7k]
  ------------------
   84|      4|      return false;
   85|      4|    }
   86|       |
   87|       |    // Add the attribute to the point cloud.
   88|  31.7k|    const DataType draco_dt = static_cast<DataType>(data_type);
   89|  31.7k|    GeometryAttribute ga;
   90|  31.7k|    ga.Init(static_cast<GeometryAttribute::Type>(att_type), nullptr,
   91|  31.7k|            num_components, draco_dt, normalized > 0,
   92|  31.7k|            DataTypeLength(draco_dt) * num_components, 0);
   93|  31.7k|    uint32_t unique_id;
   94|  31.7k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   95|  31.7k|    if (point_cloud_decoder_->bitstream_version() <
  ------------------
  |  Branch (95:9): [True: 221, False: 31.5k]
  ------------------
   96|  31.7k|        DRACO_BITSTREAM_VERSION(1, 3)) {
  ------------------
  |  |  115|  31.7k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
   97|    221|      uint16_t custom_id;
   98|    221|      if (!in_buffer->Decode(&custom_id)) {
  ------------------
  |  Branch (98:11): [True: 2, False: 219]
  ------------------
   99|      2|        return false;
  100|      2|      }
  101|       |      // TODO(draco-eng): Add "custom_id" to attribute metadata.
  102|    219|      unique_id = static_cast<uint32_t>(custom_id);
  103|    219|      ga.set_unique_id(unique_id);
  104|    219|    } else
  105|  31.5k|#endif
  106|  31.5k|    {
  107|  31.5k|      if (!DecodeVarint(&unique_id, in_buffer)) {
  ------------------
  |  Branch (107:11): [True: 21, False: 31.5k]
  ------------------
  108|     21|        return false;
  109|     21|      }
  110|  31.5k|      ga.set_unique_id(unique_id);
  111|  31.5k|    }
  112|  31.7k|    const int att_id = pc->AddAttribute(
  113|  31.7k|        std::unique_ptr<PointAttribute>(new PointAttribute(ga)));
  114|  31.7k|    pc->attribute(att_id)->set_unique_id(unique_id);
  115|  31.7k|    point_attribute_ids_[i] = att_id;
  116|       |
  117|       |    // Update the inverse map.
  118|  31.7k|    if (att_id >=
  ------------------
  |  Branch (118:9): [True: 31.7k, False: 0]
  ------------------
  119|  31.7k|        static_cast<int32_t>(point_attribute_to_local_id_map_.size())) {
  120|  31.7k|      point_attribute_to_local_id_map_.resize(att_id + 1, -1);
  121|  31.7k|    }
  122|  31.7k|    point_attribute_to_local_id_map_[att_id] = i;
  123|  31.7k|  }
  124|  10.9k|  return true;
  125|  11.1k|}

_ZNK5draco17AttributesDecoder14GetAttributeIdEi:
   44|  91.9k|  int32_t GetAttributeId(int i) const override {
   45|  91.9k|    return point_attribute_ids_[i];
   46|  91.9k|  }
_ZNK5draco17AttributesDecoder16GetNumAttributesEv:
   47|  57.5k|  int32_t GetNumAttributes() const override {
   48|  57.5k|    return static_cast<int32_t>(point_attribute_ids_.size());
   49|  57.5k|  }
_ZNK5draco17AttributesDecoder10GetDecoderEv:
   50|  55.8k|  PointCloudDecoder* GetDecoder() const override {
   51|  55.8k|    return point_cloud_decoder_;
   52|  55.8k|  }
_ZN5draco17AttributesDecoder16DecodeAttributesEPNS_13DecoderBufferE:
   55|  7.52k|  bool DecodeAttributes(DecoderBuffer* in_buffer) override {
   56|  7.52k|    if (!DecodePortableAttributes(in_buffer)) {
  ------------------
  |  Branch (56:9): [True: 3.07k, False: 4.44k]
  ------------------
   57|  3.07k|      return false;
   58|  3.07k|    }
   59|  4.44k|    if (!DecodeDataNeededByPortableTransforms(in_buffer)) {
  ------------------
  |  Branch (59:9): [True: 1.87k, False: 2.57k]
  ------------------
   60|  1.87k|      return false;
   61|  1.87k|    }
   62|  2.57k|    if (!TransformAttributesToOriginalFormat()) {
  ------------------
  |  Branch (62:9): [True: 485, False: 2.09k]
  ------------------
   63|    485|      return false;
   64|    485|    }
   65|  2.09k|    return true;
   66|  2.57k|  }
_ZNK5draco17AttributesDecoder27GetLocalIdForPointAttributeEi:
   69|  2.22k|  int32_t GetLocalIdForPointAttribute(int32_t point_attribute_id) const {
   70|  2.22k|    const int id_map_size =
   71|  2.22k|        static_cast<int>(point_attribute_to_local_id_map_.size());
   72|  2.22k|    if (point_attribute_id >= id_map_size) {
  ------------------
  |  Branch (72:9): [True: 0, False: 2.22k]
  ------------------
   73|      0|      return -1;
   74|      0|    }
   75|  2.22k|    return point_attribute_to_local_id_map_[point_attribute_id];
   76|  2.22k|  }
_ZN5draco17AttributesDecoderD2Ev:
   35|  43.7k|  virtual ~AttributesDecoder() = default;

_ZN5draco26AttributesDecoderInterfaceD2Ev:
   34|  43.7k|  virtual ~AttributesDecoderInterface() = default;
_ZN5draco26AttributesDecoderInterfaceC2Ev:
   33|  43.7k|  AttributesDecoderInterface() = default;

_ZN5draco23KdTreeAttributesDecoderC2Ev:
  132|  16.2k|KdTreeAttributesDecoder::KdTreeAttributesDecoder() = default;
_ZN5draco23KdTreeAttributesDecoder24DecodePortableAttributesEPNS_13DecoderBufferE:
  135|  2.50k|    DecoderBuffer* in_buffer) {
  136|  2.50k|  if (in_buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 3)) {
  ------------------
  |  |  115|  2.50k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (136:7): [True: 1.29k, False: 1.21k]
  ------------------
  137|       |    // Old bitstream does everything in the
  138|       |    // DecodeDataNeededByPortableTransforms() method.
  139|  1.29k|    return true;
  140|  1.29k|  }
  141|  1.21k|  uint8_t compression_level = 0;
  142|  1.21k|  if (!in_buffer->Decode(&compression_level)) {
  ------------------
  |  Branch (142:7): [True: 8, False: 1.20k]
  ------------------
  143|      8|    return false;
  144|      8|  }
  145|  1.20k|  const int32_t num_points = GetDecoder()->point_cloud()->num_points();
  146|       |
  147|       |  // Decode data using the kd tree decoding into integer (portable) attributes.
  148|       |  // We first need to go over all attributes and create a new portable storage
  149|       |  // for those attributes that need it (floating point attributes that have to
  150|       |  // be dequantized after decoding).
  151|       |
  152|  1.20k|  const int num_attributes = GetNumAttributes();
  153|  1.20k|  uint32_t total_dimensionality = 0;  // position is a required dimension
  154|  1.20k|  std::vector<AttributeTuple> atts(num_attributes);
  155|       |
  156|  3.65k|  for (int i = 0; i < GetNumAttributes(); ++i) {
  ------------------
  |  Branch (156:19): [True: 2.45k, False: 1.20k]
  ------------------
  157|  2.45k|    const int att_id = GetAttributeId(i);
  158|  2.45k|    PointAttribute* const att = GetDecoder()->point_cloud()->attribute(att_id);
  159|       |    // All attributes have the same number of values and identity mapping
  160|       |    // between PointIndex and AttributeValueIndex.
  161|  2.45k|    att->Reset(num_points);
  162|  2.45k|    att->SetIdentityMapping();
  163|       |
  164|  2.45k|    PointAttribute* target_att = nullptr;
  165|  2.45k|    if (att->data_type() == DT_UINT32 || att->data_type() == DT_UINT16 ||
  ------------------
  |  Branch (165:9): [True: 53, False: 2.39k]
  |  Branch (165:42): [True: 449, False: 1.95k]
  ------------------
  166|  1.95k|        att->data_type() == DT_UINT8) {
  ------------------
  |  Branch (166:9): [True: 294, False: 1.65k]
  ------------------
  167|       |      // We can decode to these attributes directly.
  168|    796|      target_att = att;
  169|  1.65k|    } else if (att->data_type() == DT_INT32 || att->data_type() == DT_INT16 ||
  ------------------
  |  Branch (169:16): [True: 173, False: 1.48k]
  |  Branch (169:48): [True: 214, False: 1.26k]
  ------------------
  170|  1.32k|               att->data_type() == DT_INT8) {
  ------------------
  |  Branch (170:16): [True: 938, False: 331]
  ------------------
  171|       |      // Prepare storage for data that is used to convert unsigned values back
  172|       |      // to the signed ones.
  173|  55.3k|      for (int c = 0; c < att->num_components(); ++c) {
  ------------------
  |  Branch (173:23): [True: 53.9k, False: 1.32k]
  ------------------
  174|  53.9k|        min_signed_values_.push_back(0);
  175|  53.9k|      }
  176|  1.32k|      target_att = att;
  177|  1.32k|    } else if (att->data_type() == DT_FLOAT32) {
  ------------------
  |  Branch (177:16): [True: 329, False: 2]
  ------------------
  178|       |      // Create a portable attribute that will hold the decoded data. We will
  179|       |      // dequantize the decoded data to the final attribute later on.
  180|    329|      const int num_components = att->num_components();
  181|    329|      GeometryAttribute va;
  182|    329|      va.Init(att->attribute_type(), nullptr, num_components, DT_UINT32, false,
  183|    329|              num_components * DataTypeLength(DT_UINT32), 0);
  184|    329|      std::unique_ptr<PointAttribute> port_att(new PointAttribute(va));
  185|    329|      port_att->SetIdentityMapping();
  186|    329|      port_att->Reset(num_points);
  187|    329|      quantized_portable_attributes_.push_back(std::move(port_att));
  188|    329|      target_att = quantized_portable_attributes_.back().get();
  189|    329|    } else {
  190|       |      // Unsupported type.
  191|      2|      return false;
  192|      2|    }
  193|       |    // Add attribute to the output iterator used by the core algorithm.
  194|  2.45k|    const DataType data_type = target_att->data_type();
  195|  2.45k|    const uint32_t data_size = (std::max)(0, DataTypeLength(data_type));
  196|  2.45k|    const uint32_t num_components = target_att->num_components();
  197|  2.45k|    atts[i] = std::make_tuple(target_att, total_dimensionality, data_type,
  198|  2.45k|                              data_size, num_components);
  199|  2.45k|    total_dimensionality += num_components;
  200|  2.45k|  }
  201|  1.20k|  typedef PointAttributeVectorOutputIterator<uint32_t> OutIt;
  202|  1.20k|  OutIt out_it(atts);
  203|       |
  204|  1.20k|  switch (compression_level) {
  205|    154|    case 0: {
  ------------------
  |  Branch (205:5): [True: 154, False: 1.04k]
  ------------------
  206|    154|      if (!DecodePoints<0, OutIt>(total_dimensionality, num_points, in_buffer,
  ------------------
  |  Branch (206:11): [True: 85, False: 69]
  ------------------
  207|    154|                                  &out_it)) {
  208|     85|        return false;
  209|     85|      }
  210|     69|      break;
  211|    154|    }
  212|    119|    case 1: {
  ------------------
  |  Branch (212:5): [True: 119, False: 1.08k]
  ------------------
  213|    119|      if (!DecodePoints<1, OutIt>(total_dimensionality, num_points, in_buffer,
  ------------------
  |  Branch (213:11): [True: 70, False: 49]
  ------------------
  214|    119|                                  &out_it)) {
  215|     70|        return false;
  216|     70|      }
  217|     49|      break;
  218|    119|    }
  219|    106|    case 2: {
  ------------------
  |  Branch (219:5): [True: 106, False: 1.09k]
  ------------------
  220|    106|      if (!DecodePoints<2, OutIt>(total_dimensionality, num_points, in_buffer,
  ------------------
  |  Branch (220:11): [True: 84, False: 22]
  ------------------
  221|    106|                                  &out_it)) {
  222|     84|        return false;
  223|     84|      }
  224|     22|      break;
  225|    106|    }
  226|    107|    case 3: {
  ------------------
  |  Branch (226:5): [True: 107, False: 1.09k]
  ------------------
  227|    107|      if (!DecodePoints<3, OutIt>(total_dimensionality, num_points, in_buffer,
  ------------------
  |  Branch (227:11): [True: 85, False: 22]
  ------------------
  228|    107|                                  &out_it)) {
  229|     85|        return false;
  230|     85|      }
  231|     22|      break;
  232|    107|    }
  233|    247|    case 4: {
  ------------------
  |  Branch (233:5): [True: 247, False: 954]
  ------------------
  234|    247|      if (!DecodePoints<4, OutIt>(total_dimensionality, num_points, in_buffer,
  ------------------
  |  Branch (234:11): [True: 213, False: 34]
  ------------------
  235|    247|                                  &out_it)) {
  236|    213|        return false;
  237|    213|      }
  238|     34|      break;
  239|    247|    }
  240|    224|    case 5: {
  ------------------
  |  Branch (240:5): [True: 224, False: 977]
  ------------------
  241|    224|      if (!DecodePoints<5, OutIt>(total_dimensionality, num_points, in_buffer,
  ------------------
  |  Branch (241:11): [True: 204, False: 20]
  ------------------
  242|    224|                                  &out_it)) {
  243|    204|        return false;
  244|    204|      }
  245|     20|      break;
  246|    224|    }
  247|    235|    case 6: {
  ------------------
  |  Branch (247:5): [True: 235, False: 966]
  ------------------
  248|    235|      if (!DecodePoints<6, OutIt>(total_dimensionality, num_points, in_buffer,
  ------------------
  |  Branch (248:11): [True: 155, False: 80]
  ------------------
  249|    235|                                  &out_it)) {
  250|    155|        return false;
  251|    155|      }
  252|     80|      break;
  253|    235|    }
  254|     80|    default:
  ------------------
  |  Branch (254:5): [True: 9, False: 1.19k]
  ------------------
  255|      9|      return false;
  256|  1.20k|  }
  257|    296|  return true;
  258|  1.20k|}
_ZN5draco23KdTreeAttributesDecoder36DecodeDataNeededByPortableTransformsEPNS_13DecoderBufferE:
  274|  1.59k|    DecoderBuffer* in_buffer) {
  275|  1.59k|  if (in_buffer->bitstream_version() >= DRACO_BITSTREAM_VERSION(2, 3)) {
  ------------------
  |  |  115|  1.59k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (275:7): [True: 296, False: 1.29k]
  ------------------
  276|       |    // Decode quantization data for each attribute that need it.
  277|       |    // TODO(ostava): This should be moved to AttributeQuantizationTransform.
  278|    296|    std::vector<float> min_value;
  279|  1.08k|    for (int i = 0; i < GetNumAttributes(); ++i) {
  ------------------
  |  Branch (279:21): [True: 828, False: 257]
  ------------------
  280|    828|      const int att_id = GetAttributeId(i);
  281|    828|      const PointAttribute* const att =
  282|    828|          GetDecoder()->point_cloud()->attribute(att_id);
  283|    828|      if (att->data_type() == DT_FLOAT32) {
  ------------------
  |  Branch (283:11): [True: 181, False: 647]
  ------------------
  284|    181|        const int num_components = att->num_components();
  285|    181|        min_value.resize(num_components);
  286|    181|        if (!in_buffer->Decode(&min_value[0], sizeof(float) * num_components)) {
  ------------------
  |  Branch (286:13): [True: 23, False: 158]
  ------------------
  287|     23|          return false;
  288|     23|        }
  289|    158|        float max_value_dif;
  290|    158|        if (!in_buffer->Decode(&max_value_dif)) {
  ------------------
  |  Branch (290:13): [True: 3, False: 155]
  ------------------
  291|      3|          return false;
  292|      3|        }
  293|    155|        uint8_t quantization_bits;
  294|    155|        if (!in_buffer->Decode(&quantization_bits) || quantization_bits > 31) {
  ------------------
  |  Branch (294:13): [True: 1, False: 154]
  |  Branch (294:55): [True: 5, False: 149]
  ------------------
  295|      6|          return false;
  296|      6|        }
  297|    149|        AttributeQuantizationTransform transform;
  298|    149|        if (!transform.SetParameters(quantization_bits, min_value.data(),
  ------------------
  |  Branch (298:13): [True: 7, False: 142]
  ------------------
  299|    149|                                     num_components, max_value_dif)) {
  300|      7|          return false;
  301|      7|        }
  302|    142|        const int num_transforms =
  303|    142|            static_cast<int>(attribute_quantization_transforms_.size());
  304|    142|        if (!transform.TransferToAttribute(
  ------------------
  |  Branch (304:13): [True: 0, False: 142]
  ------------------
  305|    142|                quantized_portable_attributes_[num_transforms].get())) {
  306|      0|          return false;
  307|      0|        }
  308|    142|        attribute_quantization_transforms_.push_back(transform);
  309|    142|      }
  310|    828|    }
  311|       |
  312|       |    // Decode transform data for signed integer attributes.
  313|  5.98k|    for (int i = 0; i < min_signed_values_.size(); ++i) {
  ------------------
  |  Branch (313:21): [True: 5.80k, False: 178]
  ------------------
  314|  5.80k|      int32_t val;
  315|  5.80k|      if (!DecodeVarint(&val, in_buffer)) {
  ------------------
  |  Branch (315:11): [True: 79, False: 5.72k]
  ------------------
  316|     79|        return false;
  317|     79|      }
  318|  5.72k|      min_signed_values_[i] = val;
  319|  5.72k|    }
  320|    178|    return true;
  321|    257|  }
  322|  1.29k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  323|       |  // Handle old bitstream
  324|       |  // Figure out the total dimensionality of the point cloud
  325|  1.29k|  const uint32_t attribute_count = GetNumAttributes();
  326|  1.29k|  uint32_t total_dimensionality = 0;  // position is a required dimension
  327|  1.29k|  std::vector<AttributeTuple> atts(attribute_count);
  328|  1.29k|  for (auto attribute_index = 0;
  329|  2.85k|       static_cast<uint32_t>(attribute_index) < attribute_count;
  ------------------
  |  Branch (329:8): [True: 1.55k, False: 1.29k]
  ------------------
  330|  1.55k|       attribute_index += 1)  // increment the dimensionality as needed...
  331|  1.55k|  {
  332|  1.55k|    const int att_id = GetAttributeId(attribute_index);
  333|  1.55k|    PointAttribute* const att = GetDecoder()->point_cloud()->attribute(att_id);
  334|  1.55k|    const DataType data_type = att->data_type();
  335|  1.55k|    const uint32_t data_size = (std::max)(0, DataTypeLength(data_type));
  336|  1.55k|    const uint32_t num_components = att->num_components();
  337|  1.55k|    if (data_size > 4) {
  ------------------
  |  Branch (337:9): [True: 1, False: 1.55k]
  ------------------
  338|      1|      return false;
  339|      1|    }
  340|       |
  341|  1.55k|    atts[attribute_index] = std::make_tuple(
  342|  1.55k|        att, total_dimensionality, data_type, data_size, num_components);
  343|       |    // everything is treated as 32bit in the encoder.
  344|  1.55k|    total_dimensionality += num_components;
  345|  1.55k|  }
  346|       |
  347|  1.29k|  const int att_id = GetAttributeId(0);
  348|  1.29k|  PointAttribute* const att = GetDecoder()->point_cloud()->attribute(att_id);
  349|  1.29k|  att->SetIdentityMapping();
  350|       |  // Decode method
  351|  1.29k|  uint8_t method;
  352|  1.29k|  if (!in_buffer->Decode(&method)) {
  ------------------
  |  Branch (352:7): [True: 8, False: 1.28k]
  ------------------
  353|      8|    return false;
  354|      8|  }
  355|  1.28k|  if (method == KdTreeAttributesEncodingMethod::kKdTreeQuantizationEncoding) {
  ------------------
  |  Branch (355:7): [True: 855, False: 432]
  ------------------
  356|       |    // This method only supports one attribute with exactly three components.
  357|    855|    if (atts.size() != 1 || std::get<4>(atts[0]) != 3) {
  ------------------
  |  Branch (357:9): [True: 3, False: 852]
  |  Branch (357:29): [True: 6, False: 846]
  ------------------
  358|      9|      return false;
  359|      9|    }
  360|    846|    uint8_t compression_level = 0;
  361|    846|    if (!in_buffer->Decode(&compression_level)) {
  ------------------
  |  Branch (361:9): [True: 1, False: 845]
  ------------------
  362|      1|      return false;
  363|      1|    }
  364|    845|    uint32_t num_points = 0;
  365|    845|    if (!in_buffer->Decode(&num_points)) {
  ------------------
  |  Branch (365:9): [True: 1, False: 844]
  ------------------
  366|      1|      return false;
  367|      1|    }
  368|    844|    att->Reset(num_points);
  369|    844|    FloatPointsTreeDecoder decoder;
  370|    844|    decoder.set_num_points_from_header(num_points);
  371|    844|    PointAttributeVectorOutputIterator<float> out_it(atts);
  372|    844|    if (!decoder.DecodePointCloud(in_buffer, out_it)) {
  ------------------
  |  Branch (372:9): [True: 827, False: 17]
  ------------------
  373|    827|      return false;
  374|    827|    }
  375|    844|  } else if (method == KdTreeAttributesEncodingMethod::kKdTreeIntegerEncoding) {
  ------------------
  |  Branch (375:14): [True: 422, False: 10]
  ------------------
  376|    422|    uint8_t compression_level = 0;
  377|    422|    if (!in_buffer->Decode(&compression_level)) {
  ------------------
  |  Branch (377:9): [True: 1, False: 421]
  ------------------
  378|      1|      return false;
  379|      1|    }
  380|    421|    if (6 < compression_level) {
  ------------------
  |  Branch (380:9): [True: 2, False: 419]
  ------------------
  381|      2|      DRACO_LOGE(
  ------------------
  |  |   31|      2|#define DRACO_LOGE printf
  ------------------
  382|      2|          "KdTreeAttributesDecoder: compression level %i not supported.\n",
  383|      2|          compression_level);
  384|      2|      return false;
  385|      2|    }
  386|       |
  387|    419|    uint32_t num_points;
  388|    419|    if (!in_buffer->Decode(&num_points)) {
  ------------------
  |  Branch (388:9): [True: 3, False: 416]
  ------------------
  389|      3|      return false;
  390|      3|    }
  391|       |
  392|    416|    for (auto attribute_index = 0;
  393|  1.02k|         static_cast<uint32_t>(attribute_index) < attribute_count;
  ------------------
  |  Branch (393:10): [True: 605, False: 416]
  ------------------
  394|    605|         attribute_index += 1) {
  395|    605|      const int att_id = GetAttributeId(attribute_index);
  396|    605|      PointAttribute* const attr =
  397|    605|          GetDecoder()->point_cloud()->attribute(att_id);
  398|    605|      attr->Reset(num_points);
  399|    605|      attr->SetIdentityMapping();
  400|    605|    }
  401|       |
  402|    416|    using OutIt = PointAttributeVectorOutputIterator<uint32_t>;
  403|    416|    OutIt out_it(atts);
  404|       |
  405|    416|    switch (compression_level) {
  406|    116|      case 0: {
  ------------------
  |  Branch (406:7): [True: 116, False: 300]
  ------------------
  407|    116|        if (!DecodePoints<0, OutIt>(total_dimensionality, num_points, in_buffer,
  ------------------
  |  Branch (407:13): [True: 113, False: 3]
  ------------------
  408|    116|                                    &out_it)) {
  409|    113|          return false;
  410|    113|        }
  411|      3|        break;
  412|    116|      }
  413|    130|      case 1: {
  ------------------
  |  Branch (413:7): [True: 130, False: 286]
  ------------------
  414|    130|        if (!DecodePoints<1, OutIt>(total_dimensionality, num_points, in_buffer,
  ------------------
  |  Branch (414:13): [True: 129, False: 1]
  ------------------
  415|    130|                                    &out_it)) {
  416|    129|          return false;
  417|    129|        }
  418|      1|        break;
  419|    130|      }
  420|     65|      case 2: {
  ------------------
  |  Branch (420:7): [True: 65, False: 351]
  ------------------
  421|     65|        if (!DecodePoints<2, OutIt>(total_dimensionality, num_points, in_buffer,
  ------------------
  |  Branch (421:13): [True: 64, False: 1]
  ------------------
  422|     65|                                    &out_it)) {
  423|     64|          return false;
  424|     64|        }
  425|      1|        break;
  426|     65|      }
  427|     91|      case 3: {
  ------------------
  |  Branch (427:7): [True: 91, False: 325]
  ------------------
  428|     91|        if (!DecodePoints<3, OutIt>(total_dimensionality, num_points, in_buffer,
  ------------------
  |  Branch (428:13): [True: 90, False: 1]
  ------------------
  429|     91|                                    &out_it)) {
  430|     90|          return false;
  431|     90|        }
  432|      1|        break;
  433|     91|      }
  434|      5|      case 4: {
  ------------------
  |  Branch (434:7): [True: 5, False: 411]
  ------------------
  435|      5|        if (!DecodePoints<4, OutIt>(total_dimensionality, num_points, in_buffer,
  ------------------
  |  Branch (435:13): [True: 5, False: 0]
  ------------------
  436|      5|                                    &out_it)) {
  437|      5|          return false;
  438|      5|        }
  439|      0|        break;
  440|      5|      }
  441|      3|      case 5: {
  ------------------
  |  Branch (441:7): [True: 3, False: 413]
  ------------------
  442|      3|        if (!DecodePoints<5, OutIt>(total_dimensionality, num_points, in_buffer,
  ------------------
  |  Branch (442:13): [True: 2, False: 1]
  ------------------
  443|      3|                                    &out_it)) {
  444|      2|          return false;
  445|      2|        }
  446|      1|        break;
  447|      3|      }
  448|      6|      case 6: {
  ------------------
  |  Branch (448:7): [True: 6, False: 410]
  ------------------
  449|      6|        if (!DecodePoints<6, OutIt>(total_dimensionality, num_points, in_buffer,
  ------------------
  |  Branch (449:13): [True: 5, False: 1]
  ------------------
  450|      6|                                    &out_it)) {
  451|      5|          return false;
  452|      5|        }
  453|      1|        break;
  454|      6|      }
  455|      1|      default:
  ------------------
  |  Branch (455:7): [True: 0, False: 416]
  ------------------
  456|      0|        return false;
  457|    416|    }
  458|    416|  } else {
  459|       |    // Invalid method.
  460|     10|    return false;
  461|     10|  }
  462|     25|  return true;
  463|       |#else
  464|       |  return false;
  465|       |#endif
  466|  1.28k|}
_ZN5draco23KdTreeAttributesDecoder35TransformAttributesToOriginalFormatEv:
  494|    203|bool KdTreeAttributesDecoder::TransformAttributesToOriginalFormat() {
  495|    203|  if (quantized_portable_attributes_.empty() && min_signed_values_.empty()) {
  ------------------
  |  Branch (495:7): [True: 168, False: 35]
  |  Branch (495:49): [True: 53, False: 115]
  ------------------
  496|     53|    return true;
  497|     53|  }
  498|    150|  int num_processed_quantized_attributes = 0;
  499|    150|  int num_processed_signed_components = 0;
  500|       |  // Dequantize attributes that needed it.
  501|    622|  for (int i = 0; i < GetNumAttributes(); ++i) {
  ------------------
  |  Branch (501:19): [True: 472, False: 150]
  ------------------
  502|    472|    const int att_id = GetAttributeId(i);
  503|    472|    PointAttribute* const att = GetDecoder()->point_cloud()->attribute(att_id);
  504|    472|    if (att->data_type() == DT_INT32 || att->data_type() == DT_INT16 ||
  ------------------
  |  Branch (504:9): [True: 44, False: 428]
  |  Branch (504:41): [True: 78, False: 350]
  ------------------
  505|    350|        att->data_type() == DT_INT8) {
  ------------------
  |  Branch (505:9): [True: 87, False: 263]
  ------------------
  506|    209|      std::vector<uint32_t> unsigned_val(att->num_components());
  507|    209|      std::vector<int32_t> signed_val(att->num_components());
  508|       |      // Values are stored as unsigned in the attribute, make them signed again.
  509|    209|      if (att->data_type() == DT_INT32) {
  ------------------
  |  Branch (509:11): [True: 44, False: 165]
  ------------------
  510|     44|        if (!TransformAttributeBackToSignedType<int32_t>(
  ------------------
  |  Branch (510:13): [True: 0, False: 44]
  ------------------
  511|     44|                att, num_processed_signed_components)) {
  512|      0|          return false;
  513|      0|        }
  514|    165|      } else if (att->data_type() == DT_INT16) {
  ------------------
  |  Branch (514:18): [True: 78, False: 87]
  ------------------
  515|     78|        if (!TransformAttributeBackToSignedType<int16_t>(
  ------------------
  |  Branch (515:13): [True: 0, False: 78]
  ------------------
  516|     78|                att, num_processed_signed_components)) {
  517|      0|          return false;
  518|      0|        }
  519|     87|      } else if (att->data_type() == DT_INT8) {
  ------------------
  |  Branch (519:18): [True: 87, False: 0]
  ------------------
  520|     87|        if (!TransformAttributeBackToSignedType<int8_t>(
  ------------------
  |  Branch (520:13): [True: 0, False: 87]
  ------------------
  521|     87|                att, num_processed_signed_components)) {
  522|      0|          return false;
  523|      0|        }
  524|     87|      }
  525|    209|      num_processed_signed_components += att->num_components();
  526|    263|    } else if (att->data_type() == DT_FLOAT32) {
  ------------------
  |  Branch (526:16): [True: 87, False: 176]
  ------------------
  527|       |      // TODO(ostava): This code should be probably moved out to attribute
  528|       |      // transform and shared with the SequentialQuantizationAttributeDecoder.
  529|       |
  530|     87|      const PointAttribute* const src_att =
  531|     87|          quantized_portable_attributes_[num_processed_quantized_attributes]
  532|     87|              .get();
  533|       |
  534|     87|      const AttributeQuantizationTransform& transform =
  535|     87|          attribute_quantization_transforms_
  536|     87|              [num_processed_quantized_attributes];
  537|       |
  538|     87|      num_processed_quantized_attributes++;
  539|       |
  540|     87|      if (GetDecoder()->options()->GetAttributeBool(
  ------------------
  |  Branch (540:11): [True: 25, False: 62]
  ------------------
  541|     87|              att->attribute_type(), "skip_attribute_transform", false)) {
  542|       |        // Attribute transform should not be performed. In this case, we replace
  543|       |        // the output geometry attribute with the portable attribute.
  544|       |        // TODO(ostava): We can potentially avoid this copy by introducing a new
  545|       |        // mechanism that would allow to use the final attributes as portable
  546|       |        // attributes for predictors that may need them.
  547|     25|        att->CopyFrom(*src_att);
  548|     25|        continue;
  549|     25|      }
  550|       |
  551|       |      // Convert all quantized values back to floats.
  552|     62|      const int32_t max_quantized_value =
  553|     62|          (1u << static_cast<uint32_t>(transform.quantization_bits())) - 1;
  554|     62|      const int num_components = att->num_components();
  555|     62|      const int entry_size = sizeof(float) * num_components;
  556|     62|      const std::unique_ptr<float[]> att_val(new float[num_components]);
  557|     62|      int quant_val_id = 0;
  558|     62|      int out_byte_pos = 0;
  559|     62|      Dequantizer dequantizer;
  560|     62|      if (!dequantizer.Init(transform.range(), max_quantized_value)) {
  ------------------
  |  Branch (560:11): [True: 0, False: 62]
  ------------------
  561|      0|        return false;
  562|      0|      }
  563|     62|      const uint32_t* const portable_attribute_data =
  564|     62|          reinterpret_cast<const uint32_t*>(
  565|     62|              src_att->GetAddress(AttributeValueIndex(0)));
  566|     62|      for (uint32_t i = 0; i < src_att->size(); ++i) {
  ------------------
  |  Branch (566:28): [True: 0, False: 62]
  ------------------
  567|      0|        for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (567:25): [True: 0, False: 0]
  ------------------
  568|      0|          float value = dequantizer.DequantizeFloat(
  569|      0|              portable_attribute_data[quant_val_id++]);
  570|      0|          value = value + transform.min_value(c);
  571|      0|          att_val[c] = value;
  572|      0|        }
  573|       |        // Store the floating point value into the attribute buffer.
  574|      0|        att->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
  575|      0|        out_byte_pos += entry_size;
  576|      0|      }
  577|     62|    }
  578|    472|  }
  579|    150|  return true;
  580|    150|}
_ZN5draco34PointAttributeVectorOutputIteratorIjEC2ERKNSt3__16vectorINS2_5tupleIJPNS_14PointAttributeEjNS_8DataTypeEjjEEENS2_9allocatorIS8_EEEE:
   48|  1.61k|      : attributes_(atts), point_id_(0) {
   49|  1.61k|    DRACO_DCHECK_GE(atts.size(), 1);
   50|  1.61k|    uint32_t required_decode_bytes = 0;
   51|  4.64k|    for (auto index = 0; index < attributes_.size(); index++) {
  ------------------
  |  Branch (51:26): [True: 3.03k, False: 1.61k]
  ------------------
   52|  3.03k|      const AttributeTuple& att = attributes_[index];
   53|  3.03k|      required_decode_bytes = (std::max)(required_decode_bytes,
   54|  3.03k|                                         std::get<3>(att) * std::get<4>(att));
   55|  3.03k|    }
   56|  1.61k|    memory_.resize(required_decode_bytes);
   57|  1.61k|    data_ = memory_.data();
   58|  1.61k|  }
_ZN5draco23KdTreeAttributesDecoder12DecodePointsILi0ENS_34PointAttributeVectorOutputIteratorIjEEEEbijPNS_13DecoderBufferEPT0_:
  264|    270|                                           OutIteratorT* out_iterator) {
  265|    270|  DynamicIntegerPointsKdTreeDecoder<level_t> decoder(total_dimensionality);
  266|    270|  if (!decoder.DecodePoints(in_buffer, *out_iterator, num_expected_points) ||
  ------------------
  |  Branch (266:7): [True: 169, False: 101]
  ------------------
  267|    198|      decoder.num_decoded_points() != num_expected_points) {
  ------------------
  |  Branch (267:7): [True: 29, False: 72]
  ------------------
  268|    198|    return false;
  269|    198|  }
  270|     72|  return true;
  271|    270|}
_ZN5draco34PointAttributeVectorOutputIteratorIjEdeEv:
   73|   384M|  Self& operator*() { return *this; }
_ZN5draco34PointAttributeVectorOutputIteratorIjEaSERKNSt3__16vectorIjNS2_9allocatorIjEEEE:
   91|   384M|  const Self& operator=(const std::vector<CoeffT>& val) {
   92|   768M|    for (auto index = 0; index < attributes_.size(); index++) {
  ------------------
  |  Branch (92:26): [True: 384M, False: 384M]
  ------------------
   93|   384M|      AttributeTuple& att = attributes_[index];
   94|   384M|      PointAttribute* attribute = std::get<0>(att);
   95|   384M|      const AttributeValueIndex avi = attribute->mapped_index(point_id_);
   96|   384M|      if (avi >= static_cast<uint32_t>(attribute->size())) {
  ------------------
  |  Branch (96:11): [True: 0, False: 384M]
  ------------------
   97|      0|        return *this;
   98|      0|      }
   99|   384M|      const uint32_t& offset = std::get<1>(att);
  100|   384M|      const uint32_t& data_size = std::get<3>(att);
  101|   384M|      const uint32_t& num_components = std::get<4>(att);
  102|   384M|      const uint32_t* data_source = val.data() + offset;
  103|   384M|      if (data_size < 4) {  // handle uint16_t, uint8_t
  ------------------
  |  Branch (103:11): [True: 303M, False: 81.0M]
  ------------------
  104|       |        // selectively copy data bytes
  105|   303M|        uint8_t* data_counter = data_;
  106|  1.05G|        for (uint32_t index = 0; index < num_components;
  ------------------
  |  Branch (106:34): [True: 749M, False: 303M]
  ------------------
  107|   749M|             index += 1, data_counter += data_size) {
  108|   749M|          std::memcpy(data_counter, data_source + index, data_size);
  109|   749M|        }
  110|       |        // redirect to copied data
  111|   303M|        data_source = reinterpret_cast<uint32_t*>(data_);
  112|   303M|      }
  113|   384M|      attribute->SetAttributeValue(avi, data_source);
  114|   384M|    }
  115|   384M|    return *this;
  116|   384M|  }
_ZN5draco34PointAttributeVectorOutputIteratorIjEppEv:
   60|   384M|  const Self& operator++() {
   61|   384M|    ++point_id_;
   62|   384M|    return *this;
   63|   384M|  }
_ZN5draco23KdTreeAttributesDecoder12DecodePointsILi1ENS_34PointAttributeVectorOutputIteratorIjEEEEbijPNS_13DecoderBufferEPT0_:
  264|    249|                                           OutIteratorT* out_iterator) {
  265|    249|  DynamicIntegerPointsKdTreeDecoder<level_t> decoder(total_dimensionality);
  266|    249|  if (!decoder.DecodePoints(in_buffer, *out_iterator, num_expected_points) ||
  ------------------
  |  Branch (266:7): [True: 180, False: 69]
  ------------------
  267|    199|      decoder.num_decoded_points() != num_expected_points) {
  ------------------
  |  Branch (267:7): [True: 19, False: 50]
  ------------------
  268|    199|    return false;
  269|    199|  }
  270|     50|  return true;
  271|    249|}
_ZN5draco23KdTreeAttributesDecoder12DecodePointsILi2ENS_34PointAttributeVectorOutputIteratorIjEEEEbijPNS_13DecoderBufferEPT0_:
  264|    171|                                           OutIteratorT* out_iterator) {
  265|    171|  DynamicIntegerPointsKdTreeDecoder<level_t> decoder(total_dimensionality);
  266|    171|  if (!decoder.DecodePoints(in_buffer, *out_iterator, num_expected_points) ||
  ------------------
  |  Branch (266:7): [True: 135, False: 36]
  ------------------
  267|    148|      decoder.num_decoded_points() != num_expected_points) {
  ------------------
  |  Branch (267:7): [True: 13, False: 23]
  ------------------
  268|    148|    return false;
  269|    148|  }
  270|     23|  return true;
  271|    171|}
_ZN5draco23KdTreeAttributesDecoder12DecodePointsILi3ENS_34PointAttributeVectorOutputIteratorIjEEEEbijPNS_13DecoderBufferEPT0_:
  264|    198|                                           OutIteratorT* out_iterator) {
  265|    198|  DynamicIntegerPointsKdTreeDecoder<level_t> decoder(total_dimensionality);
  266|    198|  if (!decoder.DecodePoints(in_buffer, *out_iterator, num_expected_points) ||
  ------------------
  |  Branch (266:7): [True: 165, False: 33]
  ------------------
  267|    175|      decoder.num_decoded_points() != num_expected_points) {
  ------------------
  |  Branch (267:7): [True: 10, False: 23]
  ------------------
  268|    175|    return false;
  269|    175|  }
  270|     23|  return true;
  271|    198|}
_ZN5draco23KdTreeAttributesDecoder12DecodePointsILi4ENS_34PointAttributeVectorOutputIteratorIjEEEEbijPNS_13DecoderBufferEPT0_:
  264|    252|                                           OutIteratorT* out_iterator) {
  265|    252|  DynamicIntegerPointsKdTreeDecoder<level_t> decoder(total_dimensionality);
  266|    252|  if (!decoder.DecodePoints(in_buffer, *out_iterator, num_expected_points) ||
  ------------------
  |  Branch (266:7): [True: 140, False: 112]
  ------------------
  267|    218|      decoder.num_decoded_points() != num_expected_points) {
  ------------------
  |  Branch (267:7): [True: 78, False: 34]
  ------------------
  268|    218|    return false;
  269|    218|  }
  270|     34|  return true;
  271|    252|}
_ZN5draco23KdTreeAttributesDecoder12DecodePointsILi5ENS_34PointAttributeVectorOutputIteratorIjEEEEbijPNS_13DecoderBufferEPT0_:
  264|    227|                                           OutIteratorT* out_iterator) {
  265|    227|  DynamicIntegerPointsKdTreeDecoder<level_t> decoder(total_dimensionality);
  266|    227|  if (!decoder.DecodePoints(in_buffer, *out_iterator, num_expected_points) ||
  ------------------
  |  Branch (266:7): [True: 170, False: 57]
  ------------------
  267|    206|      decoder.num_decoded_points() != num_expected_points) {
  ------------------
  |  Branch (267:7): [True: 36, False: 21]
  ------------------
  268|    206|    return false;
  269|    206|  }
  270|     21|  return true;
  271|    227|}
_ZN5draco23KdTreeAttributesDecoder12DecodePointsILi6ENS_34PointAttributeVectorOutputIteratorIjEEEEbijPNS_13DecoderBufferEPT0_:
  264|    241|                                           OutIteratorT* out_iterator) {
  265|    241|  DynamicIntegerPointsKdTreeDecoder<level_t> decoder(total_dimensionality);
  266|    241|  if (!decoder.DecodePoints(in_buffer, *out_iterator, num_expected_points) ||
  ------------------
  |  Branch (266:7): [True: 156, False: 85]
  ------------------
  267|    160|      decoder.num_decoded_points() != num_expected_points) {
  ------------------
  |  Branch (267:7): [True: 4, False: 81]
  ------------------
  268|    160|    return false;
  269|    160|  }
  270|     81|  return true;
  271|    241|}
_ZN5draco34PointAttributeVectorOutputIteratorIfEC2ERKNSt3__16vectorINS2_5tupleIJPNS_14PointAttributeEjNS_8DataTypeEjjEEENS2_9allocatorIS8_EEEE:
   48|    844|      : attributes_(atts), point_id_(0) {
   49|    844|    DRACO_DCHECK_GE(atts.size(), 1);
   50|    844|    uint32_t required_decode_bytes = 0;
   51|  1.68k|    for (auto index = 0; index < attributes_.size(); index++) {
  ------------------
  |  Branch (51:26): [True: 844, False: 844]
  ------------------
   52|    844|      const AttributeTuple& att = attributes_[index];
   53|    844|      required_decode_bytes = (std::max)(required_decode_bytes,
   54|    844|                                         std::get<3>(att) * std::get<4>(att));
   55|    844|    }
   56|    844|    memory_.resize(required_decode_bytes);
   57|    844|    data_ = memory_.data();
   58|    844|  }
_ZN5draco34PointAttributeVectorOutputIteratorIfEdeEv:
   73|     73|  Self& operator*() { return *this; }
_ZN5draco34PointAttributeVectorOutputIteratorIfEaSERKNS_7VectorDIfLi3EEE:
   77|     73|  const Self& operator=(const VectorD<CoeffT, 3>& val) {
   78|     73|    DRACO_DCHECK_EQ(attributes_.size(), 1);  // Expect only ONE attribute.
   79|     73|    AttributeTuple& att = attributes_[0];
   80|     73|    PointAttribute* attribute = std::get<0>(att);
   81|     73|    const AttributeValueIndex avi = attribute->mapped_index(point_id_);
   82|     73|    if (avi >= static_cast<uint32_t>(attribute->size())) {
  ------------------
  |  Branch (82:9): [True: 66, False: 7]
  ------------------
   83|     66|      return *this;
   84|     66|    }
   85|      7|    const uint32_t& offset = std::get<1>(att);
   86|      7|    DRACO_DCHECK_EQ(offset, 0);  // expected to be zero
   87|      7|    attribute->SetAttributeValue(avi, &val[0] + offset);
   88|      7|    return *this;
   89|     73|  }
_ZN5draco34PointAttributeVectorOutputIteratorIfEppEv:
   60|     73|  const Self& operator++() {
   61|     73|    ++point_id_;
   62|     73|    return *this;
   63|     73|  }
_ZN5draco23KdTreeAttributesDecoder34TransformAttributeBackToSignedTypeIiEEbPNS_14PointAttributeEi:
  470|     44|    PointAttribute* att, int num_processed_signed_components) {
  471|     44|  typedef typename std::make_unsigned<SignedDataTypeT>::type UnsignedType;
  472|     44|  std::vector<UnsignedType> unsigned_val(att->num_components());
  473|     44|  std::vector<SignedDataTypeT> signed_val(att->num_components());
  474|       |
  475|    180|  for (AttributeValueIndex avi(0); avi < static_cast<uint32_t>(att->size());
  ------------------
  |  Branch (475:36): [True: 136, False: 44]
  ------------------
  476|    136|       ++avi) {
  477|    136|    att->GetValue(avi, &unsigned_val[0]);
  478|  9.79k|    for (int c = 0; c < att->num_components(); ++c) {
  ------------------
  |  Branch (478:21): [True: 9.65k, False: 136]
  ------------------
  479|       |      // Up-cast |unsigned_val| to int32_t to ensure we don't overflow it for
  480|       |      // smaller data types. But first check that the up-casting does not cause
  481|       |      // signed integer overflow.
  482|  9.65k|      if (unsigned_val[c] > std::numeric_limits<int32_t>::max()) {
  ------------------
  |  Branch (482:11): [True: 0, False: 9.65k]
  ------------------
  483|      0|        return false;
  484|      0|      }
  485|  9.65k|      signed_val[c] = static_cast<SignedDataTypeT>(
  486|  9.65k|          static_cast<int32_t>(unsigned_val[c]) +
  487|  9.65k|          min_signed_values_[num_processed_signed_components + c]);
  488|  9.65k|    }
  489|    136|    att->SetAttributeValue(avi, &signed_val[0]);
  490|    136|  }
  491|     44|  return true;
  492|     44|}
_ZN5draco23KdTreeAttributesDecoder34TransformAttributeBackToSignedTypeIsEEbPNS_14PointAttributeEi:
  470|     78|    PointAttribute* att, int num_processed_signed_components) {
  471|     78|  typedef typename std::make_unsigned<SignedDataTypeT>::type UnsignedType;
  472|     78|  std::vector<UnsignedType> unsigned_val(att->num_components());
  473|     78|  std::vector<SignedDataTypeT> signed_val(att->num_components());
  474|       |
  475|     78|  for (AttributeValueIndex avi(0); avi < static_cast<uint32_t>(att->size());
  ------------------
  |  Branch (475:36): [True: 0, False: 78]
  ------------------
  476|     78|       ++avi) {
  477|      0|    att->GetValue(avi, &unsigned_val[0]);
  478|      0|    for (int c = 0; c < att->num_components(); ++c) {
  ------------------
  |  Branch (478:21): [True: 0, False: 0]
  ------------------
  479|       |      // Up-cast |unsigned_val| to int32_t to ensure we don't overflow it for
  480|       |      // smaller data types. But first check that the up-casting does not cause
  481|       |      // signed integer overflow.
  482|      0|      if (unsigned_val[c] > std::numeric_limits<int32_t>::max()) {
  ------------------
  |  Branch (482:11): [True: 0, False: 0]
  ------------------
  483|      0|        return false;
  484|      0|      }
  485|      0|      signed_val[c] = static_cast<SignedDataTypeT>(
  486|      0|          static_cast<int32_t>(unsigned_val[c]) +
  487|      0|          min_signed_values_[num_processed_signed_components + c]);
  488|      0|    }
  489|      0|    att->SetAttributeValue(avi, &signed_val[0]);
  490|      0|  }
  491|     78|  return true;
  492|     78|}
_ZN5draco23KdTreeAttributesDecoder34TransformAttributeBackToSignedTypeIaEEbPNS_14PointAttributeEi:
  470|     87|    PointAttribute* att, int num_processed_signed_components) {
  471|     87|  typedef typename std::make_unsigned<SignedDataTypeT>::type UnsignedType;
  472|     87|  std::vector<UnsignedType> unsigned_val(att->num_components());
  473|     87|  std::vector<SignedDataTypeT> signed_val(att->num_components());
  474|       |
  475|  40.6M|  for (AttributeValueIndex avi(0); avi < static_cast<uint32_t>(att->size());
  ------------------
  |  Branch (475:36): [True: 40.6M, False: 87]
  ------------------
  476|  40.6M|       ++avi) {
  477|  40.6M|    att->GetValue(avi, &unsigned_val[0]);
  478|  81.2M|    for (int c = 0; c < att->num_components(); ++c) {
  ------------------
  |  Branch (478:21): [True: 40.6M, False: 40.6M]
  ------------------
  479|       |      // Up-cast |unsigned_val| to int32_t to ensure we don't overflow it for
  480|       |      // smaller data types. But first check that the up-casting does not cause
  481|       |      // signed integer overflow.
  482|  40.6M|      if (unsigned_val[c] > std::numeric_limits<int32_t>::max()) {
  ------------------
  |  Branch (482:11): [True: 0, False: 40.6M]
  ------------------
  483|      0|        return false;
  484|      0|      }
  485|  40.6M|      signed_val[c] = static_cast<SignedDataTypeT>(
  486|  40.6M|          static_cast<int32_t>(unsigned_val[c]) +
  487|  40.6M|          min_signed_values_[num_processed_signed_components + c]);
  488|  40.6M|    }
  489|  40.6M|    att->SetAttributeValue(avi, &signed_val[0]);
  490|  40.6M|  }
  491|     87|  return true;
  492|     87|}

_ZN5draco15LinearSequencerC2Ei:
   26|  23.1k|  explicit LinearSequencer(int32_t num_points) : num_points_(num_points) {}
_ZN5draco15LinearSequencer34UpdatePointToAttributeIndexMappingEPNS_14PointAttributeE:
   28|  1.18k|  bool UpdatePointToAttributeIndexMapping(PointAttribute* attribute) override {
   29|  1.18k|    attribute->SetIdentityMapping();
   30|  1.18k|    return true;
   31|  1.18k|  }
_ZN5draco15LinearSequencer24GenerateSequenceInternalEv:
   34|    811|  bool GenerateSequenceInternal() override {
   35|    811|    if (num_points_ < 0) {
  ------------------
  |  Branch (35:9): [True: 2, False: 809]
  ------------------
   36|      2|      return false;
   37|      2|    }
   38|    809|    out_point_ids()->resize(num_points_);
   39|  2.32G|    for (int i = 0; i < num_points_; ++i) {
  ------------------
  |  Branch (39:21): [True: 2.32G, False: 809]
  ------------------
   40|  2.32G|      out_point_ids()->at(i) = PointIndex(i);
   41|  2.32G|    }
   42|    809|    return true;
   43|    811|  }

_ZN5draco32MeshAttributeIndicesEncodingDataC2Ev:
   28|  56.6k|  MeshAttributeIndicesEncodingData() : num_values(0) {}
_ZN5draco32MeshAttributeIndicesEncodingData4InitEi:
   30|  14.3k|  void Init(int num_vertices) {
   31|  14.3k|    vertex_to_encoded_attribute_value_index_map.resize(num_vertices);
   32|       |
   33|       |    // We expect to store one value for each vertex.
   34|  14.3k|    encoded_attribute_value_index_to_corner_map.reserve(num_vertices);
   35|  14.3k|  }

_ZN5draco17OctahedronToolBoxC2Ev:
   53|  2.98k|      : quantization_bits_(-1),
   54|  2.98k|        max_quantized_value_(-1),
   55|  2.98k|        max_value_(-1),
   56|  2.98k|        dequantization_scale_(1.f),
   57|  2.98k|        center_value_(-1) {}
_ZN5draco17OctahedronToolBox19SetQuantizationBitsEi:
   59|  2.74k|  bool SetQuantizationBits(int32_t q) {
   60|  2.74k|    if (q < 2 || q > 30) {
  ------------------
  |  Branch (60:9): [True: 956, False: 1.79k]
  |  Branch (60:18): [True: 187, False: 1.60k]
  ------------------
   61|  1.14k|      return false;
   62|  1.14k|    }
   63|  1.60k|    quantization_bits_ = q;
   64|  1.60k|    max_quantized_value_ = (1u << quantization_bits_) - 1;
   65|  1.60k|    max_value_ = max_quantized_value_ - 1;
   66|  1.60k|    dequantization_scale_ = 2.f / max_value_;
   67|  1.60k|    center_value_ = max_value_ / 2;
   68|  1.60k|    return true;
   69|  2.74k|  }
_ZNK5draco17OctahedronToolBox28CanonicalizeOctahedralCoordsEiiPiS1_:
   76|  3.87M|                                           int32_t* out_t) const {
   77|  3.87M|    if ((s == 0 && t == 0) || (s == 0 && t == max_value_) ||
  ------------------
  |  Branch (77:10): [True: 3.98k, False: 3.86M]
  |  Branch (77:20): [True: 0, False: 3.98k]
  |  Branch (77:32): [True: 3.98k, False: 3.86M]
  |  Branch (77:42): [True: 0, False: 3.98k]
  ------------------
   78|  3.87M|        (s == max_value_ && t == 0)) {
  ------------------
  |  Branch (78:10): [True: 3.28M, False: 585k]
  |  Branch (78:29): [True: 9.71k, False: 3.27M]
  ------------------
   79|  9.71k|      s = max_value_;
   80|  9.71k|      t = max_value_;
   81|  3.86M|    } else if (s == 0 && t > center_value_) {
  ------------------
  |  Branch (81:16): [True: 3.98k, False: 3.85M]
  |  Branch (81:26): [True: 1.59k, False: 2.39k]
  ------------------
   82|  1.59k|      t = center_value_ - (t - center_value_);
   83|  3.86M|    } else if (s == max_value_ && t < center_value_) {
  ------------------
  |  Branch (83:16): [True: 3.27M, False: 584k]
  |  Branch (83:35): [True: 9.50k, False: 3.26M]
  ------------------
   84|  9.50k|      t = center_value_ + (center_value_ - t);
   85|  3.85M|    } else if (t == max_value_ && s < center_value_) {
  ------------------
  |  Branch (85:16): [True: 3.26M, False: 582k]
  |  Branch (85:35): [True: 883, False: 3.26M]
  ------------------
   86|    883|      s = center_value_ + (center_value_ - s);
   87|  3.85M|    } else if (t == 0 && s > center_value_) {
  ------------------
  |  Branch (87:16): [True: 4.57k, False: 3.84M]
  |  Branch (87:26): [True: 1.91k, False: 2.66k]
  ------------------
   88|  1.91k|      s = center_value_ - (s - center_value_);
   89|  1.91k|    }
   90|       |
   91|  3.87M|    *out_s = s;
   92|  3.87M|    *out_t = t;
   93|  3.87M|  }
_ZNK5draco17OctahedronToolBox40IntegerVectorToQuantizedOctahedralCoordsEPKiPiS3_:
   99|  3.87M|                                                       int32_t* out_t) const {
  100|  3.87M|    DRACO_DCHECK_EQ(
  101|  3.87M|        std::abs(int_vec[0]) + std::abs(int_vec[1]) + std::abs(int_vec[2]),
  102|  3.87M|        center_value_);
  103|  3.87M|    int32_t s, t;
  104|  3.87M|    if (int_vec[0] >= 0) {
  ------------------
  |  Branch (104:9): [True: 2.32M, False: 1.55M]
  ------------------
  105|       |      // Right hemisphere.
  106|  2.32M|      s = (int_vec[1] + center_value_);
  107|  2.32M|      t = (int_vec[2] + center_value_);
  108|  2.32M|    } else {
  109|       |      // Left hemisphere.
  110|  1.55M|      if (int_vec[1] < 0) {
  ------------------
  |  Branch (110:11): [True: 48.8k, False: 1.50M]
  ------------------
  111|  48.8k|        s = std::abs(int_vec[2]);
  112|  1.50M|      } else {
  113|  1.50M|        s = (max_value_ - std::abs(int_vec[2]));
  114|  1.50M|      }
  115|  1.55M|      if (int_vec[2] < 0) {
  ------------------
  |  Branch (115:11): [True: 52.2k, False: 1.49M]
  ------------------
  116|  52.2k|        t = std::abs(int_vec[1]);
  117|  1.49M|      } else {
  118|  1.49M|        t = (max_value_ - std::abs(int_vec[1]));
  119|  1.49M|      }
  120|  1.55M|    }
  121|  3.87M|    CanonicalizeOctahedralCoords(s, t, out_s, out_t);
  122|  3.87M|  }
_ZNK5draco17OctahedronToolBox37QuantizedOctahedralCoordsToUnitVectorEiiPf:
  198|  31.7M|                                                    float* out_vector) const {
  199|  31.7M|    OctahedralCoordsToUnitVector(in_s * dequantization_scale_ - 1.f,
  200|  31.7M|                                 in_t * dequantization_scale_ - 1.f,
  201|  31.7M|                                 out_vector);
  202|  31.7M|  }
_ZNK5draco17OctahedronToolBox11IsInDiamondERKiS2_:
  205|  3.18M|  inline bool IsInDiamond(const int32_t& s, const int32_t& t) const {
  206|       |    // Expect center already at origin.
  207|  3.18M|    DRACO_DCHECK_LE(s, center_value_);
  208|  3.18M|    DRACO_DCHECK_LE(t, center_value_);
  209|  3.18M|    DRACO_DCHECK_GE(s, -center_value_);
  210|  3.18M|    DRACO_DCHECK_GE(t, -center_value_);
  211|  3.18M|    const uint32_t st =
  212|  3.18M|        static_cast<uint32_t>(std::abs(s)) + static_cast<uint32_t>(std::abs(t));
  213|  3.18M|    return st <= center_value_;
  214|  3.18M|  }
_ZNK5draco17OctahedronToolBox13InvertDiamondEPiS1_:
  216|  5.40M|  void InvertDiamond(int32_t* s, int32_t* t) const {
  217|       |    // Expect center already at origin.
  218|  5.40M|    DRACO_DCHECK_LE(*s, center_value_);
  219|  5.40M|    DRACO_DCHECK_LE(*t, center_value_);
  220|  5.40M|    DRACO_DCHECK_GE(*s, -center_value_);
  221|  5.40M|    DRACO_DCHECK_GE(*t, -center_value_);
  222|  5.40M|    int32_t sign_s = 0;
  223|  5.40M|    int32_t sign_t = 0;
  224|  5.40M|    if (*s >= 0 && *t >= 0) {
  ------------------
  |  Branch (224:9): [True: 5.15M, False: 250k]
  |  Branch (224:20): [True: 4.96M, False: 193k]
  ------------------
  225|  4.96M|      sign_s = 1;
  226|  4.96M|      sign_t = 1;
  227|  4.96M|    } else if (*s <= 0 && *t <= 0) {
  ------------------
  |  Branch (227:16): [True: 295k, False: 148k]
  |  Branch (227:27): [True: 238k, False: 57.0k]
  ------------------
  228|   238k|      sign_s = -1;
  229|   238k|      sign_t = -1;
  230|   238k|    } else {
  231|   205k|      sign_s = (*s > 0) ? 1 : -1;
  ------------------
  |  Branch (231:16): [True: 148k, False: 57.0k]
  ------------------
  232|   205k|      sign_t = (*t > 0) ? 1 : -1;
  ------------------
  |  Branch (232:16): [True: 57.0k, False: 148k]
  ------------------
  233|   205k|    }
  234|       |
  235|       |    // Perform the addition and subtraction using unsigned integers to avoid
  236|       |    // signed integer overflows for bad data. Note that the result will be
  237|       |    // unchanged for non-overflowing cases.
  238|  5.40M|    const uint32_t corner_point_s = sign_s * center_value_;
  239|  5.40M|    const uint32_t corner_point_t = sign_t * center_value_;
  240|  5.40M|    uint32_t us = *s;
  241|  5.40M|    uint32_t ut = *t;
  242|  5.40M|    us = us + us - corner_point_s;
  243|  5.40M|    ut = ut + ut - corner_point_t;
  244|  5.40M|    if (sign_s * sign_t >= 0) {
  ------------------
  |  Branch (244:9): [True: 5.20M, False: 205k]
  ------------------
  245|  5.20M|      uint32_t temp = us;
  246|  5.20M|      us = -ut;
  247|  5.20M|      ut = -temp;
  248|  5.20M|    } else {
  249|   205k|      std::swap(us, ut);
  250|   205k|    }
  251|  5.40M|    us = us + corner_point_s;
  252|  5.40M|    ut = ut + corner_point_t;
  253|       |
  254|  5.40M|    *s = us;
  255|  5.40M|    *t = ut;
  256|  5.40M|    *s /= 2;
  257|  5.40M|    *t /= 2;
  258|  5.40M|  }
_ZNK5draco17OctahedronToolBox6ModMaxEi:
  272|  6.36M|  int32_t ModMax(int32_t x) const {
  273|  6.36M|    if (x > this->center_value()) {
  ------------------
  |  Branch (273:9): [True: 3.68k, False: 6.35M]
  ------------------
  274|  3.68k|      return x - this->max_quantized_value();
  275|  3.68k|    }
  276|  6.35M|    if (x < -this->center_value()) {
  ------------------
  |  Branch (276:9): [True: 1.88k, False: 6.35M]
  ------------------
  277|  1.88k|      return x + this->max_quantized_value();
  278|  1.88k|    }
  279|  6.35M|    return x;
  280|  6.35M|  }
_ZNK5draco17OctahedronToolBox17quantization_bitsEv:
  291|  1.56k|  int32_t quantization_bits() const { return quantization_bits_; }
_ZNK5draco17OctahedronToolBox19max_quantized_valueEv:
  292|  5.56k|  int32_t max_quantized_value() const { return max_quantized_value_; }
_ZNK5draco17OctahedronToolBox12center_valueEv:
  294|  19.0M|  int32_t center_value() const { return center_value_; }
_ZNK5draco17OctahedronToolBox28OctahedralCoordsToUnitVectorEffPf:
  298|  31.7M|                                           float* out_vector) const {
  299|       |    // Background about the encoding:
  300|       |    //   A normal is encoded in a normalized space <s, t> depicted below. The
  301|       |    //   encoding correponds to an octahedron that is unwrapped to a 2D plane.
  302|       |    //   During encoding, a normal is projected to the surface of the octahedron
  303|       |    //   and the projection is then unwrapped to the 2D plane. Decoding is the
  304|       |    //   reverse of this process.
  305|       |    //   All points in the central diamond are located on triangles on the
  306|       |    //   right "hemisphere" of the octahedron while all points outside of the
  307|       |    //   diamond are on the left hemisphere (basically, they would have to be
  308|       |    //   wrapped along the diagonal edges to form the octahedron). The central
  309|       |    //   point corresponds to the right most vertex of the octahedron and all
  310|       |    //   corners of the plane correspond to the left most vertex of the
  311|       |    //   octahedron.
  312|       |    //
  313|       |    // t
  314|       |    // ^ *-----*-----*
  315|       |    // | |    /|\    |
  316|       |    //   |   / | \   |
  317|       |    //   |  /  |  \  |
  318|       |    //   | /   |   \ |
  319|       |    //   *-----*---- *
  320|       |    //   | \   |   / |
  321|       |    //   |  \  |  /  |
  322|       |    //   |   \ | /   |
  323|       |    //   |    \|/    |
  324|       |    //   *-----*-----*  --> s
  325|       |
  326|       |    // Note that the input |in_s_scaled| and |in_t_scaled| are already scaled to
  327|       |    // <-1, 1> range. This way, the central point is at coordinate (0, 0).
  328|  31.7M|    float y = in_s_scaled;
  329|  31.7M|    float z = in_t_scaled;
  330|       |
  331|       |    // Remaining coordinate can be computed by projecting the (y, z) values onto
  332|       |    // the surface of the octahedron.
  333|  31.7M|    const float x = 1.f - std::abs(y) - std::abs(z);
  334|       |
  335|       |    // |x| is essentially a signed distance from the diagonal edges of the
  336|       |    // diamond shown on the figure above. It is positive for all points in the
  337|       |    // diamond (right hemisphere) and negative for all points outside the
  338|       |    // diamond (left hemisphere). For all points on the left hemisphere we need
  339|       |    // to update their (y, z) coordinates to account for the wrapping along
  340|       |    // the edges of the diamond.
  341|  31.7M|    float x_offset = -x;
  342|  31.7M|    x_offset = x_offset < 0 ? 0 : x_offset;
  ------------------
  |  Branch (342:16): [True: 88.1k, False: 31.6M]
  ------------------
  343|       |
  344|       |    // This will do nothing for the points on the right hemisphere but it will
  345|       |    // mirror the (y, z) location along the nearest diagonal edge of the
  346|       |    // diamond.
  347|  31.7M|    y += y < 0 ? x_offset : -x_offset;
  ------------------
  |  Branch (347:10): [True: 31.2M, False: 494k]
  ------------------
  348|  31.7M|    z += z < 0 ? x_offset : -x_offset;
  ------------------
  |  Branch (348:10): [True: 31.2M, False: 494k]
  ------------------
  349|       |
  350|       |    // Normalize the computed vector.
  351|  31.7M|    const float norm_squared = x * x + y * y + z * z;
  352|  31.7M|    if (norm_squared < 1e-6) {
  ------------------
  |  Branch (352:9): [True: 0, False: 31.7M]
  ------------------
  353|      0|      out_vector[0] = 0;
  354|      0|      out_vector[1] = 0;
  355|      0|      out_vector[2] = 0;
  356|  31.7M|    } else {
  357|  31.7M|      const float d = 1.0f / std::sqrt(norm_squared);
  358|  31.7M|      out_vector[0] = x * d;
  359|  31.7M|      out_vector[1] = y * d;
  360|  31.7M|      out_vector[2] = z * d;
  361|  31.7M|    }
  362|  31.7M|  }
_ZNK5draco17OctahedronToolBox25CanonicalizeIntegerVectorIiEEvPT_:
  173|  3.87M|  void CanonicalizeIntegerVector(T* vec) const {
  174|  3.87M|    static_assert(std::is_integral<T>::value, "T must be an integral type.");
  175|  3.87M|    static_assert(std::is_signed<T>::value, "T must be a signed type.");
  176|  3.87M|    const int64_t abs_sum = static_cast<int64_t>(std::abs(vec[0])) +
  177|  3.87M|                            static_cast<int64_t>(std::abs(vec[1])) +
  178|  3.87M|                            static_cast<int64_t>(std::abs(vec[2]));
  179|       |
  180|  3.87M|    if (abs_sum == 0) {
  ------------------
  |  Branch (180:9): [True: 3.61M, False: 261k]
  ------------------
  181|  3.61M|      vec[0] = center_value_;  // vec[1] == v[2] == 0
  182|  3.61M|    } else {
  183|   261k|      vec[0] =
  184|   261k|          (static_cast<int64_t>(vec[0]) * static_cast<int64_t>(center_value_)) /
  185|   261k|          abs_sum;
  186|   261k|      vec[1] =
  187|   261k|          (static_cast<int64_t>(vec[1]) * static_cast<int64_t>(center_value_)) /
  188|   261k|          abs_sum;
  189|   261k|      if (vec[2] >= 0) {
  ------------------
  |  Branch (189:11): [True: 140k, False: 120k]
  ------------------
  190|   140k|        vec[2] = center_value_ - std::abs(vec[0]) - std::abs(vec[1]);
  191|   140k|      } else {
  192|   120k|        vec[2] = -(center_value_ - std::abs(vec[0]) - std::abs(vec[1]));
  193|   120k|      }
  194|   261k|    }
  195|  3.87M|  }

_ZN5draco15PointsSequencerC2Ev:
   29|  27.5k|  PointsSequencer() : out_point_ids_(nullptr) {}
_ZN5draco15PointsSequencer16GenerateSequenceEPNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEE:
   33|  5.01k|  bool GenerateSequence(std::vector<PointIndex>* out_point_ids) {
   34|  5.01k|    out_point_ids_ = out_point_ids;
   35|  5.01k|    return GenerateSequenceInternal();
   36|  5.01k|  }
_ZN5draco15PointsSequencer10AddPointIdENS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   39|  17.8M|  void AddPointId(PointIndex point_id) { out_point_ids_->push_back(point_id); }
_ZNK5draco15PointsSequencer13out_point_idsEv:
   55|  2.32G|  std::vector<PointIndex>* out_point_ids() const { return out_point_ids_; }
_ZN5draco15PointsSequencerD2Ev:
   30|  27.5k|  virtual ~PointsSequencer() = default;

_ZN5draco56MeshPredictionSchemeConstrainedMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   50|    503|      : MeshPredictionSchemeDecoder<DataTypeT, TransformT, MeshDataT>(
   51|    503|            attribute, transform, mesh_data),
   52|    503|        selected_mode_(Mode::OPTIMAL_MULTI_PARALLELOGRAM) {}
_ZN5draco56MeshPredictionSchemeConstrainedMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  196|    478|                                                                buffer) {
  197|    478|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  198|    478|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    478|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (198:7): [True: 2, False: 476]
  ------------------
  199|       |    // Decode prediction mode.
  200|      2|    uint8_t mode;
  201|      2|    if (!buffer->Decode(&mode)) {
  ------------------
  |  Branch (201:9): [True: 0, False: 2]
  ------------------
  202|      0|      return false;
  203|      0|    }
  204|       |
  205|      2|    if (mode != Mode::OPTIMAL_MULTI_PARALLELOGRAM) {
  ------------------
  |  Branch (205:9): [True: 1, False: 1]
  ------------------
  206|       |      // Unsupported mode.
  207|      1|      return false;
  208|      1|    }
  209|      2|  }
  210|    477|#endif
  211|       |
  212|       |  // Encode selected edges using separate rans bit coder for each context.
  213|  2.20k|  for (int i = 0; i < kMaxNumParallelograms; ++i) {
  ------------------
  |  Branch (213:19): [True: 1.79k, False: 408]
  ------------------
  214|  1.79k|    uint32_t num_flags;
  215|  1.79k|    if (!DecodeVarint<uint32_t>(&num_flags, buffer)) {
  ------------------
  |  Branch (215:9): [True: 13, False: 1.78k]
  ------------------
  216|     13|      return false;
  217|     13|    }
  218|  1.78k|    if (num_flags > this->mesh_data().corner_table()->num_corners()) {
  ------------------
  |  Branch (218:9): [True: 31, False: 1.75k]
  ------------------
  219|     31|      return false;
  220|     31|    }
  221|  1.75k|    if (num_flags > 0) {
  ------------------
  |  Branch (221:9): [True: 554, False: 1.19k]
  ------------------
  222|    554|      is_crease_edge_[i].resize(num_flags);
  223|    554|      RAnsBitDecoder decoder;
  224|    554|      if (!decoder.StartDecoding(buffer)) {
  ------------------
  |  Branch (224:11): [True: 25, False: 529]
  ------------------
  225|     25|        return false;
  226|     25|      }
  227|  2.07M|      for (uint32_t j = 0; j < num_flags; ++j) {
  ------------------
  |  Branch (227:28): [True: 2.07M, False: 529]
  ------------------
  228|  2.07M|        is_crease_edge_[i][j] = decoder.DecodeNextBit();
  229|  2.07M|      }
  230|    529|      decoder.EndDecoding();
  231|    529|    }
  232|  1.75k|  }
  233|    408|  return MeshPredictionSchemeDecoder<DataTypeT, TransformT,
  234|    408|                                     MeshDataT>::DecodePredictionData(buffer);
  235|    477|}
_ZN5draco56MeshPredictionSchemeConstrainedMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   86|    365|                          const PointIndex* /* entry_to_point_id_map */) {
   87|    365|  this->transform().Init(num_components);
   88|       |
   89|       |  // Predicted values for all simple parallelograms encountered at any given
   90|       |  // vertex.
   91|    365|  std::vector<DataTypeT> pred_vals[kMaxNumParallelograms];
   92|  1.82k|  for (int i = 0; i < kMaxNumParallelograms; ++i) {
  ------------------
  |  Branch (92:19): [True: 1.46k, False: 365]
  ------------------
   93|  1.46k|    pred_vals[i].resize(num_components, 0);
   94|  1.46k|  }
   95|    365|  this->transform().ComputeOriginalValue(pred_vals[0].data(), in_corr,
   96|    365|                                         out_data);
   97|       |
   98|    365|  const CornerTable* const table = this->mesh_data().corner_table();
   99|    365|  const std::vector<int32_t>* const vertex_to_data_map =
  100|    365|      this->mesh_data().vertex_to_data_map();
  101|       |
  102|       |  // Current position in the |is_crease_edge_| array for each context.
  103|    365|  std::vector<int> is_crease_edge_pos(kMaxNumParallelograms, 0);
  104|       |
  105|       |  // Used to store predicted value for multi-parallelogram prediction.
  106|    365|  std::vector<DataTypeT> multi_pred_vals(num_components);
  107|       |
  108|    365|  const int corner_map_size =
  109|    365|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  110|    365|  if (corner_map_size * num_components > size) {
  ------------------
  |  Branch (110:7): [True: 0, False: 365]
  ------------------
  111|      0|    return false;
  112|      0|  }
  113|  1.07M|  for (int p = 1; p < corner_map_size; ++p) {
  ------------------
  |  Branch (113:19): [True: 1.07M, False: 214]
  ------------------
  114|  1.07M|    const CornerIndex start_corner_id =
  115|  1.07M|        this->mesh_data().data_to_corner_map()->at(p);
  116|       |
  117|  1.07M|    CornerIndex corner_id(start_corner_id);
  118|  1.07M|    int num_parallelograms = 0;
  119|  1.07M|    bool first_pass = true;
  120|  2.30M|    while (corner_id != kInvalidCornerIndex) {
  ------------------
  |  Branch (120:12): [True: 1.27M, False: 1.03M]
  ------------------
  121|  1.27M|      if (ComputeParallelogramPrediction(
  ------------------
  |  Branch (121:11): [True: 80.0k, False: 1.19M]
  ------------------
  122|  1.27M|              p, corner_id, table, *vertex_to_data_map, out_data,
  123|  1.27M|              num_components, &(pred_vals[num_parallelograms][0]))) {
  124|       |        // Parallelogram prediction applied and stored in
  125|       |        // |pred_vals[num_parallelograms]|
  126|  80.0k|        ++num_parallelograms;
  127|       |        // Stop processing when we reach the maximum number of allowed
  128|       |        // parallelograms.
  129|  80.0k|        if (num_parallelograms == kMaxNumParallelograms) {
  ------------------
  |  Branch (129:13): [True: 628, False: 79.4k]
  ------------------
  130|    628|          break;
  131|    628|        }
  132|  80.0k|      }
  133|       |
  134|       |      // Proceed to the next corner attached to the vertex. First swing left
  135|       |      // and if we reach a boundary, swing right from the start corner.
  136|  1.27M|      if (first_pass) {
  ------------------
  |  Branch (136:11): [True: 1.26M, False: 8.78k]
  ------------------
  137|  1.26M|        corner_id = table->SwingLeft(corner_id);
  138|  1.26M|      } else {
  139|  8.78k|        corner_id = table->SwingRight(corner_id);
  140|  8.78k|      }
  141|  1.27M|      if (corner_id == start_corner_id) {
  ------------------
  |  Branch (141:11): [True: 36.6k, False: 1.23M]
  ------------------
  142|  36.6k|        break;
  143|  36.6k|      }
  144|  1.23M|      if (corner_id == kInvalidCornerIndex && first_pass) {
  ------------------
  |  Branch (144:11): [True: 1.03M, False: 196k]
  |  Branch (144:47): [True: 1.03M, False: 4.20k]
  ------------------
  145|  1.03M|        first_pass = false;
  146|  1.03M|        corner_id = table->SwingRight(start_corner_id);
  147|  1.03M|      }
  148|  1.23M|    }
  149|       |
  150|       |    // Check which of the available parallelograms are actually used and compute
  151|       |    // the final predicted value.
  152|  1.07M|    int num_used_parallelograms = 0;
  153|  1.07M|    if (num_parallelograms > 0) {
  ------------------
  |  Branch (153:9): [True: 43.0k, False: 1.02M]
  ------------------
  154|  6.38M|      for (int i = 0; i < num_components; ++i) {
  ------------------
  |  Branch (154:23): [True: 6.34M, False: 43.0k]
  ------------------
  155|  6.34M|        multi_pred_vals[i] = 0;
  156|  6.34M|      }
  157|       |      // Check which parallelograms are actually used.
  158|   122k|      for (int i = 0; i < num_parallelograms; ++i) {
  ------------------
  |  Branch (158:23): [True: 79.9k, False: 42.8k]
  ------------------
  159|  79.9k|        const int context = num_parallelograms - 1;
  160|  79.9k|        const int pos = is_crease_edge_pos[context]++;
  161|  79.9k|        if (is_crease_edge_[context].size() <= pos) {
  ------------------
  |  Branch (161:13): [True: 151, False: 79.8k]
  ------------------
  162|    151|          return false;
  163|    151|        }
  164|  79.8k|        const bool is_crease = is_crease_edge_[context][pos];
  165|  79.8k|        if (!is_crease) {
  ------------------
  |  Branch (165:13): [True: 21.1k, False: 58.6k]
  ------------------
  166|  21.1k|          ++num_used_parallelograms;
  167|  2.43M|          for (int j = 0; j < num_components; ++j) {
  ------------------
  |  Branch (167:27): [True: 2.41M, False: 21.1k]
  ------------------
  168|  2.41M|            multi_pred_vals[j] =
  169|  2.41M|                AddAsUnsigned(multi_pred_vals[j], pred_vals[i][j]);
  170|  2.41M|          }
  171|  21.1k|        }
  172|  79.8k|      }
  173|  43.0k|    }
  174|  1.07M|    const int dst_offset = p * num_components;
  175|  1.07M|    if (num_used_parallelograms == 0) {
  ------------------
  |  Branch (175:9): [True: 1.06M, False: 8.75k]
  ------------------
  176|       |      // No parallelogram was valid.
  177|       |      // We use the last decoded point as a reference.
  178|  1.06M|      const int src_offset = (p - 1) * num_components;
  179|  1.06M|      this->transform().ComputeOriginalValue(
  180|  1.06M|          out_data + src_offset, in_corr + dst_offset, out_data + dst_offset);
  181|  1.06M|    } else {
  182|       |      // Compute the correction from the predicted value.
  183|  1.01M|      for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (183:23): [True: 1.01M, False: 8.75k]
  ------------------
  184|  1.01M|        multi_pred_vals[c] /= num_used_parallelograms;
  185|  1.01M|      }
  186|  8.75k|      this->transform().ComputeOriginalValue(
  187|  8.75k|          multi_pred_vals.data(), in_corr + dst_offset, out_data + dst_offset);
  188|  8.75k|    }
  189|  1.07M|  }
  190|    214|  return true;
  191|    365|}
_ZN5draco56MeshPredictionSchemeConstrainedMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   50|    580|      : MeshPredictionSchemeDecoder<DataTypeT, TransformT, MeshDataT>(
   51|    580|            attribute, transform, mesh_data),
   52|    580|        selected_mode_(Mode::OPTIMAL_MULTI_PARALLELOGRAM) {}
_ZN5draco56MeshPredictionSchemeConstrainedMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  196|    561|                                                                buffer) {
  197|    561|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  198|    561|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    561|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (198:7): [True: 2, False: 559]
  ------------------
  199|       |    // Decode prediction mode.
  200|      2|    uint8_t mode;
  201|      2|    if (!buffer->Decode(&mode)) {
  ------------------
  |  Branch (201:9): [True: 0, False: 2]
  ------------------
  202|      0|      return false;
  203|      0|    }
  204|       |
  205|      2|    if (mode != Mode::OPTIMAL_MULTI_PARALLELOGRAM) {
  ------------------
  |  Branch (205:9): [True: 1, False: 1]
  ------------------
  206|       |      // Unsupported mode.
  207|      1|      return false;
  208|      1|    }
  209|      2|  }
  210|    560|#endif
  211|       |
  212|       |  // Encode selected edges using separate rans bit coder for each context.
  213|  2.52k|  for (int i = 0; i < kMaxNumParallelograms; ++i) {
  ------------------
  |  Branch (213:19): [True: 2.07k, False: 447]
  ------------------
  214|  2.07k|    uint32_t num_flags;
  215|  2.07k|    if (!DecodeVarint<uint32_t>(&num_flags, buffer)) {
  ------------------
  |  Branch (215:9): [True: 17, False: 2.06k]
  ------------------
  216|     17|      return false;
  217|     17|    }
  218|  2.06k|    if (num_flags > this->mesh_data().corner_table()->num_corners()) {
  ------------------
  |  Branch (218:9): [True: 56, False: 2.00k]
  ------------------
  219|     56|      return false;
  220|     56|    }
  221|  2.00k|    if (num_flags > 0) {
  ------------------
  |  Branch (221:9): [True: 780, False: 1.22k]
  ------------------
  222|    780|      is_crease_edge_[i].resize(num_flags);
  223|    780|      RAnsBitDecoder decoder;
  224|    780|      if (!decoder.StartDecoding(buffer)) {
  ------------------
  |  Branch (224:11): [True: 40, False: 740]
  ------------------
  225|     40|        return false;
  226|     40|      }
  227|  2.19M|      for (uint32_t j = 0; j < num_flags; ++j) {
  ------------------
  |  Branch (227:28): [True: 2.18M, False: 740]
  ------------------
  228|  2.18M|        is_crease_edge_[i][j] = decoder.DecodeNextBit();
  229|  2.18M|      }
  230|    740|      decoder.EndDecoding();
  231|    740|    }
  232|  2.00k|  }
  233|    447|  return MeshPredictionSchemeDecoder<DataTypeT, TransformT,
  234|    447|                                     MeshDataT>::DecodePredictionData(buffer);
  235|    560|}
_ZN5draco56MeshPredictionSchemeConstrainedMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   86|    411|                          const PointIndex* /* entry_to_point_id_map */) {
   87|    411|  this->transform().Init(num_components);
   88|       |
   89|       |  // Predicted values for all simple parallelograms encountered at any given
   90|       |  // vertex.
   91|    411|  std::vector<DataTypeT> pred_vals[kMaxNumParallelograms];
   92|  2.05k|  for (int i = 0; i < kMaxNumParallelograms; ++i) {
  ------------------
  |  Branch (92:19): [True: 1.64k, False: 411]
  ------------------
   93|  1.64k|    pred_vals[i].resize(num_components, 0);
   94|  1.64k|  }
   95|    411|  this->transform().ComputeOriginalValue(pred_vals[0].data(), in_corr,
   96|    411|                                         out_data);
   97|       |
   98|    411|  const CornerTable* const table = this->mesh_data().corner_table();
   99|    411|  const std::vector<int32_t>* const vertex_to_data_map =
  100|    411|      this->mesh_data().vertex_to_data_map();
  101|       |
  102|       |  // Current position in the |is_crease_edge_| array for each context.
  103|    411|  std::vector<int> is_crease_edge_pos(kMaxNumParallelograms, 0);
  104|       |
  105|       |  // Used to store predicted value for multi-parallelogram prediction.
  106|    411|  std::vector<DataTypeT> multi_pred_vals(num_components);
  107|       |
  108|    411|  const int corner_map_size =
  109|    411|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  110|    411|  if (corner_map_size * num_components > size) {
  ------------------
  |  Branch (110:7): [True: 0, False: 411]
  ------------------
  111|      0|    return false;
  112|      0|  }
  113|   152k|  for (int p = 1; p < corner_map_size; ++p) {
  ------------------
  |  Branch (113:19): [True: 152k, False: 170]
  ------------------
  114|   152k|    const CornerIndex start_corner_id =
  115|   152k|        this->mesh_data().data_to_corner_map()->at(p);
  116|       |
  117|   152k|    CornerIndex corner_id(start_corner_id);
  118|   152k|    int num_parallelograms = 0;
  119|   152k|    bool first_pass = true;
  120|   895k|    while (corner_id != kInvalidCornerIndex) {
  ------------------
  |  Branch (120:12): [True: 888k, False: 7.34k]
  ------------------
  121|   888k|      if (ComputeParallelogramPrediction(
  ------------------
  |  Branch (121:11): [True: 289k, False: 599k]
  ------------------
  122|   888k|              p, corner_id, table, *vertex_to_data_map, out_data,
  123|   888k|              num_components, &(pred_vals[num_parallelograms][0]))) {
  124|       |        // Parallelogram prediction applied and stored in
  125|       |        // |pred_vals[num_parallelograms]|
  126|   289k|        ++num_parallelograms;
  127|       |        // Stop processing when we reach the maximum number of allowed
  128|       |        // parallelograms.
  129|   289k|        if (num_parallelograms == kMaxNumParallelograms) {
  ------------------
  |  Branch (129:13): [True: 503, False: 288k]
  ------------------
  130|    503|          break;
  131|    503|        }
  132|   289k|      }
  133|       |
  134|       |      // Proceed to the next corner attached to the vertex. First swing left
  135|       |      // and if we reach a boundary, swing right from the start corner.
  136|   887k|      if (first_pass) {
  ------------------
  |  Branch (136:11): [True: 879k, False: 8.17k]
  ------------------
  137|   879k|        corner_id = table->SwingLeft(corner_id);
  138|   879k|      } else {
  139|  8.17k|        corner_id = table->SwingRight(corner_id);
  140|  8.17k|      }
  141|   887k|      if (corner_id == start_corner_id) {
  ------------------
  |  Branch (141:11): [True: 144k, False: 743k]
  ------------------
  142|   144k|        break;
  143|   144k|      }
  144|   743k|      if (corner_id == kInvalidCornerIndex && first_pass) {
  ------------------
  |  Branch (144:11): [True: 11.5k, False: 731k]
  |  Branch (144:47): [True: 7.35k, False: 4.14k]
  ------------------
  145|  7.35k|        first_pass = false;
  146|  7.35k|        corner_id = table->SwingRight(start_corner_id);
  147|  7.35k|      }
  148|   743k|    }
  149|       |
  150|       |    // Check which of the available parallelograms are actually used and compute
  151|       |    // the final predicted value.
  152|   152k|    int num_used_parallelograms = 0;
  153|   152k|    if (num_parallelograms > 0) {
  ------------------
  |  Branch (153:9): [True: 149k, False: 2.79k]
  ------------------
  154|  5.33M|      for (int i = 0; i < num_components; ++i) {
  ------------------
  |  Branch (154:23): [True: 5.18M, False: 149k]
  ------------------
  155|  5.18M|        multi_pred_vals[i] = 0;
  156|  5.18M|      }
  157|       |      // Check which parallelograms are actually used.
  158|   438k|      for (int i = 0; i < num_parallelograms; ++i) {
  ------------------
  |  Branch (158:23): [True: 288k, False: 149k]
  ------------------
  159|   288k|        const int context = num_parallelograms - 1;
  160|   288k|        const int pos = is_crease_edge_pos[context]++;
  161|   288k|        if (is_crease_edge_[context].size() <= pos) {
  ------------------
  |  Branch (161:13): [True: 241, False: 288k]
  ------------------
  162|    241|          return false;
  163|    241|        }
  164|   288k|        const bool is_crease = is_crease_edge_[context][pos];
  165|   288k|        if (!is_crease) {
  ------------------
  |  Branch (165:13): [True: 57.2k, False: 231k]
  ------------------
  166|  57.2k|          ++num_used_parallelograms;
  167|  2.69M|          for (int j = 0; j < num_components; ++j) {
  ------------------
  |  Branch (167:27): [True: 2.63M, False: 57.2k]
  ------------------
  168|  2.63M|            multi_pred_vals[j] =
  169|  2.63M|                AddAsUnsigned(multi_pred_vals[j], pred_vals[i][j]);
  170|  2.63M|          }
  171|  57.2k|        }
  172|   288k|      }
  173|   149k|    }
  174|   152k|    const int dst_offset = p * num_components;
  175|   152k|    if (num_used_parallelograms == 0) {
  ------------------
  |  Branch (175:9): [True: 124k, False: 27.5k]
  ------------------
  176|       |      // No parallelogram was valid.
  177|       |      // We use the last decoded point as a reference.
  178|   124k|      const int src_offset = (p - 1) * num_components;
  179|   124k|      this->transform().ComputeOriginalValue(
  180|   124k|          out_data + src_offset, in_corr + dst_offset, out_data + dst_offset);
  181|   124k|    } else {
  182|       |      // Compute the correction from the predicted value.
  183|  1.38M|      for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (183:23): [True: 1.35M, False: 27.5k]
  ------------------
  184|  1.35M|        multi_pred_vals[c] /= num_used_parallelograms;
  185|  1.35M|      }
  186|  27.5k|      this->transform().ComputeOriginalValue(
  187|  27.5k|          multi_pred_vals.data(), in_corr + dst_offset, out_data + dst_offset);
  188|  27.5k|    }
  189|   152k|  }
  190|    170|  return true;
  191|    411|}

_ZN5draco24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEE3SetEPKNS_4MeshEPKS1_PKNSt3__16vectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEENS8_9allocatorISC_EEEEPKNS9_IiNSD_IiEEEE:
   37|  2.67k|           const std::vector<int32_t>* vertex_to_data_map) {
   38|  2.67k|    mesh_ = mesh;
   39|  2.67k|    corner_table_ = table;
   40|  2.67k|    data_to_corner_map_ = data_to_corner_map;
   41|  2.67k|    vertex_to_data_map_ = vertex_to_data_map;
   42|  2.67k|  }
_ZNK5draco24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEE12corner_tableEv:
   45|  24.4M|  const CornerTable* corner_table() const { return corner_table_; }
_ZNK5draco24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEE18vertex_to_data_mapEv:
   46|  16.2M|  const std::vector<int32_t>* vertex_to_data_map() const {
   47|  16.2M|    return vertex_to_data_map_;
   48|  16.2M|  }
_ZNK5draco24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEE18data_to_corner_mapEv:
   49|  10.7M|  const std::vector<CornerIndex>* data_to_corner_map() const {
   50|  10.7M|    return data_to_corner_map_;
   51|  10.7M|  }
_ZN5draco24MeshPredictionSchemeDataINS_11CornerTableEE3SetEPKNS_4MeshEPKS1_PKNSt3__16vectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEENS8_9allocatorISC_EEEEPKNS9_IiNSD_IiEEEE:
   37|  2.85k|           const std::vector<int32_t>* vertex_to_data_map) {
   38|  2.85k|    mesh_ = mesh;
   39|  2.85k|    corner_table_ = table;
   40|  2.85k|    data_to_corner_map_ = data_to_corner_map;
   41|  2.85k|    vertex_to_data_map_ = vertex_to_data_map;
   42|  2.85k|  }
_ZNK5draco24MeshPredictionSchemeDataINS_11CornerTableEE12corner_tableEv:
   45|  9.98M|  const CornerTable* corner_table() const { return corner_table_; }
_ZNK5draco24MeshPredictionSchemeDataINS_11CornerTableEE18vertex_to_data_mapEv:
   46|  8.56M|  const std::vector<int32_t>* vertex_to_data_map() const {
   47|  8.56M|    return vertex_to_data_map_;
   48|  8.56M|  }
_ZNK5draco24MeshPredictionSchemeDataINS_11CornerTableEE18data_to_corner_mapEv:
   49|  2.53M|  const std::vector<CornerIndex>* data_to_corner_map() const {
   50|  2.53M|    return data_to_corner_map_;
   51|  2.53M|  }
_ZN5draco24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEC2Ev:
   30|  2.67k|      : mesh_(nullptr),
   31|  2.67k|        corner_table_(nullptr),
   32|  2.67k|        vertex_to_data_map_(nullptr),
   33|  2.67k|        data_to_corner_map_(nullptr) {}
_ZN5draco24MeshPredictionSchemeDataINS_11CornerTableEEC2Ev:
   30|  2.85k|      : mesh_(nullptr),
   31|  2.85k|        corner_table_(nullptr),
   32|  2.85k|        vertex_to_data_map_(nullptr),
   33|  2.85k|        data_to_corner_map_(nullptr) {}

_ZNK5draco27MeshPredictionSchemeDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE9mesh_dataEv:
   38|  1.03M|  const MeshData& mesh_data() const { return mesh_data_; }
_ZNK5draco27MeshPredictionSchemeDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE9mesh_dataEv:
   38|   202k|  const MeshData& mesh_data() const { return mesh_data_; }
_ZNK5draco27MeshPredictionSchemeDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE9mesh_dataEv:
   38|   404k|  const MeshData& mesh_data() const { return mesh_data_; }
_ZNK5draco27MeshPredictionSchemeDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE9mesh_dataEv:
   38|   244k|  const MeshData& mesh_data() const { return mesh_data_; }
_ZN5draco27MeshPredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   34|  2.29k|      : PredictionSchemeDecoder<DataTypeT, TransformT>(attribute, transform),
   35|  2.29k|        mesh_data_(mesh_data) {}
_ZNK5draco27MeshPredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE9mesh_dataEv:
   38|  17.5M|  const MeshData& mesh_data() const { return mesh_data_; }
_ZN5draco27MeshPredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   34|  2.50k|      : PredictionSchemeDecoder<DataTypeT, TransformT>(attribute, transform),
   35|  2.50k|        mesh_data_(mesh_data) {}
_ZNK5draco27MeshPredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE9mesh_dataEv:
   38|  3.73M|  const MeshData& mesh_data() const { return mesh_data_; }
_ZN5draco27MeshPredictionSchemeDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   34|    176|      : PredictionSchemeDecoder<DataTypeT, TransformT>(attribute, transform),
   35|    176|        mesh_data_(mesh_data) {}
_ZN5draco27MeshPredictionSchemeDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   34|    168|      : PredictionSchemeDecoder<DataTypeT, TransformT>(attribute, transform),
   35|    168|        mesh_data_(mesh_data) {}
_ZN5draco27MeshPredictionSchemeDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   34|    163|      : PredictionSchemeDecoder<DataTypeT, TransformT>(attribute, transform),
   35|    163|        mesh_data_(mesh_data) {}
_ZN5draco27MeshPredictionSchemeDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   34|    175|      : PredictionSchemeDecoder<DataTypeT, TransformT>(attribute, transform),
   35|    175|        mesh_data_(mesh_data) {}

_ZNK5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE22GetNumParentAttributesEv:
   66|    351|  int GetNumParentAttributes() const override { return 1; }
_ZNK5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE22GetParentAttributeTypeEi:
   68|    176|  GeometryAttribute::Type GetParentAttributeType(int i) const override {
   69|    176|    DRACO_DCHECK_EQ(i, 0);
   70|    176|    (void)i;
   71|    176|    return GeometryAttribute::POSITION;
   72|    176|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE18SetParentAttributeEPKNS_14PointAttributeE:
   74|    176|  bool SetParentAttribute(const PointAttribute* att) override {
   75|    176|    if (att->attribute_type() != GeometryAttribute::POSITION) {
  ------------------
  |  Branch (75:9): [True: 0, False: 176]
  ------------------
   76|      0|      return false;  // Invalid attribute type.
   77|      0|    }
   78|    176|    if (att->num_components() != 3) {
  ------------------
  |  Branch (78:9): [True: 1, False: 175]
  ------------------
   79|      1|      return false;  // Currently works only for 3 component positions.
   80|      1|    }
   81|    175|    predictor_.SetPositionAttribute(*att);
   82|    175|    return true;
   83|    176|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  145|    175|                                                                buffer) {
  146|       |  // Get data needed for transform
  147|    175|  if (!this->transform().DecodeTransformData(buffer)) {
  ------------------
  |  Branch (147:7): [True: 7, False: 168]
  ------------------
  148|      7|    return false;
  149|      7|  }
  150|       |
  151|    168|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  152|    168|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    168|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (152:7): [True: 34, False: 134]
  ------------------
  153|     34|    uint8_t prediction_mode;
  154|     34|    if (!buffer->Decode(&prediction_mode)) {
  ------------------
  |  Branch (154:9): [True: 0, False: 34]
  ------------------
  155|      0|      return false;
  156|      0|    }
  157|     34|    if (prediction_mode > TRIANGLE_AREA) {
  ------------------
  |  Branch (157:9): [True: 3, False: 31]
  ------------------
  158|       |      // Invalid prediction mode.
  159|      3|      return false;
  160|      3|    }
  161|       |
  162|     31|    if (!predictor_.SetNormalPredictionMode(
  ------------------
  |  Branch (162:9): [True: 0, False: 31]
  ------------------
  163|     31|            NormalPredictionMode(prediction_mode))) {
  164|      0|      return false;
  165|      0|    }
  166|     31|  }
  167|    165|#endif
  168|       |
  169|       |  // Init normal flips.
  170|    165|  if (!flip_normal_bit_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (170:7): [True: 13, False: 152]
  ------------------
  171|     13|    return false;
  172|     13|  }
  173|       |
  174|    152|  return true;
  175|    165|}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
  102|    152|                                      const PointIndex* entry_to_point_id_map) {
  103|    152|  this->SetQuantizationBits(this->transform().quantization_bits());
  104|    152|  predictor_.SetEntryToPointIdMap(entry_to_point_id_map);
  105|    152|  DRACO_DCHECK(this->IsInitialized());
  106|       |
  107|       |  // Expecting in_data in octahedral coordinates, i.e., portable attribute.
  108|    152|  DRACO_DCHECK_EQ(num_components, 2);
  109|       |
  110|    152|  const int corner_map_size =
  111|    152|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  112|    152|  if (corner_map_size * num_components > size) {
  ------------------
  |  Branch (112:7): [True: 0, False: 152]
  ------------------
  113|      0|    return false;
  114|      0|  }
  115|       |
  116|    152|  VectorD<int32_t, 3> pred_normal_3d;
  117|    152|  int32_t pred_normal_oct[2];
  118|       |
  119|  1.03M|  for (int data_id = 0; data_id < corner_map_size; ++data_id) {
  ------------------
  |  Branch (119:25): [True: 1.03M, False: 152]
  ------------------
  120|  1.03M|    const CornerIndex corner_id =
  121|  1.03M|        this->mesh_data().data_to_corner_map()->at(data_id);
  122|  1.03M|    predictor_.ComputePredictedValue(corner_id, pred_normal_3d.data());
  123|       |
  124|       |    // Compute predicted octahedral coordinates.
  125|  1.03M|    octahedron_tool_box_.CanonicalizeIntegerVector(pred_normal_3d.data());
  126|  1.03M|    DRACO_DCHECK_EQ(pred_normal_3d.AbsSum(),
  127|  1.03M|                    octahedron_tool_box_.center_value());
  128|  1.03M|    if (flip_normal_bit_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (128:9): [True: 732k, False: 298k]
  ------------------
  129|   732k|      pred_normal_3d = -pred_normal_3d;
  130|   732k|    }
  131|  1.03M|    octahedron_tool_box_.IntegerVectorToQuantizedOctahedralCoords(
  132|  1.03M|        pred_normal_3d.data(), pred_normal_oct, pred_normal_oct + 1);
  133|       |
  134|  1.03M|    const int data_offset = data_id * 2;
  135|  1.03M|    this->transform().ComputeOriginalValue(
  136|  1.03M|        pred_normal_oct, in_corr + data_offset, out_data + data_offset);
  137|  1.03M|  }
  138|    152|  flip_normal_bit_decoder_.EndDecoding();
  139|    152|  return true;
  140|    152|}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE19SetQuantizationBitsEi:
   84|    152|  void SetQuantizationBits(int q) {
   85|    152|    octahedron_tool_box_.SetQuantizationBits(q);
   86|    152|  }
_ZNK5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE22GetNumParentAttributesEv:
   66|    335|  int GetNumParentAttributes() const override { return 1; }
_ZNK5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE22GetParentAttributeTypeEi:
   68|    168|  GeometryAttribute::Type GetParentAttributeType(int i) const override {
   69|    168|    DRACO_DCHECK_EQ(i, 0);
   70|    168|    (void)i;
   71|    168|    return GeometryAttribute::POSITION;
   72|    168|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE18SetParentAttributeEPKNS_14PointAttributeE:
   74|    168|  bool SetParentAttribute(const PointAttribute* att) override {
   75|    168|    if (att->attribute_type() != GeometryAttribute::POSITION) {
  ------------------
  |  Branch (75:9): [True: 0, False: 168]
  ------------------
   76|      0|      return false;  // Invalid attribute type.
   77|      0|    }
   78|    168|    if (att->num_components() != 3) {
  ------------------
  |  Branch (78:9): [True: 1, False: 167]
  ------------------
   79|      1|      return false;  // Currently works only for 3 component positions.
   80|      1|    }
   81|    167|    predictor_.SetPositionAttribute(*att);
   82|    167|    return true;
   83|    168|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  145|    167|                                                                buffer) {
  146|       |  // Get data needed for transform
  147|    167|  if (!this->transform().DecodeTransformData(buffer)) {
  ------------------
  |  Branch (147:7): [True: 5, False: 162]
  ------------------
  148|      5|    return false;
  149|      5|  }
  150|       |
  151|    162|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  152|    162|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    162|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (152:7): [True: 29, False: 133]
  ------------------
  153|     29|    uint8_t prediction_mode;
  154|     29|    if (!buffer->Decode(&prediction_mode)) {
  ------------------
  |  Branch (154:9): [True: 0, False: 29]
  ------------------
  155|      0|      return false;
  156|      0|    }
  157|     29|    if (prediction_mode > TRIANGLE_AREA) {
  ------------------
  |  Branch (157:9): [True: 1, False: 28]
  ------------------
  158|       |      // Invalid prediction mode.
  159|      1|      return false;
  160|      1|    }
  161|       |
  162|     28|    if (!predictor_.SetNormalPredictionMode(
  ------------------
  |  Branch (162:9): [True: 0, False: 28]
  ------------------
  163|     28|            NormalPredictionMode(prediction_mode))) {
  164|      0|      return false;
  165|      0|    }
  166|     28|  }
  167|    161|#endif
  168|       |
  169|       |  // Init normal flips.
  170|    161|  if (!flip_normal_bit_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (170:7): [True: 3, False: 158]
  ------------------
  171|      3|    return false;
  172|      3|  }
  173|       |
  174|    158|  return true;
  175|    161|}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
  102|    158|                                      const PointIndex* entry_to_point_id_map) {
  103|    158|  this->SetQuantizationBits(this->transform().quantization_bits());
  104|    158|  predictor_.SetEntryToPointIdMap(entry_to_point_id_map);
  105|    158|  DRACO_DCHECK(this->IsInitialized());
  106|       |
  107|       |  // Expecting in_data in octahedral coordinates, i.e., portable attribute.
  108|    158|  DRACO_DCHECK_EQ(num_components, 2);
  109|       |
  110|    158|  const int corner_map_size =
  111|    158|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  112|    158|  if (corner_map_size * num_components > size) {
  ------------------
  |  Branch (112:7): [True: 0, False: 158]
  ------------------
  113|      0|    return false;
  114|      0|  }
  115|       |
  116|    158|  VectorD<int32_t, 3> pred_normal_3d;
  117|    158|  int32_t pred_normal_oct[2];
  118|       |
  119|   202k|  for (int data_id = 0; data_id < corner_map_size; ++data_id) {
  ------------------
  |  Branch (119:25): [True: 202k, False: 158]
  ------------------
  120|   202k|    const CornerIndex corner_id =
  121|   202k|        this->mesh_data().data_to_corner_map()->at(data_id);
  122|   202k|    predictor_.ComputePredictedValue(corner_id, pred_normal_3d.data());
  123|       |
  124|       |    // Compute predicted octahedral coordinates.
  125|   202k|    octahedron_tool_box_.CanonicalizeIntegerVector(pred_normal_3d.data());
  126|   202k|    DRACO_DCHECK_EQ(pred_normal_3d.AbsSum(),
  127|   202k|                    octahedron_tool_box_.center_value());
  128|   202k|    if (flip_normal_bit_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (128:9): [True: 77.6k, False: 124k]
  ------------------
  129|  77.6k|      pred_normal_3d = -pred_normal_3d;
  130|  77.6k|    }
  131|   202k|    octahedron_tool_box_.IntegerVectorToQuantizedOctahedralCoords(
  132|   202k|        pred_normal_3d.data(), pred_normal_oct, pred_normal_oct + 1);
  133|       |
  134|   202k|    const int data_offset = data_id * 2;
  135|   202k|    this->transform().ComputeOriginalValue(
  136|   202k|        pred_normal_oct, in_corr + data_offset, out_data + data_offset);
  137|   202k|  }
  138|    158|  flip_normal_bit_decoder_.EndDecoding();
  139|    158|  return true;
  140|    158|}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE19SetQuantizationBitsEi:
   84|    158|  void SetQuantizationBits(int q) {
   85|    158|    octahedron_tool_box_.SetQuantizationBits(q);
   86|    158|  }
_ZNK5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE22GetNumParentAttributesEv:
   66|    325|  int GetNumParentAttributes() const override { return 1; }
_ZNK5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE22GetParentAttributeTypeEi:
   68|    163|  GeometryAttribute::Type GetParentAttributeType(int i) const override {
   69|    163|    DRACO_DCHECK_EQ(i, 0);
   70|    163|    (void)i;
   71|    163|    return GeometryAttribute::POSITION;
   72|    163|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE18SetParentAttributeEPKNS_14PointAttributeE:
   74|    163|  bool SetParentAttribute(const PointAttribute* att) override {
   75|    163|    if (att->attribute_type() != GeometryAttribute::POSITION) {
  ------------------
  |  Branch (75:9): [True: 0, False: 163]
  ------------------
   76|      0|      return false;  // Invalid attribute type.
   77|      0|    }
   78|    163|    if (att->num_components() != 3) {
  ------------------
  |  Branch (78:9): [True: 1, False: 162]
  ------------------
   79|      1|      return false;  // Currently works only for 3 component positions.
   80|      1|    }
   81|    162|    predictor_.SetPositionAttribute(*att);
   82|    162|    return true;
   83|    163|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  145|    162|                                                                buffer) {
  146|       |  // Get data needed for transform
  147|    162|  if (!this->transform().DecodeTransformData(buffer)) {
  ------------------
  |  Branch (147:7): [True: 6, False: 156]
  ------------------
  148|      6|    return false;
  149|      6|  }
  150|       |
  151|    156|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  152|    156|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    156|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (152:7): [True: 31, False: 125]
  ------------------
  153|     31|    uint8_t prediction_mode;
  154|     31|    if (!buffer->Decode(&prediction_mode)) {
  ------------------
  |  Branch (154:9): [True: 0, False: 31]
  ------------------
  155|      0|      return false;
  156|      0|    }
  157|     31|    if (prediction_mode > TRIANGLE_AREA) {
  ------------------
  |  Branch (157:9): [True: 7, False: 24]
  ------------------
  158|       |      // Invalid prediction mode.
  159|      7|      return false;
  160|      7|    }
  161|       |
  162|     24|    if (!predictor_.SetNormalPredictionMode(
  ------------------
  |  Branch (162:9): [True: 0, False: 24]
  ------------------
  163|     24|            NormalPredictionMode(prediction_mode))) {
  164|      0|      return false;
  165|      0|    }
  166|     24|  }
  167|    149|#endif
  168|       |
  169|       |  // Init normal flips.
  170|    149|  if (!flip_normal_bit_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (170:7): [True: 4, False: 145]
  ------------------
  171|      4|    return false;
  172|      4|  }
  173|       |
  174|    145|  return true;
  175|    149|}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
  102|    145|                                      const PointIndex* entry_to_point_id_map) {
  103|    145|  this->SetQuantizationBits(this->transform().quantization_bits());
  104|    145|  predictor_.SetEntryToPointIdMap(entry_to_point_id_map);
  105|    145|  DRACO_DCHECK(this->IsInitialized());
  106|       |
  107|       |  // Expecting in_data in octahedral coordinates, i.e., portable attribute.
  108|    145|  DRACO_DCHECK_EQ(num_components, 2);
  109|       |
  110|    145|  const int corner_map_size =
  111|    145|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  112|    145|  if (corner_map_size * num_components > size) {
  ------------------
  |  Branch (112:7): [True: 0, False: 145]
  ------------------
  113|      0|    return false;
  114|      0|  }
  115|       |
  116|    145|  VectorD<int32_t, 3> pred_normal_3d;
  117|    145|  int32_t pred_normal_oct[2];
  118|       |
  119|   404k|  for (int data_id = 0; data_id < corner_map_size; ++data_id) {
  ------------------
  |  Branch (119:25): [True: 404k, False: 145]
  ------------------
  120|   404k|    const CornerIndex corner_id =
  121|   404k|        this->mesh_data().data_to_corner_map()->at(data_id);
  122|   404k|    predictor_.ComputePredictedValue(corner_id, pred_normal_3d.data());
  123|       |
  124|       |    // Compute predicted octahedral coordinates.
  125|   404k|    octahedron_tool_box_.CanonicalizeIntegerVector(pred_normal_3d.data());
  126|   404k|    DRACO_DCHECK_EQ(pred_normal_3d.AbsSum(),
  127|   404k|                    octahedron_tool_box_.center_value());
  128|   404k|    if (flip_normal_bit_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (128:9): [True: 377k, False: 27.2k]
  ------------------
  129|   377k|      pred_normal_3d = -pred_normal_3d;
  130|   377k|    }
  131|   404k|    octahedron_tool_box_.IntegerVectorToQuantizedOctahedralCoords(
  132|   404k|        pred_normal_3d.data(), pred_normal_oct, pred_normal_oct + 1);
  133|       |
  134|   404k|    const int data_offset = data_id * 2;
  135|   404k|    this->transform().ComputeOriginalValue(
  136|   404k|        pred_normal_oct, in_corr + data_offset, out_data + data_offset);
  137|   404k|  }
  138|    145|  flip_normal_bit_decoder_.EndDecoding();
  139|    145|  return true;
  140|    145|}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE19SetQuantizationBitsEi:
   84|    145|  void SetQuantizationBits(int q) {
   85|    145|    octahedron_tool_box_.SetQuantizationBits(q);
   86|    145|  }
_ZNK5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE22GetNumParentAttributesEv:
   66|    346|  int GetNumParentAttributes() const override { return 1; }
_ZNK5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE22GetParentAttributeTypeEi:
   68|    175|  GeometryAttribute::Type GetParentAttributeType(int i) const override {
   69|    175|    DRACO_DCHECK_EQ(i, 0);
   70|    175|    (void)i;
   71|    175|    return GeometryAttribute::POSITION;
   72|    175|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE18SetParentAttributeEPKNS_14PointAttributeE:
   74|    174|  bool SetParentAttribute(const PointAttribute* att) override {
   75|    174|    if (att->attribute_type() != GeometryAttribute::POSITION) {
  ------------------
  |  Branch (75:9): [True: 0, False: 174]
  ------------------
   76|      0|      return false;  // Invalid attribute type.
   77|      0|    }
   78|    174|    if (att->num_components() != 3) {
  ------------------
  |  Branch (78:9): [True: 3, False: 171]
  ------------------
   79|      3|      return false;  // Currently works only for 3 component positions.
   80|      3|    }
   81|    171|    predictor_.SetPositionAttribute(*att);
   82|    171|    return true;
   83|    174|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  145|    171|                                                                buffer) {
  146|       |  // Get data needed for transform
  147|    171|  if (!this->transform().DecodeTransformData(buffer)) {
  ------------------
  |  Branch (147:7): [True: 5, False: 166]
  ------------------
  148|      5|    return false;
  149|      5|  }
  150|       |
  151|    166|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  152|    166|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    166|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (152:7): [True: 33, False: 133]
  ------------------
  153|     33|    uint8_t prediction_mode;
  154|     33|    if (!buffer->Decode(&prediction_mode)) {
  ------------------
  |  Branch (154:9): [True: 1, False: 32]
  ------------------
  155|      1|      return false;
  156|      1|    }
  157|     32|    if (prediction_mode > TRIANGLE_AREA) {
  ------------------
  |  Branch (157:9): [True: 2, False: 30]
  ------------------
  158|       |      // Invalid prediction mode.
  159|      2|      return false;
  160|      2|    }
  161|       |
  162|     30|    if (!predictor_.SetNormalPredictionMode(
  ------------------
  |  Branch (162:9): [True: 0, False: 30]
  ------------------
  163|     30|            NormalPredictionMode(prediction_mode))) {
  164|      0|      return false;
  165|      0|    }
  166|     30|  }
  167|    163|#endif
  168|       |
  169|       |  // Init normal flips.
  170|    163|  if (!flip_normal_bit_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (170:7): [True: 4, False: 159]
  ------------------
  171|      4|    return false;
  172|      4|  }
  173|       |
  174|    159|  return true;
  175|    163|}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
  102|    159|                                      const PointIndex* entry_to_point_id_map) {
  103|    159|  this->SetQuantizationBits(this->transform().quantization_bits());
  104|    159|  predictor_.SetEntryToPointIdMap(entry_to_point_id_map);
  105|    159|  DRACO_DCHECK(this->IsInitialized());
  106|       |
  107|       |  // Expecting in_data in octahedral coordinates, i.e., portable attribute.
  108|    159|  DRACO_DCHECK_EQ(num_components, 2);
  109|       |
  110|    159|  const int corner_map_size =
  111|    159|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  112|    159|  if (corner_map_size * num_components > size) {
  ------------------
  |  Branch (112:7): [True: 0, False: 159]
  ------------------
  113|      0|    return false;
  114|      0|  }
  115|       |
  116|    159|  VectorD<int32_t, 3> pred_normal_3d;
  117|    159|  int32_t pred_normal_oct[2];
  118|       |
  119|   244k|  for (int data_id = 0; data_id < corner_map_size; ++data_id) {
  ------------------
  |  Branch (119:25): [True: 244k, False: 159]
  ------------------
  120|   244k|    const CornerIndex corner_id =
  121|   244k|        this->mesh_data().data_to_corner_map()->at(data_id);
  122|   244k|    predictor_.ComputePredictedValue(corner_id, pred_normal_3d.data());
  123|       |
  124|       |    // Compute predicted octahedral coordinates.
  125|   244k|    octahedron_tool_box_.CanonicalizeIntegerVector(pred_normal_3d.data());
  126|   244k|    DRACO_DCHECK_EQ(pred_normal_3d.AbsSum(),
  127|   244k|                    octahedron_tool_box_.center_value());
  128|   244k|    if (flip_normal_bit_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (128:9): [True: 239k, False: 4.83k]
  ------------------
  129|   239k|      pred_normal_3d = -pred_normal_3d;
  130|   239k|    }
  131|   244k|    octahedron_tool_box_.IntegerVectorToQuantizedOctahedralCoords(
  132|   244k|        pred_normal_3d.data(), pred_normal_oct, pred_normal_oct + 1);
  133|       |
  134|   244k|    const int data_offset = data_id * 2;
  135|   244k|    this->transform().ComputeOriginalValue(
  136|   244k|        pred_normal_oct, in_corr + data_offset, out_data + data_offset);
  137|   244k|  }
  138|    159|  flip_normal_bit_decoder_.EndDecoding();
  139|    159|  return true;
  140|    159|}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE19SetQuantizationBitsEi:
   84|    159|  void SetQuantizationBits(int q) {
   85|    159|    octahedron_tool_box_.SetQuantizationBits(q);
   86|    159|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   35|    374|      : MeshPredictionSchemeDecoder<DataTypeT, TransformT, MeshDataT>(
   36|    374|            attribute, transform, mesh_data),
   37|    374|        predictor_(mesh_data) {}
_ZNK5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE22GetNumParentAttributesEv:
   66|    744|  int GetNumParentAttributes() const override { return 1; }
_ZNK5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE22GetParentAttributeTypeEi:
   68|    374|  GeometryAttribute::Type GetParentAttributeType(int i) const override {
   69|    374|    DRACO_DCHECK_EQ(i, 0);
   70|    374|    (void)i;
   71|    374|    return GeometryAttribute::POSITION;
   72|    374|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE18SetParentAttributeEPKNS_14PointAttributeE:
   74|    373|  bool SetParentAttribute(const PointAttribute* att) override {
   75|    373|    if (att->attribute_type() != GeometryAttribute::POSITION) {
  ------------------
  |  Branch (75:9): [True: 0, False: 373]
  ------------------
   76|      0|      return false;  // Invalid attribute type.
   77|      0|    }
   78|    373|    if (att->num_components() != 3) {
  ------------------
  |  Branch (78:9): [True: 3, False: 370]
  ------------------
   79|      3|      return false;  // Currently works only for 3 component positions.
   80|      3|    }
   81|    370|    predictor_.SetPositionAttribute(*att);
   82|    370|    return true;
   83|    373|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  145|    367|                                                                buffer) {
  146|       |  // Get data needed for transform
  147|    367|  if (!this->transform().DecodeTransformData(buffer)) {
  ------------------
  |  Branch (147:7): [True: 24, False: 343]
  ------------------
  148|     24|    return false;
  149|     24|  }
  150|       |
  151|    343|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  152|    343|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    343|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (152:7): [True: 113, False: 230]
  ------------------
  153|    113|    uint8_t prediction_mode;
  154|    113|    if (!buffer->Decode(&prediction_mode)) {
  ------------------
  |  Branch (154:9): [True: 1, False: 112]
  ------------------
  155|      1|      return false;
  156|      1|    }
  157|    112|    if (prediction_mode > TRIANGLE_AREA) {
  ------------------
  |  Branch (157:9): [True: 2, False: 110]
  ------------------
  158|       |      // Invalid prediction mode.
  159|      2|      return false;
  160|      2|    }
  161|       |
  162|    110|    if (!predictor_.SetNormalPredictionMode(
  ------------------
  |  Branch (162:9): [True: 0, False: 110]
  ------------------
  163|    110|            NormalPredictionMode(prediction_mode))) {
  164|      0|      return false;
  165|      0|    }
  166|    110|  }
  167|    340|#endif
  168|       |
  169|       |  // Init normal flips.
  170|    340|  if (!flip_normal_bit_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (170:7): [True: 14, False: 326]
  ------------------
  171|     14|    return false;
  172|     14|  }
  173|       |
  174|    326|  return true;
  175|    340|}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
  102|    326|                                      const PointIndex* entry_to_point_id_map) {
  103|    326|  this->SetQuantizationBits(this->transform().quantization_bits());
  104|    326|  predictor_.SetEntryToPointIdMap(entry_to_point_id_map);
  105|    326|  DRACO_DCHECK(this->IsInitialized());
  106|       |
  107|       |  // Expecting in_data in octahedral coordinates, i.e., portable attribute.
  108|    326|  DRACO_DCHECK_EQ(num_components, 2);
  109|       |
  110|    326|  const int corner_map_size =
  111|    326|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  112|    326|  if (corner_map_size * num_components > size) {
  ------------------
  |  Branch (112:7): [True: 0, False: 326]
  ------------------
  113|      0|    return false;
  114|      0|  }
  115|       |
  116|    326|  VectorD<int32_t, 3> pred_normal_3d;
  117|    326|  int32_t pred_normal_oct[2];
  118|       |
  119|  1.82M|  for (int data_id = 0; data_id < corner_map_size; ++data_id) {
  ------------------
  |  Branch (119:25): [True: 1.82M, False: 326]
  ------------------
  120|  1.82M|    const CornerIndex corner_id =
  121|  1.82M|        this->mesh_data().data_to_corner_map()->at(data_id);
  122|  1.82M|    predictor_.ComputePredictedValue(corner_id, pred_normal_3d.data());
  123|       |
  124|       |    // Compute predicted octahedral coordinates.
  125|  1.82M|    octahedron_tool_box_.CanonicalizeIntegerVector(pred_normal_3d.data());
  126|  1.82M|    DRACO_DCHECK_EQ(pred_normal_3d.AbsSum(),
  127|  1.82M|                    octahedron_tool_box_.center_value());
  128|  1.82M|    if (flip_normal_bit_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (128:9): [True: 1.69M, False: 131k]
  ------------------
  129|  1.69M|      pred_normal_3d = -pred_normal_3d;
  130|  1.69M|    }
  131|  1.82M|    octahedron_tool_box_.IntegerVectorToQuantizedOctahedralCoords(
  132|  1.82M|        pred_normal_3d.data(), pred_normal_oct, pred_normal_oct + 1);
  133|       |
  134|  1.82M|    const int data_offset = data_id * 2;
  135|  1.82M|    this->transform().ComputeOriginalValue(
  136|  1.82M|        pred_normal_oct, in_corr + data_offset, out_data + data_offset);
  137|  1.82M|  }
  138|    326|  flip_normal_bit_decoder_.EndDecoding();
  139|    326|  return true;
  140|    326|}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE19SetQuantizationBitsEi:
   84|    326|  void SetQuantizationBits(int q) {
   85|    326|    octahedron_tool_box_.SetQuantizationBits(q);
   86|    326|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   35|    511|      : MeshPredictionSchemeDecoder<DataTypeT, TransformT, MeshDataT>(
   36|    511|            attribute, transform, mesh_data),
   37|    511|        predictor_(mesh_data) {}
_ZNK5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE22GetNumParentAttributesEv:
   66|  1.02k|  int GetNumParentAttributes() const override { return 1; }
_ZNK5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE22GetParentAttributeTypeEi:
   68|    511|  GeometryAttribute::Type GetParentAttributeType(int i) const override {
   69|    511|    DRACO_DCHECK_EQ(i, 0);
   70|    511|    (void)i;
   71|    511|    return GeometryAttribute::POSITION;
   72|    511|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE18SetParentAttributeEPKNS_14PointAttributeE:
   74|    510|  bool SetParentAttribute(const PointAttribute* att) override {
   75|    510|    if (att->attribute_type() != GeometryAttribute::POSITION) {
  ------------------
  |  Branch (75:9): [True: 0, False: 510]
  ------------------
   76|      0|      return false;  // Invalid attribute type.
   77|      0|    }
   78|    510|    if (att->num_components() != 3) {
  ------------------
  |  Branch (78:9): [True: 1, False: 509]
  ------------------
   79|      1|      return false;  // Currently works only for 3 component positions.
   80|      1|    }
   81|    509|    predictor_.SetPositionAttribute(*att);
   82|    509|    return true;
   83|    510|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  145|    501|                                                                buffer) {
  146|       |  // Get data needed for transform
  147|    501|  if (!this->transform().DecodeTransformData(buffer)) {
  ------------------
  |  Branch (147:7): [True: 10, False: 491]
  ------------------
  148|     10|    return false;
  149|     10|  }
  150|       |
  151|    491|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  152|    491|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    491|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (152:7): [True: 141, False: 350]
  ------------------
  153|    141|    uint8_t prediction_mode;
  154|    141|    if (!buffer->Decode(&prediction_mode)) {
  ------------------
  |  Branch (154:9): [True: 6, False: 135]
  ------------------
  155|      6|      return false;
  156|      6|    }
  157|    135|    if (prediction_mode > TRIANGLE_AREA) {
  ------------------
  |  Branch (157:9): [True: 1, False: 134]
  ------------------
  158|       |      // Invalid prediction mode.
  159|      1|      return false;
  160|      1|    }
  161|       |
  162|    134|    if (!predictor_.SetNormalPredictionMode(
  ------------------
  |  Branch (162:9): [True: 0, False: 134]
  ------------------
  163|    134|            NormalPredictionMode(prediction_mode))) {
  164|      0|      return false;
  165|      0|    }
  166|    134|  }
  167|    484|#endif
  168|       |
  169|       |  // Init normal flips.
  170|    484|  if (!flip_normal_bit_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (170:7): [True: 20, False: 464]
  ------------------
  171|     20|    return false;
  172|     20|  }
  173|       |
  174|    464|  return true;
  175|    484|}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
  102|    464|                                      const PointIndex* entry_to_point_id_map) {
  103|    464|  this->SetQuantizationBits(this->transform().quantization_bits());
  104|    464|  predictor_.SetEntryToPointIdMap(entry_to_point_id_map);
  105|    464|  DRACO_DCHECK(this->IsInitialized());
  106|       |
  107|       |  // Expecting in_data in octahedral coordinates, i.e., portable attribute.
  108|    464|  DRACO_DCHECK_EQ(num_components, 2);
  109|       |
  110|    464|  const int corner_map_size =
  111|    464|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  112|    464|  if (corner_map_size * num_components > size) {
  ------------------
  |  Branch (112:7): [True: 0, False: 464]
  ------------------
  113|      0|    return false;
  114|      0|  }
  115|       |
  116|    464|  VectorD<int32_t, 3> pred_normal_3d;
  117|    464|  int32_t pred_normal_oct[2];
  118|       |
  119|   161k|  for (int data_id = 0; data_id < corner_map_size; ++data_id) {
  ------------------
  |  Branch (119:25): [True: 161k, False: 464]
  ------------------
  120|   161k|    const CornerIndex corner_id =
  121|   161k|        this->mesh_data().data_to_corner_map()->at(data_id);
  122|   161k|    predictor_.ComputePredictedValue(corner_id, pred_normal_3d.data());
  123|       |
  124|       |    // Compute predicted octahedral coordinates.
  125|   161k|    octahedron_tool_box_.CanonicalizeIntegerVector(pred_normal_3d.data());
  126|   161k|    DRACO_DCHECK_EQ(pred_normal_3d.AbsSum(),
  127|   161k|                    octahedron_tool_box_.center_value());
  128|   161k|    if (flip_normal_bit_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (128:9): [True: 143k, False: 17.7k]
  ------------------
  129|   143k|      pred_normal_3d = -pred_normal_3d;
  130|   143k|    }
  131|   161k|    octahedron_tool_box_.IntegerVectorToQuantizedOctahedralCoords(
  132|   161k|        pred_normal_3d.data(), pred_normal_oct, pred_normal_oct + 1);
  133|       |
  134|   161k|    const int data_offset = data_id * 2;
  135|   161k|    this->transform().ComputeOriginalValue(
  136|   161k|        pred_normal_oct, in_corr + data_offset, out_data + data_offset);
  137|   161k|  }
  138|    464|  flip_normal_bit_decoder_.EndDecoding();
  139|    464|  return true;
  140|    464|}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE19SetQuantizationBitsEi:
   84|    464|  void SetQuantizationBits(int q) {
   85|    464|    octahedron_tool_box_.SetQuantizationBits(q);
   86|    464|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   35|    176|      : MeshPredictionSchemeDecoder<DataTypeT, TransformT, MeshDataT>(
   36|    176|            attribute, transform, mesh_data),
   37|    176|        predictor_(mesh_data) {}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   35|    168|      : MeshPredictionSchemeDecoder<DataTypeT, TransformT, MeshDataT>(
   36|    168|            attribute, transform, mesh_data),
   37|    168|        predictor_(mesh_data) {}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   35|    163|      : MeshPredictionSchemeDecoder<DataTypeT, TransformT, MeshDataT>(
   36|    163|            attribute, transform, mesh_data),
   37|    163|        predictor_(mesh_data) {}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   35|    175|      : MeshPredictionSchemeDecoder<DataTypeT, TransformT, MeshDataT>(
   36|    175|            attribute, transform, mesh_data),
   37|    175|        predictor_(mesh_data) {}

_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE23SetNormalPredictionModeENS_20NormalPredictionModeE:
  103|    207|  bool SetNormalPredictionMode(NormalPredictionMode mode) override {
  104|    207|    if (mode == ONE_TRIANGLE) {
  ------------------
  |  Branch (104:9): [True: 28, False: 179]
  ------------------
  105|     28|      this->normal_prediction_mode_ = mode;
  106|     28|      return true;
  107|    179|    } else if (mode == TRIANGLE_AREA) {
  ------------------
  |  Branch (107:16): [True: 179, False: 0]
  ------------------
  108|    179|      this->normal_prediction_mode_ = mode;
  109|    179|      return true;
  110|    179|    }
  111|      0|    return false;
  112|    207|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputePredictedValueENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPi:
   41|  1.03M|                             DataTypeT* prediction) override {
   42|  1.03M|    DRACO_DCHECK(this->IsInitialized());
   43|  1.03M|    typedef typename MeshDataT::CornerTable CornerTable;
   44|  1.03M|    const CornerTable* const corner_table = this->mesh_data_.corner_table();
   45|       |    // Going to compute the predicted normal from the surrounding triangles
   46|       |    // according to the connectivity of the given corner table.
   47|  1.03M|    VertexCornersIterator<CornerTable> cit(corner_table, corner_id);
   48|       |    // Position of central vertex does not change in loop.
   49|  1.03M|    const VectorD<int64_t, 3> pos_cent = this->GetPositionForCorner(corner_id);
   50|       |    // Computing normals for triangles and adding them up.
   51|       |
   52|  1.03M|    VectorD<int64_t, 3> normal;
   53|  1.03M|    CornerIndex c_next, c_prev;
   54|  2.44M|    while (!cit.End()) {
  ------------------
  |  Branch (54:12): [True: 1.41M, False: 1.03M]
  ------------------
   55|       |      // Getting corners.
   56|  1.41M|      if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
  ------------------
  |  Branch (56:11): [True: 108, False: 1.41M]
  ------------------
   57|    108|        c_next = corner_table->Next(corner_id);
   58|    108|        c_prev = corner_table->Previous(corner_id);
   59|  1.41M|      } else {
   60|  1.41M|        c_next = corner_table->Next(cit.Corner());
   61|  1.41M|        c_prev = corner_table->Previous(cit.Corner());
   62|  1.41M|      }
   63|  1.41M|      const VectorD<int64_t, 3> pos_next = this->GetPositionForCorner(c_next);
   64|  1.41M|      const VectorD<int64_t, 3> pos_prev = this->GetPositionForCorner(c_prev);
   65|       |
   66|       |      // Computing delta vectors to next and prev.
   67|  1.41M|      const VectorD<int64_t, 3> delta_next = pos_next - pos_cent;
   68|  1.41M|      const VectorD<int64_t, 3> delta_prev = pos_prev - pos_cent;
   69|       |
   70|       |      // Computing cross product.
   71|  1.41M|      const VectorD<int64_t, 3> cross = CrossProduct(delta_next, delta_prev);
   72|       |
   73|       |      // Prevent signed integer overflows by doing math as unsigned.
   74|  1.41M|      auto normal_data = reinterpret_cast<uint64_t*>(normal.data());
   75|  1.41M|      auto cross_data = reinterpret_cast<const uint64_t*>(cross.data());
   76|  1.41M|      normal_data[0] = normal_data[0] + cross_data[0];
   77|  1.41M|      normal_data[1] = normal_data[1] + cross_data[1];
   78|  1.41M|      normal_data[2] = normal_data[2] + cross_data[2];
   79|       |
   80|  1.41M|      cit.Next();
   81|  1.41M|    }
   82|       |
   83|       |    // Convert to int32_t, make sure entries are not too large.
   84|  1.03M|    constexpr int64_t upper_bound = 1 << 29;
   85|  1.03M|    if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
  ------------------
  |  Branch (85:9): [True: 72, False: 1.03M]
  ------------------
   86|     72|      const int32_t abs_sum = static_cast<int32_t>(normal.AbsSum());
   87|     72|      if (abs_sum > upper_bound) {
  ------------------
  |  Branch (87:11): [True: 31, False: 41]
  ------------------
   88|     31|        const int64_t quotient = abs_sum / upper_bound;
   89|     31|        normal = normal / quotient;
   90|     31|      }
   91|  1.03M|    } else {
   92|  1.03M|      const int64_t abs_sum = normal.AbsSum();
   93|  1.03M|      if (abs_sum > upper_bound) {
  ------------------
  |  Branch (93:11): [True: 1.64k, False: 1.02M]
  ------------------
   94|  1.64k|        const int64_t quotient = abs_sum / upper_bound;
   95|  1.64k|        normal = normal / quotient;
   96|  1.64k|      }
   97|  1.03M|    }
   98|  1.03M|    DRACO_DCHECK_LE(normal.AbsSum(), upper_bound);
   99|  1.03M|    prediction[0] = static_cast<int32_t>(normal[0]);
  100|  1.03M|    prediction[1] = static_cast<int32_t>(normal[1]);
  101|  1.03M|    prediction[2] = static_cast<int32_t>(normal[2]);
  102|  1.03M|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE23SetNormalPredictionModeENS_20NormalPredictionModeE:
  103|    196|  bool SetNormalPredictionMode(NormalPredictionMode mode) override {
  104|    196|    if (mode == ONE_TRIANGLE) {
  ------------------
  |  Branch (104:9): [True: 27, False: 169]
  ------------------
  105|     27|      this->normal_prediction_mode_ = mode;
  106|     27|      return true;
  107|    169|    } else if (mode == TRIANGLE_AREA) {
  ------------------
  |  Branch (107:16): [True: 169, False: 0]
  ------------------
  108|    169|      this->normal_prediction_mode_ = mode;
  109|    169|      return true;
  110|    169|    }
  111|      0|    return false;
  112|    196|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputePredictedValueENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPi:
   41|   202k|                             DataTypeT* prediction) override {
   42|   202k|    DRACO_DCHECK(this->IsInitialized());
   43|   202k|    typedef typename MeshDataT::CornerTable CornerTable;
   44|   202k|    const CornerTable* const corner_table = this->mesh_data_.corner_table();
   45|       |    // Going to compute the predicted normal from the surrounding triangles
   46|       |    // according to the connectivity of the given corner table.
   47|   202k|    VertexCornersIterator<CornerTable> cit(corner_table, corner_id);
   48|       |    // Position of central vertex does not change in loop.
   49|   202k|    const VectorD<int64_t, 3> pos_cent = this->GetPositionForCorner(corner_id);
   50|       |    // Computing normals for triangles and adding them up.
   51|       |
   52|   202k|    VectorD<int64_t, 3> normal;
   53|   202k|    CornerIndex c_next, c_prev;
   54|  1.40M|    while (!cit.End()) {
  ------------------
  |  Branch (54:12): [True: 1.20M, False: 202k]
  ------------------
   55|       |      // Getting corners.
   56|  1.20M|      if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
  ------------------
  |  Branch (56:11): [True: 150, False: 1.20M]
  ------------------
   57|    150|        c_next = corner_table->Next(corner_id);
   58|    150|        c_prev = corner_table->Previous(corner_id);
   59|  1.20M|      } else {
   60|  1.20M|        c_next = corner_table->Next(cit.Corner());
   61|  1.20M|        c_prev = corner_table->Previous(cit.Corner());
   62|  1.20M|      }
   63|  1.20M|      const VectorD<int64_t, 3> pos_next = this->GetPositionForCorner(c_next);
   64|  1.20M|      const VectorD<int64_t, 3> pos_prev = this->GetPositionForCorner(c_prev);
   65|       |
   66|       |      // Computing delta vectors to next and prev.
   67|  1.20M|      const VectorD<int64_t, 3> delta_next = pos_next - pos_cent;
   68|  1.20M|      const VectorD<int64_t, 3> delta_prev = pos_prev - pos_cent;
   69|       |
   70|       |      // Computing cross product.
   71|  1.20M|      const VectorD<int64_t, 3> cross = CrossProduct(delta_next, delta_prev);
   72|       |
   73|       |      // Prevent signed integer overflows by doing math as unsigned.
   74|  1.20M|      auto normal_data = reinterpret_cast<uint64_t*>(normal.data());
   75|  1.20M|      auto cross_data = reinterpret_cast<const uint64_t*>(cross.data());
   76|  1.20M|      normal_data[0] = normal_data[0] + cross_data[0];
   77|  1.20M|      normal_data[1] = normal_data[1] + cross_data[1];
   78|  1.20M|      normal_data[2] = normal_data[2] + cross_data[2];
   79|       |
   80|  1.20M|      cit.Next();
   81|  1.20M|    }
   82|       |
   83|       |    // Convert to int32_t, make sure entries are not too large.
   84|   202k|    constexpr int64_t upper_bound = 1 << 29;
   85|   202k|    if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
  ------------------
  |  Branch (85:9): [True: 100, False: 202k]
  ------------------
   86|    100|      const int32_t abs_sum = static_cast<int32_t>(normal.AbsSum());
   87|    100|      if (abs_sum > upper_bound) {
  ------------------
  |  Branch (87:11): [True: 41, False: 59]
  ------------------
   88|     41|        const int64_t quotient = abs_sum / upper_bound;
   89|     41|        normal = normal / quotient;
   90|     41|      }
   91|   202k|    } else {
   92|   202k|      const int64_t abs_sum = normal.AbsSum();
   93|   202k|      if (abs_sum > upper_bound) {
  ------------------
  |  Branch (93:11): [True: 132k, False: 70.1k]
  ------------------
   94|   132k|        const int64_t quotient = abs_sum / upper_bound;
   95|   132k|        normal = normal / quotient;
   96|   132k|      }
   97|   202k|    }
   98|   202k|    DRACO_DCHECK_LE(normal.AbsSum(), upper_bound);
   99|   202k|    prediction[0] = static_cast<int32_t>(normal[0]);
  100|   202k|    prediction[1] = static_cast<int32_t>(normal[1]);
  101|   202k|    prediction[2] = static_cast<int32_t>(normal[2]);
  102|   202k|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE23SetNormalPredictionModeENS_20NormalPredictionModeE:
  103|    187|  bool SetNormalPredictionMode(NormalPredictionMode mode) override {
  104|    187|    if (mode == ONE_TRIANGLE) {
  ------------------
  |  Branch (104:9): [True: 22, False: 165]
  ------------------
  105|     22|      this->normal_prediction_mode_ = mode;
  106|     22|      return true;
  107|    165|    } else if (mode == TRIANGLE_AREA) {
  ------------------
  |  Branch (107:16): [True: 165, False: 0]
  ------------------
  108|    165|      this->normal_prediction_mode_ = mode;
  109|    165|      return true;
  110|    165|    }
  111|      0|    return false;
  112|    187|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputePredictedValueENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPi:
   41|   404k|                             DataTypeT* prediction) override {
   42|   404k|    DRACO_DCHECK(this->IsInitialized());
   43|   404k|    typedef typename MeshDataT::CornerTable CornerTable;
   44|   404k|    const CornerTable* const corner_table = this->mesh_data_.corner_table();
   45|       |    // Going to compute the predicted normal from the surrounding triangles
   46|       |    // according to the connectivity of the given corner table.
   47|   404k|    VertexCornersIterator<CornerTable> cit(corner_table, corner_id);
   48|       |    // Position of central vertex does not change in loop.
   49|   404k|    const VectorD<int64_t, 3> pos_cent = this->GetPositionForCorner(corner_id);
   50|       |    // Computing normals for triangles and adding them up.
   51|       |
   52|   404k|    VectorD<int64_t, 3> normal;
   53|   404k|    CornerIndex c_next, c_prev;
   54|  1.07M|    while (!cit.End()) {
  ------------------
  |  Branch (54:12): [True: 670k, False: 404k]
  ------------------
   55|       |      // Getting corners.
   56|   670k|      if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
  ------------------
  |  Branch (56:11): [True: 126, False: 670k]
  ------------------
   57|    126|        c_next = corner_table->Next(corner_id);
   58|    126|        c_prev = corner_table->Previous(corner_id);
   59|   670k|      } else {
   60|   670k|        c_next = corner_table->Next(cit.Corner());
   61|   670k|        c_prev = corner_table->Previous(cit.Corner());
   62|   670k|      }
   63|   670k|      const VectorD<int64_t, 3> pos_next = this->GetPositionForCorner(c_next);
   64|   670k|      const VectorD<int64_t, 3> pos_prev = this->GetPositionForCorner(c_prev);
   65|       |
   66|       |      // Computing delta vectors to next and prev.
   67|   670k|      const VectorD<int64_t, 3> delta_next = pos_next - pos_cent;
   68|   670k|      const VectorD<int64_t, 3> delta_prev = pos_prev - pos_cent;
   69|       |
   70|       |      // Computing cross product.
   71|   670k|      const VectorD<int64_t, 3> cross = CrossProduct(delta_next, delta_prev);
   72|       |
   73|       |      // Prevent signed integer overflows by doing math as unsigned.
   74|   670k|      auto normal_data = reinterpret_cast<uint64_t*>(normal.data());
   75|   670k|      auto cross_data = reinterpret_cast<const uint64_t*>(cross.data());
   76|   670k|      normal_data[0] = normal_data[0] + cross_data[0];
   77|   670k|      normal_data[1] = normal_data[1] + cross_data[1];
   78|   670k|      normal_data[2] = normal_data[2] + cross_data[2];
   79|       |
   80|   670k|      cit.Next();
   81|   670k|    }
   82|       |
   83|       |    // Convert to int32_t, make sure entries are not too large.
   84|   404k|    constexpr int64_t upper_bound = 1 << 29;
   85|   404k|    if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
  ------------------
  |  Branch (85:9): [True: 84, False: 404k]
  ------------------
   86|     84|      const int32_t abs_sum = static_cast<int32_t>(normal.AbsSum());
   87|     84|      if (abs_sum > upper_bound) {
  ------------------
  |  Branch (87:11): [True: 26, False: 58]
  ------------------
   88|     26|        const int64_t quotient = abs_sum / upper_bound;
   89|     26|        normal = normal / quotient;
   90|     26|      }
   91|   404k|    } else {
   92|   404k|      const int64_t abs_sum = normal.AbsSum();
   93|   404k|      if (abs_sum > upper_bound) {
  ------------------
  |  Branch (93:11): [True: 1.89k, False: 402k]
  ------------------
   94|  1.89k|        const int64_t quotient = abs_sum / upper_bound;
   95|  1.89k|        normal = normal / quotient;
   96|  1.89k|      }
   97|   404k|    }
   98|   404k|    DRACO_DCHECK_LE(normal.AbsSum(), upper_bound);
   99|   404k|    prediction[0] = static_cast<int32_t>(normal[0]);
  100|   404k|    prediction[1] = static_cast<int32_t>(normal[1]);
  101|   404k|    prediction[2] = static_cast<int32_t>(normal[2]);
  102|   404k|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE23SetNormalPredictionModeENS_20NormalPredictionModeE:
  103|    205|  bool SetNormalPredictionMode(NormalPredictionMode mode) override {
  104|    205|    if (mode == ONE_TRIANGLE) {
  ------------------
  |  Branch (104:9): [True: 29, False: 176]
  ------------------
  105|     29|      this->normal_prediction_mode_ = mode;
  106|     29|      return true;
  107|    176|    } else if (mode == TRIANGLE_AREA) {
  ------------------
  |  Branch (107:16): [True: 176, False: 0]
  ------------------
  108|    176|      this->normal_prediction_mode_ = mode;
  109|    176|      return true;
  110|    176|    }
  111|      0|    return false;
  112|    205|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputePredictedValueENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPi:
   41|   244k|                             DataTypeT* prediction) override {
   42|   244k|    DRACO_DCHECK(this->IsInitialized());
   43|   244k|    typedef typename MeshDataT::CornerTable CornerTable;
   44|   244k|    const CornerTable* const corner_table = this->mesh_data_.corner_table();
   45|       |    // Going to compute the predicted normal from the surrounding triangles
   46|       |    // according to the connectivity of the given corner table.
   47|   244k|    VertexCornersIterator<CornerTable> cit(corner_table, corner_id);
   48|       |    // Position of central vertex does not change in loop.
   49|   244k|    const VectorD<int64_t, 3> pos_cent = this->GetPositionForCorner(corner_id);
   50|       |    // Computing normals for triangles and adding them up.
   51|       |
   52|   244k|    VectorD<int64_t, 3> normal;
   53|   244k|    CornerIndex c_next, c_prev;
   54|  1.70M|    while (!cit.End()) {
  ------------------
  |  Branch (54:12): [True: 1.45M, False: 244k]
  ------------------
   55|       |      // Getting corners.
   56|  1.45M|      if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
  ------------------
  |  Branch (56:11): [True: 168, False: 1.45M]
  ------------------
   57|    168|        c_next = corner_table->Next(corner_id);
   58|    168|        c_prev = corner_table->Previous(corner_id);
   59|  1.45M|      } else {
   60|  1.45M|        c_next = corner_table->Next(cit.Corner());
   61|  1.45M|        c_prev = corner_table->Previous(cit.Corner());
   62|  1.45M|      }
   63|  1.45M|      const VectorD<int64_t, 3> pos_next = this->GetPositionForCorner(c_next);
   64|  1.45M|      const VectorD<int64_t, 3> pos_prev = this->GetPositionForCorner(c_prev);
   65|       |
   66|       |      // Computing delta vectors to next and prev.
   67|  1.45M|      const VectorD<int64_t, 3> delta_next = pos_next - pos_cent;
   68|  1.45M|      const VectorD<int64_t, 3> delta_prev = pos_prev - pos_cent;
   69|       |
   70|       |      // Computing cross product.
   71|  1.45M|      const VectorD<int64_t, 3> cross = CrossProduct(delta_next, delta_prev);
   72|       |
   73|       |      // Prevent signed integer overflows by doing math as unsigned.
   74|  1.45M|      auto normal_data = reinterpret_cast<uint64_t*>(normal.data());
   75|  1.45M|      auto cross_data = reinterpret_cast<const uint64_t*>(cross.data());
   76|  1.45M|      normal_data[0] = normal_data[0] + cross_data[0];
   77|  1.45M|      normal_data[1] = normal_data[1] + cross_data[1];
   78|  1.45M|      normal_data[2] = normal_data[2] + cross_data[2];
   79|       |
   80|  1.45M|      cit.Next();
   81|  1.45M|    }
   82|       |
   83|       |    // Convert to int32_t, make sure entries are not too large.
   84|   244k|    constexpr int64_t upper_bound = 1 << 29;
   85|   244k|    if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
  ------------------
  |  Branch (85:9): [True: 112, False: 244k]
  ------------------
   86|    112|      const int32_t abs_sum = static_cast<int32_t>(normal.AbsSum());
   87|    112|      if (abs_sum > upper_bound) {
  ------------------
  |  Branch (87:11): [True: 36, False: 76]
  ------------------
   88|     36|        const int64_t quotient = abs_sum / upper_bound;
   89|     36|        normal = normal / quotient;
   90|     36|      }
   91|   244k|    } else {
   92|   244k|      const int64_t abs_sum = normal.AbsSum();
   93|   244k|      if (abs_sum > upper_bound) {
  ------------------
  |  Branch (93:11): [True: 94.1k, False: 150k]
  ------------------
   94|  94.1k|        const int64_t quotient = abs_sum / upper_bound;
   95|  94.1k|        normal = normal / quotient;
   96|  94.1k|      }
   97|   244k|    }
   98|   244k|    DRACO_DCHECK_LE(normal.AbsSum(), upper_bound);
   99|   244k|    prediction[0] = static_cast<int32_t>(normal[0]);
  100|   244k|    prediction[1] = static_cast<int32_t>(normal[1]);
  101|   244k|    prediction[2] = static_cast<int32_t>(normal[2]);
  102|   244k|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2ERKS5_:
   34|    374|      : Base(md) {
   35|    374|    this->SetNormalPredictionMode(TRIANGLE_AREA);
   36|    374|  };
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE23SetNormalPredictionModeENS_20NormalPredictionModeE:
  103|    484|  bool SetNormalPredictionMode(NormalPredictionMode mode) override {
  104|    484|    if (mode == ONE_TRIANGLE) {
  ------------------
  |  Branch (104:9): [True: 108, False: 376]
  ------------------
  105|    108|      this->normal_prediction_mode_ = mode;
  106|    108|      return true;
  107|    376|    } else if (mode == TRIANGLE_AREA) {
  ------------------
  |  Branch (107:16): [True: 376, False: 0]
  ------------------
  108|    376|      this->normal_prediction_mode_ = mode;
  109|    376|      return true;
  110|    376|    }
  111|      0|    return false;
  112|    484|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputePredictedValueENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPi:
   41|  1.82M|                             DataTypeT* prediction) override {
   42|  1.82M|    DRACO_DCHECK(this->IsInitialized());
   43|  1.82M|    typedef typename MeshDataT::CornerTable CornerTable;
   44|  1.82M|    const CornerTable* const corner_table = this->mesh_data_.corner_table();
   45|       |    // Going to compute the predicted normal from the surrounding triangles
   46|       |    // according to the connectivity of the given corner table.
   47|  1.82M|    VertexCornersIterator<CornerTable> cit(corner_table, corner_id);
   48|       |    // Position of central vertex does not change in loop.
   49|  1.82M|    const VectorD<int64_t, 3> pos_cent = this->GetPositionForCorner(corner_id);
   50|       |    // Computing normals for triangles and adding them up.
   51|       |
   52|  1.82M|    VectorD<int64_t, 3> normal;
   53|  1.82M|    CornerIndex c_next, c_prev;
   54|  3.72M|    while (!cit.End()) {
  ------------------
  |  Branch (54:12): [True: 1.89M, False: 1.82M]
  ------------------
   55|       |      // Getting corners.
   56|  1.89M|      if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
  ------------------
  |  Branch (56:11): [True: 600, False: 1.89M]
  ------------------
   57|    600|        c_next = corner_table->Next(corner_id);
   58|    600|        c_prev = corner_table->Previous(corner_id);
   59|  1.89M|      } else {
   60|  1.89M|        c_next = corner_table->Next(cit.Corner());
   61|  1.89M|        c_prev = corner_table->Previous(cit.Corner());
   62|  1.89M|      }
   63|  1.89M|      const VectorD<int64_t, 3> pos_next = this->GetPositionForCorner(c_next);
   64|  1.89M|      const VectorD<int64_t, 3> pos_prev = this->GetPositionForCorner(c_prev);
   65|       |
   66|       |      // Computing delta vectors to next and prev.
   67|  1.89M|      const VectorD<int64_t, 3> delta_next = pos_next - pos_cent;
   68|  1.89M|      const VectorD<int64_t, 3> delta_prev = pos_prev - pos_cent;
   69|       |
   70|       |      // Computing cross product.
   71|  1.89M|      const VectorD<int64_t, 3> cross = CrossProduct(delta_next, delta_prev);
   72|       |
   73|       |      // Prevent signed integer overflows by doing math as unsigned.
   74|  1.89M|      auto normal_data = reinterpret_cast<uint64_t*>(normal.data());
   75|  1.89M|      auto cross_data = reinterpret_cast<const uint64_t*>(cross.data());
   76|  1.89M|      normal_data[0] = normal_data[0] + cross_data[0];
   77|  1.89M|      normal_data[1] = normal_data[1] + cross_data[1];
   78|  1.89M|      normal_data[2] = normal_data[2] + cross_data[2];
   79|       |
   80|  1.89M|      cit.Next();
   81|  1.89M|    }
   82|       |
   83|       |    // Convert to int32_t, make sure entries are not too large.
   84|  1.82M|    constexpr int64_t upper_bound = 1 << 29;
   85|  1.82M|    if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
  ------------------
  |  Branch (85:9): [True: 554, False: 1.82M]
  ------------------
   86|    554|      const int32_t abs_sum = static_cast<int32_t>(normal.AbsSum());
   87|    554|      if (abs_sum > upper_bound) {
  ------------------
  |  Branch (87:11): [True: 213, False: 341]
  ------------------
   88|    213|        const int64_t quotient = abs_sum / upper_bound;
   89|    213|        normal = normal / quotient;
   90|    213|      }
   91|  1.82M|    } else {
   92|  1.82M|      const int64_t abs_sum = normal.AbsSum();
   93|  1.82M|      if (abs_sum > upper_bound) {
  ------------------
  |  Branch (93:11): [True: 6.31k, False: 1.82M]
  ------------------
   94|  6.31k|        const int64_t quotient = abs_sum / upper_bound;
   95|  6.31k|        normal = normal / quotient;
   96|  6.31k|      }
   97|  1.82M|    }
   98|  1.82M|    DRACO_DCHECK_LE(normal.AbsSum(), upper_bound);
   99|  1.82M|    prediction[0] = static_cast<int32_t>(normal[0]);
  100|  1.82M|    prediction[1] = static_cast<int32_t>(normal[1]);
  101|  1.82M|    prediction[2] = static_cast<int32_t>(normal[2]);
  102|  1.82M|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2ERKS5_:
   34|    511|      : Base(md) {
   35|    511|    this->SetNormalPredictionMode(TRIANGLE_AREA);
   36|    511|  };
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE23SetNormalPredictionModeENS_20NormalPredictionModeE:
  103|    645|  bool SetNormalPredictionMode(NormalPredictionMode mode) override {
  104|    645|    if (mode == ONE_TRIANGLE) {
  ------------------
  |  Branch (104:9): [True: 131, False: 514]
  ------------------
  105|    131|      this->normal_prediction_mode_ = mode;
  106|    131|      return true;
  107|    514|    } else if (mode == TRIANGLE_AREA) {
  ------------------
  |  Branch (107:16): [True: 514, False: 0]
  ------------------
  108|    514|      this->normal_prediction_mode_ = mode;
  109|    514|      return true;
  110|    514|    }
  111|      0|    return false;
  112|    645|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputePredictedValueENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPi:
   41|   161k|                             DataTypeT* prediction) override {
   42|   161k|    DRACO_DCHECK(this->IsInitialized());
   43|   161k|    typedef typename MeshDataT::CornerTable CornerTable;
   44|   161k|    const CornerTable* const corner_table = this->mesh_data_.corner_table();
   45|       |    // Going to compute the predicted normal from the surrounding triangles
   46|       |    // according to the connectivity of the given corner table.
   47|   161k|    VertexCornersIterator<CornerTable> cit(corner_table, corner_id);
   48|       |    // Position of central vertex does not change in loop.
   49|   161k|    const VectorD<int64_t, 3> pos_cent = this->GetPositionForCorner(corner_id);
   50|       |    // Computing normals for triangles and adding them up.
   51|       |
   52|   161k|    VectorD<int64_t, 3> normal;
   53|   161k|    CornerIndex c_next, c_prev;
   54|  1.07M|    while (!cit.End()) {
  ------------------
  |  Branch (54:12): [True: 912k, False: 161k]
  ------------------
   55|       |      // Getting corners.
   56|   912k|      if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
  ------------------
  |  Branch (56:11): [True: 738, False: 911k]
  ------------------
   57|    738|        c_next = corner_table->Next(corner_id);
   58|    738|        c_prev = corner_table->Previous(corner_id);
   59|   911k|      } else {
   60|   911k|        c_next = corner_table->Next(cit.Corner());
   61|   911k|        c_prev = corner_table->Previous(cit.Corner());
   62|   911k|      }
   63|   912k|      const VectorD<int64_t, 3> pos_next = this->GetPositionForCorner(c_next);
   64|   912k|      const VectorD<int64_t, 3> pos_prev = this->GetPositionForCorner(c_prev);
   65|       |
   66|       |      // Computing delta vectors to next and prev.
   67|   912k|      const VectorD<int64_t, 3> delta_next = pos_next - pos_cent;
   68|   912k|      const VectorD<int64_t, 3> delta_prev = pos_prev - pos_cent;
   69|       |
   70|       |      // Computing cross product.
   71|   912k|      const VectorD<int64_t, 3> cross = CrossProduct(delta_next, delta_prev);
   72|       |
   73|       |      // Prevent signed integer overflows by doing math as unsigned.
   74|   912k|      auto normal_data = reinterpret_cast<uint64_t*>(normal.data());
   75|   912k|      auto cross_data = reinterpret_cast<const uint64_t*>(cross.data());
   76|   912k|      normal_data[0] = normal_data[0] + cross_data[0];
   77|   912k|      normal_data[1] = normal_data[1] + cross_data[1];
   78|   912k|      normal_data[2] = normal_data[2] + cross_data[2];
   79|       |
   80|   912k|      cit.Next();
   81|   912k|    }
   82|       |
   83|       |    // Convert to int32_t, make sure entries are not too large.
   84|   161k|    constexpr int64_t upper_bound = 1 << 29;
   85|   161k|    if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
  ------------------
  |  Branch (85:9): [True: 698, False: 160k]
  ------------------
   86|    698|      const int32_t abs_sum = static_cast<int32_t>(normal.AbsSum());
   87|    698|      if (abs_sum > upper_bound) {
  ------------------
  |  Branch (87:11): [True: 165, False: 533]
  ------------------
   88|    165|        const int64_t quotient = abs_sum / upper_bound;
   89|    165|        normal = normal / quotient;
   90|    165|      }
   91|   160k|    } else {
   92|   160k|      const int64_t abs_sum = normal.AbsSum();
   93|   160k|      if (abs_sum > upper_bound) {
  ------------------
  |  Branch (93:11): [True: 6.54k, False: 153k]
  ------------------
   94|  6.54k|        const int64_t quotient = abs_sum / upper_bound;
   95|  6.54k|        normal = normal / quotient;
   96|  6.54k|      }
   97|   160k|    }
   98|   161k|    DRACO_DCHECK_LE(normal.AbsSum(), upper_bound);
   99|   161k|    prediction[0] = static_cast<int32_t>(normal[0]);
  100|   161k|    prediction[1] = static_cast<int32_t>(normal[1]);
  101|   161k|    prediction[2] = static_cast<int32_t>(normal[2]);
  102|   161k|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2ERKS5_:
   34|    176|      : Base(md) {
   35|    176|    this->SetNormalPredictionMode(TRIANGLE_AREA);
   36|    176|  };
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2ERKS5_:
   34|    168|      : Base(md) {
   35|    168|    this->SetNormalPredictionMode(TRIANGLE_AREA);
   36|    168|  };
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2ERKS5_:
   34|    163|      : Base(md) {
   35|    163|    this->SetNormalPredictionMode(TRIANGLE_AREA);
   36|    163|  };
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2ERKS5_:
   34|    175|      : Base(md) {
   35|    175|    this->SetNormalPredictionMode(TRIANGLE_AREA);
   36|    175|  };

_ZNK5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20GetPositionForCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   71|  3.86M|  VectorD<int64_t, 3> GetPositionForCorner(CornerIndex ci) const {
   72|  3.86M|    DRACO_DCHECK(this->IsInitialized());
   73|  3.86M|    const auto corner_table = mesh_data_.corner_table();
   74|  3.86M|    const auto vert_id = corner_table->Vertex(ci).value();
   75|  3.86M|    const auto data_id = mesh_data_.vertex_to_data_map()->at(vert_id);
   76|  3.86M|    return GetPositionForDataId(data_id);
   77|  3.86M|  }
_ZNK5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20GetPositionForDataIdEi:
   63|  3.86M|  VectorD<int64_t, 3> GetPositionForDataId(int data_id) const {
   64|  3.86M|    DRACO_DCHECK(this->IsInitialized());
   65|  3.86M|    const auto point_id = entry_to_point_id_map_[data_id];
   66|  3.86M|    const auto pos_val_id = pos_attribute_->mapped_index(point_id);
   67|  3.86M|    VectorD<int64_t, 3> pos;
   68|  3.86M|    pos_attribute_->ConvertValue(pos_val_id, &pos[0]);
   69|  3.86M|    return pos;
   70|  3.86M|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20SetPositionAttributeERKNS_14PointAttributeE:
   41|    175|  void SetPositionAttribute(const PointAttribute& position_attribute) {
   42|    175|    pos_attribute_ = &position_attribute;
   43|    175|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20SetEntryToPointIdMapEPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   44|    152|  void SetEntryToPointIdMap(const PointIndex* map) {
   45|    152|    entry_to_point_id_map_ = map;
   46|    152|  }
_ZNK5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20GetPositionForCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   71|  2.61M|  VectorD<int64_t, 3> GetPositionForCorner(CornerIndex ci) const {
   72|  2.61M|    DRACO_DCHECK(this->IsInitialized());
   73|  2.61M|    const auto corner_table = mesh_data_.corner_table();
   74|  2.61M|    const auto vert_id = corner_table->Vertex(ci).value();
   75|  2.61M|    const auto data_id = mesh_data_.vertex_to_data_map()->at(vert_id);
   76|  2.61M|    return GetPositionForDataId(data_id);
   77|  2.61M|  }
_ZNK5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20GetPositionForDataIdEi:
   63|  2.61M|  VectorD<int64_t, 3> GetPositionForDataId(int data_id) const {
   64|  2.61M|    DRACO_DCHECK(this->IsInitialized());
   65|  2.61M|    const auto point_id = entry_to_point_id_map_[data_id];
   66|  2.61M|    const auto pos_val_id = pos_attribute_->mapped_index(point_id);
   67|  2.61M|    VectorD<int64_t, 3> pos;
   68|  2.61M|    pos_attribute_->ConvertValue(pos_val_id, &pos[0]);
   69|  2.61M|    return pos;
   70|  2.61M|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20SetPositionAttributeERKNS_14PointAttributeE:
   41|    167|  void SetPositionAttribute(const PointAttribute& position_attribute) {
   42|    167|    pos_attribute_ = &position_attribute;
   43|    167|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20SetEntryToPointIdMapEPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   44|    158|  void SetEntryToPointIdMap(const PointIndex* map) {
   45|    158|    entry_to_point_id_map_ = map;
   46|    158|  }
_ZNK5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20GetPositionForCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   71|  1.74M|  VectorD<int64_t, 3> GetPositionForCorner(CornerIndex ci) const {
   72|  1.74M|    DRACO_DCHECK(this->IsInitialized());
   73|  1.74M|    const auto corner_table = mesh_data_.corner_table();
   74|  1.74M|    const auto vert_id = corner_table->Vertex(ci).value();
   75|  1.74M|    const auto data_id = mesh_data_.vertex_to_data_map()->at(vert_id);
   76|  1.74M|    return GetPositionForDataId(data_id);
   77|  1.74M|  }
_ZNK5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20GetPositionForDataIdEi:
   63|  1.74M|  VectorD<int64_t, 3> GetPositionForDataId(int data_id) const {
   64|  1.74M|    DRACO_DCHECK(this->IsInitialized());
   65|  1.74M|    const auto point_id = entry_to_point_id_map_[data_id];
   66|  1.74M|    const auto pos_val_id = pos_attribute_->mapped_index(point_id);
   67|  1.74M|    VectorD<int64_t, 3> pos;
   68|  1.74M|    pos_attribute_->ConvertValue(pos_val_id, &pos[0]);
   69|  1.74M|    return pos;
   70|  1.74M|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20SetPositionAttributeERKNS_14PointAttributeE:
   41|    162|  void SetPositionAttribute(const PointAttribute& position_attribute) {
   42|    162|    pos_attribute_ = &position_attribute;
   43|    162|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20SetEntryToPointIdMapEPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   44|    145|  void SetEntryToPointIdMap(const PointIndex* map) {
   45|    145|    entry_to_point_id_map_ = map;
   46|    145|  }
_ZNK5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20GetPositionForCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   71|  3.15M|  VectorD<int64_t, 3> GetPositionForCorner(CornerIndex ci) const {
   72|  3.15M|    DRACO_DCHECK(this->IsInitialized());
   73|  3.15M|    const auto corner_table = mesh_data_.corner_table();
   74|  3.15M|    const auto vert_id = corner_table->Vertex(ci).value();
   75|  3.15M|    const auto data_id = mesh_data_.vertex_to_data_map()->at(vert_id);
   76|  3.15M|    return GetPositionForDataId(data_id);
   77|  3.15M|  }
_ZNK5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20GetPositionForDataIdEi:
   63|  3.15M|  VectorD<int64_t, 3> GetPositionForDataId(int data_id) const {
   64|  3.15M|    DRACO_DCHECK(this->IsInitialized());
   65|  3.15M|    const auto point_id = entry_to_point_id_map_[data_id];
   66|  3.15M|    const auto pos_val_id = pos_attribute_->mapped_index(point_id);
   67|  3.15M|    VectorD<int64_t, 3> pos;
   68|  3.15M|    pos_attribute_->ConvertValue(pos_val_id, &pos[0]);
   69|  3.15M|    return pos;
   70|  3.15M|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20SetPositionAttributeERKNS_14PointAttributeE:
   41|    171|  void SetPositionAttribute(const PointAttribute& position_attribute) {
   42|    171|    pos_attribute_ = &position_attribute;
   43|    171|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20SetEntryToPointIdMapEPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   44|    159|  void SetEntryToPointIdMap(const PointIndex* map) {
   45|    159|    entry_to_point_id_map_ = map;
   46|    159|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2ERKS5_:
   35|    374|      : pos_attribute_(nullptr),
   36|    374|        entry_to_point_id_map_(nullptr),
   37|    374|        mesh_data_(md) {}
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEED2Ev:
   38|    374|  virtual ~MeshPredictionSchemeGeometricNormalPredictorBase() {}
_ZNK5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20GetPositionForCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   71|  5.61M|  VectorD<int64_t, 3> GetPositionForCorner(CornerIndex ci) const {
   72|  5.61M|    DRACO_DCHECK(this->IsInitialized());
   73|  5.61M|    const auto corner_table = mesh_data_.corner_table();
   74|  5.61M|    const auto vert_id = corner_table->Vertex(ci).value();
   75|  5.61M|    const auto data_id = mesh_data_.vertex_to_data_map()->at(vert_id);
   76|  5.61M|    return GetPositionForDataId(data_id);
   77|  5.61M|  }
_ZNK5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20GetPositionForDataIdEi:
   63|  5.61M|  VectorD<int64_t, 3> GetPositionForDataId(int data_id) const {
   64|  5.61M|    DRACO_DCHECK(this->IsInitialized());
   65|  5.61M|    const auto point_id = entry_to_point_id_map_[data_id];
   66|  5.61M|    const auto pos_val_id = pos_attribute_->mapped_index(point_id);
   67|  5.61M|    VectorD<int64_t, 3> pos;
   68|  5.61M|    pos_attribute_->ConvertValue(pos_val_id, &pos[0]);
   69|  5.61M|    return pos;
   70|  5.61M|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20SetPositionAttributeERKNS_14PointAttributeE:
   41|    370|  void SetPositionAttribute(const PointAttribute& position_attribute) {
   42|    370|    pos_attribute_ = &position_attribute;
   43|    370|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20SetEntryToPointIdMapEPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   44|    326|  void SetEntryToPointIdMap(const PointIndex* map) {
   45|    326|    entry_to_point_id_map_ = map;
   46|    326|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2ERKS5_:
   35|    511|      : pos_attribute_(nullptr),
   36|    511|        entry_to_point_id_map_(nullptr),
   37|    511|        mesh_data_(md) {}
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEED2Ev:
   38|    511|  virtual ~MeshPredictionSchemeGeometricNormalPredictorBase() {}
_ZNK5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20GetPositionForCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   71|  1.98M|  VectorD<int64_t, 3> GetPositionForCorner(CornerIndex ci) const {
   72|  1.98M|    DRACO_DCHECK(this->IsInitialized());
   73|  1.98M|    const auto corner_table = mesh_data_.corner_table();
   74|  1.98M|    const auto vert_id = corner_table->Vertex(ci).value();
   75|  1.98M|    const auto data_id = mesh_data_.vertex_to_data_map()->at(vert_id);
   76|  1.98M|    return GetPositionForDataId(data_id);
   77|  1.98M|  }
_ZNK5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20GetPositionForDataIdEi:
   63|  1.98M|  VectorD<int64_t, 3> GetPositionForDataId(int data_id) const {
   64|  1.98M|    DRACO_DCHECK(this->IsInitialized());
   65|  1.98M|    const auto point_id = entry_to_point_id_map_[data_id];
   66|  1.98M|    const auto pos_val_id = pos_attribute_->mapped_index(point_id);
   67|  1.98M|    VectorD<int64_t, 3> pos;
   68|  1.98M|    pos_attribute_->ConvertValue(pos_val_id, &pos[0]);
   69|  1.98M|    return pos;
   70|  1.98M|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20SetPositionAttributeERKNS_14PointAttributeE:
   41|    509|  void SetPositionAttribute(const PointAttribute& position_attribute) {
   42|    509|    pos_attribute_ = &position_attribute;
   43|    509|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20SetEntryToPointIdMapEPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   44|    464|  void SetEntryToPointIdMap(const PointIndex* map) {
   45|    464|    entry_to_point_id_map_ = map;
   46|    464|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2ERKS5_:
   35|    176|      : pos_attribute_(nullptr),
   36|    176|        entry_to_point_id_map_(nullptr),
   37|    176|        mesh_data_(md) {}
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEED2Ev:
   38|    176|  virtual ~MeshPredictionSchemeGeometricNormalPredictorBase() {}
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2ERKS5_:
   35|    168|      : pos_attribute_(nullptr),
   36|    168|        entry_to_point_id_map_(nullptr),
   37|    168|        mesh_data_(md) {}
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEED2Ev:
   38|    168|  virtual ~MeshPredictionSchemeGeometricNormalPredictorBase() {}
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2ERKS5_:
   35|    163|      : pos_attribute_(nullptr),
   36|    163|        entry_to_point_id_map_(nullptr),
   37|    163|        mesh_data_(md) {}
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEED2Ev:
   38|    163|  virtual ~MeshPredictionSchemeGeometricNormalPredictorBase() {}
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2ERKS5_:
   35|    175|      : pos_attribute_(nullptr),
   36|    175|        entry_to_point_id_map_(nullptr),
   37|    175|        mesh_data_(md) {}
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEED2Ev:
   38|    175|  virtual ~MeshPredictionSchemeGeometricNormalPredictorBase() {}

_ZN5draco45MeshPredictionSchemeMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   43|    479|      : MeshPredictionSchemeDecoder<DataTypeT, TransformT, MeshDataT>(
   44|    479|            attribute, transform, mesh_data) {}
_ZN5draco45MeshPredictionSchemeMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   63|    457|                          const PointIndex* /* entry_to_point_id_map */) {
   64|    457|  this->transform().Init(num_components);
   65|       |
   66|       |  // For storage of prediction values (already initialized to zero).
   67|    457|  std::unique_ptr<DataTypeT[]> pred_vals(new DataTypeT[num_components]());
   68|    457|  std::unique_ptr<DataTypeT[]> parallelogram_pred_vals(
   69|    457|      new DataTypeT[num_components]());
   70|       |
   71|    457|  this->transform().ComputeOriginalValue(pred_vals.get(), in_corr, out_data);
   72|       |
   73|    457|  const CornerTable* const table = this->mesh_data().corner_table();
   74|    457|  const std::vector<int32_t>* const vertex_to_data_map =
   75|    457|      this->mesh_data().vertex_to_data_map();
   76|       |
   77|    457|  const int corner_map_size =
   78|    457|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
   79|    457|  if (corner_map_size * num_components > size) {
  ------------------
  |  Branch (79:7): [True: 0, False: 457]
  ------------------
   80|      0|    return false;
   81|      0|  }
   82|  2.47M|  for (int p = 1; p < corner_map_size; ++p) {
  ------------------
  |  Branch (82:19): [True: 2.47M, False: 457]
  ------------------
   83|  2.47M|    const CornerIndex start_corner_id =
   84|  2.47M|        this->mesh_data().data_to_corner_map()->at(p);
   85|       |
   86|  2.47M|    CornerIndex corner_id(start_corner_id);
   87|  2.47M|    int num_parallelograms = 0;
   88|   195M|    for (int i = 0; i < num_components; ++i) {
  ------------------
  |  Branch (88:21): [True: 192M, False: 2.47M]
  ------------------
   89|   192M|      pred_vals[i] = static_cast<DataTypeT>(0);
   90|   192M|    }
   91|  5.65M|    while (corner_id != kInvalidCornerIndex) {
  ------------------
  |  Branch (91:12): [True: 3.18M, False: 2.47M]
  ------------------
   92|  3.18M|      if (ComputeParallelogramPrediction(
  ------------------
  |  Branch (92:11): [True: 290k, False: 2.89M]
  ------------------
   93|  3.18M|              p, corner_id, table, *vertex_to_data_map, out_data,
   94|  3.18M|              num_components, parallelogram_pred_vals.get())) {
   95|  21.3M|        for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (95:25): [True: 21.0M, False: 290k]
  ------------------
   96|  21.0M|          pred_vals[c] =
   97|  21.0M|              AddAsUnsigned(pred_vals[c], parallelogram_pred_vals[c]);
   98|  21.0M|        }
   99|   290k|        ++num_parallelograms;
  100|   290k|      }
  101|       |
  102|       |      // Proceed to the next corner attached to the vertex.
  103|  3.18M|      corner_id = table->SwingRight(corner_id);
  104|  3.18M|      if (corner_id == start_corner_id) {
  ------------------
  |  Branch (104:11): [True: 135k, False: 3.04M]
  ------------------
  105|   135k|        corner_id = kInvalidCornerIndex;
  106|   135k|      }
  107|  3.18M|    }
  108|       |
  109|  2.47M|    const int dst_offset = p * num_components;
  110|  2.47M|    if (num_parallelograms == 0) {
  ------------------
  |  Branch (110:9): [True: 2.31M, False: 156k]
  ------------------
  111|       |      // No parallelogram was valid.
  112|       |      // We use the last decoded point as a reference.
  113|  2.31M|      const int src_offset = (p - 1) * num_components;
  114|  2.31M|      this->transform().ComputeOriginalValue(
  115|  2.31M|          out_data + src_offset, in_corr + dst_offset, out_data + dst_offset);
  116|  2.31M|    } else {
  117|       |      // Compute the correction from the predicted value.
  118|  11.4M|      for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (118:23): [True: 11.3M, False: 156k]
  ------------------
  119|  11.3M|        pred_vals[c] /= num_parallelograms;
  120|  11.3M|      }
  121|   156k|      this->transform().ComputeOriginalValue(
  122|   156k|          pred_vals.get(), in_corr + dst_offset, out_data + dst_offset);
  123|   156k|    }
  124|  2.47M|  }
  125|    457|  return true;
  126|    457|}
_ZN5draco45MeshPredictionSchemeMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   43|    539|      : MeshPredictionSchemeDecoder<DataTypeT, TransformT, MeshDataT>(
   44|    539|            attribute, transform, mesh_data) {}
_ZN5draco45MeshPredictionSchemeMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   63|    520|                          const PointIndex* /* entry_to_point_id_map */) {
   64|    520|  this->transform().Init(num_components);
   65|       |
   66|       |  // For storage of prediction values (already initialized to zero).
   67|    520|  std::unique_ptr<DataTypeT[]> pred_vals(new DataTypeT[num_components]());
   68|    520|  std::unique_ptr<DataTypeT[]> parallelogram_pred_vals(
   69|    520|      new DataTypeT[num_components]());
   70|       |
   71|    520|  this->transform().ComputeOriginalValue(pred_vals.get(), in_corr, out_data);
   72|       |
   73|    520|  const CornerTable* const table = this->mesh_data().corner_table();
   74|    520|  const std::vector<int32_t>* const vertex_to_data_map =
   75|    520|      this->mesh_data().vertex_to_data_map();
   76|       |
   77|    520|  const int corner_map_size =
   78|    520|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
   79|    520|  if (corner_map_size * num_components > size) {
  ------------------
  |  Branch (79:7): [True: 0, False: 520]
  ------------------
   80|      0|    return false;
   81|      0|  }
   82|   878k|  for (int p = 1; p < corner_map_size; ++p) {
  ------------------
  |  Branch (82:19): [True: 877k, False: 520]
  ------------------
   83|   877k|    const CornerIndex start_corner_id =
   84|   877k|        this->mesh_data().data_to_corner_map()->at(p);
   85|       |
   86|   877k|    CornerIndex corner_id(start_corner_id);
   87|   877k|    int num_parallelograms = 0;
   88|  26.0M|    for (int i = 0; i < num_components; ++i) {
  ------------------
  |  Branch (88:21): [True: 25.1M, False: 877k]
  ------------------
   89|  25.1M|      pred_vals[i] = static_cast<DataTypeT>(0);
   90|  25.1M|    }
   91|  6.07M|    while (corner_id != kInvalidCornerIndex) {
  ------------------
  |  Branch (91:12): [True: 5.19M, False: 877k]
  ------------------
   92|  5.19M|      if (ComputeParallelogramPrediction(
  ------------------
  |  Branch (92:11): [True: 1.71M, False: 3.48M]
  ------------------
   93|  5.19M|              p, corner_id, table, *vertex_to_data_map, out_data,
   94|  5.19M|              num_components, parallelogram_pred_vals.get())) {
   95|  50.9M|        for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (95:25): [True: 49.1M, False: 1.71M]
  ------------------
   96|  49.1M|          pred_vals[c] =
   97|  49.1M|              AddAsUnsigned(pred_vals[c], parallelogram_pred_vals[c]);
   98|  49.1M|        }
   99|  1.71M|        ++num_parallelograms;
  100|  1.71M|      }
  101|       |
  102|       |      // Proceed to the next corner attached to the vertex.
  103|  5.19M|      corner_id = table->SwingRight(corner_id);
  104|  5.19M|      if (corner_id == start_corner_id) {
  ------------------
  |  Branch (104:11): [True: 861k, False: 4.33M]
  ------------------
  105|   861k|        corner_id = kInvalidCornerIndex;
  106|   861k|      }
  107|  5.19M|    }
  108|       |
  109|   877k|    const int dst_offset = p * num_components;
  110|   877k|    if (num_parallelograms == 0) {
  ------------------
  |  Branch (110:9): [True: 1.71k, False: 875k]
  ------------------
  111|       |      // No parallelogram was valid.
  112|       |      // We use the last decoded point as a reference.
  113|  1.71k|      const int src_offset = (p - 1) * num_components;
  114|  1.71k|      this->transform().ComputeOriginalValue(
  115|  1.71k|          out_data + src_offset, in_corr + dst_offset, out_data + dst_offset);
  116|   875k|    } else {
  117|       |      // Compute the correction from the predicted value.
  118|  25.9M|      for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (118:23): [True: 25.0M, False: 875k]
  ------------------
  119|  25.0M|        pred_vals[c] /= num_parallelograms;
  120|  25.0M|      }
  121|   875k|      this->transform().ComputeOriginalValue(
  122|   875k|          pred_vals.get(), in_corr + dst_offset, out_data + dst_offset);
  123|   875k|    }
  124|   877k|  }
  125|    520|  return true;
  126|    520|}

_ZN5draco40MeshPredictionSchemeParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   40|    580|      : MeshPredictionSchemeDecoder<DataTypeT, TransformT, MeshDataT>(
   41|    580|            attribute, transform, mesh_data) {}
_ZN5draco40MeshPredictionSchemeParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   60|    552|                          const PointIndex* /* entry_to_point_id_map */) {
   61|    552|  this->transform().Init(num_components);
   62|       |
   63|    552|  const CornerTable* const table = this->mesh_data().corner_table();
   64|    552|  const std::vector<int32_t>* const vertex_to_data_map =
   65|    552|      this->mesh_data().vertex_to_data_map();
   66|       |
   67|       |  // For storage of prediction values (already initialized to zero).
   68|    552|  std::unique_ptr<DataTypeT[]> pred_vals(new DataTypeT[num_components]());
   69|       |
   70|       |  // Restore the first value.
   71|    552|  this->transform().ComputeOriginalValue(pred_vals.get(), in_corr, out_data);
   72|       |
   73|    552|  const int corner_map_size =
   74|    552|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
   75|    552|  if (corner_map_size * num_components > size) {
  ------------------
  |  Branch (75:7): [True: 0, False: 552]
  ------------------
   76|      0|    return false;
   77|      0|  }
   78|  1.43M|  for (int p = 1; p < corner_map_size; ++p) {
  ------------------
  |  Branch (78:19): [True: 1.43M, False: 552]
  ------------------
   79|  1.43M|    const CornerIndex corner_id = this->mesh_data().data_to_corner_map()->at(p);
   80|  1.43M|    const int dst_offset = p * num_components;
   81|  1.43M|    if (!ComputeParallelogramPrediction(p, corner_id, table,
  ------------------
  |  Branch (81:9): [True: 1.38M, False: 49.7k]
  ------------------
   82|  1.43M|                                        *vertex_to_data_map, out_data,
   83|  1.43M|                                        num_components, pred_vals.get())) {
   84|       |      // Parallelogram could not be computed, Possible because some of the
   85|       |      // vertices are not valid (not encoded yet).
   86|       |      // We use the last encoded point as a reference (delta coding).
   87|  1.38M|      const int src_offset = (p - 1) * num_components;
   88|  1.38M|      this->transform().ComputeOriginalValue(
   89|  1.38M|          out_data + src_offset, in_corr + dst_offset, out_data + dst_offset);
   90|  1.38M|    } else {
   91|       |      // Apply the parallelogram prediction.
   92|  49.7k|      this->transform().ComputeOriginalValue(
   93|  49.7k|          pred_vals.get(), in_corr + dst_offset, out_data + dst_offset);
   94|  49.7k|    }
   95|  1.43M|  }
   96|    552|  return true;
   97|    552|}
_ZN5draco40MeshPredictionSchemeParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   40|    564|      : MeshPredictionSchemeDecoder<DataTypeT, TransformT, MeshDataT>(
   41|    564|            attribute, transform, mesh_data) {}
_ZN5draco40MeshPredictionSchemeParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   60|    521|                          const PointIndex* /* entry_to_point_id_map */) {
   61|    521|  this->transform().Init(num_components);
   62|       |
   63|    521|  const CornerTable* const table = this->mesh_data().corner_table();
   64|    521|  const std::vector<int32_t>* const vertex_to_data_map =
   65|    521|      this->mesh_data().vertex_to_data_map();
   66|       |
   67|       |  // For storage of prediction values (already initialized to zero).
   68|    521|  std::unique_ptr<DataTypeT[]> pred_vals(new DataTypeT[num_components]());
   69|       |
   70|       |  // Restore the first value.
   71|    521|  this->transform().ComputeOriginalValue(pred_vals.get(), in_corr, out_data);
   72|       |
   73|    521|  const int corner_map_size =
   74|    521|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
   75|    521|  if (corner_map_size * num_components > size) {
  ------------------
  |  Branch (75:7): [True: 0, False: 521]
  ------------------
   76|      0|    return false;
   77|      0|  }
   78|   489k|  for (int p = 1; p < corner_map_size; ++p) {
  ------------------
  |  Branch (78:19): [True: 488k, False: 521]
  ------------------
   79|   488k|    const CornerIndex corner_id = this->mesh_data().data_to_corner_map()->at(p);
   80|   488k|    const int dst_offset = p * num_components;
   81|   488k|    if (!ComputeParallelogramPrediction(p, corner_id, table,
  ------------------
  |  Branch (81:9): [True: 2.59k, False: 486k]
  ------------------
   82|   488k|                                        *vertex_to_data_map, out_data,
   83|   488k|                                        num_components, pred_vals.get())) {
   84|       |      // Parallelogram could not be computed, Possible because some of the
   85|       |      // vertices are not valid (not encoded yet).
   86|       |      // We use the last encoded point as a reference (delta coding).
   87|  2.59k|      const int src_offset = (p - 1) * num_components;
   88|  2.59k|      this->transform().ComputeOriginalValue(
   89|  2.59k|          out_data + src_offset, in_corr + dst_offset, out_data + dst_offset);
   90|   486k|    } else {
   91|       |      // Apply the parallelogram prediction.
   92|   486k|      this->transform().ComputeOriginalValue(
   93|   486k|          pred_vals.get(), in_corr + dst_offset, out_data + dst_offset);
   94|   486k|    }
   95|   488k|  }
   96|    521|  return true;
   97|    521|}

_ZN5draco30ComputeParallelogramPredictionINS_24MeshAttributeCornerTableEiEEbiNS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPKT_RKNSt3__16vectorIiNS8_9allocatorIiEEEEPKT0_iPSF_:
   48|  5.89M|    int num_components, DataTypeT* out_prediction) {
   49|  5.89M|  const CornerIndex oci = table->Opposite(ci);
   50|  5.89M|  if (oci == kInvalidCornerIndex) {
  ------------------
  |  Branch (50:7): [True: 4.74M, False: 1.14M]
  ------------------
   51|  4.74M|    return false;
   52|  4.74M|  }
   53|  1.14M|  int vert_opp, vert_next, vert_prev;
   54|  1.14M|  GetParallelogramEntries<CornerTableT>(oci, table, vertex_to_data_map,
   55|  1.14M|                                        &vert_opp, &vert_next, &vert_prev);
   56|  1.14M|  if (vert_opp < data_entry_id && vert_next < data_entry_id &&
  ------------------
  |  Branch (56:7): [True: 593k, False: 548k]
  |  Branch (56:35): [True: 450k, False: 142k]
  ------------------
   57|   450k|      vert_prev < data_entry_id) {
  ------------------
  |  Branch (57:7): [True: 420k, False: 30.6k]
  ------------------
   58|       |    // Apply the parallelogram prediction.
   59|   420k|    const int v_opp_off = vert_opp * num_components;
   60|   420k|    const int v_next_off = vert_next * num_components;
   61|   420k|    const int v_prev_off = vert_prev * num_components;
   62|  37.6M|    for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (62:21): [True: 37.1M, False: 420k]
  ------------------
   63|  37.1M|      const int64_t in_data_next_off = in_data[v_next_off + c];
   64|  37.1M|      const int64_t in_data_prev_off = in_data[v_prev_off + c];
   65|  37.1M|      const int64_t in_data_opp_off = in_data[v_opp_off + c];
   66|  37.1M|      const int64_t result =
   67|  37.1M|          (in_data_next_off + in_data_prev_off) - in_data_opp_off;
   68|       |
   69|  37.1M|      out_prediction[c] = static_cast<DataTypeT>(result);
   70|  37.1M|    }
   71|   420k|    return true;
   72|   420k|  }
   73|   721k|  return false;  // Not all data is available for prediction
   74|  1.14M|}
_ZN5draco23GetParallelogramEntriesINS_24MeshAttributeCornerTableEEEvNS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPKT_RKNSt3__16vectorIiNS8_9allocatorIiEEEEPiSF_SF_:
   31|  1.14M|    int* next_entry, int* prev_entry) {
   32|       |  // One vertex of the input |table| correspond to exactly one attribute value
   33|       |  // entry. The |table| can be either CornerTable for per-vertex attributes,
   34|       |  // or MeshAttributeCornerTable for attributes with interior seams.
   35|  1.14M|  *opp_entry = vertex_to_data_map[table->Vertex(ci).value()];
   36|  1.14M|  *next_entry = vertex_to_data_map[table->Vertex(table->Next(ci)).value()];
   37|  1.14M|  *prev_entry = vertex_to_data_map[table->Vertex(table->Previous(ci)).value()];
   38|  1.14M|}
_ZN5draco30ComputeParallelogramPredictionINS_11CornerTableEiEEbiNS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPKT_RKNSt3__16vectorIiNS8_9allocatorIiEEEEPKT0_iPSF_:
   48|  6.57M|    int num_components, DataTypeT* out_prediction) {
   49|  6.57M|  const CornerIndex oci = table->Opposite(ci);
   50|  6.57M|  if (oci == kInvalidCornerIndex) {
  ------------------
  |  Branch (50:7): [True: 23.0k, False: 6.55M]
  ------------------
   51|  23.0k|    return false;
   52|  23.0k|  }
   53|  6.55M|  int vert_opp, vert_next, vert_prev;
   54|  6.55M|  GetParallelogramEntries<CornerTableT>(oci, table, vertex_to_data_map,
   55|  6.55M|                                        &vert_opp, &vert_next, &vert_prev);
   56|  6.55M|  if (vert_opp < data_entry_id && vert_next < data_entry_id &&
  ------------------
  |  Branch (56:7): [True: 3.50M, False: 3.05M]
  |  Branch (56:35): [True: 2.67M, False: 828k]
  ------------------
   57|  2.67M|      vert_prev < data_entry_id) {
  ------------------
  |  Branch (57:7): [True: 2.48M, False: 184k]
  ------------------
   58|       |    // Apply the parallelogram prediction.
   59|  2.48M|    const int v_opp_off = vert_opp * num_components;
   60|  2.48M|    const int v_next_off = vert_next * num_components;
   61|  2.48M|    const int v_prev_off = vert_prev * num_components;
   62|  95.5M|    for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (62:21): [True: 93.0M, False: 2.48M]
  ------------------
   63|  93.0M|      const int64_t in_data_next_off = in_data[v_next_off + c];
   64|  93.0M|      const int64_t in_data_prev_off = in_data[v_prev_off + c];
   65|  93.0M|      const int64_t in_data_opp_off = in_data[v_opp_off + c];
   66|  93.0M|      const int64_t result =
   67|  93.0M|          (in_data_next_off + in_data_prev_off) - in_data_opp_off;
   68|       |
   69|  93.0M|      out_prediction[c] = static_cast<DataTypeT>(result);
   70|  93.0M|    }
   71|  2.48M|    return true;
   72|  2.48M|  }
   73|  4.06M|  return false;  // Not all data is available for prediction
   74|  6.55M|}
_ZN5draco23GetParallelogramEntriesINS_11CornerTableEEEvNS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPKT_RKNSt3__16vectorIiNS8_9allocatorIiEEEEPiSF_SF_:
   31|  6.55M|    int* next_entry, int* prev_entry) {
   32|       |  // One vertex of the input |table| correspond to exactly one attribute value
   33|       |  // entry. The |table| can be either CornerTable for per-vertex attributes,
   34|       |  // or MeshAttributeCornerTable for attributes with interior seams.
   35|  6.55M|  *opp_entry = vertex_to_data_map[table->Vertex(ci).value()];
   36|  6.55M|  *next_entry = vertex_to_data_map[table->Vertex(table->Next(ci)).value()];
   37|  6.55M|  *prev_entry = vertex_to_data_map[table->Vertex(table->Previous(ci)).value()];
   38|  6.55M|}

_ZN5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_i:
   44|    194|      : MeshPredictionSchemeDecoder<DataTypeT, TransformT, MeshDataT>(
   45|    194|            attribute, transform, mesh_data),
   46|    194|        pos_attribute_(nullptr),
   47|    194|        entry_to_point_id_map_(nullptr),
   48|    194|        num_components_(0),
   49|    194|        version_(version) {}
_ZNK5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE22GetNumParentAttributesEv:
   71|    384|  int GetNumParentAttributes() const override { return 1; }
_ZNK5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE22GetParentAttributeTypeEi:
   73|    194|  GeometryAttribute::Type GetParentAttributeType(int i) const override {
   74|    194|    DRACO_DCHECK_EQ(i, 0);
   75|    194|    (void)i;
   76|    194|    return GeometryAttribute::POSITION;
   77|    194|  }
_ZN5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE18SetParentAttributeEPKNS_14PointAttributeE:
   79|    193|  bool SetParentAttribute(const PointAttribute* att) override {
   80|    193|    if (att == nullptr) {
  ------------------
  |  Branch (80:9): [True: 0, False: 193]
  ------------------
   81|      0|      return false;
   82|      0|    }
   83|    193|    if (att->attribute_type() != GeometryAttribute::POSITION) {
  ------------------
  |  Branch (83:9): [True: 0, False: 193]
  ------------------
   84|      0|      return false;  // Invalid attribute type.
   85|      0|    }
   86|    193|    if (att->num_components() != 3) {
  ------------------
  |  Branch (86:9): [True: 3, False: 190]
  ------------------
   87|      3|      return false;  // Currently works only for 3 component positions.
   88|      3|    }
   89|    190|    pos_attribute_ = att;
   90|    190|    return true;
   91|    193|  }
_ZN5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  156|    184|    DecodePredictionData(DecoderBuffer* buffer) {
  157|       |  // Decode the delta coded orientations.
  158|    184|  uint32_t num_orientations = 0;
  159|    184|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    184|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (159:7): [True: 1, False: 183]
  ------------------
  160|      1|    if (!buffer->Decode(&num_orientations)) {
  ------------------
  |  Branch (160:9): [True: 0, False: 1]
  ------------------
  161|      0|      return false;
  162|      0|    }
  163|    183|  } else {
  164|    183|    if (!DecodeVarint(&num_orientations, buffer)) {
  ------------------
  |  Branch (164:9): [True: 1, False: 182]
  ------------------
  165|      1|      return false;
  166|      1|    }
  167|    183|  }
  168|    183|  if (num_orientations == 0) {
  ------------------
  |  Branch (168:7): [True: 1, False: 182]
  ------------------
  169|      1|    return false;
  170|      1|  }
  171|    182|  if (num_orientations > this->mesh_data().corner_table()->num_corners()) {
  ------------------
  |  Branch (171:7): [True: 10, False: 172]
  ------------------
  172|       |    // We can't have more orientations than the maximum number of decoded
  173|       |    // values.
  174|     10|    return false;
  175|     10|  }
  176|    172|  orientations_.resize(num_orientations);
  177|    172|  bool last_orientation = true;
  178|    172|  RAnsBitDecoder decoder;
  179|    172|  if (!decoder.StartDecoding(buffer)) {
  ------------------
  |  Branch (179:7): [True: 1, False: 171]
  ------------------
  180|      1|    return false;
  181|      1|  }
  182|   179k|  for (uint32_t i = 0; i < num_orientations; ++i) {
  ------------------
  |  Branch (182:24): [True: 178k, False: 171]
  ------------------
  183|   178k|    if (!decoder.DecodeNextBit()) {
  ------------------
  |  Branch (183:9): [True: 1.96k, False: 176k]
  ------------------
  184|  1.96k|      last_orientation = !last_orientation;
  185|  1.96k|    }
  186|   178k|    orientations_[i] = last_orientation;
  187|   178k|  }
  188|    171|  decoder.EndDecoding();
  189|    171|  return MeshPredictionSchemeDecoder<DataTypeT, TransformT,
  190|    171|                                     MeshDataT>::DecodePredictionData(buffer);
  191|    172|}
_ZN5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
  125|    135|                          const PointIndex* entry_to_point_id_map) {
  126|    135|  if (num_components != 2) {
  ------------------
  |  Branch (126:7): [True: 12, False: 123]
  ------------------
  127|       |    // Corrupt/malformed input. Two output components are req'd.
  128|     12|    return false;
  129|     12|  }
  130|    123|  num_components_ = num_components;
  131|    123|  entry_to_point_id_map_ = entry_to_point_id_map;
  132|    123|  predicted_value_ =
  133|    123|      std::unique_ptr<DataTypeT[]>(new DataTypeT[num_components]);
  134|    123|  this->transform().Init(num_components);
  135|       |
  136|    123|  const int corner_map_size =
  137|    123|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  138|    123|  if (corner_map_size * num_components > size) {
  ------------------
  |  Branch (138:7): [True: 0, False: 123]
  ------------------
  139|      0|    return false;
  140|      0|  }
  141|  1.36M|  for (int p = 0; p < corner_map_size; ++p) {
  ------------------
  |  Branch (141:19): [True: 1.36M, False: 92]
  ------------------
  142|  1.36M|    const CornerIndex corner_id = this->mesh_data().data_to_corner_map()->at(p);
  143|  1.36M|    if (!ComputePredictedValue(corner_id, out_data, p)) {
  ------------------
  |  Branch (143:9): [True: 31, False: 1.36M]
  ------------------
  144|     31|      return false;
  145|     31|    }
  146|       |
  147|  1.36M|    const int dst_offset = p * num_components;
  148|  1.36M|    this->transform().ComputeOriginalValue(
  149|  1.36M|        predicted_value_.get(), in_corr + dst_offset, out_data + dst_offset);
  150|  1.36M|  }
  151|     92|  return true;
  152|    123|}
_ZN5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputePredictedValueENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPKii:
  196|  1.36M|                          int data_id) {
  197|       |  // Compute the predicted UV coordinate from the positions on all corners
  198|       |  // of the processed triangle. For the best prediction, the UV coordinates
  199|       |  // on the next/previous corners need to be already encoded/decoded.
  200|  1.36M|  const CornerIndex next_corner_id =
  201|  1.36M|      this->mesh_data().corner_table()->Next(corner_id);
  202|  1.36M|  const CornerIndex prev_corner_id =
  203|  1.36M|      this->mesh_data().corner_table()->Previous(corner_id);
  204|       |  // Get the encoded data ids from the next and previous corners.
  205|       |  // The data id is the encoding order of the UV coordinates.
  206|  1.36M|  int next_data_id, prev_data_id;
  207|       |
  208|  1.36M|  int next_vert_id, prev_vert_id;
  209|  1.36M|  next_vert_id =
  210|  1.36M|      this->mesh_data().corner_table()->Vertex(next_corner_id).value();
  211|  1.36M|  prev_vert_id =
  212|  1.36M|      this->mesh_data().corner_table()->Vertex(prev_corner_id).value();
  213|       |
  214|  1.36M|  next_data_id = this->mesh_data().vertex_to_data_map()->at(next_vert_id);
  215|  1.36M|  prev_data_id = this->mesh_data().vertex_to_data_map()->at(prev_vert_id);
  216|       |
  217|  1.36M|  if (prev_data_id < data_id && next_data_id < data_id) {
  ------------------
  |  Branch (217:7): [True: 934k, False: 432k]
  |  Branch (217:33): [True: 502k, False: 432k]
  ------------------
  218|       |    // Both other corners have available UV coordinates for prediction.
  219|   502k|    const Vector2f n_uv = GetTexCoordForEntryId(next_data_id, data);
  220|   502k|    const Vector2f p_uv = GetTexCoordForEntryId(prev_data_id, data);
  221|   502k|    if (p_uv == n_uv) {
  ------------------
  |  Branch (221:9): [True: 499k, False: 2.94k]
  ------------------
  222|       |      // We cannot do a reliable prediction on degenerated UV triangles.
  223|       |      // Technically floats > INT_MAX are undefined, but compilers will
  224|       |      // convert those values to INT_MIN. We are being explicit here for asan.
  225|   999k|      for (const int i : {0, 1}) {
  ------------------
  |  Branch (225:24): [True: 999k, False: 499k]
  ------------------
  226|   999k|        if (std::isnan(p_uv[i]) || static_cast<double>(p_uv[i]) > INT_MAX ||
  ------------------
  |  Branch (226:13): [True: 0, False: 999k]
  |  Branch (226:36): [True: 229, False: 999k]
  ------------------
  227|   999k|            static_cast<double>(p_uv[i]) < INT_MIN) {
  ------------------
  |  Branch (227:13): [True: 0, False: 999k]
  ------------------
  228|    229|          predicted_value_[i] = INT_MIN;
  229|   999k|        } else {
  230|   999k|          predicted_value_[i] = static_cast<int>(p_uv[i]);
  231|   999k|        }
  232|   999k|      }
  233|   499k|      return true;
  234|   499k|    }
  235|       |
  236|       |    // Get positions at all corners.
  237|  2.94k|    const Vector3f tip_pos = GetPositionForEntryId(data_id);
  238|  2.94k|    const Vector3f next_pos = GetPositionForEntryId(next_data_id);
  239|  2.94k|    const Vector3f prev_pos = GetPositionForEntryId(prev_data_id);
  240|       |    // Use the positions of the above triangle to predict the texture coordinate
  241|       |    // on the tip corner C.
  242|       |    // Convert the triangle into a new coordinate system defined by orthogonal
  243|       |    // bases vectors S, T, where S is vector prev_pos - next_pos and T is an
  244|       |    // perpendicular vector to S in the same plane as vector the
  245|       |    // tip_pos - next_pos.
  246|       |    // The transformed triangle in the new coordinate system is then going to
  247|       |    // be represented as:
  248|       |    //
  249|       |    //        1 ^
  250|       |    //          |
  251|       |    //          |
  252|       |    //          |   C
  253|       |    //          |  /  \
  254|       |    //          | /      \
  255|       |    //          |/          \
  256|       |    //          N--------------P
  257|       |    //          0              1
  258|       |    //
  259|       |    // Where next_pos point (N) is at position (0, 0), prev_pos point (P) is
  260|       |    // at (1, 0). Our goal is to compute the position of the tip_pos point (C)
  261|       |    // in this new coordinate space (s, t).
  262|       |    //
  263|  2.94k|    const Vector3f pn = prev_pos - next_pos;
  264|  2.94k|    const Vector3f cn = tip_pos - next_pos;
  265|  2.94k|    const float pn_norm2_squared = pn.SquaredNorm();
  266|       |    // Coordinate s of the tip corner C is simply the dot product of the
  267|       |    // normalized vectors |pn| and |cn| (normalized by the length of |pn|).
  268|       |    // Since both of these vectors are normalized, we don't need to perform the
  269|       |    // normalization explicitly and instead we can just use the squared norm
  270|       |    // of |pn| as a denominator of the resulting dot product of non normalized
  271|       |    // vectors.
  272|  2.94k|    float s, t;
  273|       |    // |pn_norm2_squared| can be exactly 0 when the next_pos and prev_pos are
  274|       |    // the same positions (e.g. because they were quantized to the same
  275|       |    // location).
  276|  2.94k|    if (version_ < DRACO_BITSTREAM_VERSION(1, 2) || pn_norm2_squared > 0) {
  ------------------
  |  |  115|  5.89k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (276:9): [True: 0, False: 2.94k]
  |  Branch (276:53): [True: 284, False: 2.66k]
  ------------------
  277|    284|      s = pn.Dot(cn) / pn_norm2_squared;
  278|       |      // To get the coordinate t, we can use formula:
  279|       |      //      t = |C-N - (P-N) * s| / |P-N|
  280|       |      // Do not use std::sqrt to avoid changes in the bitstream.
  281|    284|      t = sqrt((cn - pn * s).SquaredNorm() / pn_norm2_squared);
  282|  2.66k|    } else {
  283|  2.66k|      s = 0;
  284|  2.66k|      t = 0;
  285|  2.66k|    }
  286|       |
  287|       |    // Now we need to transform the point (s, t) to the texture coordinate space
  288|       |    // UV. We know the UV coordinates on points N and P (N_UV and P_UV). Lets
  289|       |    // denote P_UV - N_UV = PN_UV. PN_UV is then 2 dimensional vector that can
  290|       |    // be used to define transformation from the normalized coordinate system
  291|       |    // to the texture coordinate system using a 3x3 affine matrix M:
  292|       |    //
  293|       |    //  M = | PN_UV[0]  -PN_UV[1]  N_UV[0] |
  294|       |    //      | PN_UV[1]   PN_UV[0]  N_UV[1] |
  295|       |    //      | 0          0         1       |
  296|       |    //
  297|       |    // The predicted point C_UV in the texture space is then equal to
  298|       |    // C_UV = M * (s, t, 1). Because the triangle in UV space may be flipped
  299|       |    // around the PN_UV axis, we also need to consider point C_UV' = M * (s, -t)
  300|       |    // as the prediction.
  301|  2.94k|    const Vector2f pn_uv = p_uv - n_uv;
  302|  2.94k|    const float pnus = pn_uv[0] * s + n_uv[0];
  303|  2.94k|    const float pnut = pn_uv[0] * t;
  304|  2.94k|    const float pnvs = pn_uv[1] * s + n_uv[1];
  305|  2.94k|    const float pnvt = pn_uv[1] * t;
  306|  2.94k|    Vector2f predicted_uv;
  307|  2.94k|    if (orientations_.empty()) {
  ------------------
  |  Branch (307:9): [True: 31, False: 2.91k]
  ------------------
  308|     31|      return false;
  309|     31|    }
  310|       |
  311|       |    // When decoding the data, we already know which orientation to use.
  312|  2.91k|    const bool orientation = orientations_.back();
  313|  2.91k|    orientations_.pop_back();
  314|  2.91k|    if (orientation) {
  ------------------
  |  Branch (314:9): [True: 1.04k, False: 1.87k]
  ------------------
  315|  1.04k|      predicted_uv = Vector2f(pnus - pnvt, pnvs + pnut);
  316|  1.87k|    } else {
  317|  1.87k|      predicted_uv = Vector2f(pnus + pnvt, pnvs - pnut);
  318|  1.87k|    }
  319|  2.91k|    if (std::is_integral<DataTypeT>::value) {
  ------------------
  |  Branch (319:9): [True: 2.91k, Folded]
  ------------------
  320|       |      // Round the predicted value for integer types.
  321|       |      // Technically floats > INT_MAX are undefined, but compilers will
  322|       |      // convert those values to INT_MIN. We are being explicit here for asan.
  323|  2.91k|      const double u = floor(predicted_uv[0] + 0.5);
  324|  2.91k|      if (std::isnan(u) || u > INT_MAX || u < INT_MIN) {
  ------------------
  |  Branch (324:11): [True: 0, False: 2.91k]
  |  Branch (324:28): [True: 108, False: 2.80k]
  |  Branch (324:43): [True: 31, False: 2.77k]
  ------------------
  325|    139|        predicted_value_[0] = INT_MIN;
  326|  2.77k|      } else {
  327|  2.77k|        predicted_value_[0] = static_cast<int>(u);
  328|  2.77k|      }
  329|  2.91k|      const double v = floor(predicted_uv[1] + 0.5);
  330|  2.91k|      if (std::isnan(v) || v > INT_MAX || v < INT_MIN) {
  ------------------
  |  Branch (330:11): [True: 0, False: 2.91k]
  |  Branch (330:28): [True: 89, False: 2.82k]
  |  Branch (330:43): [True: 37, False: 2.79k]
  ------------------
  331|    126|        predicted_value_[1] = INT_MIN;
  332|  2.79k|      } else {
  333|  2.79k|        predicted_value_[1] = static_cast<int>(v);
  334|  2.79k|      }
  335|  2.91k|    } else {
  336|      0|      predicted_value_[0] = static_cast<int>(predicted_uv[0]);
  337|      0|      predicted_value_[1] = static_cast<int>(predicted_uv[1]);
  338|      0|    }
  339|       |
  340|  2.91k|    return true;
  341|  2.94k|  }
  342|       |  // Else we don't have available textures on both corners. For such case we
  343|       |  // can't use positions for predicting the uv value and we resort to delta
  344|       |  // coding.
  345|   864k|  int data_offset = 0;
  346|   864k|  if (prev_data_id < data_id) {
  ------------------
  |  Branch (346:7): [True: 432k, False: 432k]
  ------------------
  347|       |    // Use the value on the previous corner as the prediction.
  348|   432k|    data_offset = prev_data_id * num_components_;
  349|   432k|  }
  350|   864k|  if (next_data_id < data_id) {
  ------------------
  |  Branch (350:7): [True: 15, False: 864k]
  ------------------
  351|       |    // Use the value on the next corner as the prediction.
  352|     15|    data_offset = next_data_id * num_components_;
  353|   864k|  } else {
  354|       |    // None of the other corners have a valid value. Use the last encoded value
  355|       |    // as the prediction if possible.
  356|   864k|    if (data_id > 0) {
  ------------------
  |  Branch (356:9): [True: 863k, False: 123]
  ------------------
  357|   863k|      data_offset = (data_id - 1) * num_components_;
  358|   863k|    } else {
  359|       |      // We are encoding the first value. Predict 0.
  360|    369|      for (int i = 0; i < num_components_; ++i) {
  ------------------
  |  Branch (360:23): [True: 246, False: 123]
  ------------------
  361|    246|        predicted_value_[i] = 0;
  362|    246|      }
  363|    123|      return true;
  364|    123|    }
  365|   864k|  }
  366|  2.59M|  for (int i = 0; i < num_components_; ++i) {
  ------------------
  |  Branch (366:19): [True: 1.72M, False: 863k]
  ------------------
  367|  1.72M|    predicted_value_[i] = data[data_offset + i];
  368|  1.72M|  }
  369|   863k|  return true;
  370|   864k|}
_ZNK5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21GetTexCoordForEntryIdEiPKi:
  102|  1.00M|  Vector2f GetTexCoordForEntryId(int entry_id, const DataTypeT* data) const {
  103|  1.00M|    const int data_offset = entry_id * num_components_;
  104|  1.00M|    return Vector2f(static_cast<float>(data[data_offset]),
  105|  1.00M|                    static_cast<float>(data[data_offset + 1]));
  106|  1.00M|  }
_ZNK5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21GetPositionForEntryIdEi:
   94|  8.84k|  Vector3f GetPositionForEntryId(int entry_id) const {
   95|  8.84k|    const PointIndex point_id = entry_to_point_id_map_[entry_id];
   96|  8.84k|    Vector3f pos;
   97|  8.84k|    pos_attribute_->ConvertValue(pos_attribute_->mapped_index(point_id),
   98|  8.84k|                                 &pos[0]);
   99|  8.84k|    return pos;
  100|  8.84k|  }
_ZN5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_i:
   44|    213|      : MeshPredictionSchemeDecoder<DataTypeT, TransformT, MeshDataT>(
   45|    213|            attribute, transform, mesh_data),
   46|    213|        pos_attribute_(nullptr),
   47|    213|        entry_to_point_id_map_(nullptr),
   48|    213|        num_components_(0),
   49|    213|        version_(version) {}
_ZNK5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE22GetNumParentAttributesEv:
   71|    421|  int GetNumParentAttributes() const override { return 1; }
_ZNK5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE22GetParentAttributeTypeEi:
   73|    213|  GeometryAttribute::Type GetParentAttributeType(int i) const override {
   74|    213|    DRACO_DCHECK_EQ(i, 0);
   75|    213|    (void)i;
   76|    213|    return GeometryAttribute::POSITION;
   77|    213|  }
_ZN5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE18SetParentAttributeEPKNS_14PointAttributeE:
   79|    211|  bool SetParentAttribute(const PointAttribute* att) override {
   80|    211|    if (att == nullptr) {
  ------------------
  |  Branch (80:9): [True: 0, False: 211]
  ------------------
   81|      0|      return false;
   82|      0|    }
   83|    211|    if (att->attribute_type() != GeometryAttribute::POSITION) {
  ------------------
  |  Branch (83:9): [True: 0, False: 211]
  ------------------
   84|      0|      return false;  // Invalid attribute type.
   85|      0|    }
   86|    211|    if (att->num_components() != 3) {
  ------------------
  |  Branch (86:9): [True: 3, False: 208]
  ------------------
   87|      3|      return false;  // Currently works only for 3 component positions.
   88|      3|    }
   89|    208|    pos_attribute_ = att;
   90|    208|    return true;
   91|    211|  }
_ZN5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  156|    201|    DecodePredictionData(DecoderBuffer* buffer) {
  157|       |  // Decode the delta coded orientations.
  158|    201|  uint32_t num_orientations = 0;
  159|    201|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    201|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (159:7): [True: 1, False: 200]
  ------------------
  160|      1|    if (!buffer->Decode(&num_orientations)) {
  ------------------
  |  Branch (160:9): [True: 0, False: 1]
  ------------------
  161|      0|      return false;
  162|      0|    }
  163|    200|  } else {
  164|    200|    if (!DecodeVarint(&num_orientations, buffer)) {
  ------------------
  |  Branch (164:9): [True: 1, False: 199]
  ------------------
  165|      1|      return false;
  166|      1|    }
  167|    200|  }
  168|    200|  if (num_orientations == 0) {
  ------------------
  |  Branch (168:7): [True: 1, False: 199]
  ------------------
  169|      1|    return false;
  170|      1|  }
  171|    199|  if (num_orientations > this->mesh_data().corner_table()->num_corners()) {
  ------------------
  |  Branch (171:7): [True: 35, False: 164]
  ------------------
  172|       |    // We can't have more orientations than the maximum number of decoded
  173|       |    // values.
  174|     35|    return false;
  175|     35|  }
  176|    164|  orientations_.resize(num_orientations);
  177|    164|  bool last_orientation = true;
  178|    164|  RAnsBitDecoder decoder;
  179|    164|  if (!decoder.StartDecoding(buffer)) {
  ------------------
  |  Branch (179:7): [True: 3, False: 161]
  ------------------
  180|      3|    return false;
  181|      3|  }
  182|  25.4k|  for (uint32_t i = 0; i < num_orientations; ++i) {
  ------------------
  |  Branch (182:24): [True: 25.3k, False: 161]
  ------------------
  183|  25.3k|    if (!decoder.DecodeNextBit()) {
  ------------------
  |  Branch (183:9): [True: 3.17k, False: 22.1k]
  ------------------
  184|  3.17k|      last_orientation = !last_orientation;
  185|  3.17k|    }
  186|  25.3k|    orientations_[i] = last_orientation;
  187|  25.3k|  }
  188|    161|  decoder.EndDecoding();
  189|    161|  return MeshPredictionSchemeDecoder<DataTypeT, TransformT,
  190|    161|                                     MeshDataT>::DecodePredictionData(buffer);
  191|    164|}
_ZN5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
  125|    129|                          const PointIndex* entry_to_point_id_map) {
  126|    129|  if (num_components != 2) {
  ------------------
  |  Branch (126:7): [True: 3, False: 126]
  ------------------
  127|       |    // Corrupt/malformed input. Two output components are req'd.
  128|      3|    return false;
  129|      3|  }
  130|    126|  num_components_ = num_components;
  131|    126|  entry_to_point_id_map_ = entry_to_point_id_map;
  132|    126|  predicted_value_ =
  133|    126|      std::unique_ptr<DataTypeT[]>(new DataTypeT[num_components]);
  134|    126|  this->transform().Init(num_components);
  135|       |
  136|    126|  const int corner_map_size =
  137|    126|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  138|    126|  if (corner_map_size * num_components > size) {
  ------------------
  |  Branch (138:7): [True: 0, False: 126]
  ------------------
  139|      0|    return false;
  140|      0|  }
  141|   273k|  for (int p = 0; p < corner_map_size; ++p) {
  ------------------
  |  Branch (141:19): [True: 273k, False: 99]
  ------------------
  142|   273k|    const CornerIndex corner_id = this->mesh_data().data_to_corner_map()->at(p);
  143|   273k|    if (!ComputePredictedValue(corner_id, out_data, p)) {
  ------------------
  |  Branch (143:9): [True: 27, False: 273k]
  ------------------
  144|     27|      return false;
  145|     27|    }
  146|       |
  147|   273k|    const int dst_offset = p * num_components;
  148|   273k|    this->transform().ComputeOriginalValue(
  149|   273k|        predicted_value_.get(), in_corr + dst_offset, out_data + dst_offset);
  150|   273k|  }
  151|     99|  return true;
  152|    126|}
_ZN5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputePredictedValueENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPKii:
  196|   273k|                          int data_id) {
  197|       |  // Compute the predicted UV coordinate from the positions on all corners
  198|       |  // of the processed triangle. For the best prediction, the UV coordinates
  199|       |  // on the next/previous corners need to be already encoded/decoded.
  200|   273k|  const CornerIndex next_corner_id =
  201|   273k|      this->mesh_data().corner_table()->Next(corner_id);
  202|   273k|  const CornerIndex prev_corner_id =
  203|   273k|      this->mesh_data().corner_table()->Previous(corner_id);
  204|       |  // Get the encoded data ids from the next and previous corners.
  205|       |  // The data id is the encoding order of the UV coordinates.
  206|   273k|  int next_data_id, prev_data_id;
  207|       |
  208|   273k|  int next_vert_id, prev_vert_id;
  209|   273k|  next_vert_id =
  210|   273k|      this->mesh_data().corner_table()->Vertex(next_corner_id).value();
  211|   273k|  prev_vert_id =
  212|   273k|      this->mesh_data().corner_table()->Vertex(prev_corner_id).value();
  213|       |
  214|   273k|  next_data_id = this->mesh_data().vertex_to_data_map()->at(next_vert_id);
  215|   273k|  prev_data_id = this->mesh_data().vertex_to_data_map()->at(prev_vert_id);
  216|       |
  217|   273k|  if (prev_data_id < data_id && next_data_id < data_id) {
  ------------------
  |  Branch (217:7): [True: 273k, False: 210]
  |  Branch (217:33): [True: 272k, False: 201]
  ------------------
  218|       |    // Both other corners have available UV coordinates for prediction.
  219|   272k|    const Vector2f n_uv = GetTexCoordForEntryId(next_data_id, data);
  220|   272k|    const Vector2f p_uv = GetTexCoordForEntryId(prev_data_id, data);
  221|   272k|    if (p_uv == n_uv) {
  ------------------
  |  Branch (221:9): [True: 269k, False: 3.11k]
  ------------------
  222|       |      // We cannot do a reliable prediction on degenerated UV triangles.
  223|       |      // Technically floats > INT_MAX are undefined, but compilers will
  224|       |      // convert those values to INT_MIN. We are being explicit here for asan.
  225|   539k|      for (const int i : {0, 1}) {
  ------------------
  |  Branch (225:24): [True: 539k, False: 269k]
  ------------------
  226|   539k|        if (std::isnan(p_uv[i]) || static_cast<double>(p_uv[i]) > INT_MAX ||
  ------------------
  |  Branch (226:13): [True: 0, False: 539k]
  |  Branch (226:36): [True: 167, False: 539k]
  ------------------
  227|   539k|            static_cast<double>(p_uv[i]) < INT_MIN) {
  ------------------
  |  Branch (227:13): [True: 0, False: 539k]
  ------------------
  228|    167|          predicted_value_[i] = INT_MIN;
  229|   539k|        } else {
  230|   539k|          predicted_value_[i] = static_cast<int>(p_uv[i]);
  231|   539k|        }
  232|   539k|      }
  233|   269k|      return true;
  234|   269k|    }
  235|       |
  236|       |    // Get positions at all corners.
  237|  3.11k|    const Vector3f tip_pos = GetPositionForEntryId(data_id);
  238|  3.11k|    const Vector3f next_pos = GetPositionForEntryId(next_data_id);
  239|  3.11k|    const Vector3f prev_pos = GetPositionForEntryId(prev_data_id);
  240|       |    // Use the positions of the above triangle to predict the texture coordinate
  241|       |    // on the tip corner C.
  242|       |    // Convert the triangle into a new coordinate system defined by orthogonal
  243|       |    // bases vectors S, T, where S is vector prev_pos - next_pos and T is an
  244|       |    // perpendicular vector to S in the same plane as vector the
  245|       |    // tip_pos - next_pos.
  246|       |    // The transformed triangle in the new coordinate system is then going to
  247|       |    // be represented as:
  248|       |    //
  249|       |    //        1 ^
  250|       |    //          |
  251|       |    //          |
  252|       |    //          |   C
  253|       |    //          |  /  \
  254|       |    //          | /      \
  255|       |    //          |/          \
  256|       |    //          N--------------P
  257|       |    //          0              1
  258|       |    //
  259|       |    // Where next_pos point (N) is at position (0, 0), prev_pos point (P) is
  260|       |    // at (1, 0). Our goal is to compute the position of the tip_pos point (C)
  261|       |    // in this new coordinate space (s, t).
  262|       |    //
  263|  3.11k|    const Vector3f pn = prev_pos - next_pos;
  264|  3.11k|    const Vector3f cn = tip_pos - next_pos;
  265|  3.11k|    const float pn_norm2_squared = pn.SquaredNorm();
  266|       |    // Coordinate s of the tip corner C is simply the dot product of the
  267|       |    // normalized vectors |pn| and |cn| (normalized by the length of |pn|).
  268|       |    // Since both of these vectors are normalized, we don't need to perform the
  269|       |    // normalization explicitly and instead we can just use the squared norm
  270|       |    // of |pn| as a denominator of the resulting dot product of non normalized
  271|       |    // vectors.
  272|  3.11k|    float s, t;
  273|       |    // |pn_norm2_squared| can be exactly 0 when the next_pos and prev_pos are
  274|       |    // the same positions (e.g. because they were quantized to the same
  275|       |    // location).
  276|  3.11k|    if (version_ < DRACO_BITSTREAM_VERSION(1, 2) || pn_norm2_squared > 0) {
  ------------------
  |  |  115|  6.23k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (276:9): [True: 0, False: 3.11k]
  |  Branch (276:53): [True: 472, False: 2.64k]
  ------------------
  277|    472|      s = pn.Dot(cn) / pn_norm2_squared;
  278|       |      // To get the coordinate t, we can use formula:
  279|       |      //      t = |C-N - (P-N) * s| / |P-N|
  280|       |      // Do not use std::sqrt to avoid changes in the bitstream.
  281|    472|      t = sqrt((cn - pn * s).SquaredNorm() / pn_norm2_squared);
  282|  2.64k|    } else {
  283|  2.64k|      s = 0;
  284|  2.64k|      t = 0;
  285|  2.64k|    }
  286|       |
  287|       |    // Now we need to transform the point (s, t) to the texture coordinate space
  288|       |    // UV. We know the UV coordinates on points N and P (N_UV and P_UV). Lets
  289|       |    // denote P_UV - N_UV = PN_UV. PN_UV is then 2 dimensional vector that can
  290|       |    // be used to define transformation from the normalized coordinate system
  291|       |    // to the texture coordinate system using a 3x3 affine matrix M:
  292|       |    //
  293|       |    //  M = | PN_UV[0]  -PN_UV[1]  N_UV[0] |
  294|       |    //      | PN_UV[1]   PN_UV[0]  N_UV[1] |
  295|       |    //      | 0          0         1       |
  296|       |    //
  297|       |    // The predicted point C_UV in the texture space is then equal to
  298|       |    // C_UV = M * (s, t, 1). Because the triangle in UV space may be flipped
  299|       |    // around the PN_UV axis, we also need to consider point C_UV' = M * (s, -t)
  300|       |    // as the prediction.
  301|  3.11k|    const Vector2f pn_uv = p_uv - n_uv;
  302|  3.11k|    const float pnus = pn_uv[0] * s + n_uv[0];
  303|  3.11k|    const float pnut = pn_uv[0] * t;
  304|  3.11k|    const float pnvs = pn_uv[1] * s + n_uv[1];
  305|  3.11k|    const float pnvt = pn_uv[1] * t;
  306|  3.11k|    Vector2f predicted_uv;
  307|  3.11k|    if (orientations_.empty()) {
  ------------------
  |  Branch (307:9): [True: 27, False: 3.09k]
  ------------------
  308|     27|      return false;
  309|     27|    }
  310|       |
  311|       |    // When decoding the data, we already know which orientation to use.
  312|  3.09k|    const bool orientation = orientations_.back();
  313|  3.09k|    orientations_.pop_back();
  314|  3.09k|    if (orientation) {
  ------------------
  |  Branch (314:9): [True: 1.56k, False: 1.52k]
  ------------------
  315|  1.56k|      predicted_uv = Vector2f(pnus - pnvt, pnvs + pnut);
  316|  1.56k|    } else {
  317|  1.52k|      predicted_uv = Vector2f(pnus + pnvt, pnvs - pnut);
  318|  1.52k|    }
  319|  3.09k|    if (std::is_integral<DataTypeT>::value) {
  ------------------
  |  Branch (319:9): [True: 3.09k, Folded]
  ------------------
  320|       |      // Round the predicted value for integer types.
  321|       |      // Technically floats > INT_MAX are undefined, but compilers will
  322|       |      // convert those values to INT_MIN. We are being explicit here for asan.
  323|  3.09k|      const double u = floor(predicted_uv[0] + 0.5);
  324|  3.09k|      if (std::isnan(u) || u > INT_MAX || u < INT_MIN) {
  ------------------
  |  Branch (324:11): [True: 0, False: 3.09k]
  |  Branch (324:28): [True: 103, False: 2.98k]
  |  Branch (324:43): [True: 28, False: 2.96k]
  ------------------
  325|    131|        predicted_value_[0] = INT_MIN;
  326|  2.96k|      } else {
  327|  2.96k|        predicted_value_[0] = static_cast<int>(u);
  328|  2.96k|      }
  329|  3.09k|      const double v = floor(predicted_uv[1] + 0.5);
  330|  3.09k|      if (std::isnan(v) || v > INT_MAX || v < INT_MIN) {
  ------------------
  |  Branch (330:11): [True: 0, False: 3.09k]
  |  Branch (330:28): [True: 124, False: 2.96k]
  |  Branch (330:43): [True: 23, False: 2.94k]
  ------------------
  331|    147|        predicted_value_[1] = INT_MIN;
  332|  2.94k|      } else {
  333|  2.94k|        predicted_value_[1] = static_cast<int>(v);
  334|  2.94k|      }
  335|  3.09k|    } else {
  336|      0|      predicted_value_[0] = static_cast<int>(predicted_uv[0]);
  337|      0|      predicted_value_[1] = static_cast<int>(predicted_uv[1]);
  338|      0|    }
  339|       |
  340|  3.09k|    return true;
  341|  3.11k|  }
  342|       |  // Else we don't have available textures on both corners. For such case we
  343|       |  // can't use positions for predicting the uv value and we resort to delta
  344|       |  // coding.
  345|    411|  int data_offset = 0;
  346|    411|  if (prev_data_id < data_id) {
  ------------------
  |  Branch (346:7): [True: 201, False: 210]
  ------------------
  347|       |    // Use the value on the previous corner as the prediction.
  348|    201|    data_offset = prev_data_id * num_components_;
  349|    201|  }
  350|    411|  if (next_data_id < data_id) {
  ------------------
  |  Branch (350:7): [True: 11, False: 400]
  ------------------
  351|       |    // Use the value on the next corner as the prediction.
  352|     11|    data_offset = next_data_id * num_components_;
  353|    400|  } else {
  354|       |    // None of the other corners have a valid value. Use the last encoded value
  355|       |    // as the prediction if possible.
  356|    400|    if (data_id > 0) {
  ------------------
  |  Branch (356:9): [True: 274, False: 126]
  ------------------
  357|    274|      data_offset = (data_id - 1) * num_components_;
  358|    274|    } else {
  359|       |      // We are encoding the first value. Predict 0.
  360|    378|      for (int i = 0; i < num_components_; ++i) {
  ------------------
  |  Branch (360:23): [True: 252, False: 126]
  ------------------
  361|    252|        predicted_value_[i] = 0;
  362|    252|      }
  363|    126|      return true;
  364|    126|    }
  365|    400|  }
  366|    855|  for (int i = 0; i < num_components_; ++i) {
  ------------------
  |  Branch (366:19): [True: 570, False: 285]
  ------------------
  367|    570|    predicted_value_[i] = data[data_offset + i];
  368|    570|  }
  369|    285|  return true;
  370|    411|}
_ZNK5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21GetTexCoordForEntryIdEiPKi:
  102|   545k|  Vector2f GetTexCoordForEntryId(int entry_id, const DataTypeT* data) const {
  103|   545k|    const int data_offset = entry_id * num_components_;
  104|   545k|    return Vector2f(static_cast<float>(data[data_offset]),
  105|   545k|                    static_cast<float>(data[data_offset + 1]));
  106|   545k|  }
_ZNK5draco36MeshPredictionSchemeTexCoordsDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21GetPositionForEntryIdEi:
   94|  9.35k|  Vector3f GetPositionForEntryId(int entry_id) const {
   95|  9.35k|    const PointIndex point_id = entry_to_point_id_map_[entry_id];
   96|  9.35k|    Vector3f pos;
   97|  9.35k|    pos_attribute_->ConvertValue(pos_attribute_->mapped_index(point_id),
   98|  9.35k|                                 &pos[0]);
   99|  9.35k|    return pos;
  100|  9.35k|  }

_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   38|    163|      : MeshPredictionSchemeDecoder<DataTypeT, TransformT, MeshDataT>(
   39|    163|            attribute, transform, mesh_data),
   40|    163|        predictor_(mesh_data) {}
_ZNK5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE22GetNumParentAttributesEv:
   62|    323|  int GetNumParentAttributes() const override { return 1; }
_ZNK5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE22GetParentAttributeTypeEi:
   64|    163|  GeometryAttribute::Type GetParentAttributeType(int i) const override {
   65|    163|    DRACO_DCHECK_EQ(i, 0);
   66|    163|    (void)i;
   67|    163|    return GeometryAttribute::POSITION;
   68|    163|  }
_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE18SetParentAttributeEPKNS_14PointAttributeE:
   70|    161|  bool SetParentAttribute(const PointAttribute* att) override {
   71|    161|    if (!att || att->attribute_type() != GeometryAttribute::POSITION) {
  ------------------
  |  Branch (71:9): [True: 0, False: 161]
  |  Branch (71:17): [True: 0, False: 161]
  ------------------
   72|      0|      return false;  // Invalid attribute type.
   73|      0|    }
   74|    161|    if (att->num_components() != 3) {
  ------------------
  |  Branch (74:9): [True: 1, False: 160]
  ------------------
   75|      1|      return false;  // Currently works only for 3 component positions.
   76|      1|    }
   77|    160|    predictor_.SetPositionAttribute(*att);
   78|    160|    return true;
   79|    161|  }
_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  128|    159|                                                                buffer) {
  129|       |  // Decode the delta coded orientations.
  130|    159|  int32_t num_orientations = 0;
  131|    159|  if (!buffer->Decode(&num_orientations) || num_orientations < 0) {
  ------------------
  |  Branch (131:7): [True: 4, False: 155]
  |  Branch (131:45): [True: 8, False: 147]
  ------------------
  132|     12|    return false;
  133|     12|  }
  134|       |
  135|       |  // Check that the decoded number of orientations is not unreasonably high.
  136|    147|  const int32_t max_num_orientations = max_num_predicted_values_;
  137|    147|  if (max_num_orientations != -1 && num_orientations > max_num_orientations) {
  ------------------
  |  Branch (137:7): [True: 147, False: 0]
  |  Branch (137:37): [True: 51, False: 96]
  ------------------
  138|     51|    return false;
  139|     51|  }
  140|       |
  141|     96|  predictor_.ResizeOrientations(num_orientations);
  142|     96|  bool last_orientation = true;
  143|     96|  RAnsBitDecoder decoder;
  144|     96|  if (!decoder.StartDecoding(buffer)) {
  ------------------
  |  Branch (144:7): [True: 3, False: 93]
  ------------------
  145|      3|    return false;
  146|      3|  }
  147|  35.6k|  for (int i = 0; i < num_orientations; ++i) {
  ------------------
  |  Branch (147:19): [True: 35.5k, False: 93]
  ------------------
  148|  35.5k|    if (!decoder.DecodeNextBit()) {
  ------------------
  |  Branch (148:9): [True: 19.0k, False: 16.4k]
  ------------------
  149|  19.0k|      last_orientation = !last_orientation;
  150|  19.0k|    }
  151|  35.5k|    predictor_.set_orientation(i, last_orientation);
  152|  35.5k|  }
  153|     93|  decoder.EndDecoding();
  154|     93|  return MeshPredictionSchemeDecoder<DataTypeT, TransformT,
  155|     93|                                     MeshDataT>::DecodePredictionData(buffer);
  156|     96|}
_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE24SetMaxNumPredictedValuesEi:
   81|    159|  virtual void SetMaxNumPredictedValues(int32_t num) {
   82|    159|    max_num_predicted_values_ = num;
   83|    159|  }
_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   97|     73|                                      const PointIndex* entry_to_point_id_map) {
   98|     73|  if (num_components != MeshPredictionSchemeTexCoordsPortablePredictor<
  ------------------
  |  Branch (98:7): [True: 2, False: 71]
  ------------------
   99|     73|                            DataTypeT, MeshDataT>::kNumComponents) {
  100|      2|    return false;
  101|      2|  }
  102|     71|  predictor_.SetEntryToPointIdMap(entry_to_point_id_map);
  103|     71|  this->transform().Init(num_components);
  104|       |
  105|     71|  const int corner_map_size =
  106|     71|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  107|     71|  if (corner_map_size * num_components > size) {
  ------------------
  |  Branch (107:7): [True: 0, False: 71]
  ------------------
  108|      0|    return false;
  109|      0|  }
  110|  1.12M|  for (int p = 0; p < corner_map_size; ++p) {
  ------------------
  |  Branch (110:19): [True: 1.12M, False: 50]
  ------------------
  111|  1.12M|    const CornerIndex corner_id = this->mesh_data().data_to_corner_map()->at(p);
  112|  1.12M|    if (!predictor_.template ComputePredictedValue<false>(corner_id, out_data,
  ------------------
  |  Branch (112:9): [True: 21, False: 1.12M]
  ------------------
  113|  1.12M|                                                          p)) {
  114|     21|      return false;
  115|     21|    }
  116|       |
  117|  1.12M|    const int dst_offset = p * num_components;
  118|  1.12M|    this->transform().ComputeOriginalValue(predictor_.predicted_value(),
  119|  1.12M|                                           in_corr + dst_offset,
  120|  1.12M|                                           out_data + dst_offset);
  121|  1.12M|  }
  122|     50|  return true;
  123|     71|}
_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   38|     93|      : MeshPredictionSchemeDecoder<DataTypeT, TransformT, MeshDataT>(
   39|     93|            attribute, transform, mesh_data),
   40|     93|        predictor_(mesh_data) {}
_ZNK5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE22GetNumParentAttributesEv:
   62|    184|  int GetNumParentAttributes() const override { return 1; }
_ZNK5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE22GetParentAttributeTypeEi:
   64|     93|  GeometryAttribute::Type GetParentAttributeType(int i) const override {
   65|     93|    DRACO_DCHECK_EQ(i, 0);
   66|     93|    (void)i;
   67|     93|    return GeometryAttribute::POSITION;
   68|     93|  }
_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE18SetParentAttributeEPKNS_14PointAttributeE:
   70|     92|  bool SetParentAttribute(const PointAttribute* att) override {
   71|     92|    if (!att || att->attribute_type() != GeometryAttribute::POSITION) {
  ------------------
  |  Branch (71:9): [True: 0, False: 92]
  |  Branch (71:17): [True: 0, False: 92]
  ------------------
   72|      0|      return false;  // Invalid attribute type.
   73|      0|    }
   74|     92|    if (att->num_components() != 3) {
  ------------------
  |  Branch (74:9): [True: 1, False: 91]
  ------------------
   75|      1|      return false;  // Currently works only for 3 component positions.
   76|      1|    }
   77|     91|    predictor_.SetPositionAttribute(*att);
   78|     91|    return true;
   79|     92|  }
_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  128|     90|                                                                buffer) {
  129|       |  // Decode the delta coded orientations.
  130|     90|  int32_t num_orientations = 0;
  131|     90|  if (!buffer->Decode(&num_orientations) || num_orientations < 0) {
  ------------------
  |  Branch (131:7): [True: 1, False: 89]
  |  Branch (131:45): [True: 5, False: 84]
  ------------------
  132|      6|    return false;
  133|      6|  }
  134|       |
  135|       |  // Check that the decoded number of orientations is not unreasonably high.
  136|     84|  const int32_t max_num_orientations = max_num_predicted_values_;
  137|     84|  if (max_num_orientations != -1 && num_orientations > max_num_orientations) {
  ------------------
  |  Branch (137:7): [True: 84, False: 0]
  |  Branch (137:37): [True: 43, False: 41]
  ------------------
  138|     43|    return false;
  139|     43|  }
  140|       |
  141|     41|  predictor_.ResizeOrientations(num_orientations);
  142|     41|  bool last_orientation = true;
  143|     41|  RAnsBitDecoder decoder;
  144|     41|  if (!decoder.StartDecoding(buffer)) {
  ------------------
  |  Branch (144:7): [True: 1, False: 40]
  ------------------
  145|      1|    return false;
  146|      1|  }
  147|  13.9k|  for (int i = 0; i < num_orientations; ++i) {
  ------------------
  |  Branch (147:19): [True: 13.9k, False: 40]
  ------------------
  148|  13.9k|    if (!decoder.DecodeNextBit()) {
  ------------------
  |  Branch (148:9): [True: 51, False: 13.8k]
  ------------------
  149|     51|      last_orientation = !last_orientation;
  150|     51|    }
  151|  13.9k|    predictor_.set_orientation(i, last_orientation);
  152|  13.9k|  }
  153|     40|  decoder.EndDecoding();
  154|     40|  return MeshPredictionSchemeDecoder<DataTypeT, TransformT,
  155|     40|                                     MeshDataT>::DecodePredictionData(buffer);
  156|     41|}
_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE24SetMaxNumPredictedValuesEi:
   81|     90|  virtual void SetMaxNumPredictedValues(int32_t num) {
   82|     90|    max_num_predicted_values_ = num;
   83|     90|  }
_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   97|     36|                                      const PointIndex* entry_to_point_id_map) {
   98|     36|  if (num_components != MeshPredictionSchemeTexCoordsPortablePredictor<
  ------------------
  |  Branch (98:7): [True: 1, False: 35]
  ------------------
   99|     36|                            DataTypeT, MeshDataT>::kNumComponents) {
  100|      1|    return false;
  101|      1|  }
  102|     35|  predictor_.SetEntryToPointIdMap(entry_to_point_id_map);
  103|     35|  this->transform().Init(num_components);
  104|       |
  105|     35|  const int corner_map_size =
  106|     35|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  107|     35|  if (corner_map_size * num_components > size) {
  ------------------
  |  Branch (107:7): [True: 0, False: 35]
  ------------------
  108|      0|    return false;
  109|      0|  }
  110|   132k|  for (int p = 0; p < corner_map_size; ++p) {
  ------------------
  |  Branch (110:19): [True: 132k, False: 24]
  ------------------
  111|   132k|    const CornerIndex corner_id = this->mesh_data().data_to_corner_map()->at(p);
  112|   132k|    if (!predictor_.template ComputePredictedValue<false>(corner_id, out_data,
  ------------------
  |  Branch (112:9): [True: 11, False: 132k]
  ------------------
  113|   132k|                                                          p)) {
  114|     11|      return false;
  115|     11|    }
  116|       |
  117|   132k|    const int dst_offset = p * num_components;
  118|   132k|    this->transform().ComputeOriginalValue(predictor_.predicted_value(),
  119|   132k|                                           in_corr + dst_offset,
  120|   132k|                                           out_data + dst_offset);
  121|   132k|  }
  122|     24|  return true;
  123|     35|}

_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2ERKS3_:
   38|    163|      : pos_attribute_(nullptr),
   39|    163|        entry_to_point_id_map_(nullptr),
   40|    163|        mesh_data_(md) {}
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20SetPositionAttributeERKNS_14PointAttributeE:
   41|    160|  void SetPositionAttribute(const PointAttribute& position_attribute) {
   42|    160|    pos_attribute_ = &position_attribute;
   43|    160|  }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE18ResizeOrientationsEi:
   73|     96|  void ResizeOrientations(int num_orientations) {
   74|     96|    orientations_.resize(num_orientations);
   75|     96|  }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE15set_orientationEib:
   71|  35.5k|  void set_orientation(int i, bool v) { orientations_[i] = v; }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20SetEntryToPointIdMapEPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   44|     71|  void SetEntryToPointIdMap(const PointIndex* map) {
   45|     71|    entry_to_point_id_map_ = map;
   46|     71|  }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputePredictedValueILb0EEEbNS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPKii:
   93|  1.12M|                                                 int data_id) {
   94|       |  // Compute the predicted UV coordinate from the positions on all corners
   95|       |  // of the processed triangle. For the best prediction, the UV coordinates
   96|       |  // on the next/previous corners need to be already encoded/decoded.
   97|  1.12M|  const CornerIndex next_corner_id = mesh_data_.corner_table()->Next(corner_id);
   98|  1.12M|  const CornerIndex prev_corner_id =
   99|  1.12M|      mesh_data_.corner_table()->Previous(corner_id);
  100|       |  // Get the encoded data ids from the next and previous corners.
  101|       |  // The data id is the encoding order of the UV coordinates.
  102|  1.12M|  int next_data_id, prev_data_id;
  103|       |
  104|  1.12M|  int next_vert_id, prev_vert_id;
  105|  1.12M|  next_vert_id = mesh_data_.corner_table()->Vertex(next_corner_id).value();
  106|  1.12M|  prev_vert_id = mesh_data_.corner_table()->Vertex(prev_corner_id).value();
  107|       |
  108|  1.12M|  next_data_id = mesh_data_.vertex_to_data_map()->at(next_vert_id);
  109|  1.12M|  prev_data_id = mesh_data_.vertex_to_data_map()->at(prev_vert_id);
  110|       |
  111|  1.12M|  typedef VectorD<int64_t, 2> Vec2;
  112|  1.12M|  typedef VectorD<int64_t, 3> Vec3;
  113|  1.12M|  typedef VectorD<uint64_t, 2> Vec2u;
  114|       |
  115|  1.12M|  if (prev_data_id < data_id && next_data_id < data_id) {
  ------------------
  |  Branch (115:7): [True: 772k, False: 352k]
  |  Branch (115:33): [True: 419k, False: 352k]
  ------------------
  116|       |    // Both other corners have available UV coordinates for prediction.
  117|   419k|    const Vec2 n_uv = GetTexCoordForEntryId(next_data_id, data);
  118|   419k|    const Vec2 p_uv = GetTexCoordForEntryId(prev_data_id, data);
  119|   419k|    if (p_uv == n_uv) {
  ------------------
  |  Branch (119:9): [True: 360k, False: 58.8k]
  ------------------
  120|       |      // We cannot do a reliable prediction on degenerated UV triangles.
  121|   360k|      predicted_value_[0] = p_uv[0];
  122|   360k|      predicted_value_[1] = p_uv[1];
  123|   360k|      return true;
  124|   360k|    }
  125|       |
  126|       |    // Get positions at all corners.
  127|  58.8k|    const Vec3 tip_pos = GetPositionForEntryId(data_id);
  128|  58.8k|    const Vec3 next_pos = GetPositionForEntryId(next_data_id);
  129|  58.8k|    const Vec3 prev_pos = GetPositionForEntryId(prev_data_id);
  130|       |    // We use the positions of the above triangle to predict the texture
  131|       |    // coordinate on the tip corner C.
  132|       |    // To convert the triangle into the UV coordinate system we first compute
  133|       |    // position X on the vector |prev_pos - next_pos| that is the projection of
  134|       |    // point C onto vector |prev_pos - next_pos|:
  135|       |    //
  136|       |    //              C
  137|       |    //             /.  \
  138|       |    //            / .     \
  139|       |    //           /  .        \
  140|       |    //          N---X----------P
  141|       |    //
  142|       |    // Where next_pos is point (N), prev_pos is point (P) and tip_pos is the
  143|       |    // position of predicted coordinate (C).
  144|       |    //
  145|  58.8k|    const Vec3 pn = prev_pos - next_pos;
  146|  58.8k|    const uint64_t pn_norm2_squared = pn.SquaredNorm();
  147|  58.8k|    if (pn_norm2_squared != 0) {
  ------------------
  |  Branch (147:9): [True: 73, False: 58.7k]
  ------------------
  148|       |      // Compute the projection of C onto PN by computing dot product of CN with
  149|       |      // PN and normalizing it by length of PN. This gives us a factor |s| where
  150|       |      // |s = PN.Dot(CN) / PN.SquaredNorm2()|. This factor can be used to
  151|       |      // compute X in UV space |X_UV| as |X_UV = N_UV + s * PN_UV|.
  152|     73|      const Vec3 cn = tip_pos - next_pos;
  153|     73|      const int64_t cn_dot_pn = pn.Dot(cn);
  154|       |
  155|     73|      const Vec2 pn_uv = p_uv - n_uv;
  156|       |      // Because we perform all computations with integers, we don't explicitly
  157|       |      // compute the normalized factor |s|, but rather we perform all operations
  158|       |      // over UV vectors in a non-normalized coordinate system scaled with a
  159|       |      // scaling factor |pn_norm2_squared|:
  160|       |      //
  161|       |      //      x_uv = X_UV * PN.Norm2Squared()
  162|       |      //
  163|     73|      const int64_t n_uv_absmax_element =
  164|     73|          std::max(std::abs(n_uv[0]), std::abs(n_uv[1]));
  165|     73|      if (n_uv_absmax_element >
  ------------------
  |  Branch (165:11): [True: 0, False: 73]
  ------------------
  166|     73|          std::numeric_limits<int64_t>::max() / pn_norm2_squared) {
  167|       |        // Return false if the below multiplication would overflow.
  168|      0|        return false;
  169|      0|      }
  170|     73|      const int64_t pn_uv_absmax_element =
  171|     73|          std::max(std::abs(pn_uv[0]), std::abs(pn_uv[1]));
  172|     73|      if (std::abs(cn_dot_pn) >
  ------------------
  |  Branch (172:11): [True: 0, False: 73]
  ------------------
  173|     73|          std::numeric_limits<int64_t>::max() / pn_uv_absmax_element) {
  174|       |        // Return false if squared length calculation would overflow.
  175|      0|        return false;
  176|      0|      }
  177|       |      // Keep the scaled prediction arithmetic in the unsigned domain.
  178|     73|      const Vec2 x_uv = Vec2(Vec2u(n_uv) * pn_norm2_squared +
  179|     73|                             Vec2u(pn_uv) * static_cast<uint64_t>(cn_dot_pn));
  180|     73|      const int64_t pn_absmax_element =
  181|     73|          std::max(std::max(std::abs(pn[0]), std::abs(pn[1])), std::abs(pn[2]));
  182|     73|      if (std::abs(cn_dot_pn) >
  ------------------
  |  Branch (182:11): [True: 0, False: 73]
  ------------------
  183|     73|          std::numeric_limits<int64_t>::max() / pn_absmax_element) {
  184|       |        // Return false if squared length calculation would overflow.
  185|      0|        return false;
  186|      0|      }
  187|       |
  188|       |      // Compute squared length of vector CX in position coordinate system:
  189|     73|      const Vec3 x_pos = next_pos + (cn_dot_pn * pn) / pn_norm2_squared;
  190|     73|      const uint64_t cx_norm2_squared = (tip_pos - x_pos).SquaredNorm();
  191|       |
  192|       |      // Compute vector CX_UV in the uv space by rotating vector PN_UV by 90
  193|       |      // degrees and scaling it with factor CX.Norm2() / PN.Norm2():
  194|       |      //
  195|       |      //     CX_UV = (CX.Norm2() / PN.Norm2()) * Rot(PN_UV)
  196|       |      //
  197|       |      // To preserve precision, we perform all operations in scaled space as
  198|       |      // explained above, so we want the final vector to be:
  199|       |      //
  200|       |      //     cx_uv = CX_UV * PN.Norm2Squared()
  201|       |      //
  202|       |      // We can then rewrite the formula as:
  203|       |      //
  204|       |      //     cx_uv = CX.Norm2() * PN.Norm2() * Rot(PN_UV)
  205|       |      //
  206|     73|      Vec2 cx_uv(pn_uv[1], -pn_uv[0]);  // Rotated PN_UV.
  207|       |      // Compute CX.Norm2() * PN.Norm2()
  208|     73|      const uint64_t norm_squared =
  209|     73|          IntSqrt(cx_norm2_squared * pn_norm2_squared);
  210|       |      // Final cx_uv in the scaled coordinate space.
  211|     73|      cx_uv = cx_uv * norm_squared;
  212|       |
  213|       |      // Predicted uv coordinate is then computed by either adding or
  214|       |      // subtracting CX_UV to/from X_UV.
  215|     73|      Vec2 predicted_uv;
  216|     73|      if (is_encoder_t) {
  ------------------
  |  Branch (216:11): [Folded, False: 73]
  ------------------
  217|       |        // When encoding, compute both possible vectors and determine which one
  218|       |        // results in a better prediction.
  219|       |        // Both vectors need to be transformed back from the scaled space to
  220|       |        // the real UV coordinate space.
  221|      0|        const Vec2 predicted_uv_0((x_uv + cx_uv) / pn_norm2_squared);
  222|      0|        const Vec2 predicted_uv_1((x_uv - cx_uv) / pn_norm2_squared);
  223|      0|        const Vec2 c_uv = GetTexCoordForEntryId(data_id, data);
  224|      0|        if ((c_uv - predicted_uv_0).SquaredNorm() <
  ------------------
  |  Branch (224:13): [True: 0, False: 0]
  ------------------
  225|      0|            (c_uv - predicted_uv_1).SquaredNorm()) {
  226|      0|          predicted_uv = predicted_uv_0;
  227|      0|          orientations_.push_back(true);
  228|      0|        } else {
  229|      0|          predicted_uv = predicted_uv_1;
  230|      0|          orientations_.push_back(false);
  231|      0|        }
  232|     73|      } else {
  233|       |        // When decoding the data, we already know which orientation to use.
  234|     73|        if (orientations_.empty()) {
  ------------------
  |  Branch (234:13): [True: 21, False: 52]
  ------------------
  235|     21|          return false;
  236|     21|        }
  237|     52|        const bool orientation = orientations_.back();
  238|     52|        orientations_.pop_back();
  239|       |        // Perform operations in unsigned type to avoid signed integer overflow.
  240|       |        // Note that the result will be the same (for non-overflowing values).
  241|     52|        if (orientation) {
  ------------------
  |  Branch (241:13): [True: 40, False: 12]
  ------------------
  242|     40|          predicted_uv = Vec2(Vec2u(x_uv) + Vec2u(cx_uv)) / pn_norm2_squared;
  243|     40|        } else {
  244|     12|          predicted_uv = Vec2(Vec2u(x_uv) - Vec2u(cx_uv)) / pn_norm2_squared;
  245|     12|        }
  246|     52|      }
  247|     52|      predicted_value_[0] = static_cast<int>(predicted_uv[0]);
  248|     52|      predicted_value_[1] = static_cast<int>(predicted_uv[1]);
  249|     52|      return true;
  250|     73|    }
  251|  58.8k|  }
  252|       |  // Else we don't have available textures on both corners or the position data
  253|       |  // is invalid. For such cases we can't use positions for predicting the uv
  254|       |  // value and we resort to delta coding.
  255|   764k|  int data_offset = 0;
  256|   764k|  if (prev_data_id < data_id) {
  ------------------
  |  Branch (256:7): [True: 411k, False: 352k]
  ------------------
  257|       |    // Use the value on the previous corner as the prediction.
  258|   411k|    data_offset = prev_data_id * kNumComponents;
  259|   411k|  }
  260|   764k|  if (next_data_id < data_id) {
  ------------------
  |  Branch (260:7): [True: 58.7k, False: 705k]
  ------------------
  261|       |    // Use the value on the next corner as the prediction.
  262|  58.7k|    data_offset = next_data_id * kNumComponents;
  263|   705k|  } else {
  264|       |    // None of the other corners have a valid value. Use the last encoded value
  265|       |    // as the prediction if possible.
  266|   705k|    if (data_id > 0) {
  ------------------
  |  Branch (266:9): [True: 705k, False: 71]
  ------------------
  267|   705k|      data_offset = (data_id - 1) * kNumComponents;
  268|   705k|    } else {
  269|       |      // We are encoding the first value. Predict 0.
  270|    213|      for (int i = 0; i < kNumComponents; ++i) {
  ------------------
  |  Branch (270:23): [True: 142, False: 71]
  ------------------
  271|    142|        predicted_value_[i] = 0;
  272|    142|      }
  273|     71|      return true;
  274|     71|    }
  275|   705k|  }
  276|  2.29M|  for (int i = 0; i < kNumComponents; ++i) {
  ------------------
  |  Branch (276:19): [True: 1.52M, False: 764k]
  ------------------
  277|  1.52M|    predicted_value_[i] = data[data_offset + i];
  278|  1.52M|  }
  279|   764k|  return true;
  280|   764k|}
_ZNK5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21GetTexCoordForEntryIdEiPKi:
   58|   838k|                                            const DataTypeT* data) const {
   59|   838k|    const int data_offset = entry_id * kNumComponents;
   60|   838k|    return VectorD<int64_t, 2>(data[data_offset], data[data_offset + 1]);
   61|   838k|  }
_ZNK5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21GetPositionForEntryIdEi:
   49|   176k|  VectorD<int64_t, 3> GetPositionForEntryId(int entry_id) const {
   50|   176k|    const PointIndex point_id = entry_to_point_id_map_[entry_id];
   51|   176k|    VectorD<int64_t, 3> pos;
   52|   176k|    pos_attribute_->ConvertValue(pos_attribute_->mapped_index(point_id),
   53|   176k|                                 &pos[0]);
   54|   176k|    return pos;
   55|   176k|  }
_ZNK5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE15predicted_valueEv:
   69|  1.12M|  const DataTypeT* predicted_value() const { return predicted_value_; }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2ERKS3_:
   38|     93|      : pos_attribute_(nullptr),
   39|     93|        entry_to_point_id_map_(nullptr),
   40|     93|        mesh_data_(md) {}
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20SetPositionAttributeERKNS_14PointAttributeE:
   41|     91|  void SetPositionAttribute(const PointAttribute& position_attribute) {
   42|     91|    pos_attribute_ = &position_attribute;
   43|     91|  }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEE18ResizeOrientationsEi:
   73|     41|  void ResizeOrientations(int num_orientations) {
   74|     41|    orientations_.resize(num_orientations);
   75|     41|  }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEE15set_orientationEib:
   71|  13.9k|  void set_orientation(int i, bool v) { orientations_[i] = v; }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20SetEntryToPointIdMapEPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   44|     35|  void SetEntryToPointIdMap(const PointIndex* map) {
   45|     35|    entry_to_point_id_map_ = map;
   46|     35|  }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputePredictedValueILb0EEEbNS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPKii:
   93|   132k|                                                 int data_id) {
   94|       |  // Compute the predicted UV coordinate from the positions on all corners
   95|       |  // of the processed triangle. For the best prediction, the UV coordinates
   96|       |  // on the next/previous corners need to be already encoded/decoded.
   97|   132k|  const CornerIndex next_corner_id = mesh_data_.corner_table()->Next(corner_id);
   98|   132k|  const CornerIndex prev_corner_id =
   99|   132k|      mesh_data_.corner_table()->Previous(corner_id);
  100|       |  // Get the encoded data ids from the next and previous corners.
  101|       |  // The data id is the encoding order of the UV coordinates.
  102|   132k|  int next_data_id, prev_data_id;
  103|       |
  104|   132k|  int next_vert_id, prev_vert_id;
  105|   132k|  next_vert_id = mesh_data_.corner_table()->Vertex(next_corner_id).value();
  106|   132k|  prev_vert_id = mesh_data_.corner_table()->Vertex(prev_corner_id).value();
  107|       |
  108|   132k|  next_data_id = mesh_data_.vertex_to_data_map()->at(next_vert_id);
  109|   132k|  prev_data_id = mesh_data_.vertex_to_data_map()->at(prev_vert_id);
  110|       |
  111|   132k|  typedef VectorD<int64_t, 2> Vec2;
  112|   132k|  typedef VectorD<int64_t, 3> Vec3;
  113|   132k|  typedef VectorD<uint64_t, 2> Vec2u;
  114|       |
  115|   132k|  if (prev_data_id < data_id && next_data_id < data_id) {
  ------------------
  |  Branch (115:7): [True: 132k, False: 80]
  |  Branch (115:33): [True: 132k, False: 82]
  ------------------
  116|       |    // Both other corners have available UV coordinates for prediction.
  117|   132k|    const Vec2 n_uv = GetTexCoordForEntryId(next_data_id, data);
  118|   132k|    const Vec2 p_uv = GetTexCoordForEntryId(prev_data_id, data);
  119|   132k|    if (p_uv == n_uv) {
  ------------------
  |  Branch (119:9): [True: 132k, False: 11]
  ------------------
  120|       |      // We cannot do a reliable prediction on degenerated UV triangles.
  121|   132k|      predicted_value_[0] = p_uv[0];
  122|   132k|      predicted_value_[1] = p_uv[1];
  123|   132k|      return true;
  124|   132k|    }
  125|       |
  126|       |    // Get positions at all corners.
  127|     11|    const Vec3 tip_pos = GetPositionForEntryId(data_id);
  128|     11|    const Vec3 next_pos = GetPositionForEntryId(next_data_id);
  129|     11|    const Vec3 prev_pos = GetPositionForEntryId(prev_data_id);
  130|       |    // We use the positions of the above triangle to predict the texture
  131|       |    // coordinate on the tip corner C.
  132|       |    // To convert the triangle into the UV coordinate system we first compute
  133|       |    // position X on the vector |prev_pos - next_pos| that is the projection of
  134|       |    // point C onto vector |prev_pos - next_pos|:
  135|       |    //
  136|       |    //              C
  137|       |    //             /.  \
  138|       |    //            / .     \
  139|       |    //           /  .        \
  140|       |    //          N---X----------P
  141|       |    //
  142|       |    // Where next_pos is point (N), prev_pos is point (P) and tip_pos is the
  143|       |    // position of predicted coordinate (C).
  144|       |    //
  145|     11|    const Vec3 pn = prev_pos - next_pos;
  146|     11|    const uint64_t pn_norm2_squared = pn.SquaredNorm();
  147|     11|    if (pn_norm2_squared != 0) {
  ------------------
  |  Branch (147:9): [True: 11, False: 0]
  ------------------
  148|       |      // Compute the projection of C onto PN by computing dot product of CN with
  149|       |      // PN and normalizing it by length of PN. This gives us a factor |s| where
  150|       |      // |s = PN.Dot(CN) / PN.SquaredNorm2()|. This factor can be used to
  151|       |      // compute X in UV space |X_UV| as |X_UV = N_UV + s * PN_UV|.
  152|     11|      const Vec3 cn = tip_pos - next_pos;
  153|     11|      const int64_t cn_dot_pn = pn.Dot(cn);
  154|       |
  155|     11|      const Vec2 pn_uv = p_uv - n_uv;
  156|       |      // Because we perform all computations with integers, we don't explicitly
  157|       |      // compute the normalized factor |s|, but rather we perform all operations
  158|       |      // over UV vectors in a non-normalized coordinate system scaled with a
  159|       |      // scaling factor |pn_norm2_squared|:
  160|       |      //
  161|       |      //      x_uv = X_UV * PN.Norm2Squared()
  162|       |      //
  163|     11|      const int64_t n_uv_absmax_element =
  164|     11|          std::max(std::abs(n_uv[0]), std::abs(n_uv[1]));
  165|     11|      if (n_uv_absmax_element >
  ------------------
  |  Branch (165:11): [True: 1, False: 10]
  ------------------
  166|     11|          std::numeric_limits<int64_t>::max() / pn_norm2_squared) {
  167|       |        // Return false if the below multiplication would overflow.
  168|      1|        return false;
  169|      1|      }
  170|     10|      const int64_t pn_uv_absmax_element =
  171|     10|          std::max(std::abs(pn_uv[0]), std::abs(pn_uv[1]));
  172|     10|      if (std::abs(cn_dot_pn) >
  ------------------
  |  Branch (172:11): [True: 0, False: 10]
  ------------------
  173|     10|          std::numeric_limits<int64_t>::max() / pn_uv_absmax_element) {
  174|       |        // Return false if squared length calculation would overflow.
  175|      0|        return false;
  176|      0|      }
  177|       |      // Keep the scaled prediction arithmetic in the unsigned domain.
  178|     10|      const Vec2 x_uv = Vec2(Vec2u(n_uv) * pn_norm2_squared +
  179|     10|                             Vec2u(pn_uv) * static_cast<uint64_t>(cn_dot_pn));
  180|     10|      const int64_t pn_absmax_element =
  181|     10|          std::max(std::max(std::abs(pn[0]), std::abs(pn[1])), std::abs(pn[2]));
  182|     10|      if (std::abs(cn_dot_pn) >
  ------------------
  |  Branch (182:11): [True: 0, False: 10]
  ------------------
  183|     10|          std::numeric_limits<int64_t>::max() / pn_absmax_element) {
  184|       |        // Return false if squared length calculation would overflow.
  185|      0|        return false;
  186|      0|      }
  187|       |
  188|       |      // Compute squared length of vector CX in position coordinate system:
  189|     10|      const Vec3 x_pos = next_pos + (cn_dot_pn * pn) / pn_norm2_squared;
  190|     10|      const uint64_t cx_norm2_squared = (tip_pos - x_pos).SquaredNorm();
  191|       |
  192|       |      // Compute vector CX_UV in the uv space by rotating vector PN_UV by 90
  193|       |      // degrees and scaling it with factor CX.Norm2() / PN.Norm2():
  194|       |      //
  195|       |      //     CX_UV = (CX.Norm2() / PN.Norm2()) * Rot(PN_UV)
  196|       |      //
  197|       |      // To preserve precision, we perform all operations in scaled space as
  198|       |      // explained above, so we want the final vector to be:
  199|       |      //
  200|       |      //     cx_uv = CX_UV * PN.Norm2Squared()
  201|       |      //
  202|       |      // We can then rewrite the formula as:
  203|       |      //
  204|       |      //     cx_uv = CX.Norm2() * PN.Norm2() * Rot(PN_UV)
  205|       |      //
  206|     10|      Vec2 cx_uv(pn_uv[1], -pn_uv[0]);  // Rotated PN_UV.
  207|       |      // Compute CX.Norm2() * PN.Norm2()
  208|     10|      const uint64_t norm_squared =
  209|     10|          IntSqrt(cx_norm2_squared * pn_norm2_squared);
  210|       |      // Final cx_uv in the scaled coordinate space.
  211|     10|      cx_uv = cx_uv * norm_squared;
  212|       |
  213|       |      // Predicted uv coordinate is then computed by either adding or
  214|       |      // subtracting CX_UV to/from X_UV.
  215|     10|      Vec2 predicted_uv;
  216|     10|      if (is_encoder_t) {
  ------------------
  |  Branch (216:11): [Folded, False: 10]
  ------------------
  217|       |        // When encoding, compute both possible vectors and determine which one
  218|       |        // results in a better prediction.
  219|       |        // Both vectors need to be transformed back from the scaled space to
  220|       |        // the real UV coordinate space.
  221|      0|        const Vec2 predicted_uv_0((x_uv + cx_uv) / pn_norm2_squared);
  222|      0|        const Vec2 predicted_uv_1((x_uv - cx_uv) / pn_norm2_squared);
  223|      0|        const Vec2 c_uv = GetTexCoordForEntryId(data_id, data);
  224|      0|        if ((c_uv - predicted_uv_0).SquaredNorm() <
  ------------------
  |  Branch (224:13): [True: 0, False: 0]
  ------------------
  225|      0|            (c_uv - predicted_uv_1).SquaredNorm()) {
  226|      0|          predicted_uv = predicted_uv_0;
  227|      0|          orientations_.push_back(true);
  228|      0|        } else {
  229|      0|          predicted_uv = predicted_uv_1;
  230|      0|          orientations_.push_back(false);
  231|      0|        }
  232|     10|      } else {
  233|       |        // When decoding the data, we already know which orientation to use.
  234|     10|        if (orientations_.empty()) {
  ------------------
  |  Branch (234:13): [True: 10, False: 0]
  ------------------
  235|     10|          return false;
  236|     10|        }
  237|      0|        const bool orientation = orientations_.back();
  238|      0|        orientations_.pop_back();
  239|       |        // Perform operations in unsigned type to avoid signed integer overflow.
  240|       |        // Note that the result will be the same (for non-overflowing values).
  241|      0|        if (orientation) {
  ------------------
  |  Branch (241:13): [True: 0, False: 0]
  ------------------
  242|      0|          predicted_uv = Vec2(Vec2u(x_uv) + Vec2u(cx_uv)) / pn_norm2_squared;
  243|      0|        } else {
  244|      0|          predicted_uv = Vec2(Vec2u(x_uv) - Vec2u(cx_uv)) / pn_norm2_squared;
  245|      0|        }
  246|      0|      }
  247|      0|      predicted_value_[0] = static_cast<int>(predicted_uv[0]);
  248|      0|      predicted_value_[1] = static_cast<int>(predicted_uv[1]);
  249|      0|      return true;
  250|     10|    }
  251|     11|  }
  252|       |  // Else we don't have available textures on both corners or the position data
  253|       |  // is invalid. For such cases we can't use positions for predicting the uv
  254|       |  // value and we resort to delta coding.
  255|    162|  int data_offset = 0;
  256|    162|  if (prev_data_id < data_id) {
  ------------------
  |  Branch (256:7): [True: 82, False: 80]
  ------------------
  257|       |    // Use the value on the previous corner as the prediction.
  258|     82|    data_offset = prev_data_id * kNumComponents;
  259|     82|  }
  260|    162|  if (next_data_id < data_id) {
  ------------------
  |  Branch (260:7): [True: 0, False: 162]
  ------------------
  261|       |    // Use the value on the next corner as the prediction.
  262|      0|    data_offset = next_data_id * kNumComponents;
  263|    162|  } else {
  264|       |    // None of the other corners have a valid value. Use the last encoded value
  265|       |    // as the prediction if possible.
  266|    162|    if (data_id > 0) {
  ------------------
  |  Branch (266:9): [True: 127, False: 35]
  ------------------
  267|    127|      data_offset = (data_id - 1) * kNumComponents;
  268|    127|    } else {
  269|       |      // We are encoding the first value. Predict 0.
  270|    105|      for (int i = 0; i < kNumComponents; ++i) {
  ------------------
  |  Branch (270:23): [True: 70, False: 35]
  ------------------
  271|     70|        predicted_value_[i] = 0;
  272|     70|      }
  273|     35|      return true;
  274|     35|    }
  275|    162|  }
  276|    381|  for (int i = 0; i < kNumComponents; ++i) {
  ------------------
  |  Branch (276:19): [True: 254, False: 127]
  ------------------
  277|    254|    predicted_value_[i] = data[data_offset + i];
  278|    254|  }
  279|    127|  return true;
  280|    162|}
_ZNK5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21GetTexCoordForEntryIdEiPKi:
   58|   264k|                                            const DataTypeT* data) const {
   59|   264k|    const int data_offset = entry_id * kNumComponents;
   60|   264k|    return VectorD<int64_t, 2>(data[data_offset], data[data_offset + 1]);
   61|   264k|  }
_ZNK5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21GetPositionForEntryIdEi:
   49|     33|  VectorD<int64_t, 3> GetPositionForEntryId(int entry_id) const {
   50|     33|    const PointIndex point_id = entry_to_point_id_map_[entry_id];
   51|     33|    VectorD<int64_t, 3> pos;
   52|     33|    pos_attribute_->ConvertValue(pos_attribute_->mapped_index(point_id),
   53|     33|                                 &pos[0]);
   54|     33|    return pos;
   55|     33|  }
_ZNK5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEE15predicted_valueEv:
   69|   132k|  const DataTypeT* predicted_value() const { return predicted_value_; }

_ZNK5draco23PredictionSchemeDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEE22GetNumParentAttributesEv:
   58|    104|  int GetNumParentAttributes() const override { return 0; }
_ZN5draco23PredictionSchemeDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEE22AreCorrectionsPositiveEv:
   70|    433|  bool AreCorrectionsPositive() override {
   71|    433|    return transform_.AreCorrectionsPositive();
   72|    433|  }
_ZN5draco23PredictionSchemeDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEE20DecodePredictionDataEPNS_13DecoderBufferE:
   48|     91|  bool DecodePredictionData(DecoderBuffer* buffer) override {
   49|     91|    if (!transform_.DecodeTransformData(buffer)) {
  ------------------
  |  Branch (49:9): [True: 25, False: 66]
  ------------------
   50|     25|      return false;
   51|     25|    }
   52|     66|    return true;
   53|     91|  }
_ZN5draco23PredictionSchemeDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEE9transformEv:
   81|  2.20M|  inline Transform& transform() { return transform_; }
_ZNK5draco23PredictionSchemeDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEE22GetNumParentAttributesEv:
   58|    199|  int GetNumParentAttributes() const override { return 0; }
_ZN5draco23PredictionSchemeDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEE22AreCorrectionsPositiveEv:
   70|    521|  bool AreCorrectionsPositive() override {
   71|    521|    return transform_.AreCorrectionsPositive();
   72|    521|  }
_ZN5draco23PredictionSchemeDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEE20DecodePredictionDataEPNS_13DecoderBufferE:
   48|    188|  bool DecodePredictionData(DecoderBuffer* buffer) override {
   49|    188|    if (!transform_.DecodeTransformData(buffer)) {
  ------------------
  |  Branch (49:9): [True: 35, False: 153]
  ------------------
   50|     35|      return false;
   51|     35|    }
   52|    153|    return true;
   53|    188|  }
_ZN5draco23PredictionSchemeDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEE9transformEv:
   81|   972k|  inline Transform& transform() { return transform_; }
_ZN5draco23PredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEEC2EPKNS_14PointAttributeERKS2_:
   46|  5.17k|      : attribute_(attribute), transform_(transform) {}
_ZNK5draco23PredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEE22GetNumParentAttributesEv:
   58|  3.63k|  int GetNumParentAttributes() const override { return 0; }
_ZN5draco23PredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEE22AreCorrectionsPositiveEv:
   70|  4.95k|  bool AreCorrectionsPositive() override {
   71|  4.95k|    return transform_.AreCorrectionsPositive();
   72|  4.95k|  }
_ZN5draco23PredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEE20DecodePredictionDataEPNS_13DecoderBufferE:
   48|  3.73k|  bool DecodePredictionData(DecoderBuffer* buffer) override {
   49|  3.73k|    if (!transform_.DecodeTransformData(buffer)) {
  ------------------
  |  Branch (49:9): [True: 234, False: 3.49k]
  ------------------
   50|    234|      return false;
   51|    234|    }
   52|  3.49k|    return true;
   53|  3.73k|  }
_ZN5draco23PredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEE9transformEv:
   81|   105M|  inline Transform& transform() { return transform_; }
_ZN5draco23PredictionSchemeDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEEC2EPKNS_14PointAttributeERKS2_:
   46|    448|      : attribute_(attribute), transform_(transform) {}
_ZN5draco23PredictionSchemeDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEEC2EPKNS_14PointAttributeERKS2_:
   46|    537|      : attribute_(attribute), transform_(transform) {}

_ZN5draco32CreatePredictionSchemeForDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIT_T0_EENS3_14default_deleteIS8_EEEENS_22PredictionSchemeMethodEiPKNS_17PointCloudDecoderE:
  187|    448|                                 const PointCloudDecoder* decoder) {
  188|    448|  return CreatePredictionSchemeForDecoder<DataTypeT, TransformT>(
  189|    448|      method, att_id, decoder, TransformT());
  190|    448|}
_ZN5draco32CreatePredictionSchemeForDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIT_T0_EENS3_14default_deleteIS8_EEEENS_22PredictionSchemeMethodEiPKNS_17PointCloudDecoderERKS7_:
  155|    448|                                 const TransformT& transform) {
  156|    448|  if (method == PREDICTION_NONE) {
  ------------------
  |  Branch (156:7): [True: 0, False: 448]
  ------------------
  157|      0|    return nullptr;
  158|      0|  }
  159|    448|  const PointAttribute* const att = decoder->point_cloud()->attribute(att_id);
  160|    448|  if (decoder->GetGeometryType() == TRIANGULAR_MESH) {
  ------------------
  |  Branch (160:7): [True: 400, False: 48]
  ------------------
  161|       |    // Cast the decoder to mesh decoder. This is not necessarily safe if there
  162|       |    // is some other decoder decides to use TRIANGULAR_MESH as the return type,
  163|       |    // but unfortunately there is not nice work around for this without using
  164|       |    // RTTI (double dispatch and similar concepts will not work because of the
  165|       |    // template nature of the prediction schemes).
  166|    400|    const MeshDecoder* const mesh_decoder =
  167|    400|        static_cast<const MeshDecoder*>(decoder);
  168|       |
  169|    400|    auto ret = CreateMeshPredictionScheme<
  170|    400|        MeshDecoder, PredictionSchemeDecoder<DataTypeT, TransformT>,
  171|    400|        MeshPredictionSchemeDecoderFactory<DataTypeT>>(
  172|    400|        mesh_decoder, method, att_id, transform, decoder->bitstream_version());
  173|    400|    if (ret) {
  ------------------
  |  Branch (173:9): [True: 344, False: 56]
  ------------------
  174|    344|      return ret;
  175|    344|    }
  176|       |    // Otherwise try to create another prediction scheme.
  177|    400|  }
  178|       |  // Create delta decoder.
  179|    104|  return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
  180|    104|      new PredictionSchemeDeltaDecoder<DataTypeT, TransformT>(att, transform));
  181|    448|}
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiEclINS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIiT_EENS8_14default_deleteISC_EEEENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKSB_RKT0_t:
  142|    190|      uint16_t bitstream_version) {
  143|    190|    return DispatchFunctor<TransformT, MeshDataT, TransformT::GetType()>()(
  144|    190|        method, attribute, transform, mesh_data, bitstream_version);
  145|    190|  }
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiE15DispatchFunctorINS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEELNS_29PredictionSchemeTransformTypeE2EEclENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKS4_RKS7_t:
  126|    190|        uint16_t bitstream_version) {
  127|    190|      if (method == MESH_PREDICTION_GEOMETRIC_NORMAL) {
  ------------------
  |  Branch (127:11): [True: 176, False: 14]
  ------------------
  128|    176|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
  129|    176|            new MeshPredictionSchemeGeometricNormalDecoder<
  130|    176|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
  131|    176|                                                  mesh_data));
  132|    176|      }
  133|     14|      return nullptr;
  134|    190|    }
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiEclINS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIiT_EENS8_14default_deleteISC_EEEENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKSB_RKT0_t:
  142|    172|      uint16_t bitstream_version) {
  143|    172|    return DispatchFunctor<TransformT, MeshDataT, TransformT::GetType()>()(
  144|    172|        method, attribute, transform, mesh_data, bitstream_version);
  145|    172|  }
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiE15DispatchFunctorINS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEELNS_29PredictionSchemeTransformTypeE2EEclENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKS4_RKS7_t:
  126|    172|        uint16_t bitstream_version) {
  127|    172|      if (method == MESH_PREDICTION_GEOMETRIC_NORMAL) {
  ------------------
  |  Branch (127:11): [True: 168, False: 4]
  ------------------
  128|    168|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
  129|    168|            new MeshPredictionSchemeGeometricNormalDecoder<
  130|    168|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
  131|    168|                                                  mesh_data));
  132|    168|      }
  133|      4|      return nullptr;
  134|    172|    }
_ZN5draco32CreatePredictionSchemeForDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIT_T0_EENS3_14default_deleteIS8_EEEENS_22PredictionSchemeMethodEiPKNS_17PointCloudDecoderE:
  187|    537|                                 const PointCloudDecoder* decoder) {
  188|    537|  return CreatePredictionSchemeForDecoder<DataTypeT, TransformT>(
  189|    537|      method, att_id, decoder, TransformT());
  190|    537|}
_ZN5draco32CreatePredictionSchemeForDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIT_T0_EENS3_14default_deleteIS8_EEEENS_22PredictionSchemeMethodEiPKNS_17PointCloudDecoderERKS7_:
  155|    537|                                 const TransformT& transform) {
  156|    537|  if (method == PREDICTION_NONE) {
  ------------------
  |  Branch (156:7): [True: 0, False: 537]
  ------------------
  157|      0|    return nullptr;
  158|      0|  }
  159|    537|  const PointAttribute* const att = decoder->point_cloud()->attribute(att_id);
  160|    537|  if (decoder->GetGeometryType() == TRIANGULAR_MESH) {
  ------------------
  |  Branch (160:7): [True: 534, False: 3]
  ------------------
  161|       |    // Cast the decoder to mesh decoder. This is not necessarily safe if there
  162|       |    // is some other decoder decides to use TRIANGULAR_MESH as the return type,
  163|       |    // but unfortunately there is not nice work around for this without using
  164|       |    // RTTI (double dispatch and similar concepts will not work because of the
  165|       |    // template nature of the prediction schemes).
  166|    534|    const MeshDecoder* const mesh_decoder =
  167|    534|        static_cast<const MeshDecoder*>(decoder);
  168|       |
  169|    534|    auto ret = CreateMeshPredictionScheme<
  170|    534|        MeshDecoder, PredictionSchemeDecoder<DataTypeT, TransformT>,
  171|    534|        MeshPredictionSchemeDecoderFactory<DataTypeT>>(
  172|    534|        mesh_decoder, method, att_id, transform, decoder->bitstream_version());
  173|    534|    if (ret) {
  ------------------
  |  Branch (173:9): [True: 338, False: 196]
  ------------------
  174|    338|      return ret;
  175|    338|    }
  176|       |    // Otherwise try to create another prediction scheme.
  177|    534|  }
  178|       |  // Create delta decoder.
  179|    199|  return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
  180|    199|      new PredictionSchemeDeltaDecoder<DataTypeT, TransformT>(att, transform));
  181|    537|}
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiEclINS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIiT_EENS8_14default_deleteISC_EEEENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKSB_RKT0_t:
  142|    189|      uint16_t bitstream_version) {
  143|    189|    return DispatchFunctor<TransformT, MeshDataT, TransformT::GetType()>()(
  144|    189|        method, attribute, transform, mesh_data, bitstream_version);
  145|    189|  }
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiE15DispatchFunctorINS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEELNS_29PredictionSchemeTransformTypeE3EEclENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKS4_RKS7_t:
  110|    189|        uint16_t bitstream_version) {
  111|    189|      if (method == MESH_PREDICTION_GEOMETRIC_NORMAL) {
  ------------------
  |  Branch (111:11): [True: 163, False: 26]
  ------------------
  112|    163|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
  113|    163|            new MeshPredictionSchemeGeometricNormalDecoder<
  114|    163|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
  115|    163|                                                  mesh_data));
  116|    163|      }
  117|     26|      return nullptr;
  118|    189|    }
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiEclINS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIiT_EENS8_14default_deleteISC_EEEENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKSB_RKT0_t:
  142|    178|      uint16_t bitstream_version) {
  143|    178|    return DispatchFunctor<TransformT, MeshDataT, TransformT::GetType()>()(
  144|    178|        method, attribute, transform, mesh_data, bitstream_version);
  145|    178|  }
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiE15DispatchFunctorINS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEELNS_29PredictionSchemeTransformTypeE3EEclENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKS4_RKS7_t:
  110|    178|        uint16_t bitstream_version) {
  111|    178|      if (method == MESH_PREDICTION_GEOMETRIC_NORMAL) {
  ------------------
  |  Branch (111:11): [True: 175, False: 3]
  ------------------
  112|    175|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
  113|    175|            new MeshPredictionSchemeGeometricNormalDecoder<
  114|    175|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
  115|    175|                                                  mesh_data));
  116|    175|      }
  117|      3|      return nullptr;
  118|    178|    }
_ZN5draco32CreatePredictionSchemeForDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIT_T0_EENS3_14default_deleteIS8_EEEENS_22PredictionSchemeMethodEiPKNS_17PointCloudDecoderE:
  187|  5.17k|                                 const PointCloudDecoder* decoder) {
  188|  5.17k|  return CreatePredictionSchemeForDecoder<DataTypeT, TransformT>(
  189|  5.17k|      method, att_id, decoder, TransformT());
  190|  5.17k|}
_ZN5draco32CreatePredictionSchemeForDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIT_T0_EENS3_14default_deleteIS8_EEEENS_22PredictionSchemeMethodEiPKNS_17PointCloudDecoderERKS7_:
  155|  5.17k|                                 const TransformT& transform) {
  156|  5.17k|  if (method == PREDICTION_NONE) {
  ------------------
  |  Branch (156:7): [True: 0, False: 5.17k]
  ------------------
  157|      0|    return nullptr;
  158|      0|  }
  159|  5.17k|  const PointAttribute* const att = decoder->point_cloud()->attribute(att_id);
  160|  5.17k|  if (decoder->GetGeometryType() == TRIANGULAR_MESH) {
  ------------------
  |  Branch (160:7): [True: 5.14k, False: 36]
  ------------------
  161|       |    // Cast the decoder to mesh decoder. This is not necessarily safe if there
  162|       |    // is some other decoder decides to use TRIANGULAR_MESH as the return type,
  163|       |    // but unfortunately there is not nice work around for this without using
  164|       |    // RTTI (double dispatch and similar concepts will not work because of the
  165|       |    // template nature of the prediction schemes).
  166|  5.14k|    const MeshDecoder* const mesh_decoder =
  167|  5.14k|        static_cast<const MeshDecoder*>(decoder);
  168|       |
  169|  5.14k|    auto ret = CreateMeshPredictionScheme<
  170|  5.14k|        MeshDecoder, PredictionSchemeDecoder<DataTypeT, TransformT>,
  171|  5.14k|        MeshPredictionSchemeDecoderFactory<DataTypeT>>(
  172|  5.14k|        mesh_decoder, method, att_id, transform, decoder->bitstream_version());
  173|  5.14k|    if (ret) {
  ------------------
  |  Branch (173:9): [True: 4.79k, False: 350]
  ------------------
  174|  4.79k|      return ret;
  175|  4.79k|    }
  176|       |    // Otherwise try to create another prediction scheme.
  177|  5.14k|  }
  178|       |  // Create delta decoder.
  179|    386|  return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
  180|    386|      new PredictionSchemeDeltaDecoder<DataTypeT, TransformT>(att, transform));
  181|  5.17k|}
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiEclINS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIiT_EENS8_14default_deleteISC_EEEENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKSB_RKT0_t:
  142|  2.29k|      uint16_t bitstream_version) {
  143|  2.29k|    return DispatchFunctor<TransformT, MeshDataT, TransformT::GetType()>()(
  144|  2.29k|        method, attribute, transform, mesh_data, bitstream_version);
  145|  2.29k|  }
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiE15DispatchFunctorINS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEELNS_29PredictionSchemeTransformTypeE1EEclENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKS4_RKS7_t:
   52|  2.29k|        uint16_t bitstream_version) {
   53|  2.29k|      if (method == MESH_PREDICTION_PARALLELOGRAM) {
  ------------------
  |  Branch (53:11): [True: 580, False: 1.71k]
  ------------------
   54|    580|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   55|    580|            new MeshPredictionSchemeParallelogramDecoder<DataTypeT, TransformT,
   56|    580|                                                         MeshDataT>(
   57|    580|                attribute, transform, mesh_data));
   58|    580|      }
   59|  1.71k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   60|  1.71k|      else if (method == MESH_PREDICTION_MULTI_PARALLELOGRAM) {
  ------------------
  |  Branch (60:16): [True: 479, False: 1.23k]
  ------------------
   61|    479|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   62|    479|            new MeshPredictionSchemeMultiParallelogramDecoder<
   63|    479|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
   64|    479|                                                  mesh_data));
   65|    479|      }
   66|  1.23k|#endif
   67|  1.23k|      else if (method == MESH_PREDICTION_CONSTRAINED_MULTI_PARALLELOGRAM) {
  ------------------
  |  Branch (67:16): [True: 503, False: 731]
  ------------------
   68|    503|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   69|    503|            new MeshPredictionSchemeConstrainedMultiParallelogramDecoder<
   70|    503|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
   71|    503|                                                  mesh_data));
   72|    503|      }
   73|    731|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   74|    731|      else if (method == MESH_PREDICTION_TEX_COORDS_DEPRECATED) {
  ------------------
  |  Branch (74:16): [True: 194, False: 537]
  ------------------
   75|    194|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   76|    194|            new MeshPredictionSchemeTexCoordsDecoder<DataTypeT, TransformT,
   77|    194|                                                     MeshDataT>(
   78|    194|                attribute, transform, mesh_data, bitstream_version));
   79|    194|      }
   80|    537|#endif
   81|    537|      else if (method == MESH_PREDICTION_TEX_COORDS_PORTABLE) {
  ------------------
  |  Branch (81:16): [True: 163, False: 374]
  ------------------
   82|    163|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   83|    163|            new MeshPredictionSchemeTexCoordsPortableDecoder<
   84|    163|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
   85|    163|                                                  mesh_data));
   86|    163|      }
   87|    374|#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
   88|    374|      else if (method == MESH_PREDICTION_GEOMETRIC_NORMAL) {
  ------------------
  |  Branch (88:16): [True: 374, False: 0]
  ------------------
   89|    374|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   90|    374|            new MeshPredictionSchemeGeometricNormalDecoder<
   91|    374|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
   92|    374|                                                  mesh_data));
   93|    374|      }
   94|      0|#endif
   95|      0|      return nullptr;
   96|  2.29k|    }
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiEclINS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIiT_EENS8_14default_deleteISC_EEEENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKSB_RKT0_t:
  142|  2.50k|      uint16_t bitstream_version) {
  143|  2.50k|    return DispatchFunctor<TransformT, MeshDataT, TransformT::GetType()>()(
  144|  2.50k|        method, attribute, transform, mesh_data, bitstream_version);
  145|  2.50k|  }
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiE15DispatchFunctorINS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEELNS_29PredictionSchemeTransformTypeE1EEclENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKS4_RKS7_t:
   52|  2.50k|        uint16_t bitstream_version) {
   53|  2.50k|      if (method == MESH_PREDICTION_PARALLELOGRAM) {
  ------------------
  |  Branch (53:11): [True: 564, False: 1.93k]
  ------------------
   54|    564|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   55|    564|            new MeshPredictionSchemeParallelogramDecoder<DataTypeT, TransformT,
   56|    564|                                                         MeshDataT>(
   57|    564|                attribute, transform, mesh_data));
   58|    564|      }
   59|  1.93k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   60|  1.93k|      else if (method == MESH_PREDICTION_MULTI_PARALLELOGRAM) {
  ------------------
  |  Branch (60:16): [True: 539, False: 1.39k]
  ------------------
   61|    539|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   62|    539|            new MeshPredictionSchemeMultiParallelogramDecoder<
   63|    539|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
   64|    539|                                                  mesh_data));
   65|    539|      }
   66|  1.39k|#endif
   67|  1.39k|      else if (method == MESH_PREDICTION_CONSTRAINED_MULTI_PARALLELOGRAM) {
  ------------------
  |  Branch (67:16): [True: 580, False: 817]
  ------------------
   68|    580|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   69|    580|            new MeshPredictionSchemeConstrainedMultiParallelogramDecoder<
   70|    580|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
   71|    580|                                                  mesh_data));
   72|    580|      }
   73|    817|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   74|    817|      else if (method == MESH_PREDICTION_TEX_COORDS_DEPRECATED) {
  ------------------
  |  Branch (74:16): [True: 213, False: 604]
  ------------------
   75|    213|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   76|    213|            new MeshPredictionSchemeTexCoordsDecoder<DataTypeT, TransformT,
   77|    213|                                                     MeshDataT>(
   78|    213|                attribute, transform, mesh_data, bitstream_version));
   79|    213|      }
   80|    604|#endif
   81|    604|      else if (method == MESH_PREDICTION_TEX_COORDS_PORTABLE) {
  ------------------
  |  Branch (81:16): [True: 93, False: 511]
  ------------------
   82|     93|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   83|     93|            new MeshPredictionSchemeTexCoordsPortableDecoder<
   84|     93|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
   85|     93|                                                  mesh_data));
   86|     93|      }
   87|    511|#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
   88|    511|      else if (method == MESH_PREDICTION_GEOMETRIC_NORMAL) {
  ------------------
  |  Branch (88:16): [True: 511, False: 0]
  ------------------
   89|    511|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   90|    511|            new MeshPredictionSchemeGeometricNormalDecoder<
   91|    511|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
   92|    511|                                                  mesh_data));
   93|    511|      }
   94|      0|#endif
   95|      0|      return nullptr;
   96|  2.50k|    }

_ZN5draco32PredictionSchemeDecoderInterface24SetMaxNumPredictedValuesEi:
   38|  5.65k|  virtual void SetMaxNumPredictedValues(int32_t num) {};

_ZN5draco28PredictionSchemeDeltaDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   49|     66|    const PointIndex*) {
   50|     66|  this->transform().Init(num_components);
   51|       |  // Decode the original value for the first element.
   52|     66|  std::unique_ptr<DataTypeT[]> zero_vals(new DataTypeT[num_components]());
   53|     66|  this->transform().ComputeOriginalValue(zero_vals.get(), in_corr, out_data);
   54|       |
   55|       |  // Decode data from the front using D(i) = D(i) + D(i - 1).
   56|   976k|  for (int i = num_components; i < size; i += num_components) {
  ------------------
  |  Branch (56:32): [True: 976k, False: 66]
  ------------------
   57|   976k|    this->transform().ComputeOriginalValue(out_data + i - num_components,
   58|   976k|                                           in_corr + i, out_data + i);
   59|   976k|  }
   60|     66|  return true;
   61|     66|}
_ZN5draco28PredictionSchemeDeltaDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   49|    153|    const PointIndex*) {
   50|    153|  this->transform().Init(num_components);
   51|       |  // Decode the original value for the first element.
   52|    153|  std::unique_ptr<DataTypeT[]> zero_vals(new DataTypeT[num_components]());
   53|    153|  this->transform().ComputeOriginalValue(zero_vals.get(), in_corr, out_data);
   54|       |
   55|       |  // Decode data from the front using D(i) = D(i) + D(i - 1).
   56|   322k|  for (int i = num_components; i < size; i += num_components) {
  ------------------
  |  Branch (56:32): [True: 322k, False: 153]
  ------------------
   57|   322k|    this->transform().ComputeOriginalValue(out_data + i - num_components,
   58|   322k|                                           in_corr + i, out_data + i);
   59|   322k|  }
   60|    153|  return true;
   61|    153|}
_ZN5draco28PredictionSchemeDeltaDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEEC2EPKNS_14PointAttributeERKS2_:
   35|    386|      : PredictionSchemeDecoder<DataTypeT, TransformT>(attribute, transform) {}
_ZN5draco28PredictionSchemeDeltaDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   49|    299|    const PointIndex*) {
   50|    299|  this->transform().Init(num_components);
   51|       |  // Decode the original value for the first element.
   52|    299|  std::unique_ptr<DataTypeT[]> zero_vals(new DataTypeT[num_components]());
   53|    299|  this->transform().ComputeOriginalValue(zero_vals.get(), in_corr, out_data);
   54|       |
   55|       |  // Decode data from the front using D(i) = D(i) + D(i - 1).
   56|  93.6M|  for (int i = num_components; i < size; i += num_components) {
  ------------------
  |  Branch (56:32): [True: 93.6M, False: 299]
  ------------------
   57|  93.6M|    this->transform().ComputeOriginalValue(out_data + i - num_components,
   58|  93.6M|                                           in_corr + i, out_data + i);
   59|  93.6M|  }
   60|    299|  return true;
   61|    299|}
_ZN5draco28PredictionSchemeDeltaDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEEC2EPKNS_14PointAttributeERKS2_:
   35|    104|      : PredictionSchemeDecoder<DataTypeT, TransformT>(attribute, transform) {}
_ZN5draco28PredictionSchemeDeltaDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEEC2EPKNS_14PointAttributeERKS2_:
   35|    199|      : PredictionSchemeDecoder<DataTypeT, TransformT>(attribute, transform) {}

_ZN5draco26CreateMeshPredictionSchemeINS_11MeshDecoderENS_23PredictionSchemeDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEEENS_34MeshPredictionSchemeDecoderFactoryIiEEEENSt3__110unique_ptrIT0_NS8_14default_deleteISA_EEEEPKT_NS_22PredictionSchemeMethodEiRKNSA_9TransformEt:
   37|    400|    uint16_t bitstream_version) {
   38|    400|  const PointAttribute* const att = source->point_cloud()->attribute(att_id);
   39|    400|  if (source->GetGeometryType() == TRIANGULAR_MESH &&
  ------------------
  |  Branch (39:7): [True: 400, False: 0]
  ------------------
   40|    400|      (method == MESH_PREDICTION_PARALLELOGRAM ||
  ------------------
  |  Branch (40:8): [True: 11, False: 389]
  ------------------
   41|    389|       method == MESH_PREDICTION_MULTI_PARALLELOGRAM ||
  ------------------
  |  Branch (41:8): [True: 4, False: 385]
  ------------------
   42|    385|       method == MESH_PREDICTION_CONSTRAINED_MULTI_PARALLELOGRAM ||
  ------------------
  |  Branch (42:8): [True: 2, False: 383]
  ------------------
   43|    383|       method == MESH_PREDICTION_TEX_COORDS_PORTABLE ||
  ------------------
  |  Branch (43:8): [True: 4, False: 379]
  ------------------
   44|    379|       method == MESH_PREDICTION_GEOMETRIC_NORMAL ||
  ------------------
  |  Branch (44:8): [True: 368, False: 11]
  ------------------
   45|    391|       method == MESH_PREDICTION_TEX_COORDS_DEPRECATED)) {
  ------------------
  |  Branch (45:8): [True: 2, False: 9]
  ------------------
   46|    391|    const CornerTable* const ct = source->GetCornerTable();
   47|    391|    const MeshAttributeIndicesEncodingData* const encoding_data =
   48|    391|        source->GetAttributeEncodingData(att_id);
   49|    391|    if (ct == nullptr || encoding_data == nullptr) {
  ------------------
  |  Branch (49:9): [True: 29, False: 362]
  |  Branch (49:26): [True: 0, False: 362]
  ------------------
   50|       |      // No connectivity data found.
   51|     29|      return nullptr;
   52|     29|    }
   53|       |    // Connectivity data exists.
   54|    362|    const MeshAttributeCornerTable* const att_ct =
   55|    362|        source->GetAttributeCornerTable(att_id);
   56|    362|    if (att_ct != nullptr) {
  ------------------
  |  Branch (56:9): [True: 190, False: 172]
  ------------------
   57|    190|      typedef MeshPredictionSchemeData<MeshAttributeCornerTable> MeshData;
   58|    190|      MeshData md;
   59|    190|      md.Set(source->mesh(), att_ct,
   60|    190|             &encoding_data->encoded_attribute_value_index_to_corner_map,
   61|    190|             &encoding_data->vertex_to_encoded_attribute_value_index_map);
   62|    190|      MeshPredictionSchemeFactoryT factory;
   63|    190|      auto ret = factory(method, att, transform, md, bitstream_version);
   64|    190|      if (ret) {
  ------------------
  |  Branch (64:11): [True: 176, False: 14]
  ------------------
   65|    176|        return ret;
   66|    176|      }
   67|    190|    } else {
   68|    172|      typedef MeshPredictionSchemeData<CornerTable> MeshData;
   69|    172|      MeshData md;
   70|    172|      md.Set(source->mesh(), ct,
   71|    172|             &encoding_data->encoded_attribute_value_index_to_corner_map,
   72|    172|             &encoding_data->vertex_to_encoded_attribute_value_index_map);
   73|    172|      MeshPredictionSchemeFactoryT factory;
   74|    172|      auto ret = factory(method, att, transform, md, bitstream_version);
   75|    172|      if (ret) {
  ------------------
  |  Branch (75:11): [True: 168, False: 4]
  ------------------
   76|    168|        return ret;
   77|    168|      }
   78|    172|    }
   79|    362|  }
   80|     27|  return nullptr;
   81|    400|}
_ZN5draco26CreateMeshPredictionSchemeINS_11MeshDecoderENS_23PredictionSchemeDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEEENS_34MeshPredictionSchemeDecoderFactoryIiEEEENSt3__110unique_ptrIT0_NS8_14default_deleteISA_EEEEPKT_NS_22PredictionSchemeMethodEiRKNSA_9TransformEt:
   37|    534|    uint16_t bitstream_version) {
   38|    534|  const PointAttribute* const att = source->point_cloud()->attribute(att_id);
   39|    534|  if (source->GetGeometryType() == TRIANGULAR_MESH &&
  ------------------
  |  Branch (39:7): [True: 534, False: 0]
  ------------------
   40|    534|      (method == MESH_PREDICTION_PARALLELOGRAM ||
  ------------------
  |  Branch (40:8): [True: 26, False: 508]
  ------------------
   41|    508|       method == MESH_PREDICTION_MULTI_PARALLELOGRAM ||
  ------------------
  |  Branch (41:8): [True: 2, False: 506]
  ------------------
   42|    506|       method == MESH_PREDICTION_CONSTRAINED_MULTI_PARALLELOGRAM ||
  ------------------
  |  Branch (42:8): [True: 3, False: 503]
  ------------------
   43|    503|       method == MESH_PREDICTION_TEX_COORDS_PORTABLE ||
  ------------------
  |  Branch (43:8): [True: 2, False: 501]
  ------------------
   44|    501|       method == MESH_PREDICTION_GEOMETRIC_NORMAL ||
  ------------------
  |  Branch (44:8): [True: 482, False: 19]
  ------------------
   45|    516|       method == MESH_PREDICTION_TEX_COORDS_DEPRECATED)) {
  ------------------
  |  Branch (45:8): [True: 1, False: 18]
  ------------------
   46|    516|    const CornerTable* const ct = source->GetCornerTable();
   47|    516|    const MeshAttributeIndicesEncodingData* const encoding_data =
   48|    516|        source->GetAttributeEncodingData(att_id);
   49|    516|    if (ct == nullptr || encoding_data == nullptr) {
  ------------------
  |  Branch (49:9): [True: 149, False: 367]
  |  Branch (49:26): [True: 0, False: 367]
  ------------------
   50|       |      // No connectivity data found.
   51|    149|      return nullptr;
   52|    149|    }
   53|       |    // Connectivity data exists.
   54|    367|    const MeshAttributeCornerTable* const att_ct =
   55|    367|        source->GetAttributeCornerTable(att_id);
   56|    367|    if (att_ct != nullptr) {
  ------------------
  |  Branch (56:9): [True: 189, False: 178]
  ------------------
   57|    189|      typedef MeshPredictionSchemeData<MeshAttributeCornerTable> MeshData;
   58|    189|      MeshData md;
   59|    189|      md.Set(source->mesh(), att_ct,
   60|    189|             &encoding_data->encoded_attribute_value_index_to_corner_map,
   61|    189|             &encoding_data->vertex_to_encoded_attribute_value_index_map);
   62|    189|      MeshPredictionSchemeFactoryT factory;
   63|    189|      auto ret = factory(method, att, transform, md, bitstream_version);
   64|    189|      if (ret) {
  ------------------
  |  Branch (64:11): [True: 163, False: 26]
  ------------------
   65|    163|        return ret;
   66|    163|      }
   67|    189|    } else {
   68|    178|      typedef MeshPredictionSchemeData<CornerTable> MeshData;
   69|    178|      MeshData md;
   70|    178|      md.Set(source->mesh(), ct,
   71|    178|             &encoding_data->encoded_attribute_value_index_to_corner_map,
   72|    178|             &encoding_data->vertex_to_encoded_attribute_value_index_map);
   73|    178|      MeshPredictionSchemeFactoryT factory;
   74|    178|      auto ret = factory(method, att, transform, md, bitstream_version);
   75|    178|      if (ret) {
  ------------------
  |  Branch (75:11): [True: 175, False: 3]
  ------------------
   76|    175|        return ret;
   77|    175|      }
   78|    178|    }
   79|    367|  }
   80|     47|  return nullptr;
   81|    534|}
_ZN5draco26CreateMeshPredictionSchemeINS_11MeshDecoderENS_23PredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEEENS_34MeshPredictionSchemeDecoderFactoryIiEEEENSt3__110unique_ptrIT0_NS8_14default_deleteISA_EEEEPKT_NS_22PredictionSchemeMethodEiRKNSA_9TransformEt:
   37|  5.14k|    uint16_t bitstream_version) {
   38|  5.14k|  const PointAttribute* const att = source->point_cloud()->attribute(att_id);
   39|  5.14k|  if (source->GetGeometryType() == TRIANGULAR_MESH &&
  ------------------
  |  Branch (39:7): [True: 5.14k, False: 0]
  ------------------
   40|  5.14k|      (method == MESH_PREDICTION_PARALLELOGRAM ||
  ------------------
  |  Branch (40:8): [True: 1.29k, False: 3.85k]
  ------------------
   41|  3.85k|       method == MESH_PREDICTION_MULTI_PARALLELOGRAM ||
  ------------------
  |  Branch (41:8): [True: 1.02k, False: 2.82k]
  ------------------
   42|  2.82k|       method == MESH_PREDICTION_CONSTRAINED_MULTI_PARALLELOGRAM ||
  ------------------
  |  Branch (42:8): [True: 1.08k, False: 1.74k]
  ------------------
   43|  1.74k|       method == MESH_PREDICTION_TEX_COORDS_PORTABLE ||
  ------------------
  |  Branch (43:8): [True: 257, False: 1.48k]
  ------------------
   44|  1.48k|       method == MESH_PREDICTION_GEOMETRIC_NORMAL ||
  ------------------
  |  Branch (44:8): [True: 896, False: 588]
  ------------------
   45|  4.96k|       method == MESH_PREDICTION_TEX_COORDS_DEPRECATED)) {
  ------------------
  |  Branch (45:8): [True: 408, False: 180]
  ------------------
   46|  4.96k|    const CornerTable* const ct = source->GetCornerTable();
   47|  4.96k|    const MeshAttributeIndicesEncodingData* const encoding_data =
   48|  4.96k|        source->GetAttributeEncodingData(att_id);
   49|  4.96k|    if (ct == nullptr || encoding_data == nullptr) {
  ------------------
  |  Branch (49:9): [True: 170, False: 4.79k]
  |  Branch (49:26): [True: 0, False: 4.79k]
  ------------------
   50|       |      // No connectivity data found.
   51|    170|      return nullptr;
   52|    170|    }
   53|       |    // Connectivity data exists.
   54|  4.79k|    const MeshAttributeCornerTable* const att_ct =
   55|  4.79k|        source->GetAttributeCornerTable(att_id);
   56|  4.79k|    if (att_ct != nullptr) {
  ------------------
  |  Branch (56:9): [True: 2.29k, False: 2.50k]
  ------------------
   57|  2.29k|      typedef MeshPredictionSchemeData<MeshAttributeCornerTable> MeshData;
   58|  2.29k|      MeshData md;
   59|  2.29k|      md.Set(source->mesh(), att_ct,
   60|  2.29k|             &encoding_data->encoded_attribute_value_index_to_corner_map,
   61|  2.29k|             &encoding_data->vertex_to_encoded_attribute_value_index_map);
   62|  2.29k|      MeshPredictionSchemeFactoryT factory;
   63|  2.29k|      auto ret = factory(method, att, transform, md, bitstream_version);
   64|  2.29k|      if (ret) {
  ------------------
  |  Branch (64:11): [True: 2.29k, False: 0]
  ------------------
   65|  2.29k|        return ret;
   66|  2.29k|      }
   67|  2.50k|    } else {
   68|  2.50k|      typedef MeshPredictionSchemeData<CornerTable> MeshData;
   69|  2.50k|      MeshData md;
   70|  2.50k|      md.Set(source->mesh(), ct,
   71|  2.50k|             &encoding_data->encoded_attribute_value_index_to_corner_map,
   72|  2.50k|             &encoding_data->vertex_to_encoded_attribute_value_index_map);
   73|  2.50k|      MeshPredictionSchemeFactoryT factory;
   74|  2.50k|      auto ret = factory(method, att, transform, md, bitstream_version);
   75|  2.50k|      if (ret) {
  ------------------
  |  Branch (75:11): [True: 2.50k, False: 0]
  ------------------
   76|  2.50k|        return ret;
   77|  2.50k|      }
   78|  2.50k|    }
   79|  4.79k|  }
   80|    180|  return nullptr;
   81|  5.14k|}

_ZN5draco25PredictionSchemeInterfaceD2Ev:
   29|  6.16k|  virtual ~PredictionSchemeInterface() = default;

_ZN5draco62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiE19DecodeTransformDataEPNS_13DecoderBufferE:
   46|    521|  bool DecodeTransformData(DecoderBuffer* buffer) {
   47|    521|    DataTypeT max_quantized_value, center_value;
   48|    521|    if (!buffer->Decode(&max_quantized_value)) {
  ------------------
  |  Branch (48:9): [True: 9, False: 512]
  ------------------
   49|      9|      return false;
   50|      9|    }
   51|    512|    if (!buffer->Decode(&center_value)) {
  ------------------
  |  Branch (51:9): [True: 8, False: 504]
  ------------------
   52|      8|      return false;
   53|      8|    }
   54|    504|    (void)center_value;
   55|    504|    if (!this->set_max_quantized_value(max_quantized_value)) {
  ------------------
  |  Branch (55:9): [True: 29, False: 475]
  ------------------
   56|     29|      return false;
   57|     29|    }
   58|       |    // Account for reading wrong values, e.g., due to fuzzing.
   59|    475|    if (this->quantization_bits() < 2) {
  ------------------
  |  Branch (59:9): [True: 0, False: 475]
  ------------------
   60|      0|      return false;
   61|      0|    }
   62|    475|    if (this->quantization_bits() > 30) {
  ------------------
  |  Branch (62:9): [True: 0, False: 475]
  ------------------
   63|      0|      return false;
   64|      0|    }
   65|    475|    return true;
   66|    475|  }
_ZNK5draco62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiE20ComputeOriginalValueEPKiS3_Pi:
   70|   971k|                                   DataType* out_orig_vals) const {
   71|   971k|    DRACO_DCHECK_LE(pred_vals[0], 2 * this->center_value());
   72|   971k|    DRACO_DCHECK_LE(pred_vals[1], 2 * this->center_value());
   73|   971k|    DRACO_DCHECK_LE(corr_vals[0], 2 * this->center_value());
   74|   971k|    DRACO_DCHECK_LE(corr_vals[1], 2 * this->center_value());
   75|       |
   76|   971k|    DRACO_DCHECK_LE(0, pred_vals[0]);
   77|   971k|    DRACO_DCHECK_LE(0, pred_vals[1]);
   78|   971k|    DRACO_DCHECK_LE(0, corr_vals[0]);
   79|   971k|    DRACO_DCHECK_LE(0, corr_vals[1]);
   80|       |
   81|   971k|    const Point2 pred = Point2(pred_vals[0], pred_vals[1]);
   82|   971k|    const Point2 corr = Point2(corr_vals[0], corr_vals[1]);
   83|   971k|    const Point2 orig = ComputeOriginalValue(pred, corr);
   84|       |
   85|   971k|    out_orig_vals[0] = orig[0];
   86|   971k|    out_orig_vals[1] = orig[1];
   87|   971k|  }
_ZNK5draco62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiE20ComputeOriginalValueENS_7VectorDIiLi2EEES3_:
   90|   971k|  Point2 ComputeOriginalValue(Point2 pred, Point2 corr) const {
   91|   971k|    const Point2 t(this->center_value(), this->center_value());
   92|   971k|    pred = pred - t;
   93|   971k|    const bool pred_is_in_diamond = this->IsInDiamond(pred[0], pred[1]);
   94|   971k|    if (!pred_is_in_diamond) {
  ------------------
  |  Branch (94:9): [True: 887k, False: 84.2k]
  ------------------
   95|   887k|      this->InvertDiamond(&pred[0], &pred[1]);
   96|   887k|    }
   97|   971k|    const bool pred_is_in_bottom_left = this->IsInBottomLeft(pred);
   98|   971k|    const int32_t rotation_count = this->GetRotationCount(pred);
   99|   971k|    if (!pred_is_in_bottom_left) {
  ------------------
  |  Branch (99:9): [True: 308k, False: 662k]
  ------------------
  100|   308k|      pred = this->RotatePoint(pred, rotation_count);
  101|   308k|    }
  102|   971k|    Point2 orig(this->ModMax(AddAsUnsigned(pred[0], corr[0])),
  103|   971k|                this->ModMax(AddAsUnsigned(pred[1], corr[1])));
  104|   971k|    if (!pred_is_in_bottom_left) {
  ------------------
  |  Branch (104:9): [True: 308k, False: 662k]
  ------------------
  105|   308k|      const int32_t reverse_rotation_count = (4 - rotation_count) % 4;
  106|   308k|      orig = this->RotatePoint(orig, reverse_rotation_count);
  107|   308k|    }
  108|   971k|    if (!pred_is_in_diamond) {
  ------------------
  |  Branch (108:9): [True: 887k, False: 84.2k]
  ------------------
  109|   887k|      this->InvertDiamond(&orig[0], &orig[1]);
  110|   887k|    }
  111|   971k|    orig = orig + t;
  112|   971k|    return orig;
  113|   971k|  }
_ZN5draco62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiE4InitEi:
   44|    153|  void Init(int num_components) {}
_ZN5draco62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEC2Ev:
   41|    537|  PredictionSchemeNormalOctahedronCanonicalizedDecodingTransform() {}

_ZNK5draco58PredictionSchemeNormalOctahedronCanonicalizedTransformBaseIiE14IsInBottomLeftERKNS_7VectorDIiLi2EEE:
   92|   971k|  bool IsInBottomLeft(const Point2& p) const {
   93|   971k|    if (p[0] == 0 && p[1] == 0) {
  ------------------
  |  Branch (93:9): [True: 665k, False: 305k]
  |  Branch (93:22): [True: 589k, False: 76.6k]
  ------------------
   94|   589k|      return true;
   95|   589k|    }
   96|   382k|    return (p[0] < 0 && p[1] <= 0);
  ------------------
  |  Branch (96:13): [True: 97.5k, False: 285k]
  |  Branch (96:25): [True: 73.7k, False: 23.7k]
  ------------------
   97|   971k|  }
_ZNK5draco58PredictionSchemeNormalOctahedronCanonicalizedTransformBaseIiE16GetRotationCountENS_7VectorDIiLi2EEE:
   50|   971k|  int32_t GetRotationCount(Point2 pred) const {
   51|   971k|    const DataType sign_x = pred[0];
   52|   971k|    const DataType sign_y = pred[1];
   53|       |
   54|   971k|    int32_t rotation_count = 0;
   55|   971k|    if (sign_x == 0) {
  ------------------
  |  Branch (55:9): [True: 665k, False: 305k]
  ------------------
   56|   665k|      if (sign_y == 0) {
  ------------------
  |  Branch (56:11): [True: 589k, False: 76.6k]
  ------------------
   57|   589k|        rotation_count = 0;
   58|   589k|      } else if (sign_y > 0) {
  ------------------
  |  Branch (58:18): [True: 29.8k, False: 46.7k]
  ------------------
   59|  29.8k|        rotation_count = 3;
   60|  46.7k|      } else {
   61|  46.7k|        rotation_count = 1;
   62|  46.7k|      }
   63|   665k|    } else if (sign_x > 0) {
  ------------------
  |  Branch (63:16): [True: 208k, False: 97.5k]
  ------------------
   64|   208k|      if (sign_y >= 0) {
  ------------------
  |  Branch (64:11): [True: 140k, False: 68.3k]
  ------------------
   65|   140k|        rotation_count = 2;
   66|   140k|      } else {
   67|  68.3k|        rotation_count = 1;
   68|  68.3k|      }
   69|   208k|    } else {
   70|  97.5k|      if (sign_y <= 0) {
  ------------------
  |  Branch (70:11): [True: 73.7k, False: 23.7k]
  ------------------
   71|  73.7k|        rotation_count = 0;
   72|  73.7k|      } else {
   73|  23.7k|        rotation_count = 3;
   74|  23.7k|      }
   75|  97.5k|    }
   76|   971k|    return rotation_count;
   77|   971k|  }
_ZNK5draco58PredictionSchemeNormalOctahedronCanonicalizedTransformBaseIiE11RotatePointENS_7VectorDIiLi2EEEi:
   79|   617k|  Point2 RotatePoint(Point2 p, int32_t rotation_count) const {
   80|   617k|    switch (rotation_count) {
   81|   168k|      case 1:
  ------------------
  |  Branch (81:7): [True: 168k, False: 448k]
  ------------------
   82|   168k|        return Point2(p[1], -p[0]);
   83|   280k|      case 2:
  ------------------
  |  Branch (83:7): [True: 280k, False: 337k]
  ------------------
   84|   280k|        return Point2(-p[0], -p[1]);
   85|   168k|      case 3:
  ------------------
  |  Branch (85:7): [True: 168k, False: 448k]
  ------------------
   86|   168k|        return Point2(-p[1], p[0]);
   87|      0|      default:
  ------------------
  |  Branch (87:7): [True: 0, False: 617k]
  ------------------
   88|      0|        return p;
   89|   617k|    }
   90|   617k|  }
_ZN5draco58PredictionSchemeNormalOctahedronCanonicalizedTransformBaseIiEC2Ev:
   40|    537|  PredictionSchemeNormalOctahedronCanonicalizedTransformBase() : Base() {}

_ZN5draco49PredictionSchemeNormalOctahedronDecodingTransformIiE19DecodeTransformDataEPNS_13DecoderBufferE:
   45|    433|  bool DecodeTransformData(DecoderBuffer* buffer) {
   46|    433|    DataTypeT max_quantized_value, center_value;
   47|    433|    if (!buffer->Decode(&max_quantized_value)) {
  ------------------
  |  Branch (47:9): [True: 6, False: 427]
  ------------------
   48|      6|      return false;
   49|      6|    }
   50|    427|    if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    427|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (50:9): [True: 110, False: 317]
  ------------------
   51|    110|      if (!buffer->Decode(&center_value)) {
  ------------------
  |  Branch (51:11): [True: 7, False: 103]
  ------------------
   52|      7|        return false;
   53|      7|      }
   54|    110|    }
   55|    420|    (void)center_value;
   56|    420|    return this->set_max_quantized_value(max_quantized_value);
   57|    427|  }
_ZNK5draco49PredictionSchemeNormalOctahedronDecodingTransformIiE20ComputeOriginalValueEPKiS3_Pi:
   61|  2.20M|                                   DataType* out_orig_vals) const {
   62|  2.20M|    DRACO_DCHECK_LE(pred_vals[0], 2 * this->center_value());
   63|  2.20M|    DRACO_DCHECK_LE(pred_vals[1], 2 * this->center_value());
   64|  2.20M|    DRACO_DCHECK_LE(corr_vals[0], 2 * this->center_value());
   65|  2.20M|    DRACO_DCHECK_LE(corr_vals[1], 2 * this->center_value());
   66|       |
   67|  2.20M|    DRACO_DCHECK_LE(0, pred_vals[0]);
   68|  2.20M|    DRACO_DCHECK_LE(0, pred_vals[1]);
   69|  2.20M|    DRACO_DCHECK_LE(0, corr_vals[0]);
   70|  2.20M|    DRACO_DCHECK_LE(0, corr_vals[1]);
   71|       |
   72|  2.20M|    const Point2 pred = Point2(pred_vals[0], pred_vals[1]);
   73|  2.20M|    const Point2 corr = Point2(corr_vals[0], corr_vals[1]);
   74|  2.20M|    const Point2 orig = ComputeOriginalValue(pred, corr);
   75|       |
   76|  2.20M|    out_orig_vals[0] = orig[0];
   77|  2.20M|    out_orig_vals[1] = orig[1];
   78|  2.20M|  }
_ZNK5draco49PredictionSchemeNormalOctahedronDecodingTransformIiE20ComputeOriginalValueENS_7VectorDIiLi2EEERKS3_:
   81|  2.20M|  Point2 ComputeOriginalValue(Point2 pred, const Point2& corr) const {
   82|  2.20M|    const Point2 t(this->center_value(), this->center_value());
   83|  2.20M|    typedef typename std::make_unsigned<DataTypeT>::type UnsignedDataTypeT;
   84|  2.20M|    typedef VectorD<UnsignedDataTypeT, 2> Point2u;
   85|       |
   86|       |    // Perform the addition in unsigned type to avoid signed integer overflow.
   87|       |    // Note that the result will be the same (for non-overflowing values).
   88|  2.20M|    pred = Point2(Point2u(pred) - Point2u(t));
   89|       |
   90|  2.20M|    const bool pred_is_in_diamond = this->IsInDiamond(pred[0], pred[1]);
   91|  2.20M|    if (!pred_is_in_diamond) {
  ------------------
  |  Branch (91:9): [True: 1.81M, False: 392k]
  ------------------
   92|  1.81M|      this->InvertDiamond(&pred[0], &pred[1]);
   93|  1.81M|    }
   94|       |
   95|       |    // Perform the addition in unsigned type to avoid signed integer overflow.
   96|       |    // Note that the result will be the same (for non-overflowing values).
   97|  2.20M|    Point2 orig(Point2u(pred) + Point2u(corr));
   98|       |
   99|  2.20M|    orig[0] = this->ModMax(orig[0]);
  100|  2.20M|    orig[1] = this->ModMax(orig[1]);
  101|  2.20M|    if (!pred_is_in_diamond) {
  ------------------
  |  Branch (101:9): [True: 1.81M, False: 392k]
  ------------------
  102|  1.81M|      this->InvertDiamond(&orig[0], &orig[1]);
  103|  1.81M|    }
  104|       |
  105|       |    // Perform the addition in unsigned type to avoid signed integer overflow.
  106|       |    // Note that the result will be the same (for non-overflowing values).
  107|  2.20M|    orig = Point2(Point2u(orig) + Point2u(t));
  108|  2.20M|    return orig;
  109|  2.20M|  }
_ZN5draco49PredictionSchemeNormalOctahedronDecodingTransformIiE4InitEi:
   44|     66|  void Init(int num_components) {}
_ZN5draco49PredictionSchemeNormalOctahedronDecodingTransformIiEC2Ev:
   41|    448|  PredictionSchemeNormalOctahedronDecodingTransform() {}

_ZNK5draco45PredictionSchemeNormalOctahedronTransformBaseIiE22AreCorrectionsPositiveEv:
   49|    954|  bool AreCorrectionsPositive() const { return true; }
_ZN5draco45PredictionSchemeNormalOctahedronTransformBaseIiE23set_max_quantized_valueEi:
   62|    924|  inline bool set_max_quantized_value(DataTypeT max_quantized_value) {
   63|    924|    if (max_quantized_value % 2 == 0) {
  ------------------
  |  Branch (63:9): [True: 15, False: 909]
  ------------------
   64|     15|      return false;
   65|     15|    }
   66|    909|    int q = MostSignificantBit(max_quantized_value) + 1;
   67|    909|    return octahedron_tool_box_.SetQuantizationBits(q);
   68|    924|  }
_ZNK5draco45PredictionSchemeNormalOctahedronTransformBaseIiE17quantization_bitsEv:
   57|  1.56k|  inline int32_t quantization_bits() const {
   58|  1.56k|    return octahedron_tool_box_.quantization_bits();
   59|  1.56k|  }
_ZNK5draco45PredictionSchemeNormalOctahedronTransformBaseIiE12center_valueEv:
   54|  6.36M|  inline DataTypeT center_value() const {
   55|  6.36M|    return octahedron_tool_box_.center_value();
   56|  6.36M|  }
_ZNK5draco45PredictionSchemeNormalOctahedronTransformBaseIiE11IsInDiamondEii:
   70|  3.18M|  bool IsInDiamond(DataTypeT s, DataTypeT t) const {
   71|  3.18M|    return octahedron_tool_box_.IsInDiamond(s, t);
   72|  3.18M|  }
_ZNK5draco45PredictionSchemeNormalOctahedronTransformBaseIiE13InvertDiamondEPiS2_:
   73|  5.40M|  void InvertDiamond(DataTypeT* s, DataTypeT* t) const {
   74|  5.40M|    return octahedron_tool_box_.InvertDiamond(s, t);
   75|  5.40M|  }
_ZNK5draco45PredictionSchemeNormalOctahedronTransformBaseIiE6ModMaxEi:
   77|  6.36M|  int32_t ModMax(int32_t x) const { return octahedron_tool_box_.ModMax(x); }
_ZN5draco45PredictionSchemeNormalOctahedronTransformBaseIiEC2Ev:
   37|    985|  PredictionSchemeNormalOctahedronTransformBase() {}

_ZN5draco37PredictionSchemeWrapDecodingTransformIiiE19DecodeTransformDataEPNS_13DecoderBufferE:
   65|  4.60k|  bool DecodeTransformData(DecoderBuffer* buffer) {
   66|  4.60k|    DataTypeT min_value, max_value;
   67|  4.60k|    if (!buffer->Decode(&min_value)) {
  ------------------
  |  Branch (67:9): [True: 51, False: 4.54k]
  ------------------
   68|     51|      return false;
   69|     51|    }
   70|  4.54k|    if (!buffer->Decode(&max_value)) {
  ------------------
  |  Branch (70:9): [True: 46, False: 4.50k]
  ------------------
   71|     46|      return false;
   72|     46|    }
   73|  4.50k|    if (min_value > max_value) {
  ------------------
  |  Branch (73:9): [True: 155, False: 4.34k]
  ------------------
   74|    155|      return false;
   75|    155|    }
   76|  4.34k|    this->set_min_value(min_value);
   77|  4.34k|    this->set_max_value(max_value);
   78|  4.34k|    if (!this->InitCorrectionBounds()) {
  ------------------
  |  Branch (78:9): [True: 16, False: 4.33k]
  ------------------
   79|     16|      return false;
   80|     16|    }
   81|  4.33k|    return true;
   82|  4.34k|  }
_ZNK5draco37PredictionSchemeWrapDecodingTransformIiiE20ComputeOriginalValueEPKiS3_Pi:
   38|   105M|                                   DataTypeT* out_original_vals) const {
   39|       |    // For now we assume both |DataTypeT| and |CorrTypeT| are equal.
   40|   105M|    static_assert(std::is_same<DataTypeT, CorrTypeT>::value,
   41|   105M|                  "Predictions and corrections must have the same type.");
   42|       |
   43|       |    // The only valid implementation right now is for int32_t.
   44|   105M|    static_assert(std::is_same<DataTypeT, int32_t>::value,
   45|   105M|                  "Only int32_t is supported for predicted values.");
   46|       |
   47|   105M|    predicted_vals = this->ClampPredictedValue(predicted_vals);
   48|       |
   49|       |    // The sum is computed in int64_t, where it is exact. The encoder keeps each
   50|       |    // correction within half of the span, so the sum lies at most one span
   51|       |    // outside [min, max] and a single wrap gives the original value. Malformed
   52|       |    // corrections cannot overflow int64_t either.
   53|   797M|    for (int i = 0; i < this->num_components(); ++i) {
  ------------------
  |  Branch (53:21): [True: 692M, False: 105M]
  ------------------
   54|   692M|      int64_t value = static_cast<int64_t>(predicted_vals[i]) +
   55|   692M|                      static_cast<int64_t>(corr_vals[i]);
   56|   692M|      if (value > this->max_value()) {
  ------------------
  |  Branch (56:11): [True: 150k, False: 692M]
  ------------------
   57|   150k|        value -= this->max_dif();
   58|   692M|      } else if (value < this->min_value()) {
  ------------------
  |  Branch (58:18): [True: 1.12M, False: 691M]
  ------------------
   59|  1.12M|        value += this->max_dif();
   60|  1.12M|      }
   61|   692M|      out_original_vals[i] = static_cast<DataTypeT>(value);
   62|   692M|    }
   63|   105M|  }
_ZN5draco37PredictionSchemeWrapDecodingTransformIiiEC2Ev:
   32|  5.17k|  PredictionSchemeWrapDecodingTransform() {}

_ZNK5draco33PredictionSchemeWrapTransformBaseIiE22AreCorrectionsPositiveEv:
   60|  4.95k|  bool AreCorrectionsPositive() const { return false; }
_ZN5draco33PredictionSchemeWrapTransformBaseIiE13set_min_valueERKi:
  100|  4.34k|  inline void set_min_value(const DataTypeT& v) { min_value_ = v; }
_ZN5draco33PredictionSchemeWrapTransformBaseIiE13set_max_valueERKi:
  102|  4.34k|  inline void set_max_value(const DataTypeT& v) { max_value_ = v; }
_ZN5draco33PredictionSchemeWrapTransformBaseIiE20InitCorrectionBoundsEv:
   83|  4.34k|  bool InitCorrectionBounds() {
   84|  4.34k|    const int64_t dif =
   85|  4.34k|        static_cast<int64_t>(max_value_) - static_cast<int64_t>(min_value_);
   86|  4.34k|    if (dif < 0 || dif >= std::numeric_limits<DataTypeT>::max()) {
  ------------------
  |  Branch (86:9): [True: 0, False: 4.34k]
  |  Branch (86:20): [True: 16, False: 4.33k]
  ------------------
   87|     16|      return false;
   88|     16|    }
   89|  4.33k|    max_dif_ = 1 + static_cast<DataTypeT>(dif);
   90|  4.33k|    max_correction_ = max_dif_ / 2;
   91|  4.33k|    min_correction_ = -max_correction_;
   92|  4.33k|    if ((max_dif_ & 1) == 0) {
  ------------------
  |  Branch (92:9): [True: 2.03k, False: 2.29k]
  ------------------
   93|  2.03k|      max_correction_ -= 1;
   94|  2.03k|    }
   95|  4.33k|    return true;
   96|  4.34k|  }
_ZN5draco33PredictionSchemeWrapTransformBaseIiE4InitEi:
   55|  3.48k|  void Init(int num_components) {
   56|  3.48k|    num_components_ = num_components;
   57|  3.48k|    clamped_value_.resize(num_components);
   58|  3.48k|  }
_ZNK5draco33PredictionSchemeWrapTransformBaseIiE19ClampPredictedValueEPKi:
   63|   105M|      const DataTypeT* predicted_val) const {
   64|   797M|    for (int i = 0; i < this->num_components(); ++i) {
  ------------------
  |  Branch (64:21): [True: 692M, False: 105M]
  ------------------
   65|   692M|      if (predicted_val[i] > max_value_) {
  ------------------
  |  Branch (65:11): [True: 529k, False: 691M]
  ------------------
   66|   529k|        clamped_value_[i] = max_value_;
   67|   691M|      } else if (predicted_val[i] < min_value_) {
  ------------------
  |  Branch (67:18): [True: 5.72M, False: 686M]
  ------------------
   68|  5.72M|        clamped_value_[i] = min_value_;
   69|   686M|      } else {
   70|   686M|        clamped_value_[i] = predicted_val[i];
   71|   686M|      }
   72|   692M|    }
   73|   105M|    return clamped_value_.data();
   74|   105M|  }
_ZNK5draco33PredictionSchemeWrapTransformBaseIiE14num_componentsEv:
   98|  1.59G|  inline int num_components() const { return num_components_; }
_ZNK5draco33PredictionSchemeWrapTransformBaseIiE9max_valueEv:
  101|   692M|  inline DataTypeT max_value() const { return max_value_; }
_ZNK5draco33PredictionSchemeWrapTransformBaseIiE7max_difEv:
  103|  1.27M|  inline DataTypeT max_dif() const { return max_dif_; }
_ZNK5draco33PredictionSchemeWrapTransformBaseIiE9min_valueEv:
   99|   692M|  inline DataTypeT min_value() const { return min_value_; }
_ZNK5draco33PredictionSchemeWrapTransformBaseIiE17quantization_bitsEv:
   77|    790|  int quantization_bits() const {
   78|    790|    DRACO_DCHECK(false);
   79|    790|    return -1;
   80|    790|  }
_ZN5draco33PredictionSchemeWrapTransformBaseIiEC2Ev:
   44|  5.17k|      : num_components_(0),
   45|  5.17k|        min_value_(0),
   46|  5.17k|        max_value_(0),
   47|  5.17k|        max_dif_(0),
   48|  5.17k|        max_correction_(0),
   49|  5.17k|        min_correction_(0) {}

_ZN5draco26SequentialAttributeDecoderC2Ev:
   20|  20.4k|    : decoder_(nullptr), attribute_(nullptr), attribute_id_(-1) {}
_ZN5draco26SequentialAttributeDecoder4InitEPNS_17PointCloudDecoderEi:
   23|  20.4k|                                      int attribute_id) {
   24|  20.4k|  decoder_ = decoder;
   25|  20.4k|  attribute_ = decoder->point_cloud()->attribute(attribute_id);
   26|  20.4k|  attribute_id_ = attribute_id;
   27|  20.4k|  return true;
   28|  20.4k|}
_ZN5draco26SequentialAttributeDecoder23DecodePortableAttributeERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
   38|  11.2k|    const std::vector<PointIndex>& point_ids, DecoderBuffer* in_buffer) {
   39|  11.2k|  if (attribute_->num_components() <= 0 ||
  ------------------
  |  Branch (39:7): [True: 0, False: 11.2k]
  ------------------
   40|  11.2k|      !attribute_->Reset(point_ids.size())) {
  ------------------
  |  Branch (40:7): [True: 0, False: 11.2k]
  ------------------
   41|      0|    return false;
   42|      0|  }
   43|  11.2k|  if (!DecodeValues(point_ids, in_buffer)) {
  ------------------
  |  Branch (43:7): [True: 2.15k, False: 9.07k]
  ------------------
   44|  2.15k|    return false;
   45|  2.15k|  }
   46|  9.07k|  return true;
   47|  11.2k|}
_ZN5draco26SequentialAttributeDecoder35DecodeDataNeededByPortableTransformERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
   50|  4.03k|    const std::vector<PointIndex>& point_ids, DecoderBuffer* in_buffer) {
   51|       |  // Default implementation does not apply any transform.
   52|  4.03k|  return true;
   53|  4.03k|}
_ZN5draco26SequentialAttributeDecoder34TransformAttributeToOriginalFormatERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEE:
   56|    455|    const std::vector<PointIndex>& point_ids) {
   57|       |  // Default implementation does not apply any transform.
   58|    455|  return true;
   59|    455|}
_ZN5draco26SequentialAttributeDecoder20GetPortableAttributeEv:
   61|  7.80k|const PointAttribute* SequentialAttributeDecoder::GetPortableAttribute() {
   62|       |  // If needed, copy point to attribute value index mapping from the final
   63|       |  // attribute to the portable attribute.
   64|  7.80k|  if (!attribute_->is_mapping_identity() && portable_attribute_ &&
  ------------------
  |  Branch (64:7): [True: 6.77k, False: 1.03k]
  |  Branch (64:45): [True: 6.35k, False: 419]
  ------------------
   65|  6.35k|      portable_attribute_->is_mapping_identity()) {
  ------------------
  |  Branch (65:7): [True: 4.62k, False: 1.72k]
  ------------------
   66|  4.62k|    portable_attribute_->SetExplicitMapping(attribute_->indices_map_size());
   67|  4.62k|    for (PointIndex i(0);
   68|  36.6M|         i < static_cast<uint32_t>(attribute_->indices_map_size()); ++i) {
  ------------------
  |  Branch (68:10): [True: 36.6M, False: 4.62k]
  ------------------
   69|  36.6M|      portable_attribute_->SetPointMapEntry(i, attribute_->mapped_index(i));
   70|  36.6M|    }
   71|  4.62k|  }
   72|  7.80k|  return portable_attribute_.get();
   73|  7.80k|}
_ZN5draco26SequentialAttributeDecoder20InitPredictionSchemeEPNS_25PredictionSchemeInterfaceE:
   76|  6.16k|    PredictionSchemeInterface* ps) {
   77|  8.36k|  for (int i = 0; i < ps->GetNumParentAttributes(); ++i) {
  ------------------
  |  Branch (77:19): [True: 2.23k, False: 6.13k]
  ------------------
   78|  2.23k|    const int att_id = decoder_->point_cloud()->GetNamedAttributeId(
   79|  2.23k|        ps->GetParentAttributeType(i));
   80|  2.23k|    if (att_id == -1) {
  ------------------
  |  Branch (80:9): [True: 5, False: 2.22k]
  ------------------
   81|      5|      return false;  // Requested attribute does not exist.
   82|      5|    }
   83|  2.22k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   84|  2.22k|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  2.22k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (84:9): [True: 0, False: 2.22k]
  ------------------
   85|      0|      if (!ps->SetParentAttribute(decoder_->point_cloud()->attribute(att_id))) {
  ------------------
  |  Branch (85:11): [True: 0, False: 0]
  ------------------
   86|      0|        return false;
   87|      0|      }
   88|      0|    } else
   89|  2.22k|#endif
   90|  2.22k|    {
   91|  2.22k|      const PointAttribute* const pa = decoder_->GetPortableAttribute(att_id);
   92|  2.22k|      if (pa == nullptr || !ps->SetParentAttribute(pa)) {
  ------------------
  |  Branch (92:11): [True: 4, False: 2.22k]
  |  Branch (92:28): [True: 18, False: 2.20k]
  ------------------
   93|     22|        return false;
   94|     22|      }
   95|  2.22k|    }
   96|  2.22k|  }
   97|  6.13k|  return true;
   98|  6.16k|}
_ZN5draco26SequentialAttributeDecoder12DecodeValuesERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
  101|  1.32k|    const std::vector<PointIndex>& point_ids, DecoderBuffer* in_buffer) {
  102|  1.32k|  const int32_t num_values = static_cast<uint32_t>(point_ids.size());
  103|  1.32k|  const int entry_size = static_cast<int>(attribute_->byte_stride());
  104|  1.32k|  std::unique_ptr<uint8_t[]> value_data_ptr(new uint8_t[entry_size]);
  105|  1.32k|  uint8_t* const value_data = value_data_ptr.get();
  106|  1.32k|  int out_byte_pos = 0;
  107|       |  // Decode raw attribute values in their original format.
  108|  9.00k|  for (int i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (108:19): [True: 7.80k, False: 1.19k]
  ------------------
  109|  7.80k|    if (!in_buffer->Decode(value_data, entry_size)) {
  ------------------
  |  Branch (109:9): [True: 126, False: 7.68k]
  ------------------
  110|    126|      return false;
  111|    126|    }
  112|  7.68k|    attribute_->buffer()->Write(out_byte_pos, value_data, entry_size);
  113|  7.68k|    out_byte_pos += entry_size;
  114|  7.68k|  }
  115|  1.19k|  return true;
  116|  1.32k|}

_ZNK5draco26SequentialAttributeDecoder9attributeEv:
   53|  8.49k|  const PointAttribute* attribute() const { return attribute_; }
_ZN5draco26SequentialAttributeDecoder9attributeEv:
   54|   248M|  PointAttribute* attribute() { return attribute_; }
_ZNK5draco26SequentialAttributeDecoder12attribute_idEv:
   55|  6.16k|  int attribute_id() const { return attribute_id_; }
_ZNK5draco26SequentialAttributeDecoder7decoderEv:
   56|  29.1k|  PointCloudDecoder* decoder() const { return decoder_; }
_ZN5draco26SequentialAttributeDecoder20SetPortableAttributeENSt3__110unique_ptrINS_14PointAttributeENS1_14default_deleteIS3_EEEE:
   69|  9.52k|  void SetPortableAttribute(std::unique_ptr<PointAttribute> att) {
   70|  9.52k|    portable_attribute_ = std::move(att);
   71|  9.52k|  }
_ZN5draco26SequentialAttributeDecoder18portable_attributeEv:
   73|  31.8k|  PointAttribute* portable_attribute() { return portable_attribute_.get(); }
_ZN5draco26SequentialAttributeDecoderD2Ev:
   29|  20.4k|  virtual ~SequentialAttributeDecoder() = default;

_ZN5draco37SequentialAttributeDecodersControllerC2ENSt3__110unique_ptrINS_15PointsSequencerENS1_14default_deleteIS3_EEEE:
   26|  27.5k|    : sequencer_(std::move(sequencer)) {}
_ZN5draco37SequentialAttributeDecodersController27DecodeAttributesDecoderDataEPNS_13DecoderBufferE:
   29|  5.69k|    DecoderBuffer* buffer) {
   30|  5.69k|  if (!AttributesDecoder::DecodeAttributesDecoderData(buffer)) {
  ------------------
  |  Branch (30:7): [True: 284, False: 5.40k]
  ------------------
   31|    284|    return false;
   32|    284|  }
   33|       |  // Decode unique ids of all sequential encoders and create them.
   34|  5.40k|  const int32_t num_attributes = GetNumAttributes();
   35|  5.40k|  sequential_decoders_.resize(num_attributes);
   36|  25.8k|  for (int i = 0; i < num_attributes; ++i) {
  ------------------
  |  Branch (36:19): [True: 20.4k, False: 5.36k]
  ------------------
   37|  20.4k|    uint8_t decoder_type;
   38|  20.4k|    if (!buffer->Decode(&decoder_type)) {
  ------------------
  |  Branch (38:9): [True: 14, False: 20.4k]
  ------------------
   39|     14|      return false;
   40|     14|    }
   41|       |    // Create the decoder from the id.
   42|  20.4k|    sequential_decoders_[i] = CreateSequentialDecoder(decoder_type);
   43|  20.4k|    if (!sequential_decoders_[i]) {
  ------------------
  |  Branch (43:9): [True: 20, False: 20.4k]
  ------------------
   44|     20|      return false;
   45|     20|    }
   46|  20.4k|    if (!sequential_decoders_[i]->Init(GetDecoder(), GetAttributeId(i))) {
  ------------------
  |  Branch (46:9): [True: 9, False: 20.4k]
  ------------------
   47|      9|      return false;
   48|      9|    }
   49|  20.4k|  }
   50|  5.36k|  return true;
   51|  5.40k|}
_ZN5draco37SequentialAttributeDecodersController16DecodeAttributesEPNS_13DecoderBufferE:
   54|  5.01k|    DecoderBuffer* buffer) {
   55|  5.01k|  if (!sequencer_ || !sequencer_->GenerateSequence(&point_ids_)) {
  ------------------
  |  Branch (55:7): [True: 0, False: 5.01k]
  |  Branch (55:22): [True: 2, False: 5.01k]
  ------------------
   56|      2|    return false;
   57|      2|  }
   58|       |  // Initialize point to attribute value mapping for all decoded attributes.
   59|  5.01k|  const int32_t num_attributes = GetNumAttributes();
   60|  24.1k|  for (int i = 0; i < num_attributes; ++i) {
  ------------------
  |  Branch (60:19): [True: 19.1k, False: 5.01k]
  ------------------
   61|  19.1k|    PointAttribute* const pa =
   62|  19.1k|        GetDecoder()->point_cloud()->attribute(GetAttributeId(i));
   63|  19.1k|    if (!sequencer_->UpdatePointToAttributeIndexMapping(pa)) {
  ------------------
  |  Branch (63:9): [True: 1, False: 19.1k]
  ------------------
   64|      1|      return false;
   65|      1|    }
   66|  19.1k|  }
   67|  5.01k|  return AttributesDecoder::DecodeAttributes(buffer);
   68|  5.01k|}
_ZN5draco37SequentialAttributeDecodersController24DecodePortableAttributesEPNS_13DecoderBufferE:
   71|  5.01k|    DecoderBuffer* in_buffer) {
   72|  5.01k|  const int32_t num_attributes = GetNumAttributes();
   73|  14.0k|  for (int i = 0; i < num_attributes; ++i) {
  ------------------
  |  Branch (73:19): [True: 11.2k, False: 2.85k]
  ------------------
   74|  11.2k|    if (!sequential_decoders_[i]->DecodePortableAttribute(point_ids_,
  ------------------
  |  Branch (74:9): [True: 2.15k, False: 9.07k]
  ------------------
   75|  11.2k|                                                          in_buffer)) {
   76|  2.15k|      return false;
   77|  2.15k|    }
   78|  11.2k|  }
   79|  2.85k|  return true;
   80|  5.01k|}
_ZN5draco37SequentialAttributeDecodersController36DecodeDataNeededByPortableTransformsEPNS_13DecoderBufferE:
   83|  2.85k|    DecodeDataNeededByPortableTransforms(DecoderBuffer* in_buffer) {
   84|  2.85k|  const int32_t num_attributes = GetNumAttributes();
   85|  7.40k|  for (int i = 0; i < num_attributes; ++i) {
  ------------------
  |  Branch (85:19): [True: 5.03k, False: 2.37k]
  ------------------
   86|  5.03k|    if (!sequential_decoders_[i]->DecodeDataNeededByPortableTransform(
  ------------------
  |  Branch (86:9): [True: 481, False: 4.55k]
  ------------------
   87|  5.03k|            point_ids_, in_buffer)) {
   88|    481|      return false;
   89|    481|    }
   90|  5.03k|  }
   91|  2.37k|  return true;
   92|  2.85k|}
_ZN5draco37SequentialAttributeDecodersController35TransformAttributesToOriginalFormatEv:
   95|  2.37k|    TransformAttributesToOriginalFormat() {
   96|  2.37k|  const int32_t num_attributes = GetNumAttributes();
   97|  5.99k|  for (int i = 0; i < num_attributes; ++i) {
  ------------------
  |  Branch (97:19): [True: 4.10k, False: 1.88k]
  ------------------
   98|       |    // Check whether the attribute transform should be skipped.
   99|  4.10k|    if (GetDecoder()->options()) {
  ------------------
  |  Branch (99:9): [True: 4.10k, False: 0]
  ------------------
  100|  4.10k|      const PointAttribute* const attribute =
  101|  4.10k|          sequential_decoders_[i]->attribute();
  102|  4.10k|      const PointAttribute* const portable_attribute =
  103|  4.10k|          sequential_decoders_[i]->GetPortableAttribute();
  104|  4.10k|      if (portable_attribute &&
  ------------------
  |  Branch (104:11): [True: 3.64k, False: 455]
  |  Branch (104:11): [True: 1.22k, False: 2.88k]
  ------------------
  105|  3.64k|          GetDecoder()->options()->GetAttributeBool(
  ------------------
  |  Branch (105:11): [True: 1.22k, False: 2.42k]
  ------------------
  106|  3.64k|              attribute->attribute_type(), "skip_attribute_transform", false)) {
  107|       |        // Attribute transform should not be performed. In this case, we replace
  108|       |        // the output geometry attribute with the portable attribute.
  109|       |        // TODO(ostava): We can potentially avoid this copy by introducing a new
  110|       |        // mechanism that would allow to use the final attributes as portable
  111|       |        // attributes for predictors that may need them.
  112|  1.22k|        sequential_decoders_[i]->attribute()->CopyFrom(*portable_attribute);
  113|  1.22k|        continue;
  114|  1.22k|      }
  115|  4.10k|    }
  116|  2.88k|    if (!sequential_decoders_[i]->TransformAttributeToOriginalFormat(
  ------------------
  |  Branch (116:9): [True: 485, False: 2.39k]
  ------------------
  117|  2.88k|            point_ids_)) {
  118|    485|      return false;
  119|    485|    }
  120|  2.88k|  }
  121|  1.88k|  return true;
  122|  2.37k|}
_ZN5draco37SequentialAttributeDecodersController23CreateSequentialDecoderEh:
  126|  20.4k|    uint8_t decoder_type) {
  127|  20.4k|  switch (decoder_type) {
  128|  3.63k|    case SEQUENTIAL_ATTRIBUTE_ENCODER_GENERIC:
  ------------------
  |  Branch (128:5): [True: 3.63k, False: 16.8k]
  ------------------
  129|  3.63k|      return std::unique_ptr<SequentialAttributeDecoder>(
  130|  3.63k|          new SequentialAttributeDecoder());
  131|  15.4k|    case SEQUENTIAL_ATTRIBUTE_ENCODER_INTEGER:
  ------------------
  |  Branch (131:5): [True: 15.4k, False: 5.02k]
  ------------------
  132|  15.4k|      return std::unique_ptr<SequentialAttributeDecoder>(
  133|  15.4k|          new SequentialIntegerAttributeDecoder());
  134|    257|    case SEQUENTIAL_ATTRIBUTE_ENCODER_QUANTIZATION:
  ------------------
  |  Branch (134:5): [True: 257, False: 20.2k]
  ------------------
  135|    257|      return std::unique_ptr<SequentialAttributeDecoder>(
  136|    257|          new SequentialQuantizationAttributeDecoder());
  137|      0|#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
  138|  1.11k|    case SEQUENTIAL_ATTRIBUTE_ENCODER_NORMALS:
  ------------------
  |  Branch (138:5): [True: 1.11k, False: 19.3k]
  ------------------
  139|  1.11k|      return std::unique_ptr<SequentialNormalAttributeDecoder>(
  140|  1.11k|          new SequentialNormalAttributeDecoder());
  141|      0|#endif
  142|     20|    default:
  ------------------
  |  Branch (142:5): [True: 20, False: 20.4k]
  ------------------
  143|     20|      break;
  144|  20.4k|  }
  145|       |  // Unknown or unsupported decoder type.
  146|     20|  return nullptr;
  147|  20.4k|}

_ZN5draco37SequentialAttributeDecodersController20GetPortableAttributeEi:
   38|  2.22k|      int32_t point_attribute_id) override {
   39|  2.22k|    const int32_t loc_id = GetLocalIdForPointAttribute(point_attribute_id);
   40|  2.22k|    if (loc_id < 0) {
  ------------------
  |  Branch (40:9): [True: 0, False: 2.22k]
  ------------------
   41|      0|      return nullptr;
   42|      0|    }
   43|  2.22k|    return sequential_decoders_[loc_id]->GetPortableAttribute();
   44|  2.22k|  }

_ZN5draco33SequentialIntegerAttributeDecoderC2Ev:
   23|  16.8k|SequentialIntegerAttributeDecoder::SequentialIntegerAttributeDecoder() =
_ZN5draco33SequentialIntegerAttributeDecoder4InitEPNS_17PointCloudDecoderEi:
   27|  16.8k|                                             int attribute_id) {
   28|  16.8k|  if (!SequentialAttributeDecoder::Init(decoder, attribute_id)) {
  ------------------
  |  Branch (28:7): [True: 0, False: 16.8k]
  ------------------
   29|      0|    return false;
   30|      0|  }
   31|  16.8k|  return true;
   32|  16.8k|}
_ZN5draco33SequentialIntegerAttributeDecoder34TransformAttributeToOriginalFormatERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEE:
   35|  2.42k|    const std::vector<PointIndex>& point_ids) {
   36|  2.42k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   37|  2.42k|  if (decoder() &&
  ------------------
  |  Branch (37:7): [True: 2.42k, False: 0]
  ------------------
   38|  2.42k|      decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  2.42k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (38:7): [True: 0, False: 2.42k]
  ------------------
   39|      0|    return true;  // Don't revert the transform here for older files.
   40|      0|  }
   41|  2.42k|#endif
   42|  2.42k|  return StoreValues(static_cast<uint32_t>(point_ids.size()));
   43|  2.42k|}
_ZN5draco33SequentialIntegerAttributeDecoder12DecodeValuesERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
   46|  9.91k|    const std::vector<PointIndex>& point_ids, DecoderBuffer* in_buffer) {
   47|       |  // Decode prediction scheme.
   48|  9.91k|  int8_t prediction_scheme_method;
   49|  9.91k|  if (!in_buffer->Decode(&prediction_scheme_method)) {
  ------------------
  |  Branch (49:7): [True: 50, False: 9.86k]
  ------------------
   50|     50|    return false;
   51|     50|  }
   52|       |  // Check that decoded prediction scheme method type is valid.
   53|  9.86k|  if (prediction_scheme_method < PREDICTION_NONE ||
  ------------------
  |  Branch (53:7): [True: 60, False: 9.80k]
  ------------------
   54|  9.80k|      prediction_scheme_method >= NUM_PREDICTION_SCHEMES) {
  ------------------
  |  Branch (54:7): [True: 110, False: 9.69k]
  ------------------
   55|    170|    return false;
   56|    170|  }
   57|  9.69k|  if (prediction_scheme_method != PREDICTION_NONE) {
  ------------------
  |  Branch (57:7): [True: 9.68k, False: 6]
  ------------------
   58|  9.68k|    int8_t prediction_transform_type;
   59|  9.68k|    if (!in_buffer->Decode(&prediction_transform_type)) {
  ------------------
  |  Branch (59:9): [True: 36, False: 9.65k]
  ------------------
   60|     36|      return false;
   61|     36|    }
   62|       |    // Check that decoded prediction scheme transform type is valid.
   63|  9.65k|    if (prediction_transform_type < PREDICTION_TRANSFORM_NONE ||
  ------------------
  |  Branch (63:9): [True: 15, False: 9.63k]
  ------------------
   64|  9.63k|        prediction_transform_type >= NUM_PREDICTION_SCHEME_TRANSFORM_TYPES) {
  ------------------
  |  Branch (64:9): [True: 93, False: 9.54k]
  ------------------
   65|    108|      return false;
   66|    108|    }
   67|  9.54k|    prediction_scheme_ = CreateIntPredictionScheme(
   68|  9.54k|        static_cast<PredictionSchemeMethod>(prediction_scheme_method),
   69|  9.54k|        static_cast<PredictionSchemeTransformType>(prediction_transform_type));
   70|  9.54k|  }
   71|       |
   72|  9.55k|  if (prediction_scheme_) {
  ------------------
  |  Branch (72:7): [True: 6.16k, False: 3.38k]
  ------------------
   73|  6.16k|    if (!InitPredictionScheme(prediction_scheme_.get())) {
  ------------------
  |  Branch (73:9): [True: 27, False: 6.13k]
  ------------------
   74|     27|      return false;
   75|     27|    }
   76|  6.16k|  }
   77|       |
   78|  9.52k|  if (!DecodeIntegerValues(point_ids, in_buffer)) {
  ------------------
  |  Branch (78:7): [True: 1.64k, False: 7.88k]
  ------------------
   79|  1.64k|    return false;
   80|  1.64k|  }
   81|       |
   82|  7.88k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   83|  7.88k|  const int32_t num_values = static_cast<uint32_t>(point_ids.size());
   84|  7.88k|  if (decoder() &&
  ------------------
  |  Branch (84:7): [True: 7.88k, False: 0]
  ------------------
   85|  7.88k|      decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  7.88k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (85:7): [True: 0, False: 7.88k]
  ------------------
   86|       |    // For older files, revert the transform right after we decode the data.
   87|      0|    if (!StoreValues(num_values)) {
  ------------------
  |  Branch (87:9): [True: 0, False: 0]
  ------------------
   88|      0|      return false;
   89|      0|    }
   90|      0|  }
   91|  7.88k|#endif
   92|  7.88k|  return true;
   93|  7.88k|}
_ZN5draco33SequentialIntegerAttributeDecoder25CreateIntPredictionSchemeENS_22PredictionSchemeMethodENS_29PredictionSchemeTransformTypeE:
   98|  8.50k|    PredictionSchemeTransformType transform_type) {
   99|  8.50k|  if (transform_type != PREDICTION_TRANSFORM_WRAP) {
  ------------------
  |  Branch (99:7): [True: 3.32k, False: 5.17k]
  ------------------
  100|  3.32k|    return nullptr;  // For now we support only wrap transform.
  101|  3.32k|  }
  102|  5.17k|  return CreatePredictionSchemeForDecoder<
  103|  5.17k|      int32_t, PredictionSchemeWrapDecodingTransform<int32_t>>(
  104|  5.17k|      method, attribute_id(), decoder());
  105|  8.50k|}
_ZN5draco33SequentialIntegerAttributeDecoder19DecodeIntegerValuesERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
  108|  9.52k|    const std::vector<PointIndex>& point_ids, DecoderBuffer* in_buffer) {
  109|  9.52k|  const int num_components = GetNumValueComponents();
  110|  9.52k|  if (num_components <= 0) {
  ------------------
  |  Branch (110:7): [True: 0, False: 9.52k]
  ------------------
  111|      0|    return false;
  112|      0|  }
  113|  9.52k|  const size_t num_entries = point_ids.size();
  114|  9.52k|  const size_t num_values = num_entries * num_components;
  115|  9.52k|  PreparePortableAttribute(static_cast<int>(num_entries), num_components);
  116|  9.52k|  int32_t* const portable_attribute_data = GetPortableAttributeData();
  117|  9.52k|  if (portable_attribute_data == nullptr) {
  ------------------
  |  Branch (117:7): [True: 11, False: 9.51k]
  ------------------
  118|     11|    return false;
  119|     11|  }
  120|  9.51k|  uint8_t compressed;
  121|  9.51k|  if (!in_buffer->Decode(&compressed)) {
  ------------------
  |  Branch (121:7): [True: 35, False: 9.47k]
  ------------------
  122|     35|    return false;
  123|     35|  }
  124|  9.47k|  if (compressed > 0) {
  ------------------
  |  Branch (124:7): [True: 675, False: 8.80k]
  ------------------
  125|       |    // Decode compressed values.
  126|    675|    if (!DecodeSymbols(static_cast<uint32_t>(num_values), num_components,
  ------------------
  |  Branch (126:9): [True: 205, False: 470]
  ------------------
  127|    675|                       in_buffer,
  128|    675|                       reinterpret_cast<uint32_t*>(portable_attribute_data))) {
  129|    205|      return false;
  130|    205|    }
  131|  8.80k|  } else {
  132|       |    // Decode the integer data directly.
  133|       |    // Get the number of bytes for a given entry.
  134|  8.80k|    uint8_t num_bytes;
  135|  8.80k|    if (!in_buffer->Decode(&num_bytes)) {
  ------------------
  |  Branch (135:9): [True: 21, False: 8.78k]
  ------------------
  136|     21|      return false;
  137|     21|    }
  138|  8.78k|    if (num_bytes == DataTypeLength(DT_INT32)) {
  ------------------
  |  Branch (138:9): [True: 454, False: 8.32k]
  ------------------
  139|    454|      if (portable_attribute()->buffer()->data_size() <
  ------------------
  |  Branch (139:11): [True: 0, False: 454]
  ------------------
  140|    454|          sizeof(int32_t) * num_values) {
  141|      0|        return false;
  142|      0|      }
  143|    454|      if (!in_buffer->Decode(portable_attribute_data,
  ------------------
  |  Branch (143:11): [True: 24, False: 430]
  ------------------
  144|    454|                             sizeof(int32_t) * num_values)) {
  145|     24|        return false;
  146|     24|      }
  147|  8.32k|    } else {
  148|  8.32k|      if (portable_attribute()->buffer()->data_size() <
  ------------------
  |  Branch (148:11): [True: 25, False: 8.30k]
  ------------------
  149|  8.32k|          num_bytes * num_values) {
  150|     25|        return false;
  151|     25|      }
  152|  8.30k|      if (in_buffer->remaining_size() <
  ------------------
  |  Branch (152:11): [True: 35, False: 8.26k]
  ------------------
  153|  8.30k|          static_cast<int64_t>(num_bytes) * static_cast<int64_t>(num_values)) {
  154|     35|        return false;
  155|     35|      }
  156|  2.19G|      for (size_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (156:26): [True: 2.19G, False: 8.26k]
  ------------------
  157|  2.19G|        if (!in_buffer->Decode(portable_attribute_data + i, num_bytes)) {
  ------------------
  |  Branch (157:13): [True: 0, False: 2.19G]
  ------------------
  158|      0|          return false;
  159|      0|        }
  160|  2.19G|      }
  161|  8.26k|    }
  162|  8.78k|  }
  163|       |
  164|  9.16k|  if (num_values > 0 && (prediction_scheme_ == nullptr ||
  ------------------
  |  Branch (164:7): [True: 9.16k, False: 0]
  |  Branch (164:26): [True: 3.26k, False: 5.90k]
  ------------------
  165|  8.21k|                         !prediction_scheme_->AreCorrectionsPositive())) {
  ------------------
  |  Branch (165:26): [True: 4.95k, False: 954]
  ------------------
  166|       |    // Convert the values back to the original signed format.
  167|  8.21k|    ConvertSymbolsToSignedInts(
  168|  8.21k|        reinterpret_cast<const uint32_t*>(portable_attribute_data),
  169|  8.21k|        static_cast<int>(num_values), portable_attribute_data);
  170|  8.21k|  }
  171|       |
  172|       |  // If the data was encoded with a prediction scheme, we must revert it.
  173|  9.16k|  if (prediction_scheme_) {
  ------------------
  |  Branch (173:7): [True: 5.90k, False: 3.26k]
  ------------------
  174|  5.90k|    prediction_scheme_->SetMaxNumPredictedValues(num_values);
  175|  5.90k|    if (!prediction_scheme_->DecodePredictionData(in_buffer)) {
  ------------------
  |  Branch (175:9): [True: 786, False: 5.12k]
  ------------------
  176|    786|      return false;
  177|    786|    }
  178|       |
  179|  5.12k|    if (num_values > 0) {
  ------------------
  |  Branch (179:9): [True: 5.12k, False: 0]
  ------------------
  180|  5.12k|      if (!prediction_scheme_->ComputeOriginalValues(
  ------------------
  |  Branch (180:11): [True: 500, False: 4.62k]
  ------------------
  181|  5.12k|              portable_attribute_data, portable_attribute_data,
  182|  5.12k|              static_cast<int>(num_values), num_components, point_ids.data())) {
  183|    500|        return false;
  184|    500|      }
  185|  5.12k|    }
  186|  5.12k|  }
  187|  7.88k|  return true;
  188|  9.16k|}
_ZN5draco33SequentialIntegerAttributeDecoder11StoreValuesEj:
  190|  1.94k|bool SequentialIntegerAttributeDecoder::StoreValues(uint32_t num_values) {
  191|  1.94k|  switch (attribute()->data_type()) {
  192|    175|    case DT_UINT8:
  ------------------
  |  Branch (192:5): [True: 175, False: 1.76k]
  ------------------
  193|    175|      StoreTypedValues<uint8_t>(num_values);
  194|    175|      break;
  195|    939|    case DT_INT8:
  ------------------
  |  Branch (195:5): [True: 939, False: 1.00k]
  ------------------
  196|    939|      StoreTypedValues<int8_t>(num_values);
  197|    939|      break;
  198|    103|    case DT_UINT16:
  ------------------
  |  Branch (198:5): [True: 103, False: 1.83k]
  ------------------
  199|    103|      StoreTypedValues<uint16_t>(num_values);
  200|    103|      break;
  201|    199|    case DT_INT16:
  ------------------
  |  Branch (201:5): [True: 199, False: 1.74k]
  ------------------
  202|    199|      StoreTypedValues<int16_t>(num_values);
  203|    199|      break;
  204|    178|    case DT_UINT32:
  ------------------
  |  Branch (204:5): [True: 178, False: 1.76k]
  ------------------
  205|    178|      StoreTypedValues<uint32_t>(num_values);
  206|    178|      break;
  207|    178|    case DT_INT32:
  ------------------
  |  Branch (207:5): [True: 178, False: 1.76k]
  ------------------
  208|    178|      StoreTypedValues<int32_t>(num_values);
  209|    178|      break;
  210|    170|    default:
  ------------------
  |  Branch (210:5): [True: 170, False: 1.77k]
  ------------------
  211|    170|      return false;
  212|  1.94k|  }
  213|  1.77k|  return true;
  214|  1.94k|}
_ZN5draco33SequentialIntegerAttributeDecoder24PreparePortableAttributeEii:
  238|  9.52k|    int num_entries, int num_components) {
  239|  9.52k|  GeometryAttribute ga;
  240|  9.52k|  ga.Init(attribute()->attribute_type(), nullptr, num_components, DT_INT32,
  241|  9.52k|          false, num_components * DataTypeLength(DT_INT32), 0);
  242|  9.52k|  std::unique_ptr<PointAttribute> port_att(new PointAttribute(ga));
  243|  9.52k|  port_att->SetIdentityMapping();
  244|  9.52k|  port_att->Reset(num_entries);
  245|  9.52k|  port_att->set_unique_id(attribute()->unique_id());
  246|  9.52k|  SetPortableAttribute(std::move(port_att));
  247|  9.52k|}
_ZN5draco33SequentialIntegerAttributeDecoder16StoreTypedValuesIhEEvj:
  217|    175|void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) {
  218|    175|  const int num_components = attribute()->num_components();
  219|    175|  const int entry_size = sizeof(AttributeTypeT) * num_components;
  220|    175|  const std::unique_ptr<AttributeTypeT[]> att_val(
  221|    175|      new AttributeTypeT[num_components]);
  222|    175|  const int32_t* const portable_attribute_data = GetPortableAttributeData();
  223|    175|  int val_id = 0;
  224|    175|  int out_byte_pos = 0;
  225|  24.5M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (225:24): [True: 24.5M, False: 175]
  ------------------
  226|   195M|    for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (226:21): [True: 170M, False: 24.5M]
  ------------------
  227|   170M|      const AttributeTypeT value =
  228|   170M|          static_cast<AttributeTypeT>(portable_attribute_data[val_id++]);
  229|   170M|      att_val[c] = value;
  230|   170M|    }
  231|       |    // Store the integer value into the attribute buffer.
  232|  24.5M|    attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
  233|  24.5M|    out_byte_pos += entry_size;
  234|  24.5M|  }
  235|    175|}
_ZN5draco33SequentialIntegerAttributeDecoder16StoreTypedValuesIaEEvj:
  217|    939|void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) {
  218|    939|  const int num_components = attribute()->num_components();
  219|    939|  const int entry_size = sizeof(AttributeTypeT) * num_components;
  220|    939|  const std::unique_ptr<AttributeTypeT[]> att_val(
  221|    939|      new AttributeTypeT[num_components]);
  222|    939|  const int32_t* const portable_attribute_data = GetPortableAttributeData();
  223|    939|  int val_id = 0;
  224|    939|  int out_byte_pos = 0;
  225|   192M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (225:24): [True: 192M, False: 939]
  ------------------
  226|   712M|    for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (226:21): [True: 520M, False: 192M]
  ------------------
  227|   520M|      const AttributeTypeT value =
  228|   520M|          static_cast<AttributeTypeT>(portable_attribute_data[val_id++]);
  229|   520M|      att_val[c] = value;
  230|   520M|    }
  231|       |    // Store the integer value into the attribute buffer.
  232|   192M|    attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
  233|   192M|    out_byte_pos += entry_size;
  234|   192M|  }
  235|    939|}
_ZN5draco33SequentialIntegerAttributeDecoder16StoreTypedValuesItEEvj:
  217|    103|void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) {
  218|    103|  const int num_components = attribute()->num_components();
  219|    103|  const int entry_size = sizeof(AttributeTypeT) * num_components;
  220|    103|  const std::unique_ptr<AttributeTypeT[]> att_val(
  221|    103|      new AttributeTypeT[num_components]);
  222|    103|  const int32_t* const portable_attribute_data = GetPortableAttributeData();
  223|    103|  int val_id = 0;
  224|    103|  int out_byte_pos = 0;
  225|   708k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (225:24): [True: 708k, False: 103]
  ------------------
  226|  44.1M|    for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (226:21): [True: 43.3M, False: 708k]
  ------------------
  227|  43.3M|      const AttributeTypeT value =
  228|  43.3M|          static_cast<AttributeTypeT>(portable_attribute_data[val_id++]);
  229|  43.3M|      att_val[c] = value;
  230|  43.3M|    }
  231|       |    // Store the integer value into the attribute buffer.
  232|   708k|    attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
  233|   708k|    out_byte_pos += entry_size;
  234|   708k|  }
  235|    103|}
_ZN5draco33SequentialIntegerAttributeDecoder16StoreTypedValuesIsEEvj:
  217|    199|void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) {
  218|    199|  const int num_components = attribute()->num_components();
  219|    199|  const int entry_size = sizeof(AttributeTypeT) * num_components;
  220|    199|  const std::unique_ptr<AttributeTypeT[]> att_val(
  221|    199|      new AttributeTypeT[num_components]);
  222|    199|  const int32_t* const portable_attribute_data = GetPortableAttributeData();
  223|    199|  int val_id = 0;
  224|    199|  int out_byte_pos = 0;
  225|  1.27M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (225:24): [True: 1.27M, False: 199]
  ------------------
  226|  48.9M|    for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (226:21): [True: 47.6M, False: 1.27M]
  ------------------
  227|  47.6M|      const AttributeTypeT value =
  228|  47.6M|          static_cast<AttributeTypeT>(portable_attribute_data[val_id++]);
  229|  47.6M|      att_val[c] = value;
  230|  47.6M|    }
  231|       |    // Store the integer value into the attribute buffer.
  232|  1.27M|    attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
  233|  1.27M|    out_byte_pos += entry_size;
  234|  1.27M|  }
  235|    199|}
_ZN5draco33SequentialIntegerAttributeDecoder16StoreTypedValuesIjEEvj:
  217|    178|void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) {
  218|    178|  const int num_components = attribute()->num_components();
  219|    178|  const int entry_size = sizeof(AttributeTypeT) * num_components;
  220|    178|  const std::unique_ptr<AttributeTypeT[]> att_val(
  221|    178|      new AttributeTypeT[num_components]);
  222|    178|  const int32_t* const portable_attribute_data = GetPortableAttributeData();
  223|    178|  int val_id = 0;
  224|    178|  int out_byte_pos = 0;
  225|  1.44M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (225:24): [True: 1.44M, False: 178]
  ------------------
  226|   127M|    for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (226:21): [True: 126M, False: 1.44M]
  ------------------
  227|   126M|      const AttributeTypeT value =
  228|   126M|          static_cast<AttributeTypeT>(portable_attribute_data[val_id++]);
  229|   126M|      att_val[c] = value;
  230|   126M|    }
  231|       |    // Store the integer value into the attribute buffer.
  232|  1.44M|    attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
  233|  1.44M|    out_byte_pos += entry_size;
  234|  1.44M|  }
  235|    178|}
_ZN5draco33SequentialIntegerAttributeDecoder16StoreTypedValuesIiEEvj:
  217|    178|void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) {
  218|    178|  const int num_components = attribute()->num_components();
  219|    178|  const int entry_size = sizeof(AttributeTypeT) * num_components;
  220|    178|  const std::unique_ptr<AttributeTypeT[]> att_val(
  221|    178|      new AttributeTypeT[num_components]);
  222|    178|  const int32_t* const portable_attribute_data = GetPortableAttributeData();
  223|    178|  int val_id = 0;
  224|    178|  int out_byte_pos = 0;
  225|  28.0M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (225:24): [True: 28.0M, False: 178]
  ------------------
  226|   119M|    for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (226:21): [True: 91.2M, False: 28.0M]
  ------------------
  227|  91.2M|      const AttributeTypeT value =
  228|  91.2M|          static_cast<AttributeTypeT>(portable_attribute_data[val_id++]);
  229|  91.2M|      att_val[c] = value;
  230|  91.2M|    }
  231|       |    // Store the integer value into the attribute buffer.
  232|  28.0M|    attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
  233|  28.0M|    out_byte_pos += entry_size;
  234|  28.0M|  }
  235|    178|}

_ZNK5draco33SequentialIntegerAttributeDecoder21GetNumValueComponentsEv:
   47|  8.49k|  virtual int32_t GetNumValueComponents() const {
   48|  8.49k|    return attribute()->num_components();
   49|  8.49k|  }
_ZN5draco33SequentialIntegerAttributeDecoder24GetPortableAttributeDataEv:
   57|  11.2k|  int32_t* GetPortableAttributeData() {
   58|  11.2k|    if (portable_attribute()->size() == 0) {
  ------------------
  |  Branch (58:9): [True: 11, False: 11.2k]
  ------------------
   59|     11|      return nullptr;
   60|     11|    }
   61|  11.2k|    return reinterpret_cast<int32_t*>(
   62|  11.2k|        portable_attribute()->GetAddress(AttributeValueIndex(0)));
   63|  11.2k|  }

_ZN5draco32SequentialNormalAttributeDecoderC2Ev:
   21|  1.11k|SequentialNormalAttributeDecoder::SequentialNormalAttributeDecoder() = default;
_ZN5draco32SequentialNormalAttributeDecoder4InitEPNS_17PointCloudDecoderEi:
   24|  1.11k|                                            int attribute_id) {
   25|  1.11k|  if (!SequentialIntegerAttributeDecoder::Init(decoder, attribute_id)) {
  ------------------
  |  Branch (25:7): [True: 0, False: 1.11k]
  ------------------
   26|      0|    return false;
   27|      0|  }
   28|       |  // Currently, this encoder works only for 3-component normal vectors.
   29|  1.11k|  if (attribute()->num_components() != 3) {
  ------------------
  |  Branch (29:7): [True: 2, False: 1.11k]
  ------------------
   30|      2|    return false;
   31|      2|  }
   32|       |  // Also the data type must be DT_FLOAT32.
   33|  1.11k|  if (attribute()->data_type() != DT_FLOAT32) {
  ------------------
  |  Branch (33:7): [True: 3, False: 1.11k]
  ------------------
   34|      3|    return false;
   35|      3|  }
   36|  1.11k|  return true;
   37|  1.11k|}
_ZN5draco32SequentialNormalAttributeDecoder19DecodeIntegerValuesERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
   40|  1.03k|    const std::vector<PointIndex>& point_ids, DecoderBuffer* in_buffer) {
   41|  1.03k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   42|  1.03k|  if (decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  1.03k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (42:7): [True: 0, False: 1.03k]
  ------------------
   43|       |    // Note: in older bitstreams, we do not have a PortableAttribute() decoded
   44|       |    // at this stage so we cannot pass it down to the DecodeParameters() call.
   45|       |    // It still works fine for octahedral transform because it does not need to
   46|       |    // use any data from the attribute.
   47|      0|    if (!octahedral_transform_.DecodeParameters(*attribute(), in_buffer)) {
  ------------------
  |  Branch (47:9): [True: 0, False: 0]
  ------------------
   48|      0|      return false;
   49|      0|    }
   50|      0|  }
   51|  1.03k|#endif
   52|  1.03k|  return SequentialIntegerAttributeDecoder::DecodeIntegerValues(point_ids,
   53|  1.03k|                                                                in_buffer);
   54|  1.03k|}
_ZN5draco32SequentialNormalAttributeDecoder35DecodeDataNeededByPortableTransformERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
   57|    860|    const std::vector<PointIndex>& point_ids, DecoderBuffer* in_buffer) {
   58|    860|  if (decoder()->bitstream_version() >= DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    860|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (58:7): [True: 860, False: 0]
  ------------------
   59|       |    // For newer file version, decode attribute transform data here.
   60|    860|    if (!octahedral_transform_.DecodeParameters(*GetPortableAttribute(),
  ------------------
  |  Branch (60:9): [True: 410, False: 450]
  ------------------
   61|    860|                                                in_buffer)) {
   62|    410|      return false;
   63|    410|    }
   64|    860|  }
   65|       |
   66|       |  // Store the decoded transform data in portable attribute.
   67|    450|  return octahedral_transform_.TransferToAttribute(portable_attribute());
   68|    860|}
_ZN5draco32SequentialNormalAttributeDecoder11StoreValuesEj:
   70|    434|bool SequentialNormalAttributeDecoder::StoreValues(uint32_t num_points) {
   71|       |  // Convert all quantized values back to floats.
   72|    434|  return octahedral_transform_.InverseTransformAttribute(
   73|    434|      *GetPortableAttribute(), attribute());
   74|    434|}

_ZNK5draco32SequentialNormalAttributeDecoder21GetNumValueComponentsEv:
   35|  1.03k|  int32_t GetNumValueComponents() const override {
   36|  1.03k|    return 2;  // We quantize everything into two components.
   37|  1.03k|  }
_ZN5draco32SequentialNormalAttributeDecoder25CreateIntPredictionSchemeENS_22PredictionSchemeMethodENS_29PredictionSchemeTransformTypeE:
   51|  1.03k|      PredictionSchemeTransformType transform_type) override {
   52|  1.03k|    switch (transform_type) {
   53|      0|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   54|    448|      case PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON: {
  ------------------
  |  Branch (54:7): [True: 448, False: 590]
  ------------------
   55|    448|        typedef PredictionSchemeNormalOctahedronDecodingTransform<int32_t>
   56|    448|            Transform;
   57|       |        // At this point the decoder has not read the quantization bits,
   58|       |        // which is why we must construct the transform by default.
   59|       |        // See Transform.DecodeTransformData for more details.
   60|    448|        return CreatePredictionSchemeForDecoder<int32_t, Transform>(
   61|    448|            method, attribute_id(), decoder());
   62|      0|      }
   63|      0|#endif
   64|    537|      case PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON_CANONICALIZED: {
  ------------------
  |  Branch (64:7): [True: 537, False: 501]
  ------------------
   65|    537|        typedef PredictionSchemeNormalOctahedronCanonicalizedDecodingTransform<
   66|    537|            int32_t>
   67|    537|            Transform;
   68|       |        // At this point the decoder has not read the quantization bits,
   69|       |        // which is why we must construct the transform by default.
   70|       |        // See Transform.DecodeTransformData for more details.
   71|    537|        return CreatePredictionSchemeForDecoder<int32_t, Transform>(
   72|    537|            method, attribute_id(), decoder());
   73|      0|      }
   74|     53|      default:
  ------------------
  |  Branch (74:7): [True: 53, False: 985]
  ------------------
   75|     53|        return nullptr;  // Currently, we support only octahedron transform and
   76|       |                         // octahedron transform canonicalized.
   77|  1.03k|    }
   78|  1.03k|  }

_ZN5draco38SequentialQuantizationAttributeDecoderC2Ev:
   22|    257|    SequentialQuantizationAttributeDecoder() = default;
_ZN5draco38SequentialQuantizationAttributeDecoder4InitEPNS_17PointCloudDecoderEi:
   25|    257|                                                  int attribute_id) {
   26|    257|  if (!SequentialIntegerAttributeDecoder::Init(decoder, attribute_id)) {
  ------------------
  |  Branch (26:7): [True: 0, False: 257]
  ------------------
   27|      0|    return false;
   28|      0|  }
   29|    257|  const PointAttribute* const attribute =
   30|    257|      decoder->point_cloud()->attribute(attribute_id);
   31|       |  // Currently we can quantize only floating point arguments.
   32|    257|  if (attribute->data_type() != DT_FLOAT32) {
  ------------------
  |  Branch (32:7): [True: 4, False: 253]
  ------------------
   33|      4|    return false;
   34|      4|  }
   35|    253|  return true;
   36|    257|}
_ZN5draco38SequentialQuantizationAttributeDecoder19DecodeIntegerValuesERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
   39|    220|    const std::vector<PointIndex>& point_ids, DecoderBuffer* in_buffer) {
   40|    220|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   41|    220|  if (decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0) &&
  ------------------
  |  |  115|    440|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (41:7): [True: 0, False: 220]
  ------------------
   42|      0|      !DecodeQuantizedDataInfo()) {
  ------------------
  |  Branch (42:7): [True: 0, False: 0]
  ------------------
   43|      0|    return false;
   44|      0|  }
   45|    220|#endif
   46|    220|  return SequentialIntegerAttributeDecoder::DecodeIntegerValues(point_ids,
   47|    220|                                                                in_buffer);
   48|    220|}
_ZN5draco38SequentialQuantizationAttributeDecoder35DecodeDataNeededByPortableTransformERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
   52|    135|        const std::vector<PointIndex>& point_ids, DecoderBuffer* in_buffer) {
   53|    135|  if (decoder()->bitstream_version() >= DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    135|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (53:7): [True: 135, False: 0]
  ------------------
   54|       |    // Decode quantization data here only for files with bitstream version 2.0+
   55|    135|    if (!DecodeQuantizedDataInfo()) {
  ------------------
  |  Branch (55:9): [True: 71, False: 64]
  ------------------
   56|     71|      return false;
   57|     71|    }
   58|    135|  }
   59|       |
   60|       |  // Store the decoded transform data in portable attribute;
   61|     64|  return quantization_transform_.TransferToAttribute(portable_attribute());
   62|    135|}
_ZN5draco38SequentialQuantizationAttributeDecoder11StoreValuesEj:
   64|     50|bool SequentialQuantizationAttributeDecoder::StoreValues(uint32_t num_points) {
   65|     50|  return DequantizeValues(num_points);
   66|     50|}
_ZN5draco38SequentialQuantizationAttributeDecoder23DecodeQuantizedDataInfoEv:
   68|    135|bool SequentialQuantizationAttributeDecoder::DecodeQuantizedDataInfo() {
   69|       |  // Get attribute used as source for decoding.
   70|    135|  auto att = GetPortableAttribute();
   71|    135|  if (att == nullptr) {
  ------------------
  |  Branch (71:7): [True: 0, False: 135]
  ------------------
   72|       |    // This should happen only in the backward compatibility mode. It will still
   73|       |    // work fine for this case because the only thing the quantization transform
   74|       |    // cares about is the number of components that is the same for both source
   75|       |    // and target attributes.
   76|      0|    att = attribute();
   77|      0|  }
   78|    135|  return quantization_transform_.DecodeParameters(*att, decoder()->buffer());
   79|    135|}
_ZN5draco38SequentialQuantizationAttributeDecoder16DequantizeValuesEj:
   82|     50|    uint32_t num_values) {
   83|       |  // Convert all quantized values back to floats.
   84|     50|  return quantization_transform_.InverseTransformAttribute(
   85|     50|      *GetPortableAttribute(), attribute());
   86|     50|}

_ZN5draco16DirectBitDecoderC2Ev:
   19|  7.71k|DirectBitDecoder::DirectBitDecoder() : pos_(bits_.end()), num_used_bits_(0) {}
_ZN5draco16DirectBitDecoderD2Ev:
   21|  7.71k|DirectBitDecoder::~DirectBitDecoder() { Clear(); }
_ZN5draco16DirectBitDecoder13StartDecodingEPNS_13DecoderBufferE:
   23|  3.46k|bool DirectBitDecoder::StartDecoding(DecoderBuffer* source_buffer) {
   24|  3.46k|  Clear();
   25|  3.46k|  uint32_t size_in_bytes;
   26|  3.46k|  if (!source_buffer->Decode(&size_in_bytes)) {
  ------------------
  |  Branch (26:7): [True: 48, False: 3.42k]
  ------------------
   27|     48|    return false;
   28|     48|  }
   29|       |
   30|       |  // Check that size_in_bytes is > 0 and a multiple of 4 as the encoder always
   31|       |  // encodes 32 bit elements.
   32|  3.42k|  if (size_in_bytes == 0 || size_in_bytes & 0x3) {
  ------------------
  |  Branch (32:7): [True: 12, False: 3.40k]
  |  Branch (32:29): [True: 54, False: 3.35k]
  ------------------
   33|     66|    return false;
   34|     66|  }
   35|  3.35k|  if (size_in_bytes > source_buffer->remaining_size()) {
  ------------------
  |  Branch (35:7): [True: 63, False: 3.29k]
  ------------------
   36|     63|    return false;
   37|     63|  }
   38|  3.29k|  const uint32_t num_32bit_elements = size_in_bytes / 4;
   39|  3.29k|  bits_.resize(num_32bit_elements);
   40|  3.29k|  if (!source_buffer->Decode(bits_.data(), size_in_bytes)) {
  ------------------
  |  Branch (40:7): [True: 0, False: 3.29k]
  ------------------
   41|      0|    return false;
   42|      0|  }
   43|  3.29k|  pos_ = bits_.begin();
   44|  3.29k|  num_used_bits_ = 0;
   45|  3.29k|  return true;
   46|  3.29k|}
_ZN5draco16DirectBitDecoder5ClearEv:
   48|  11.1k|void DirectBitDecoder::Clear() {
   49|  11.1k|  bits_.clear();
   50|  11.1k|  num_used_bits_ = 0;
   51|  11.1k|  pos_ = bits_.end();
   52|  11.1k|}

_ZN5draco16DirectBitDecoder28DecodeLeastSignificantBits32EiPj:
   50|  10.2M|  bool DecodeLeastSignificantBits32(int nbits, uint32_t* value) {
   51|  10.2M|    DRACO_DCHECK_EQ(true, nbits <= 32);
   52|  10.2M|    DRACO_DCHECK_EQ(true, nbits > 0);
   53|  10.2M|    const int remaining = 32 - num_used_bits_;
   54|  10.2M|    if (nbits <= remaining) {
  ------------------
  |  Branch (54:9): [True: 8.16M, False: 2.03M]
  ------------------
   55|  8.16M|      if (pos_ == bits_.end()) {
  ------------------
  |  Branch (55:11): [True: 7.71M, False: 455k]
  ------------------
   56|  7.71M|        return false;
   57|  7.71M|      }
   58|   455k|      *value = (*pos_ << num_used_bits_) >> (32 - nbits);
   59|   455k|      num_used_bits_ += nbits;
   60|   455k|      if (num_used_bits_ == 32) {
  ------------------
  |  Branch (60:11): [True: 15.1k, False: 440k]
  ------------------
   61|  15.1k|        ++pos_;
   62|  15.1k|        num_used_bits_ = 0;
   63|  15.1k|      }
   64|  2.03M|    } else {
   65|  2.03M|      if (pos_ + 1 == bits_.end()) {
  ------------------
  |  Branch (65:11): [True: 2.01M, False: 15.8k]
  ------------------
   66|  2.01M|        return false;
   67|  2.01M|      }
   68|  15.8k|      const uint32_t value_l = ((*pos_) << num_used_bits_);
   69|  15.8k|      num_used_bits_ = nbits - remaining;
   70|  15.8k|      ++pos_;
   71|  15.8k|      const uint32_t value_r = (*pos_) >> (32 - num_used_bits_);
   72|  15.8k|      *value = (value_l >> (32 - num_used_bits_ - remaining)) | value_r;
   73|  15.8k|    }
   74|   471k|    return true;
   75|  10.2M|  }
_ZN5draco16DirectBitDecoder13DecodeNextBitEv:
   34|  10.8M|  bool DecodeNextBit() {
   35|  10.8M|    const uint32_t selector = 1 << (31 - num_used_bits_);
   36|  10.8M|    if (pos_ == bits_.end()) {
  ------------------
  |  Branch (36:9): [True: 10.4M, False: 431k]
  ------------------
   37|  10.4M|      return false;
   38|  10.4M|    }
   39|   431k|    const bool bit = *pos_ & selector;
   40|   431k|    ++num_used_bits_;
   41|   431k|    if (num_used_bits_ == 32) {
  ------------------
  |  Branch (41:9): [True: 13.3k, False: 417k]
  ------------------
   42|  13.3k|      ++pos_;
   43|  13.3k|      num_used_bits_ = 0;
   44|  13.3k|    }
   45|   431k|    return bit;
   46|  10.8M|  }
_ZN5draco16DirectBitDecoder11EndDecodingEv:
   77|    910|  void EndDecoding() {}

_ZN5draco18FoldedBit32DecoderINS_14RAnsBitDecoderEEC2Ev:
   29|    871|  FoldedBit32Decoder() {}
_ZN5draco18FoldedBit32DecoderINS_14RAnsBitDecoderEED2Ev:
   30|    871|  ~FoldedBit32Decoder() {}
_ZN5draco18FoldedBit32DecoderINS_14RAnsBitDecoderEE13StartDecodingEPNS_13DecoderBufferE:
   33|    559|  bool StartDecoding(DecoderBuffer* source_buffer) {
   34|  13.3k|    for (int i = 0; i < 32; i++) {
  ------------------
  |  Branch (34:21): [True: 12.9k, False: 368]
  ------------------
   35|  12.9k|      if (!folded_number_decoders_[i].StartDecoding(source_buffer)) {
  ------------------
  |  Branch (35:11): [True: 191, False: 12.7k]
  ------------------
   36|    191|        return false;
   37|    191|      }
   38|  12.9k|    }
   39|    368|    return bit_decoder_.StartDecoding(source_buffer);
   40|    559|  }
_ZN5draco18FoldedBit32DecoderINS_14RAnsBitDecoderEE28DecodeLeastSignificantBits32EiPj:
   47|  3.22M|  void DecodeLeastSignificantBits32(int nbits, uint32_t* value) {
   48|  3.22M|    uint32_t result = 0;
   49|  20.2M|    for (int i = 0; i < nbits; ++i) {
  ------------------
  |  Branch (49:21): [True: 17.0M, False: 3.22M]
  ------------------
   50|  17.0M|      const bool bit = folded_number_decoders_[i].DecodeNextBit();
   51|  17.0M|      result = (result << 1) + bit;
   52|  17.0M|    }
   53|  3.22M|    *value = result;
   54|  3.22M|  }
_ZN5draco18FoldedBit32DecoderINS_14RAnsBitDecoderEE11EndDecodingEv:
   56|    160|  void EndDecoding() {
   57|  5.28k|    for (int i = 0; i < 32; i++) {
  ------------------
  |  Branch (57:21): [True: 5.12k, False: 160]
  ------------------
   58|  5.12k|      folded_number_decoders_[i].EndDecoding();
   59|  5.12k|    }
   60|    160|    bit_decoder_.EndDecoding();
   61|    160|  }

_ZN5draco14RAnsBitDecoderC2Ev:
   23|  58.7k|RAnsBitDecoder::RAnsBitDecoder() : prob_zero_(0) {}
_ZN5draco14RAnsBitDecoderD2Ev:
   25|  58.7k|RAnsBitDecoder::~RAnsBitDecoder() { Clear(); }
_ZN5draco14RAnsBitDecoder13StartDecodingEPNS_13DecoderBufferE:
   27|  36.8k|bool RAnsBitDecoder::StartDecoding(DecoderBuffer* source_buffer) {
   28|  36.8k|  Clear();
   29|       |
   30|  36.8k|  if (!source_buffer->Decode(&prob_zero_)) {
  ------------------
  |  Branch (30:7): [True: 94, False: 36.8k]
  ------------------
   31|     94|    return false;
   32|     94|  }
   33|       |
   34|  36.8k|  uint32_t size_in_bytes;
   35|  36.8k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   36|  36.8k|  if (source_buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  36.8k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (36:7): [True: 1.14k, False: 35.6k]
  ------------------
   37|  1.14k|    if (!source_buffer->Decode(&size_in_bytes)) {
  ------------------
  |  Branch (37:9): [True: 31, False: 1.11k]
  ------------------
   38|     31|      return false;
   39|     31|    }
   40|       |
   41|  1.14k|  } else
   42|  35.6k|#endif
   43|  35.6k|  {
   44|  35.6k|    if (!DecodeVarint(&size_in_bytes, source_buffer)) {
  ------------------
  |  Branch (44:9): [True: 49, False: 35.6k]
  ------------------
   45|     49|      return false;
   46|     49|    }
   47|  35.6k|  }
   48|       |
   49|  36.7k|  if (size_in_bytes > source_buffer->remaining_size()) {
  ------------------
  |  Branch (49:7): [True: 258, False: 36.4k]
  ------------------
   50|    258|    return false;
   51|    258|  }
   52|       |
   53|  36.4k|  if (ans_read_init(&ans_decoder_,
  ------------------
  |  Branch (53:7): [True: 118, False: 36.3k]
  ------------------
   54|  36.4k|                    reinterpret_cast<uint8_t*>(
   55|  36.4k|                        const_cast<char*>(source_buffer->data_head())),
   56|  36.4k|                    size_in_bytes) != 0) {
   57|    118|    return false;
   58|    118|  }
   59|  36.3k|  source_buffer->Advance(size_in_bytes);
   60|  36.3k|  return true;
   61|  36.4k|}
_ZN5draco14RAnsBitDecoder13DecodeNextBitEv:
   63|   132M|bool RAnsBitDecoder::DecodeNextBit() {
   64|   132M|  const uint8_t bit = rabs_read(&ans_decoder_, prob_zero_);
  ------------------
  |  |  246|   132M|#define rabs_read rabs_desc_read
  ------------------
   65|   132M|  return bit > 0;
   66|   132M|}
_ZN5draco14RAnsBitDecoder28DecodeLeastSignificantBits32EiPj:
   68|  4.30M|void RAnsBitDecoder::DecodeLeastSignificantBits32(int nbits, uint32_t* value) {
   69|  4.30M|  DRACO_DCHECK_EQ(true, nbits <= 32);
   70|  4.30M|  DRACO_DCHECK_EQ(true, nbits > 0);
   71|       |
   72|  4.30M|  uint32_t result = 0;
   73|  21.5M|  while (nbits) {
  ------------------
  |  Branch (73:10): [True: 17.2M, False: 4.30M]
  ------------------
   74|  17.2M|    result = (result << 1) + DecodeNextBit();
   75|  17.2M|    --nbits;
   76|  17.2M|  }
   77|  4.30M|  *value = result;
   78|  4.30M|}
_ZN5draco14RAnsBitDecoder5ClearEv:
   80|  95.6k|void RAnsBitDecoder::Clear() { ans_read_end(&ans_decoder_); }

_ZN5draco14RAnsBitDecoder11EndDecodingEv:
   44|  13.1k|  void EndDecoding() {}

_ZN5draco12DracoOptionsINS_17GeometryAttribute4TypeEE16SetAttributeBoolERKS2_RKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEb:
  206|  19.5k|                                                   bool val) {
  207|  19.5k|  GetAttributeOptions(att_key)->SetBool(name, val);
  208|  19.5k|}
_ZN5draco12DracoOptionsINS_17GeometryAttribute4TypeEE19GetAttributeOptionsERKS2_:
  147|  19.5k|    const AttributeKeyT& att_key) {
  148|  19.5k|  auto it = attribute_options_.find(att_key);
  149|  19.5k|  if (it != attribute_options_.end()) {
  ------------------
  |  Branch (149:7): [True: 0, False: 19.5k]
  ------------------
  150|      0|    return &it->second;
  151|      0|  }
  152|  19.5k|  Options new_options;
  153|  19.5k|  it = attribute_options_.insert(std::make_pair(att_key, new_options)).first;
  154|  19.5k|  return &it->second;
  155|  19.5k|}
_ZNK5draco12DracoOptionsINS_17GeometryAttribute4TypeEE16GetAttributeBoolERKS2_RKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEb:
  195|  3.73k|                                                   bool default_val) const {
  196|  3.73k|  const Options* const att_options = FindAttributeOptions(att_key);
  197|  3.73k|  if (att_options && att_options->IsOptionSet(name)) {
  ------------------
  |  Branch (197:7): [True: 1.24k, False: 2.48k]
  |  Branch (197:22): [True: 1.24k, False: 0]
  ------------------
  198|  1.24k|    return att_options->GetBool(name, default_val);
  199|  1.24k|  }
  200|  2.48k|  return global_options_.GetBool(name, default_val);
  201|  3.73k|}
_ZNK5draco12DracoOptionsINS_17GeometryAttribute4TypeEE20FindAttributeOptionsERKS2_:
  137|  3.73k|    const AttributeKeyT& att_key) const {
  138|  3.73k|  auto it = attribute_options_.find(att_key);
  139|  3.73k|  if (it == attribute_options_.end()) {
  ------------------
  |  Branch (139:7): [True: 2.48k, False: 1.24k]
  ------------------
  140|  2.48k|    return nullptr;
  141|  2.48k|  }
  142|  1.24k|  return &it->second;
  143|  3.73k|}

_ZN5draco23CreatePointCloudDecoderEa:
   33|  3.10k|    int8_t method) {
   34|  3.10k|  if (method == POINT_CLOUD_SEQUENTIAL_ENCODING) {
  ------------------
  |  Branch (34:7): [True: 447, False: 2.65k]
  ------------------
   35|    447|    return std::unique_ptr<PointCloudDecoder>(
   36|    447|        new PointCloudSequentialDecoder());
   37|  2.65k|  } else if (method == POINT_CLOUD_KD_TREE_ENCODING) {
  ------------------
  |  Branch (37:14): [True: 2.64k, False: 10]
  ------------------
   38|  2.64k|    return std::unique_ptr<PointCloudDecoder>(new PointCloudKdTreeDecoder());
   39|  2.64k|  }
   40|     10|  return Status(Status::DRACO_ERROR, "Unsupported encoding method.");
   41|  3.10k|}
_ZN5draco17CreateMeshDecoderEh:
   45|  16.3k|StatusOr<std::unique_ptr<MeshDecoder>> CreateMeshDecoder(uint8_t method) {
   46|  16.3k|  if (method == MESH_SEQUENTIAL_ENCODING) {
  ------------------
  |  Branch (46:7): [True: 5.59k, False: 10.7k]
  ------------------
   47|  5.59k|    return std::unique_ptr<MeshDecoder>(new MeshSequentialDecoder());
   48|  10.7k|  } else if (method == MESH_EDGEBREAKER_ENCODING) {
  ------------------
  |  Branch (48:14): [True: 10.7k, False: 9]
  ------------------
   49|  10.7k|    return std::unique_ptr<MeshDecoder>(new MeshEdgebreakerDecoder());
   50|  10.7k|  }
   51|      9|  return Status(Status::DRACO_ERROR, "Unsupported encoding method.");
   52|  16.3k|}
_ZN5draco7Decoder22GetEncodedGeometryTypeEPNS_13DecoderBufferE:
   56|  19.5k|    DecoderBuffer* in_buffer) {
   57|  19.5k|  DecoderBuffer temp_buffer(*in_buffer);
   58|  19.5k|  DracoHeader header;
   59|  19.5k|  DRACO_RETURN_IF_ERROR(PointCloudDecoder::DecodeHeader(&temp_buffer, &header));
  ------------------
  |  |   74|  19.5k|  {                                                   \
  |  |   75|  19.5k|    const draco::Status _local_status = (expression); \
  |  |   76|  19.5k|    if (!_local_status.ok()) {                        \
  |  |  ------------------
  |  |  |  Branch (76:9): [True: 54, False: 19.4k]
  |  |  ------------------
  |  |   77|     54|      return _local_status;                           \
  |  |   78|     54|    }                                                 \
  |  |   79|  19.5k|  }
  ------------------
   60|  19.4k|  if (header.encoder_type >= NUM_ENCODED_GEOMETRY_TYPES) {
  ------------------
  |  Branch (60:7): [True: 7, False: 19.4k]
  ------------------
   61|      7|    return Status(Status::DRACO_ERROR, "Unsupported geometry type.");
   62|      7|  }
   63|  19.4k|  return static_cast<EncodedGeometryType>(header.encoder_type);
   64|  19.4k|}
_ZN5draco7Decoder26DecodePointCloudFromBufferEPNS_13DecoderBufferE:
   67|  19.5k|    DecoderBuffer* in_buffer) {
   68|  19.5k|  DRACO_ASSIGN_OR_RETURN(EncodedGeometryType type,
  ------------------
  |  |   66|  19.5k|  DRACO_ASSIGN_OR_RETURN_IMPL_(DRACO_MACROS_IMPL_CONCAT_(_statusor, __LINE__), \
  |  |  ------------------
  |  |  |  |   71|  19.5k|  auto statusor = (expression);                                             \
  |  |  |  |   72|  19.5k|  if (!statusor.ok()) {                                                     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (72:7): [True: 61, False: 19.4k]
  |  |  |  |  ------------------
  |  |  |  |   73|     61|    auto _status = std::move(statusor.status());                            \
  |  |  |  |   74|     61|    (void)_status; /* error_expression may not use it */                    \
  |  |  |  |   75|     61|    return error_expr;                                                      \
  |  |  |  |   76|     61|  }                                                                         \
  |  |  |  |   77|  19.5k|  lhs = std::move(statusor).value();
  |  |  ------------------
  |  |   67|  19.4k|                               lhs, expression, _status)
  ------------------
   69|  19.4k|                         GetEncodedGeometryType(in_buffer))
   70|  19.4k|  if (type == POINT_CLOUD) {
  ------------------
  |  Branch (70:7): [True: 3.10k, False: 16.3k]
  ------------------
   71|  3.10k|#ifdef DRACO_POINT_CLOUD_COMPRESSION_SUPPORTED
   72|  3.10k|    std::unique_ptr<PointCloud> point_cloud(new PointCloud());
   73|  3.10k|    DRACO_RETURN_IF_ERROR(DecodeBufferToGeometry(in_buffer, point_cloud.get()))
  ------------------
  |  |   74|  3.10k|  {                                                   \
  |  |   75|  3.10k|    const draco::Status _local_status = (expression); \
  |  |   76|  3.10k|    if (!_local_status.ok()) {                        \
  |  |  ------------------
  |  |  |  Branch (76:9): [True: 2.98k, False: 116]
  |  |  ------------------
  |  |   77|  2.98k|      return _local_status;                           \
  |  |   78|  2.98k|    }                                                 \
  |  |   79|  3.10k|  }
  ------------------
   74|    116|    return std::move(point_cloud);
   75|  3.10k|#endif
   76|  16.3k|  } else if (type == TRIANGULAR_MESH) {
  ------------------
  |  Branch (76:14): [True: 16.3k, False: 0]
  ------------------
   77|  16.3k|#ifdef DRACO_MESH_COMPRESSION_SUPPORTED
   78|  16.3k|    std::unique_ptr<Mesh> mesh(new Mesh());
   79|  16.3k|    DRACO_RETURN_IF_ERROR(DecodeBufferToGeometry(in_buffer, mesh.get()))
  ------------------
  |  |   74|  16.3k|  {                                                   \
  |  |   75|  16.3k|    const draco::Status _local_status = (expression); \
  |  |   76|  16.3k|    if (!_local_status.ok()) {                        \
  |  |  ------------------
  |  |  |  Branch (76:9): [True: 14.5k, False: 1.77k]
  |  |  ------------------
  |  |   77|  14.5k|      return _local_status;                           \
  |  |   78|  14.5k|    }                                                 \
  |  |   79|  16.3k|  }
  ------------------
   80|  1.77k|    return static_cast<std::unique_ptr<PointCloud>>(std::move(mesh));
   81|  16.3k|#endif
   82|  16.3k|  }
   83|      0|  return Status(Status::DRACO_ERROR, "Unsupported geometry type.");
   84|  19.4k|}
_ZN5draco7Decoder22DecodeBufferToGeometryEPNS_13DecoderBufferEPNS_10PointCloudE:
   94|  3.10k|                                       PointCloud* out_geometry) {
   95|  3.10k|#ifdef DRACO_POINT_CLOUD_COMPRESSION_SUPPORTED
   96|  3.10k|  DecoderBuffer temp_buffer(*in_buffer);
   97|  3.10k|  DracoHeader header;
   98|  3.10k|  DRACO_RETURN_IF_ERROR(PointCloudDecoder::DecodeHeader(&temp_buffer, &header))
  ------------------
  |  |   74|  3.10k|  {                                                   \
  |  |   75|  3.10k|    const draco::Status _local_status = (expression); \
  |  |   76|  3.10k|    if (!_local_status.ok()) {                        \
  |  |  ------------------
  |  |  |  Branch (76:9): [True: 0, False: 3.10k]
  |  |  ------------------
  |  |   77|      0|      return _local_status;                           \
  |  |   78|      0|    }                                                 \
  |  |   79|  3.10k|  }
  ------------------
   99|  3.10k|  if (header.encoder_type != POINT_CLOUD) {
  ------------------
  |  Branch (99:7): [True: 0, False: 3.10k]
  ------------------
  100|      0|    return Status(Status::DRACO_ERROR, "Input is not a point cloud.");
  101|      0|  }
  102|  6.19k|  DRACO_ASSIGN_OR_RETURN(std::unique_ptr<PointCloudDecoder> decoder,
  ------------------
  |  |   66|  3.10k|  DRACO_ASSIGN_OR_RETURN_IMPL_(DRACO_MACROS_IMPL_CONCAT_(_statusor, __LINE__), \
  |  |  ------------------
  |  |  |  |   71|  3.10k|  auto statusor = (expression);                                             \
  |  |  |  |   72|  3.10k|  if (!statusor.ok()) {                                                     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (72:7): [True: 10, False: 3.09k]
  |  |  |  |  ------------------
  |  |  |  |   73|     10|    auto _status = std::move(statusor.status());                            \
  |  |  |  |   74|     10|    (void)_status; /* error_expression may not use it */                    \
  |  |  |  |   75|     10|    return error_expr;                                                      \
  |  |  |  |   76|     10|  }                                                                         \
  |  |  |  |   77|  3.10k|  lhs = std::move(statusor).value();
  |  |  ------------------
  |  |   67|  3.09k|                               lhs, expression, _status)
  ------------------
  103|  6.19k|                         CreatePointCloudDecoder(header.encoder_method))
  104|       |
  105|  6.19k|  DRACO_RETURN_IF_ERROR(decoder->Decode(options_, in_buffer, out_geometry))
  ------------------
  |  |   74|  3.09k|  {                                                   \
  |  |   75|  3.09k|    const draco::Status _local_status = (expression); \
  |  |   76|  3.09k|    if (!_local_status.ok()) {                        \
  |  |  ------------------
  |  |  |  Branch (76:9): [True: 2.97k, False: 116]
  |  |  ------------------
  |  |   77|  2.97k|      return _local_status;                           \
  |  |   78|  2.97k|    }                                                 \
  |  |   79|  3.09k|  }
  ------------------
  106|    116|  return OkStatus();
  107|       |#else
  108|       |  return Status(Status::DRACO_ERROR, "Unsupported geometry type.");
  109|       |#endif
  110|  6.19k|}
_ZN5draco7Decoder22DecodeBufferToGeometryEPNS_13DecoderBufferEPNS_4MeshE:
  113|  16.3k|                                       Mesh* out_geometry) {
  114|  16.3k|#ifdef DRACO_MESH_COMPRESSION_SUPPORTED
  115|  16.3k|  DecoderBuffer temp_buffer(*in_buffer);
  116|  16.3k|  DracoHeader header;
  117|  16.3k|  DRACO_RETURN_IF_ERROR(PointCloudDecoder::DecodeHeader(&temp_buffer, &header))
  ------------------
  |  |   74|  16.3k|  {                                                   \
  |  |   75|  16.3k|    const draco::Status _local_status = (expression); \
  |  |   76|  16.3k|    if (!_local_status.ok()) {                        \
  |  |  ------------------
  |  |  |  Branch (76:9): [True: 0, False: 16.3k]
  |  |  ------------------
  |  |   77|      0|      return _local_status;                           \
  |  |   78|      0|    }                                                 \
  |  |   79|  16.3k|  }
  ------------------
  118|  16.3k|  if (header.encoder_type != TRIANGULAR_MESH) {
  ------------------
  |  Branch (118:7): [True: 0, False: 16.3k]
  ------------------
  119|      0|    return Status(Status::DRACO_ERROR, "Input is not a mesh.");
  120|      0|  }
  121|  32.6k|  DRACO_ASSIGN_OR_RETURN(std::unique_ptr<MeshDecoder> decoder,
  ------------------
  |  |   66|  16.3k|  DRACO_ASSIGN_OR_RETURN_IMPL_(DRACO_MACROS_IMPL_CONCAT_(_statusor, __LINE__), \
  |  |  ------------------
  |  |  |  |   71|  16.3k|  auto statusor = (expression);                                             \
  |  |  |  |   72|  16.3k|  if (!statusor.ok()) {                                                     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (72:7): [True: 9, False: 16.3k]
  |  |  |  |  ------------------
  |  |  |  |   73|      9|    auto _status = std::move(statusor.status());                            \
  |  |  |  |   74|      9|    (void)_status; /* error_expression may not use it */                    \
  |  |  |  |   75|      9|    return error_expr;                                                      \
  |  |  |  |   76|      9|  }                                                                         \
  |  |  |  |   77|  16.3k|  lhs = std::move(statusor).value();
  |  |  ------------------
  |  |   67|  16.3k|                               lhs, expression, _status)
  ------------------
  122|  32.6k|                         CreateMeshDecoder(header.encoder_method))
  123|       |
  124|  32.6k|  DRACO_RETURN_IF_ERROR(decoder->Decode(options_, in_buffer, out_geometry))
  ------------------
  |  |   74|  16.3k|  {                                                   \
  |  |   75|  16.3k|    const draco::Status _local_status = (expression); \
  |  |   76|  16.3k|    if (!_local_status.ok()) {                        \
  |  |  ------------------
  |  |  |  Branch (76:9): [True: 14.5k, False: 1.77k]
  |  |  ------------------
  |  |   77|  14.5k|      return _local_status;                           \
  |  |   78|  14.5k|    }                                                 \
  |  |   79|  16.3k|  }
  ------------------
  125|  1.77k|  return OkStatus();
  126|       |#else
  127|       |  return Status(Status::DRACO_ERROR, "Unsupported geometry type.");
  128|       |#endif
  129|  32.6k|}
_ZN5draco7Decoder25SetSkipAttributeTransformENS_17GeometryAttribute4TypeE:
  131|  19.5k|void Decoder::SetSkipAttributeTransform(GeometryAttribute::Type att_type) {
  132|  19.5k|  options_.SetAttributeBool(att_type, "skip_attribute_transform", true);
  133|  19.5k|}

_ZN5draco10AnsDecoderC2Ev:
   56|  68.6k|  AnsDecoder() : buf(nullptr), buf_offset(0), state(0) {}
rans_bit_decoder.cc:_ZN5dracoL13ans_read_initEPNS_10AnsDecoderEPKhi:
  300|  36.4k|                                const uint8_t* const buf, int offset) {
  301|  36.4k|  unsigned x;
  302|  36.4k|  if (offset < 1) {
  ------------------
  |  Branch (302:7): [True: 71, False: 36.3k]
  ------------------
  303|     71|    return 1;
  304|     71|  }
  305|  36.3k|  ans->buf = buf;
  306|  36.3k|  x = buf[offset - 1] >> 6;
  307|  36.3k|  if (x == 0) {
  ------------------
  |  Branch (307:7): [True: 32.2k, False: 4.16k]
  ------------------
  308|  32.2k|    ans->buf_offset = offset - 1;
  309|  32.2k|    ans->state = buf[offset - 1] & 0x3F;
  310|  32.2k|  } else if (x == 1) {
  ------------------
  |  Branch (310:14): [True: 3.82k, False: 339]
  ------------------
  311|  3.82k|    if (offset < 2) {
  ------------------
  |  Branch (311:9): [True: 4, False: 3.81k]
  ------------------
  312|      4|      return 1;
  313|      4|    }
  314|  3.81k|    ans->buf_offset = offset - 2;
  315|  3.81k|    ans->state = mem_get_le16(buf + offset - 2) & 0x3FFF;
  316|  3.81k|  } else if (x == 2) {
  ------------------
  |  Branch (316:14): [True: 315, False: 24]
  ------------------
  317|    315|    if (offset < 3) {
  ------------------
  |  Branch (317:9): [True: 10, False: 305]
  ------------------
  318|     10|      return 1;
  319|     10|    }
  320|    305|    ans->buf_offset = offset - 3;
  321|    305|    ans->state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
  322|    305|  } else {
  323|     24|    return 1;
  324|     24|  }
  325|  36.3k|  ans->state += DRACO_ANS_L_BASE;
  ------------------
  |  |   64|  36.3k|#define DRACO_ANS_L_BASE (4096u)
  ------------------
  326|  36.3k|  if (ans->state >= DRACO_ANS_L_BASE * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   64|  36.3k|#define DRACO_ANS_L_BASE (4096u)
  ------------------
                if (ans->state >= DRACO_ANS_L_BASE * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   65|  36.3k|#define DRACO_ANS_IO_BASE 256
  ------------------
  |  Branch (326:7): [True: 9, False: 36.3k]
  ------------------
  327|      9|    return 1;
  328|      9|  }
  329|  36.3k|  return 0;
  330|  36.3k|}
rans_bit_decoder.cc:_ZN5dracoL12mem_get_le16EPKv:
   67|  3.81k|static uint32_t mem_get_le16(const void* vmem) {
   68|  3.81k|  uint32_t val;
   69|  3.81k|  const uint8_t* mem = (const uint8_t*)vmem;
   70|       |
   71|  3.81k|  val = mem[1] << 8;
   72|  3.81k|  val |= mem[0];
   73|  3.81k|  return val;
   74|  3.81k|}
rans_bit_decoder.cc:_ZN5dracoL12mem_get_le24EPKv:
   76|    305|static uint32_t mem_get_le24(const void* vmem) {
   77|    305|  uint32_t val;
   78|    305|  const uint8_t* mem = (const uint8_t*)vmem;
   79|       |
   80|    305|  val = mem[2] << 16;
   81|    305|  val |= mem[1] << 8;
   82|    305|  val |= mem[0];
   83|    305|  return val;
   84|    305|}
rans_bit_decoder.cc:_ZN5dracoL14rabs_desc_readEPNS_10AnsDecoderEh:
  166|   132M|static inline int rabs_desc_read(struct AnsDecoder* ans, AnsP8 p0) {
  167|   132M|  int val;
  168|       |#if DRACO_ANS_IMPL1
  169|       |  unsigned l_s;
  170|       |#else
  171|   132M|  unsigned quot, rem, x, xn;
  172|   132M|#endif
  173|   132M|  const AnsP8 p = DRACO_ANS_P8_PRECISION - p0;
  ------------------
  |  |   63|   132M|#define DRACO_ANS_P8_PRECISION 256u
  ------------------
  174|   132M|  if (ans->state < DRACO_ANS_L_BASE && ans->buf_offset > 0) {
  ------------------
  |  |   64|   265M|#define DRACO_ANS_L_BASE (4096u)
  ------------------
  |  Branch (174:7): [True: 99.8M, False: 32.9M]
  |  Branch (174:40): [True: 106k, False: 99.7M]
  ------------------
  175|   106k|    ans->state = ans->state * DRACO_ANS_IO_BASE + ans->buf[--ans->buf_offset];
  ------------------
  |  |   65|   106k|#define DRACO_ANS_IO_BASE 256
  ------------------
  176|   106k|  }
  177|       |#if DRACO_ANS_IMPL1
  178|       |  val = ans->state % DRACO_ANS_P8_PRECISION < p;
  179|       |  l_s = val ? p : p0;
  180|       |  ans->state = (ans->state / DRACO_ANS_P8_PRECISION) * l_s +
  181|       |               ans->state % DRACO_ANS_P8_PRECISION - (!val * p);
  182|       |#else
  183|   132M|  x = ans->state;
  184|   132M|  quot = x / DRACO_ANS_P8_PRECISION;
  ------------------
  |  |   63|   132M|#define DRACO_ANS_P8_PRECISION 256u
  ------------------
  185|   132M|  rem = x % DRACO_ANS_P8_PRECISION;
  ------------------
  |  |   63|   132M|#define DRACO_ANS_P8_PRECISION 256u
  ------------------
  186|   132M|  xn = quot * p;
  187|   132M|  val = rem < p;
  188|   132M|  if (UNPREDICTABLE(val)) {
  ------------------
  |  |  165|   265M|#define UNPREDICTABLE(x) x
  |  |  ------------------
  |  |  |  Branch (165:26): [True: 105M, False: 27.7M]
  |  |  ------------------
  ------------------
  189|   105M|    ans->state = xn + rem;
  190|   105M|  } else {
  191|       |    // ans->state = quot * p0 + rem - p;
  192|  27.7M|    ans->state = x - xn - p;
  193|  27.7M|  }
  194|   132M|#endif
  195|   132M|  return val;
  196|   132M|}
rans_bit_decoder.cc:_ZN5dracoL12ans_read_endEPNS_10AnsDecoderE:
  332|  95.6k|static inline int ans_read_end(struct AnsDecoder* const ans) {
  333|  95.6k|  return ans->state == DRACO_ANS_L_BASE;
  ------------------
  |  |   64|  95.6k|#define DRACO_ANS_L_BASE (4096u)
  ------------------
  334|  95.6k|}
_ZN5draco11RAnsDecoderILi12EEC2Ev:
  416|  5.15k|  RAnsDecoder() {}
_ZN5draco11RAnsDecoderILi12EE24rans_build_look_up_tableEPKjj:
  484|  2.68k|                                       uint32_t num_symbols) {
  485|  2.68k|    lut_table_.resize(rans_precision);
  486|  2.68k|    probability_table_.resize(num_symbols);
  487|  2.68k|    uint32_t cum_prob = 0;
  488|  2.68k|    uint32_t act_prob = 0;
  489|  20.8k|    for (uint32_t i = 0; i < num_symbols; ++i) {
  ------------------
  |  Branch (489:26): [True: 18.3k, False: 2.46k]
  ------------------
  490|  18.3k|      probability_table_[i].prob = token_probs[i];
  491|  18.3k|      probability_table_[i].cum_prob = cum_prob;
  492|  18.3k|      cum_prob += token_probs[i];
  493|  18.3k|      if (cum_prob > rans_precision) {
  ------------------
  |  Branch (493:11): [True: 223, False: 18.1k]
  ------------------
  494|    223|        return false;
  495|    223|      }
  496|  9.06M|      for (uint32_t j = act_prob; j < cum_prob; ++j) {
  ------------------
  |  Branch (496:35): [True: 9.04M, False: 18.1k]
  ------------------
  497|  9.04M|        lut_table_[j] = i;
  498|  9.04M|      }
  499|  18.1k|      act_prob = cum_prob;
  500|  18.1k|    }
  501|  2.46k|    if (cum_prob != rans_precision) {
  ------------------
  |  Branch (501:9): [True: 301, False: 2.16k]
  ------------------
  502|    301|      return false;
  503|    301|    }
  504|  2.16k|    return true;
  505|  2.46k|  }
_ZN5draco11RAnsDecoderILi12EE9read_initEPKhi:
  421|  2.00k|  inline int read_init(const uint8_t* const buf, int offset) {
  422|  2.00k|    unsigned x;
  423|  2.00k|    if (offset < 1) {
  ------------------
  |  Branch (423:9): [True: 160, False: 1.84k]
  ------------------
  424|    160|      return 1;
  425|    160|    }
  426|  1.84k|    ans_.buf = buf;
  427|  1.84k|    x = buf[offset - 1] >> 6;
  428|  1.84k|    if (x == 0) {
  ------------------
  |  Branch (428:9): [True: 1.18k, False: 661]
  ------------------
  429|  1.18k|      ans_.buf_offset = offset - 1;
  430|  1.18k|      ans_.state = buf[offset - 1] & 0x3F;
  431|  1.18k|    } else if (x == 1) {
  ------------------
  |  Branch (431:16): [True: 277, False: 384]
  ------------------
  432|    277|      if (offset < 2) {
  ------------------
  |  Branch (432:11): [True: 42, False: 235]
  ------------------
  433|     42|        return 1;
  434|     42|      }
  435|    235|      ans_.buf_offset = offset - 2;
  436|    235|      ans_.state = mem_get_le16(buf + offset - 2) & 0x3FFF;
  437|    384|    } else if (x == 2) {
  ------------------
  |  Branch (437:16): [True: 252, False: 132]
  ------------------
  438|    252|      if (offset < 3) {
  ------------------
  |  Branch (438:11): [True: 54, False: 198]
  ------------------
  439|     54|        return 1;
  440|     54|      }
  441|    198|      ans_.buf_offset = offset - 3;
  442|    198|      ans_.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
  443|    198|    } else if (x == 3) {
  ------------------
  |  Branch (443:16): [True: 132, False: 0]
  ------------------
  444|    132|      if (offset < 4) {
  ------------------
  |  Branch (444:11): [True: 29, False: 103]
  ------------------
  445|     29|        return 1;
  446|     29|      }
  447|    103|      ans_.buf_offset = offset - 4;
  448|    103|      ans_.state = mem_get_le32(buf + offset - 4) & 0x3FFFFFFF;
  449|    103|    } else {
  450|      0|      return 1;
  451|      0|    }
  452|  1.72k|    ans_.state += l_rans_base;
  453|  1.72k|    if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   65|  1.72k|#define DRACO_ANS_IO_BASE 256
  ------------------
  |  Branch (453:9): [True: 100, False: 1.62k]
  ------------------
  454|    100|      return 1;
  455|    100|    }
  456|  1.62k|    return 0;
  457|  1.72k|  }
symbol_decoding.cc:_ZN5dracoL12mem_get_le16EPKv:
   67|    363|static uint32_t mem_get_le16(const void* vmem) {
   68|    363|  uint32_t val;
   69|    363|  const uint8_t* mem = (const uint8_t*)vmem;
   70|       |
   71|    363|  val = mem[1] << 8;
   72|    363|  val |= mem[0];
   73|    363|  return val;
   74|    363|}
symbol_decoding.cc:_ZN5dracoL12mem_get_le24EPKv:
   76|    343|static uint32_t mem_get_le24(const void* vmem) {
   77|    343|  uint32_t val;
   78|    343|  const uint8_t* mem = (const uint8_t*)vmem;
   79|       |
   80|    343|  val = mem[2] << 16;
   81|    343|  val |= mem[1] << 8;
   82|    343|  val |= mem[0];
   83|    343|  return val;
   84|    343|}
symbol_decoding.cc:_ZN5dracoL12mem_get_le32EPKv:
   86|    354|static inline uint32_t mem_get_le32(const void* vmem) {
   87|    354|  uint32_t val;
   88|    354|  const uint8_t* mem = (const uint8_t*)vmem;
   89|       |
   90|    354|  val = mem[3] << 24;
   91|    354|  val |= mem[2] << 16;
   92|    354|  val |= mem[1] << 8;
   93|    354|  val |= mem[0];
   94|    354|  return val;
   95|    354|}
_ZN5draco11RAnsDecoderILi12EE9rans_readEv:
  465|   134M|  inline int rans_read() {
  466|   134M|    unsigned rem;
  467|   134M|    unsigned quo;
  468|   134M|    struct rans_dec_sym sym;
  469|   134M|    while (ans_.state < l_rans_base && ans_.buf_offset > 0) {
  ------------------
  |  Branch (469:12): [True: 122M, False: 12.8M]
  |  Branch (469:40): [True: 28.2k, False: 122M]
  ------------------
  470|  28.2k|      ans_.state = ans_.state * DRACO_ANS_IO_BASE + ans_.buf[--ans_.buf_offset];
  ------------------
  |  |   65|  28.2k|#define DRACO_ANS_IO_BASE 256
  ------------------
  471|  28.2k|    }
  472|       |    // |rans_precision| is a power of two compile time constant, and the below
  473|       |    // division and modulo are going to be optimized by the compiler.
  474|   134M|    quo = ans_.state / rans_precision;
  475|   134M|    rem = ans_.state % rans_precision;
  476|   134M|    fetch_sym(&sym, rem);
  477|   134M|    ans_.state = quo * sym.prob + rem - sym.cum_prob;
  478|   134M|    return sym.val;
  479|   134M|  }
_ZN5draco11RAnsDecoderILi12EE9fetch_symEPNS_12rans_dec_symEj:
  508|   134M|  inline void fetch_sym(struct rans_dec_sym* out, uint32_t rem) {
  509|   134M|    uint32_t symbol = lut_table_[rem];
  510|   134M|    out->val = symbol;
  511|   134M|    out->prob = probability_table_[symbol].prob;
  512|   134M|    out->cum_prob = probability_table_[symbol].cum_prob;
  513|   134M|  }
_ZN5draco11RAnsDecoderILi12EE8read_endEv:
  459|  1.53k|  inline int read_end() { return ans_.state == l_rans_base; }
_ZN5draco11RAnsDecoderILi13EEC2Ev:
  416|    369|  RAnsDecoder() {}
_ZN5draco11RAnsDecoderILi13EE24rans_build_look_up_tableEPKjj:
  484|    212|                                       uint32_t num_symbols) {
  485|    212|    lut_table_.resize(rans_precision);
  486|    212|    probability_table_.resize(num_symbols);
  487|    212|    uint32_t cum_prob = 0;
  488|    212|    uint32_t act_prob = 0;
  489|  5.20k|    for (uint32_t i = 0; i < num_symbols; ++i) {
  ------------------
  |  Branch (489:26): [True: 5.02k, False: 180]
  ------------------
  490|  5.02k|      probability_table_[i].prob = token_probs[i];
  491|  5.02k|      probability_table_[i].cum_prob = cum_prob;
  492|  5.02k|      cum_prob += token_probs[i];
  493|  5.02k|      if (cum_prob > rans_precision) {
  ------------------
  |  Branch (493:11): [True: 32, False: 4.99k]
  ------------------
  494|     32|        return false;
  495|     32|      }
  496|  1.19M|      for (uint32_t j = act_prob; j < cum_prob; ++j) {
  ------------------
  |  Branch (496:35): [True: 1.19M, False: 4.99k]
  ------------------
  497|  1.19M|        lut_table_[j] = i;
  498|  1.19M|      }
  499|  4.99k|      act_prob = cum_prob;
  500|  4.99k|    }
  501|    180|    if (cum_prob != rans_precision) {
  ------------------
  |  Branch (501:9): [True: 49, False: 131]
  ------------------
  502|     49|      return false;
  503|     49|    }
  504|    131|    return true;
  505|    180|  }
_ZN5draco11RAnsDecoderILi13EE9read_initEPKhi:
  421|     97|  inline int read_init(const uint8_t* const buf, int offset) {
  422|     97|    unsigned x;
  423|     97|    if (offset < 1) {
  ------------------
  |  Branch (423:9): [True: 3, False: 94]
  ------------------
  424|      3|      return 1;
  425|      3|    }
  426|     94|    ans_.buf = buf;
  427|     94|    x = buf[offset - 1] >> 6;
  428|     94|    if (x == 0) {
  ------------------
  |  Branch (428:9): [True: 42, False: 52]
  ------------------
  429|     42|      ans_.buf_offset = offset - 1;
  430|     42|      ans_.state = buf[offset - 1] & 0x3F;
  431|     52|    } else if (x == 1) {
  ------------------
  |  Branch (431:16): [True: 15, False: 37]
  ------------------
  432|     15|      if (offset < 2) {
  ------------------
  |  Branch (432:11): [True: 1, False: 14]
  ------------------
  433|      1|        return 1;
  434|      1|      }
  435|     14|      ans_.buf_offset = offset - 2;
  436|     14|      ans_.state = mem_get_le16(buf + offset - 2) & 0x3FFF;
  437|     37|    } else if (x == 2) {
  ------------------
  |  Branch (437:16): [True: 27, False: 10]
  ------------------
  438|     27|      if (offset < 3) {
  ------------------
  |  Branch (438:11): [True: 17, False: 10]
  ------------------
  439|     17|        return 1;
  440|     17|      }
  441|     10|      ans_.buf_offset = offset - 3;
  442|     10|      ans_.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
  443|     10|    } else if (x == 3) {
  ------------------
  |  Branch (443:16): [True: 10, False: 0]
  ------------------
  444|     10|      if (offset < 4) {
  ------------------
  |  Branch (444:11): [True: 2, False: 8]
  ------------------
  445|      2|        return 1;
  446|      2|      }
  447|      8|      ans_.buf_offset = offset - 4;
  448|      8|      ans_.state = mem_get_le32(buf + offset - 4) & 0x3FFFFFFF;
  449|      8|    } else {
  450|      0|      return 1;
  451|      0|    }
  452|     74|    ans_.state += l_rans_base;
  453|     74|    if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   65|     74|#define DRACO_ANS_IO_BASE 256
  ------------------
  |  Branch (453:9): [True: 7, False: 67]
  ------------------
  454|      7|      return 1;
  455|      7|    }
  456|     67|    return 0;
  457|     74|  }
_ZN5draco11RAnsDecoderILi13EE9rans_readEv:
  465|   131k|  inline int rans_read() {
  466|   131k|    unsigned rem;
  467|   131k|    unsigned quo;
  468|   131k|    struct rans_dec_sym sym;
  469|   132k|    while (ans_.state < l_rans_base && ans_.buf_offset > 0) {
  ------------------
  |  Branch (469:12): [True: 44.0k, False: 88.9k]
  |  Branch (469:40): [True: 1.14k, False: 42.9k]
  ------------------
  470|  1.14k|      ans_.state = ans_.state * DRACO_ANS_IO_BASE + ans_.buf[--ans_.buf_offset];
  ------------------
  |  |   65|  1.14k|#define DRACO_ANS_IO_BASE 256
  ------------------
  471|  1.14k|    }
  472|       |    // |rans_precision| is a power of two compile time constant, and the below
  473|       |    // division and modulo are going to be optimized by the compiler.
  474|   131k|    quo = ans_.state / rans_precision;
  475|   131k|    rem = ans_.state % rans_precision;
  476|   131k|    fetch_sym(&sym, rem);
  477|   131k|    ans_.state = quo * sym.prob + rem - sym.cum_prob;
  478|   131k|    return sym.val;
  479|   131k|  }
_ZN5draco11RAnsDecoderILi13EE9fetch_symEPNS_12rans_dec_symEj:
  508|   131k|  inline void fetch_sym(struct rans_dec_sym* out, uint32_t rem) {
  509|   131k|    uint32_t symbol = lut_table_[rem];
  510|   131k|    out->val = symbol;
  511|   131k|    out->prob = probability_table_[symbol].prob;
  512|   131k|    out->cum_prob = probability_table_[symbol].cum_prob;
  513|   131k|  }
_ZN5draco11RAnsDecoderILi13EE8read_endEv:
  459|     67|  inline int read_end() { return ans_.state == l_rans_base; }
_ZN5draco11RAnsDecoderILi15EEC2Ev:
  416|    438|  RAnsDecoder() {}
_ZN5draco11RAnsDecoderILi15EE24rans_build_look_up_tableEPKjj:
  484|    255|                                       uint32_t num_symbols) {
  485|    255|    lut_table_.resize(rans_precision);
  486|    255|    probability_table_.resize(num_symbols);
  487|    255|    uint32_t cum_prob = 0;
  488|    255|    uint32_t act_prob = 0;
  489|  3.01k|    for (uint32_t i = 0; i < num_symbols; ++i) {
  ------------------
  |  Branch (489:26): [True: 2.77k, False: 233]
  ------------------
  490|  2.77k|      probability_table_[i].prob = token_probs[i];
  491|  2.77k|      probability_table_[i].cum_prob = cum_prob;
  492|  2.77k|      cum_prob += token_probs[i];
  493|  2.77k|      if (cum_prob > rans_precision) {
  ------------------
  |  Branch (493:11): [True: 22, False: 2.75k]
  ------------------
  494|     22|        return false;
  495|     22|      }
  496|  6.21M|      for (uint32_t j = act_prob; j < cum_prob; ++j) {
  ------------------
  |  Branch (496:35): [True: 6.21M, False: 2.75k]
  ------------------
  497|  6.21M|        lut_table_[j] = i;
  498|  6.21M|      }
  499|  2.75k|      act_prob = cum_prob;
  500|  2.75k|    }
  501|    233|    if (cum_prob != rans_precision) {
  ------------------
  |  Branch (501:9): [True: 53, False: 180]
  ------------------
  502|     53|      return false;
  503|     53|    }
  504|    180|    return true;
  505|    233|  }
_ZN5draco11RAnsDecoderILi15EE9read_initEPKhi:
  421|    104|  inline int read_init(const uint8_t* const buf, int offset) {
  422|    104|    unsigned x;
  423|    104|    if (offset < 1) {
  ------------------
  |  Branch (423:9): [True: 3, False: 101]
  ------------------
  424|      3|      return 1;
  425|      3|    }
  426|    101|    ans_.buf = buf;
  427|    101|    x = buf[offset - 1] >> 6;
  428|    101|    if (x == 0) {
  ------------------
  |  Branch (428:9): [True: 36, False: 65]
  ------------------
  429|     36|      ans_.buf_offset = offset - 1;
  430|     36|      ans_.state = buf[offset - 1] & 0x3F;
  431|     65|    } else if (x == 1) {
  ------------------
  |  Branch (431:16): [True: 25, False: 40]
  ------------------
  432|     25|      if (offset < 2) {
  ------------------
  |  Branch (432:11): [True: 6, False: 19]
  ------------------
  433|      6|        return 1;
  434|      6|      }
  435|     19|      ans_.buf_offset = offset - 2;
  436|     19|      ans_.state = mem_get_le16(buf + offset - 2) & 0x3FFF;
  437|     40|    } else if (x == 2) {
  ------------------
  |  Branch (437:16): [True: 26, False: 14]
  ------------------
  438|     26|      if (offset < 3) {
  ------------------
  |  Branch (438:11): [True: 3, False: 23]
  ------------------
  439|      3|        return 1;
  440|      3|      }
  441|     23|      ans_.buf_offset = offset - 3;
  442|     23|      ans_.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
  443|     23|    } else if (x == 3) {
  ------------------
  |  Branch (443:16): [True: 14, False: 0]
  ------------------
  444|     14|      if (offset < 4) {
  ------------------
  |  Branch (444:11): [True: 3, False: 11]
  ------------------
  445|      3|        return 1;
  446|      3|      }
  447|     11|      ans_.buf_offset = offset - 4;
  448|     11|      ans_.state = mem_get_le32(buf + offset - 4) & 0x3FFFFFFF;
  449|     11|    } else {
  450|      0|      return 1;
  451|      0|    }
  452|     89|    ans_.state += l_rans_base;
  453|     89|    if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   65|     89|#define DRACO_ANS_IO_BASE 256
  ------------------
  |  Branch (453:9): [True: 8, False: 81]
  ------------------
  454|      8|      return 1;
  455|      8|    }
  456|     81|    return 0;
  457|     89|  }
_ZN5draco11RAnsDecoderILi15EE9rans_readEv:
  465|   521k|  inline int rans_read() {
  466|   521k|    unsigned rem;
  467|   521k|    unsigned quo;
  468|   521k|    struct rans_dec_sym sym;
  469|   522k|    while (ans_.state < l_rans_base && ans_.buf_offset > 0) {
  ------------------
  |  Branch (469:12): [True: 517k, False: 4.92k]
  |  Branch (469:40): [True: 804, False: 516k]
  ------------------
  470|    804|      ans_.state = ans_.state * DRACO_ANS_IO_BASE + ans_.buf[--ans_.buf_offset];
  ------------------
  |  |   65|    804|#define DRACO_ANS_IO_BASE 256
  ------------------
  471|    804|    }
  472|       |    // |rans_precision| is a power of two compile time constant, and the below
  473|       |    // division and modulo are going to be optimized by the compiler.
  474|   521k|    quo = ans_.state / rans_precision;
  475|   521k|    rem = ans_.state % rans_precision;
  476|   521k|    fetch_sym(&sym, rem);
  477|   521k|    ans_.state = quo * sym.prob + rem - sym.cum_prob;
  478|   521k|    return sym.val;
  479|   521k|  }
_ZN5draco11RAnsDecoderILi15EE9fetch_symEPNS_12rans_dec_symEj:
  508|   521k|  inline void fetch_sym(struct rans_dec_sym* out, uint32_t rem) {
  509|   521k|    uint32_t symbol = lut_table_[rem];
  510|   521k|    out->val = symbol;
  511|   521k|    out->prob = probability_table_[symbol].prob;
  512|   521k|    out->cum_prob = probability_table_[symbol].cum_prob;
  513|   521k|  }
_ZN5draco11RAnsDecoderILi15EE8read_endEv:
  459|     81|  inline int read_end() { return ans_.state == l_rans_base; }
_ZN5draco11RAnsDecoderILi16EEC2Ev:
  416|    484|  RAnsDecoder() {}
_ZN5draco11RAnsDecoderILi16EE24rans_build_look_up_tableEPKjj:
  484|    309|                                       uint32_t num_symbols) {
  485|    309|    lut_table_.resize(rans_precision);
  486|    309|    probability_table_.resize(num_symbols);
  487|    309|    uint32_t cum_prob = 0;
  488|    309|    uint32_t act_prob = 0;
  489|  6.64k|    for (uint32_t i = 0; i < num_symbols; ++i) {
  ------------------
  |  Branch (489:26): [True: 6.36k, False: 276]
  ------------------
  490|  6.36k|      probability_table_[i].prob = token_probs[i];
  491|  6.36k|      probability_table_[i].cum_prob = cum_prob;
  492|  6.36k|      cum_prob += token_probs[i];
  493|  6.36k|      if (cum_prob > rans_precision) {
  ------------------
  |  Branch (493:11): [True: 33, False: 6.33k]
  ------------------
  494|     33|        return false;
  495|     33|      }
  496|  15.8M|      for (uint32_t j = act_prob; j < cum_prob; ++j) {
  ------------------
  |  Branch (496:35): [True: 15.8M, False: 6.33k]
  ------------------
  497|  15.8M|        lut_table_[j] = i;
  498|  15.8M|      }
  499|  6.33k|      act_prob = cum_prob;
  500|  6.33k|    }
  501|    276|    if (cum_prob != rans_precision) {
  ------------------
  |  Branch (501:9): [True: 69, False: 207]
  ------------------
  502|     69|      return false;
  503|     69|    }
  504|    207|    return true;
  505|    276|  }
_ZN5draco11RAnsDecoderILi16EE9read_initEPKhi:
  421|    114|  inline int read_init(const uint8_t* const buf, int offset) {
  422|    114|    unsigned x;
  423|    114|    if (offset < 1) {
  ------------------
  |  Branch (423:9): [True: 10, False: 104]
  ------------------
  424|     10|      return 1;
  425|     10|    }
  426|    104|    ans_.buf = buf;
  427|    104|    x = buf[offset - 1] >> 6;
  428|    104|    if (x == 0) {
  ------------------
  |  Branch (428:9): [True: 34, False: 70]
  ------------------
  429|     34|      ans_.buf_offset = offset - 1;
  430|     34|      ans_.state = buf[offset - 1] & 0x3F;
  431|     70|    } else if (x == 1) {
  ------------------
  |  Branch (431:16): [True: 22, False: 48]
  ------------------
  432|     22|      if (offset < 2) {
  ------------------
  |  Branch (432:11): [True: 10, False: 12]
  ------------------
  433|     10|        return 1;
  434|     10|      }
  435|     12|      ans_.buf_offset = offset - 2;
  436|     12|      ans_.state = mem_get_le16(buf + offset - 2) & 0x3FFF;
  437|     48|    } else if (x == 2) {
  ------------------
  |  Branch (437:16): [True: 23, False: 25]
  ------------------
  438|     23|      if (offset < 3) {
  ------------------
  |  Branch (438:11): [True: 17, False: 6]
  ------------------
  439|     17|        return 1;
  440|     17|      }
  441|      6|      ans_.buf_offset = offset - 3;
  442|      6|      ans_.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
  443|     25|    } else if (x == 3) {
  ------------------
  |  Branch (443:16): [True: 25, False: 0]
  ------------------
  444|     25|      if (offset < 4) {
  ------------------
  |  Branch (444:11): [True: 6, False: 19]
  ------------------
  445|      6|        return 1;
  446|      6|      }
  447|     19|      ans_.buf_offset = offset - 4;
  448|     19|      ans_.state = mem_get_le32(buf + offset - 4) & 0x3FFFFFFF;
  449|     19|    } else {
  450|      0|      return 1;
  451|      0|    }
  452|     71|    ans_.state += l_rans_base;
  453|     71|    if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   65|     71|#define DRACO_ANS_IO_BASE 256
  ------------------
  |  Branch (453:9): [True: 14, False: 57]
  ------------------
  454|     14|      return 1;
  455|     14|    }
  456|     57|    return 0;
  457|     71|  }
_ZN5draco11RAnsDecoderILi16EE9rans_readEv:
  465|  37.4k|  inline int rans_read() {
  466|  37.4k|    unsigned rem;
  467|  37.4k|    unsigned quo;
  468|  37.4k|    struct rans_dec_sym sym;
  469|  37.9k|    while (ans_.state < l_rans_base && ans_.buf_offset > 0) {
  ------------------
  |  Branch (469:12): [True: 35.6k, False: 2.32k]
  |  Branch (469:40): [True: 494, False: 35.1k]
  ------------------
  470|    494|      ans_.state = ans_.state * DRACO_ANS_IO_BASE + ans_.buf[--ans_.buf_offset];
  ------------------
  |  |   65|    494|#define DRACO_ANS_IO_BASE 256
  ------------------
  471|    494|    }
  472|       |    // |rans_precision| is a power of two compile time constant, and the below
  473|       |    // division and modulo are going to be optimized by the compiler.
  474|  37.4k|    quo = ans_.state / rans_precision;
  475|  37.4k|    rem = ans_.state % rans_precision;
  476|  37.4k|    fetch_sym(&sym, rem);
  477|  37.4k|    ans_.state = quo * sym.prob + rem - sym.cum_prob;
  478|  37.4k|    return sym.val;
  479|  37.4k|  }
_ZN5draco11RAnsDecoderILi16EE9fetch_symEPNS_12rans_dec_symEj:
  508|  37.4k|  inline void fetch_sym(struct rans_dec_sym* out, uint32_t rem) {
  509|  37.4k|    uint32_t symbol = lut_table_[rem];
  510|  37.4k|    out->val = symbol;
  511|  37.4k|    out->prob = probability_table_[symbol].prob;
  512|  37.4k|    out->cum_prob = probability_table_[symbol].cum_prob;
  513|  37.4k|  }
_ZN5draco11RAnsDecoderILi16EE8read_endEv:
  459|     57|  inline int read_end() { return ans_.state == l_rans_base; }
_ZN5draco11RAnsDecoderILi18EEC2Ev:
  416|    492|  RAnsDecoder() {}
_ZN5draco11RAnsDecoderILi18EE24rans_build_look_up_tableEPKjj:
  484|    292|                                       uint32_t num_symbols) {
  485|    292|    lut_table_.resize(rans_precision);
  486|    292|    probability_table_.resize(num_symbols);
  487|    292|    uint32_t cum_prob = 0;
  488|    292|    uint32_t act_prob = 0;
  489|  4.92k|    for (uint32_t i = 0; i < num_symbols; ++i) {
  ------------------
  |  Branch (489:26): [True: 4.66k, False: 261]
  ------------------
  490|  4.66k|      probability_table_[i].prob = token_probs[i];
  491|  4.66k|      probability_table_[i].cum_prob = cum_prob;
  492|  4.66k|      cum_prob += token_probs[i];
  493|  4.66k|      if (cum_prob > rans_precision) {
  ------------------
  |  Branch (493:11): [True: 31, False: 4.63k]
  ------------------
  494|     31|        return false;
  495|     31|      }
  496|  50.5M|      for (uint32_t j = act_prob; j < cum_prob; ++j) {
  ------------------
  |  Branch (496:35): [True: 50.4M, False: 4.63k]
  ------------------
  497|  50.4M|        lut_table_[j] = i;
  498|  50.4M|      }
  499|  4.63k|      act_prob = cum_prob;
  500|  4.63k|    }
  501|    261|    if (cum_prob != rans_precision) {
  ------------------
  |  Branch (501:9): [True: 82, False: 179]
  ------------------
  502|     82|      return false;
  503|     82|    }
  504|    179|    return true;
  505|    261|  }
_ZN5draco11RAnsDecoderILi18EE9read_initEPKhi:
  421|    101|  inline int read_init(const uint8_t* const buf, int offset) {
  422|    101|    unsigned x;
  423|    101|    if (offset < 1) {
  ------------------
  |  Branch (423:9): [True: 6, False: 95]
  ------------------
  424|      6|      return 1;
  425|      6|    }
  426|     95|    ans_.buf = buf;
  427|     95|    x = buf[offset - 1] >> 6;
  428|     95|    if (x == 0) {
  ------------------
  |  Branch (428:9): [True: 23, False: 72]
  ------------------
  429|     23|      ans_.buf_offset = offset - 1;
  430|     23|      ans_.state = buf[offset - 1] & 0x3F;
  431|     72|    } else if (x == 1) {
  ------------------
  |  Branch (431:16): [True: 14, False: 58]
  ------------------
  432|     14|      if (offset < 2) {
  ------------------
  |  Branch (432:11): [True: 3, False: 11]
  ------------------
  433|      3|        return 1;
  434|      3|      }
  435|     11|      ans_.buf_offset = offset - 2;
  436|     11|      ans_.state = mem_get_le16(buf + offset - 2) & 0x3FFF;
  437|     58|    } else if (x == 2) {
  ------------------
  |  Branch (437:16): [True: 30, False: 28]
  ------------------
  438|     30|      if (offset < 3) {
  ------------------
  |  Branch (438:11): [True: 11, False: 19]
  ------------------
  439|     11|        return 1;
  440|     11|      }
  441|     19|      ans_.buf_offset = offset - 3;
  442|     19|      ans_.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
  443|     28|    } else if (x == 3) {
  ------------------
  |  Branch (443:16): [True: 28, False: 0]
  ------------------
  444|     28|      if (offset < 4) {
  ------------------
  |  Branch (444:11): [True: 11, False: 17]
  ------------------
  445|     11|        return 1;
  446|     11|      }
  447|     17|      ans_.buf_offset = offset - 4;
  448|     17|      ans_.state = mem_get_le32(buf + offset - 4) & 0x3FFFFFFF;
  449|     17|    } else {
  450|      0|      return 1;
  451|      0|    }
  452|     70|    ans_.state += l_rans_base;
  453|     70|    if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   65|     70|#define DRACO_ANS_IO_BASE 256
  ------------------
  |  Branch (453:9): [True: 9, False: 61]
  ------------------
  454|      9|      return 1;
  455|      9|    }
  456|     61|    return 0;
  457|     70|  }
_ZN5draco11RAnsDecoderILi18EE9rans_readEv:
  465|   212k|  inline int rans_read() {
  466|   212k|    unsigned rem;
  467|   212k|    unsigned quo;
  468|   212k|    struct rans_dec_sym sym;
  469|   212k|    while (ans_.state < l_rans_base && ans_.buf_offset > 0) {
  ------------------
  |  Branch (469:12): [True: 174k, False: 38.4k]
  |  Branch (469:40): [True: 513, False: 173k]
  ------------------
  470|    513|      ans_.state = ans_.state * DRACO_ANS_IO_BASE + ans_.buf[--ans_.buf_offset];
  ------------------
  |  |   65|    513|#define DRACO_ANS_IO_BASE 256
  ------------------
  471|    513|    }
  472|       |    // |rans_precision| is a power of two compile time constant, and the below
  473|       |    // division and modulo are going to be optimized by the compiler.
  474|   212k|    quo = ans_.state / rans_precision;
  475|   212k|    rem = ans_.state % rans_precision;
  476|   212k|    fetch_sym(&sym, rem);
  477|   212k|    ans_.state = quo * sym.prob + rem - sym.cum_prob;
  478|   212k|    return sym.val;
  479|   212k|  }
_ZN5draco11RAnsDecoderILi18EE9fetch_symEPNS_12rans_dec_symEj:
  508|   212k|  inline void fetch_sym(struct rans_dec_sym* out, uint32_t rem) {
  509|   212k|    uint32_t symbol = lut_table_[rem];
  510|   212k|    out->val = symbol;
  511|   212k|    out->prob = probability_table_[symbol].prob;
  512|   212k|    out->cum_prob = probability_table_[symbol].cum_prob;
  513|   212k|  }
_ZN5draco11RAnsDecoderILi18EE8read_endEv:
  459|     61|  inline int read_end() { return ans_.state == l_rans_base; }
_ZN5draco11RAnsDecoderILi19EEC2Ev:
  416|    589|  RAnsDecoder() {}
_ZN5draco11RAnsDecoderILi19EE24rans_build_look_up_tableEPKjj:
  484|    381|                                       uint32_t num_symbols) {
  485|    381|    lut_table_.resize(rans_precision);
  486|    381|    probability_table_.resize(num_symbols);
  487|    381|    uint32_t cum_prob = 0;
  488|    381|    uint32_t act_prob = 0;
  489|  7.84k|    for (uint32_t i = 0; i < num_symbols; ++i) {
  ------------------
  |  Branch (489:26): [True: 7.49k, False: 349]
  ------------------
  490|  7.49k|      probability_table_[i].prob = token_probs[i];
  491|  7.49k|      probability_table_[i].cum_prob = cum_prob;
  492|  7.49k|      cum_prob += token_probs[i];
  493|  7.49k|      if (cum_prob > rans_precision) {
  ------------------
  |  Branch (493:11): [True: 32, False: 7.46k]
  ------------------
  494|     32|        return false;
  495|     32|      }
  496|   146M|      for (uint32_t j = act_prob; j < cum_prob; ++j) {
  ------------------
  |  Branch (496:35): [True: 146M, False: 7.46k]
  ------------------
  497|   146M|        lut_table_[j] = i;
  498|   146M|      }
  499|  7.46k|      act_prob = cum_prob;
  500|  7.46k|    }
  501|    349|    if (cum_prob != rans_precision) {
  ------------------
  |  Branch (501:9): [True: 95, False: 254]
  ------------------
  502|     95|      return false;
  503|     95|    }
  504|    254|    return true;
  505|    349|  }
_ZN5draco11RAnsDecoderILi19EE9read_initEPKhi:
  421|    147|  inline int read_init(const uint8_t* const buf, int offset) {
  422|    147|    unsigned x;
  423|    147|    if (offset < 1) {
  ------------------
  |  Branch (423:9): [True: 19, False: 128]
  ------------------
  424|     19|      return 1;
  425|     19|    }
  426|    128|    ans_.buf = buf;
  427|    128|    x = buf[offset - 1] >> 6;
  428|    128|    if (x == 0) {
  ------------------
  |  Branch (428:9): [True: 45, False: 83]
  ------------------
  429|     45|      ans_.buf_offset = offset - 1;
  430|     45|      ans_.state = buf[offset - 1] & 0x3F;
  431|     83|    } else if (x == 1) {
  ------------------
  |  Branch (431:16): [True: 16, False: 67]
  ------------------
  432|     16|      if (offset < 2) {
  ------------------
  |  Branch (432:11): [True: 6, False: 10]
  ------------------
  433|      6|        return 1;
  434|      6|      }
  435|     10|      ans_.buf_offset = offset - 2;
  436|     10|      ans_.state = mem_get_le16(buf + offset - 2) & 0x3FFF;
  437|     67|    } else if (x == 2) {
  ------------------
  |  Branch (437:16): [True: 27, False: 40]
  ------------------
  438|     27|      if (offset < 3) {
  ------------------
  |  Branch (438:11): [True: 1, False: 26]
  ------------------
  439|      1|        return 1;
  440|      1|      }
  441|     26|      ans_.buf_offset = offset - 3;
  442|     26|      ans_.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
  443|     40|    } else if (x == 3) {
  ------------------
  |  Branch (443:16): [True: 40, False: 0]
  ------------------
  444|     40|      if (offset < 4) {
  ------------------
  |  Branch (444:11): [True: 4, False: 36]
  ------------------
  445|      4|        return 1;
  446|      4|      }
  447|     36|      ans_.buf_offset = offset - 4;
  448|     36|      ans_.state = mem_get_le32(buf + offset - 4) & 0x3FFFFFFF;
  449|     36|    } else {
  450|      0|      return 1;
  451|      0|    }
  452|    117|    ans_.state += l_rans_base;
  453|    117|    if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   65|    117|#define DRACO_ANS_IO_BASE 256
  ------------------
  |  Branch (453:9): [True: 24, False: 93]
  ------------------
  454|     24|      return 1;
  455|     24|    }
  456|     93|    return 0;
  457|    117|  }
_ZN5draco11RAnsDecoderILi19EE9rans_readEv:
  465|   714k|  inline int rans_read() {
  466|   714k|    unsigned rem;
  467|   714k|    unsigned quo;
  468|   714k|    struct rans_dec_sym sym;
  469|   716k|    while (ans_.state < l_rans_base && ans_.buf_offset > 0) {
  ------------------
  |  Branch (469:12): [True: 544k, False: 171k]
  |  Branch (469:40): [True: 1.27k, False: 543k]
  ------------------
  470|  1.27k|      ans_.state = ans_.state * DRACO_ANS_IO_BASE + ans_.buf[--ans_.buf_offset];
  ------------------
  |  |   65|  1.27k|#define DRACO_ANS_IO_BASE 256
  ------------------
  471|  1.27k|    }
  472|       |    // |rans_precision| is a power of two compile time constant, and the below
  473|       |    // division and modulo are going to be optimized by the compiler.
  474|   714k|    quo = ans_.state / rans_precision;
  475|   714k|    rem = ans_.state % rans_precision;
  476|   714k|    fetch_sym(&sym, rem);
  477|   714k|    ans_.state = quo * sym.prob + rem - sym.cum_prob;
  478|   714k|    return sym.val;
  479|   714k|  }
_ZN5draco11RAnsDecoderILi19EE9fetch_symEPNS_12rans_dec_symEj:
  508|   714k|  inline void fetch_sym(struct rans_dec_sym* out, uint32_t rem) {
  509|   714k|    uint32_t symbol = lut_table_[rem];
  510|   714k|    out->val = symbol;
  511|   714k|    out->prob = probability_table_[symbol].prob;
  512|   714k|    out->cum_prob = probability_table_[symbol].cum_prob;
  513|   714k|  }
_ZN5draco11RAnsDecoderILi19EE8read_endEv:
  459|     93|  inline int read_end() { return ans_.state == l_rans_base; }
_ZN5draco11RAnsDecoderILi20EEC2Ev:
  416|  2.32k|  RAnsDecoder() {}
_ZN5draco11RAnsDecoderILi20EE24rans_build_look_up_tableEPKjj:
  484|  1.29k|                                       uint32_t num_symbols) {
  485|  1.29k|    lut_table_.resize(rans_precision);
  486|  1.29k|    probability_table_.resize(num_symbols);
  487|  1.29k|    uint32_t cum_prob = 0;
  488|  1.29k|    uint32_t act_prob = 0;
  489|  24.5k|    for (uint32_t i = 0; i < num_symbols; ++i) {
  ------------------
  |  Branch (489:26): [True: 23.3k, False: 1.23k]
  ------------------
  490|  23.3k|      probability_table_[i].prob = token_probs[i];
  491|  23.3k|      probability_table_[i].cum_prob = cum_prob;
  492|  23.3k|      cum_prob += token_probs[i];
  493|  23.3k|      if (cum_prob > rans_precision) {
  ------------------
  |  Branch (493:11): [True: 60, False: 23.2k]
  ------------------
  494|     60|        return false;
  495|     60|      }
  496|  1.18G|      for (uint32_t j = act_prob; j < cum_prob; ++j) {
  ------------------
  |  Branch (496:35): [True: 1.18G, False: 23.2k]
  ------------------
  497|  1.18G|        lut_table_[j] = i;
  498|  1.18G|      }
  499|  23.2k|      act_prob = cum_prob;
  500|  23.2k|    }
  501|  1.23k|    if (cum_prob != rans_precision) {
  ------------------
  |  Branch (501:9): [True: 145, False: 1.09k]
  ------------------
  502|    145|      return false;
  503|    145|    }
  504|  1.09k|    return true;
  505|  1.23k|  }
_ZN5draco11RAnsDecoderILi20EE9read_initEPKhi:
  421|    544|  inline int read_init(const uint8_t* const buf, int offset) {
  422|    544|    unsigned x;
  423|    544|    if (offset < 1) {
  ------------------
  |  Branch (423:9): [True: 30, False: 514]
  ------------------
  424|     30|      return 1;
  425|     30|    }
  426|    514|    ans_.buf = buf;
  427|    514|    x = buf[offset - 1] >> 6;
  428|    514|    if (x == 0) {
  ------------------
  |  Branch (428:9): [True: 131, False: 383]
  ------------------
  429|    131|      ans_.buf_offset = offset - 1;
  430|    131|      ans_.state = buf[offset - 1] & 0x3F;
  431|    383|    } else if (x == 1) {
  ------------------
  |  Branch (431:16): [True: 99, False: 284]
  ------------------
  432|     99|      if (offset < 2) {
  ------------------
  |  Branch (432:11): [True: 37, False: 62]
  ------------------
  433|     37|        return 1;
  434|     37|      }
  435|     62|      ans_.buf_offset = offset - 2;
  436|     62|      ans_.state = mem_get_le16(buf + offset - 2) & 0x3FFF;
  437|    284|    } else if (x == 2) {
  ------------------
  |  Branch (437:16): [True: 81, False: 203]
  ------------------
  438|     81|      if (offset < 3) {
  ------------------
  |  Branch (438:11): [True: 20, False: 61]
  ------------------
  439|     20|        return 1;
  440|     20|      }
  441|     61|      ans_.buf_offset = offset - 3;
  442|     61|      ans_.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
  443|    203|    } else if (x == 3) {
  ------------------
  |  Branch (443:16): [True: 203, False: 0]
  ------------------
  444|    203|      if (offset < 4) {
  ------------------
  |  Branch (444:11): [True: 43, False: 160]
  ------------------
  445|     43|        return 1;
  446|     43|      }
  447|    160|      ans_.buf_offset = offset - 4;
  448|    160|      ans_.state = mem_get_le32(buf + offset - 4) & 0x3FFFFFFF;
  449|    160|    } else {
  450|      0|      return 1;
  451|      0|    }
  452|    414|    ans_.state += l_rans_base;
  453|    414|    if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   65|    414|#define DRACO_ANS_IO_BASE 256
  ------------------
  |  Branch (453:9): [True: 42, False: 372]
  ------------------
  454|     42|      return 1;
  455|     42|    }
  456|    372|    return 0;
  457|    414|  }
_ZN5draco11RAnsDecoderILi20EE9rans_readEv:
  465|   141M|  inline int rans_read() {
  466|   141M|    unsigned rem;
  467|   141M|    unsigned quo;
  468|   141M|    struct rans_dec_sym sym;
  469|   141M|    while (ans_.state < l_rans_base && ans_.buf_offset > 0) {
  ------------------
  |  Branch (469:12): [True: 124M, False: 16.8M]
  |  Branch (469:40): [True: 5.80k, False: 124M]
  ------------------
  470|  5.80k|      ans_.state = ans_.state * DRACO_ANS_IO_BASE + ans_.buf[--ans_.buf_offset];
  ------------------
  |  |   65|  5.80k|#define DRACO_ANS_IO_BASE 256
  ------------------
  471|  5.80k|    }
  472|       |    // |rans_precision| is a power of two compile time constant, and the below
  473|       |    // division and modulo are going to be optimized by the compiler.
  474|   141M|    quo = ans_.state / rans_precision;
  475|   141M|    rem = ans_.state % rans_precision;
  476|   141M|    fetch_sym(&sym, rem);
  477|   141M|    ans_.state = quo * sym.prob + rem - sym.cum_prob;
  478|   141M|    return sym.val;
  479|   141M|  }
_ZN5draco11RAnsDecoderILi20EE9fetch_symEPNS_12rans_dec_symEj:
  508|   141M|  inline void fetch_sym(struct rans_dec_sym* out, uint32_t rem) {
  509|   141M|    uint32_t symbol = lut_table_[rem];
  510|   141M|    out->val = symbol;
  511|   141M|    out->prob = probability_table_[symbol].prob;
  512|   141M|    out->cum_prob = probability_table_[symbol].cum_prob;
  513|   141M|  }
_ZN5draco11RAnsDecoderILi20EE8read_endEv:
  459|    372|  inline int read_end() { return ans_.state == l_rans_base; }

_ZN5draco17RAnsSymbolDecoderILi5EEC2Ev:
   33|  1.79k|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi5EE6CreateEPNS_13DecoderBufferE:
   59|  1.79k|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|  1.79k|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 1.79k]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|  1.79k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|  1.79k|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  1.79k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 92, False: 1.70k]
  ------------------
   67|     92|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 9, False: 83]
  ------------------
   68|      9|      return false;
   69|      9|    }
   70|       |
   71|     92|  } else
   72|  1.70k|#endif
   73|  1.70k|  {
   74|  1.70k|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 69, False: 1.63k]
  ------------------
   75|     69|      return false;
   76|     69|    }
   77|  1.70k|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|  1.72k|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 96, False: 1.62k]
  ------------------
   83|     96|    return false;
   84|     96|  }
   85|  1.62k|  probability_table_.resize(num_symbols_);
   86|  1.62k|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 617, False: 1.00k]
  ------------------
   87|    617|    return true;
   88|    617|  }
   89|       |  // Decode the table.
   90|   587k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 586k, False: 726]
  ------------------
   91|   586k|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|   586k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 116, False: 586k]
  ------------------
   95|    116|      return false;
   96|    116|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|   586k|    const int token = prob_data & 3;
  102|   586k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 188k, False: 398k]
  ------------------
  103|   188k|      const uint32_t offset = prob_data >> 2;
  104|   188k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 115, False: 188k]
  ------------------
  105|    115|        return false;
  106|    115|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  8.35M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 8.17M, False: 188k]
  ------------------
  109|  8.17M|        probability_table_[i + j] = 0;
  110|  8.17M|      }
  111|   188k|      i += offset;
  112|   398k|    } else {
  113|   398k|      const int extra_bytes = token;
  114|   398k|      uint32_t prob = prob_data >> 2;
  115|   666k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 268k, False: 398k]
  ------------------
  116|   268k|        uint8_t eb;
  117|   268k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 50, False: 268k]
  ------------------
  118|     50|          return false;
  119|     50|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|   268k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|   268k|      }
  124|   398k|      probability_table_[i] = prob;
  125|   398k|    }
  126|   586k|  }
  127|    726|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 209, False: 517]
  ------------------
  128|    209|    return false;
  129|    209|  }
  130|    517|  return true;
  131|    726|}
_ZN5draco17RAnsSymbolDecoderILi5EE13StartDecodingEPNS_13DecoderBufferE:
  135|    945|    DecoderBuffer* buffer) {
  136|    945|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    945|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    945|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    945|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 56, False: 889]
  ------------------
  140|     56|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 10, False: 46]
  ------------------
  141|     10|      return false;
  142|     10|    }
  143|       |
  144|     56|  } else
  145|    889|#endif
  146|    889|  {
  147|    889|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 50, False: 839]
  ------------------
  148|     50|      return false;
  149|     50|    }
  150|    889|  }
  151|    885|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 158, False: 727]
  ------------------
  152|    158|    return false;
  153|    158|  }
  154|    727|  const uint8_t* const data_head =
  155|    727|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|    727|  buffer->Advance(bytes_encoded);
  158|    727|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 159, False: 568]
  ------------------
  159|    159|    return false;
  160|    159|  }
  161|    568|  return true;
  162|    727|}
_ZNK5draco17RAnsSymbolDecoderILi5EE11num_symbolsEv:
   38|    777|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi5EE12DecodeSymbolEv:
   43|  19.0M|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi5EE11EndDecodingEv:
  165|    484|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|    484|  ans_.read_end();
  167|    484|}
_ZN5draco17RAnsSymbolDecoderILi1EEC2Ev:
   33|    743|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi1EE6CreateEPNS_13DecoderBufferE:
   59|    743|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    743|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 743]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    743|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    743|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    743|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 74, False: 669]
  ------------------
   67|     74|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 7, False: 67]
  ------------------
   68|      7|      return false;
   69|      7|    }
   70|       |
   71|     74|  } else
   72|    669|#endif
   73|    669|  {
   74|    669|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 13, False: 656]
  ------------------
   75|     13|      return false;
   76|     13|    }
   77|    669|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|    723|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 66, False: 657]
  ------------------
   83|     66|    return false;
   84|     66|  }
   85|    657|  probability_table_.resize(num_symbols_);
   86|    657|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 24, False: 633]
  ------------------
   87|     24|    return true;
   88|     24|  }
   89|       |  // Decode the table.
   90|  1.89M|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 1.89M, False: 425]
  ------------------
   91|  1.89M|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|  1.89M|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 94, False: 1.89M]
  ------------------
   95|     94|      return false;
   96|     94|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|  1.89M|    const int token = prob_data & 3;
  102|  1.89M|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 471k, False: 1.42M]
  ------------------
  103|   471k|      const uint32_t offset = prob_data >> 2;
  104|   471k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 75, False: 471k]
  ------------------
  105|     75|        return false;
  106|     75|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  14.6M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 14.1M, False: 471k]
  ------------------
  109|  14.1M|        probability_table_[i + j] = 0;
  110|  14.1M|      }
  111|   471k|      i += offset;
  112|  1.42M|    } else {
  113|  1.42M|      const int extra_bytes = token;
  114|  1.42M|      uint32_t prob = prob_data >> 2;
  115|  1.43M|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 16.6k, False: 1.42M]
  ------------------
  116|  16.6k|        uint8_t eb;
  117|  16.6k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 39, False: 16.5k]
  ------------------
  118|     39|          return false;
  119|     39|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  16.5k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  16.5k|      }
  124|  1.42M|      probability_table_[i] = prob;
  125|  1.42M|    }
  126|  1.89M|  }
  127|    425|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 145, False: 280]
  ------------------
  128|    145|    return false;
  129|    145|  }
  130|    280|  return true;
  131|    425|}
_ZNK5draco17RAnsSymbolDecoderILi1EE11num_symbolsEv:
   38|    304|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi1EE13StartDecodingEPNS_13DecoderBufferE:
  135|    280|    DecoderBuffer* buffer) {
  136|    280|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    280|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    280|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    280|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 4, False: 276]
  ------------------
  140|      4|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 1, False: 3]
  ------------------
  141|      1|      return false;
  142|      1|    }
  143|       |
  144|      4|  } else
  145|    276|#endif
  146|    276|  {
  147|    276|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 7, False: 269]
  ------------------
  148|      7|      return false;
  149|      7|    }
  150|    276|  }
  151|    272|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 28, False: 244]
  ------------------
  152|     28|    return false;
  153|     28|  }
  154|    244|  const uint8_t* const data_head =
  155|    244|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|    244|  buffer->Advance(bytes_encoded);
  158|    244|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 27, False: 217]
  ------------------
  159|     27|    return false;
  160|     27|  }
  161|    217|  return true;
  162|    244|}
_ZN5draco17RAnsSymbolDecoderILi1EE12DecodeSymbolEv:
   43|  67.8M|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi1EE11EndDecodingEv:
  165|    217|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|    217|  ans_.read_end();
  167|    217|}
_ZN5draco17RAnsSymbolDecoderILi2EEC2Ev:
   33|    565|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi2EE6CreateEPNS_13DecoderBufferE:
   59|    565|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    565|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 565]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    565|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    565|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    565|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 23, False: 542]
  ------------------
   67|     23|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 2, False: 21]
  ------------------
   68|      2|      return false;
   69|      2|    }
   70|       |
   71|     23|  } else
   72|    542|#endif
   73|    542|  {
   74|    542|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 16, False: 526]
  ------------------
   75|     16|      return false;
   76|     16|    }
   77|    542|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|    547|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 41, False: 506]
  ------------------
   83|     41|    return false;
   84|     41|  }
   85|    506|  probability_table_.resize(num_symbols_);
   86|    506|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 15, False: 491]
  ------------------
   87|     15|    return true;
   88|     15|  }
   89|       |  // Decode the table.
   90|   915k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 914k, False: 357]
  ------------------
   91|   914k|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|   914k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 75, False: 914k]
  ------------------
   95|     75|      return false;
   96|     75|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|   914k|    const int token = prob_data & 3;
  102|   914k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 396k, False: 518k]
  ------------------
  103|   396k|      const uint32_t offset = prob_data >> 2;
  104|   396k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 25, False: 395k]
  ------------------
  105|     25|        return false;
  106|     25|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  12.7M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 12.3M, False: 395k]
  ------------------
  109|  12.3M|        probability_table_[i + j] = 0;
  110|  12.3M|      }
  111|   395k|      i += offset;
  112|   518k|    } else {
  113|   518k|      const int extra_bytes = token;
  114|   518k|      uint32_t prob = prob_data >> 2;
  115|   960k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 442k, False: 518k]
  ------------------
  116|   442k|        uint8_t eb;
  117|   442k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 34, False: 442k]
  ------------------
  118|     34|          return false;
  119|     34|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|   442k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|   442k|      }
  124|   518k|      probability_table_[i] = prob;
  125|   518k|    }
  126|   914k|  }
  127|    357|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 33, False: 324]
  ------------------
  128|     33|    return false;
  129|     33|  }
  130|    324|  return true;
  131|    357|}
_ZNK5draco17RAnsSymbolDecoderILi2EE11num_symbolsEv:
   38|    339|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi2EE13StartDecodingEPNS_13DecoderBufferE:
  135|    324|    DecoderBuffer* buffer) {
  136|    324|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    324|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    324|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    324|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 10, False: 314]
  ------------------
  140|     10|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 3, False: 7]
  ------------------
  141|      3|      return false;
  142|      3|    }
  143|       |
  144|     10|  } else
  145|    314|#endif
  146|    314|  {
  147|    314|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 12, False: 302]
  ------------------
  148|     12|      return false;
  149|     12|    }
  150|    314|  }
  151|    309|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 47, False: 262]
  ------------------
  152|     47|    return false;
  153|     47|  }
  154|    262|  const uint8_t* const data_head =
  155|    262|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|    262|  buffer->Advance(bytes_encoded);
  158|    262|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 23, False: 239]
  ------------------
  159|     23|    return false;
  160|     23|  }
  161|    239|  return true;
  162|    262|}
_ZN5draco17RAnsSymbolDecoderILi2EE12DecodeSymbolEv:
   43|  7.21M|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi2EE11EndDecodingEv:
  165|    239|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|    239|  ans_.read_end();
  167|    239|}
_ZN5draco17RAnsSymbolDecoderILi3EEC2Ev:
   33|    402|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi3EE6CreateEPNS_13DecoderBufferE:
   59|    402|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    402|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 402]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    402|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    402|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    402|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 48, False: 354]
  ------------------
   67|     48|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 1, False: 47]
  ------------------
   68|      1|      return false;
   69|      1|    }
   70|       |
   71|     48|  } else
   72|    354|#endif
   73|    354|  {
   74|    354|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 7, False: 347]
  ------------------
   75|      7|      return false;
   76|      7|    }
   77|    354|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|    394|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 18, False: 376]
  ------------------
   83|     18|    return false;
   84|     18|  }
   85|    376|  probability_table_.resize(num_symbols_);
   86|    376|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 12, False: 364]
  ------------------
   87|     12|    return true;
   88|     12|  }
   89|       |  // Decode the table.
   90|  6.57k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 6.34k, False: 231]
  ------------------
   91|  6.34k|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|  6.34k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 62, False: 6.28k]
  ------------------
   95|     62|      return false;
   96|     62|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|  6.28k|    const int token = prob_data & 3;
  102|  6.28k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 3.10k, False: 3.17k]
  ------------------
  103|  3.10k|      const uint32_t offset = prob_data >> 2;
  104|  3.10k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 35, False: 3.07k]
  ------------------
  105|     35|        return false;
  106|     35|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|   113k|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 110k, False: 3.07k]
  ------------------
  109|   110k|        probability_table_[i + j] = 0;
  110|   110k|      }
  111|  3.07k|      i += offset;
  112|  3.17k|    } else {
  113|  3.17k|      const int extra_bytes = token;
  114|  3.17k|      uint32_t prob = prob_data >> 2;
  115|  5.18k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 2.04k, False: 3.14k]
  ------------------
  116|  2.04k|        uint8_t eb;
  117|  2.04k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 36, False: 2.00k]
  ------------------
  118|     36|          return false;
  119|     36|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  2.00k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  2.00k|      }
  124|  3.14k|      probability_table_[i] = prob;
  125|  3.14k|    }
  126|  6.28k|  }
  127|    231|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 37, False: 194]
  ------------------
  128|     37|    return false;
  129|     37|  }
  130|    194|  return true;
  131|    231|}
_ZNK5draco17RAnsSymbolDecoderILi3EE11num_symbolsEv:
   38|    206|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi3EE13StartDecodingEPNS_13DecoderBufferE:
  135|    194|    DecoderBuffer* buffer) {
  136|    194|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    194|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    194|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    194|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 43, False: 151]
  ------------------
  140|     43|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 4, False: 39]
  ------------------
  141|      4|      return false;
  142|      4|    }
  143|       |
  144|     43|  } else
  145|    151|#endif
  146|    151|  {
  147|    151|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 2, False: 149]
  ------------------
  148|      2|      return false;
  149|      2|    }
  150|    151|  }
  151|    188|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 65, False: 123]
  ------------------
  152|     65|    return false;
  153|     65|  }
  154|    123|  const uint8_t* const data_head =
  155|    123|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|    123|  buffer->Advance(bytes_encoded);
  158|    123|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 31, False: 92]
  ------------------
  159|     31|    return false;
  160|     31|  }
  161|     92|  return true;
  162|    123|}
_ZN5draco17RAnsSymbolDecoderILi3EE12DecodeSymbolEv:
   43|  11.9M|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi3EE11EndDecodingEv:
  165|     92|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|     92|  ans_.read_end();
  167|     92|}
_ZN5draco17RAnsSymbolDecoderILi4EEC2Ev:
   33|    396|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi4EE6CreateEPNS_13DecoderBufferE:
   59|    396|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    396|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 396]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    396|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    396|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    396|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 22, False: 374]
  ------------------
   67|     22|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 2, False: 20]
  ------------------
   68|      2|      return false;
   69|      2|    }
   70|       |
   71|     22|  } else
   72|    374|#endif
   73|    374|  {
   74|    374|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 10, False: 364]
  ------------------
   75|     10|      return false;
   76|     10|    }
   77|    374|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|    384|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 10, False: 374]
  ------------------
   83|     10|    return false;
   84|     10|  }
   85|    374|  probability_table_.resize(num_symbols_);
   86|    374|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 13, False: 361]
  ------------------
   87|     13|    return true;
   88|     13|  }
   89|       |  // Decode the table.
   90|  8.66k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 8.44k, False: 220]
  ------------------
   91|  8.44k|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|  8.44k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 83, False: 8.35k]
  ------------------
   95|     83|      return false;
   96|     83|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|  8.35k|    const int token = prob_data & 3;
  102|  8.35k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 3.96k, False: 4.39k]
  ------------------
  103|  3.96k|      const uint32_t offset = prob_data >> 2;
  104|  3.96k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 30, False: 3.93k]
  ------------------
  105|     30|        return false;
  106|     30|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|   128k|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 124k, False: 3.93k]
  ------------------
  109|   124k|        probability_table_[i + j] = 0;
  110|   124k|      }
  111|  3.93k|      i += offset;
  112|  4.39k|    } else {
  113|  4.39k|      const int extra_bytes = token;
  114|  4.39k|      uint32_t prob = prob_data >> 2;
  115|  7.44k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 3.07k, False: 4.36k]
  ------------------
  116|  3.07k|        uint8_t eb;
  117|  3.07k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 28, False: 3.05k]
  ------------------
  118|     28|          return false;
  119|     28|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  3.05k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  3.05k|      }
  124|  4.36k|      probability_table_[i] = prob;
  125|  4.36k|    }
  126|  8.35k|  }
  127|    220|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 29, False: 191]
  ------------------
  128|     29|    return false;
  129|     29|  }
  130|    191|  return true;
  131|    220|}
_ZNK5draco17RAnsSymbolDecoderILi4EE11num_symbolsEv:
   38|    204|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi4EE13StartDecodingEPNS_13DecoderBufferE:
  135|    191|    DecoderBuffer* buffer) {
  136|    191|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    191|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    191|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    191|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 16, False: 175]
  ------------------
  140|     16|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 3, False: 13]
  ------------------
  141|      3|      return false;
  142|      3|    }
  143|       |
  144|     16|  } else
  145|    175|#endif
  146|    175|  {
  147|    175|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 5, False: 170]
  ------------------
  148|      5|      return false;
  149|      5|    }
  150|    175|  }
  151|    183|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 24, False: 159]
  ------------------
  152|     24|    return false;
  153|     24|  }
  154|    159|  const uint8_t* const data_head =
  155|    159|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|    159|  buffer->Advance(bytes_encoded);
  158|    159|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 29, False: 130]
  ------------------
  159|     29|    return false;
  160|     29|  }
  161|    130|  return true;
  162|    159|}
_ZN5draco17RAnsSymbolDecoderILi4EE12DecodeSymbolEv:
   43|  2.32M|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi4EE11EndDecodingEv:
  165|    130|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|    130|  ans_.read_end();
  167|    130|}
_ZN5draco17RAnsSymbolDecoderILi6EEC2Ev:
   33|    411|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi6EE6CreateEPNS_13DecoderBufferE:
   59|    411|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    411|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 411]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    411|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    411|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    411|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 30, False: 381]
  ------------------
   67|     30|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 1, False: 29]
  ------------------
   68|      1|      return false;
   69|      1|    }
   70|       |
   71|     30|  } else
   72|    381|#endif
   73|    381|  {
   74|    381|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 9, False: 372]
  ------------------
   75|      9|      return false;
   76|      9|    }
   77|    381|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|    401|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 21, False: 380]
  ------------------
   83|     21|    return false;
   84|     21|  }
   85|    380|  probability_table_.resize(num_symbols_);
   86|    380|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 9, False: 371]
  ------------------
   87|      9|    return true;
   88|      9|  }
   89|       |  // Decode the table.
   90|  5.31k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 5.06k, False: 252]
  ------------------
   91|  5.06k|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|  5.06k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 74, False: 4.99k]
  ------------------
   95|     74|      return false;
   96|     74|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|  4.99k|    const int token = prob_data & 3;
  102|  4.99k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 2.73k, False: 2.25k]
  ------------------
  103|  2.73k|      const uint32_t offset = prob_data >> 2;
  104|  2.73k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 25, False: 2.71k]
  ------------------
  105|     25|        return false;
  106|     25|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|   101k|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 98.9k, False: 2.71k]
  ------------------
  109|  98.9k|        probability_table_[i + j] = 0;
  110|  98.9k|      }
  111|  2.71k|      i += offset;
  112|  2.71k|    } else {
  113|  2.25k|      const int extra_bytes = token;
  114|  2.25k|      uint32_t prob = prob_data >> 2;
  115|  3.91k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 1.68k, False: 2.23k]
  ------------------
  116|  1.68k|        uint8_t eb;
  117|  1.68k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 20, False: 1.66k]
  ------------------
  118|     20|          return false;
  119|     20|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  1.66k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  1.66k|      }
  124|  2.23k|      probability_table_[i] = prob;
  125|  2.23k|    }
  126|  4.99k|  }
  127|    252|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 20, False: 232]
  ------------------
  128|     20|    return false;
  129|     20|  }
  130|    232|  return true;
  131|    252|}
_ZNK5draco17RAnsSymbolDecoderILi6EE11num_symbolsEv:
   38|    241|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi6EE13StartDecodingEPNS_13DecoderBufferE:
  135|    232|    DecoderBuffer* buffer) {
  136|    232|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    232|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    232|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    232|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 23, False: 209]
  ------------------
  140|     23|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 4, False: 19]
  ------------------
  141|      4|      return false;
  142|      4|    }
  143|       |
  144|     23|  } else
  145|    209|#endif
  146|    209|  {
  147|    209|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 3, False: 206]
  ------------------
  148|      3|      return false;
  149|      3|    }
  150|    209|  }
  151|    225|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 49, False: 176]
  ------------------
  152|     49|    return false;
  153|     49|  }
  154|    176|  const uint8_t* const data_head =
  155|    176|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|    176|  buffer->Advance(bytes_encoded);
  158|    176|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 40, False: 136]
  ------------------
  159|     40|    return false;
  160|     40|  }
  161|    136|  return true;
  162|    176|}
_ZN5draco17RAnsSymbolDecoderILi6EE12DecodeSymbolEv:
   43|  8.34M|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi6EE11EndDecodingEv:
  165|    136|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|    136|  ans_.read_end();
  167|    136|}
_ZN5draco17RAnsSymbolDecoderILi7EEC2Ev:
   33|    454|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi7EE6CreateEPNS_13DecoderBufferE:
   59|    454|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    454|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 454]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    454|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    454|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    454|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 34, False: 420]
  ------------------
   67|     34|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 1, False: 33]
  ------------------
   68|      1|      return false;
   69|      1|    }
   70|       |
   71|     34|  } else
   72|    420|#endif
   73|    420|  {
   74|    420|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 8, False: 412]
  ------------------
   75|      8|      return false;
   76|      8|    }
   77|    420|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|    445|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 17, False: 428]
  ------------------
   83|     17|    return false;
   84|     17|  }
   85|    428|  probability_table_.resize(num_symbols_);
   86|    428|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 15, False: 413]
  ------------------
   87|     15|    return true;
   88|     15|  }
   89|       |  // Decode the table.
   90|   667k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 667k, False: 266]
  ------------------
   91|   667k|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|   667k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 86, False: 667k]
  ------------------
   95|     86|      return false;
   96|     86|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|   667k|    const int token = prob_data & 3;
  102|   667k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 208k, False: 458k]
  ------------------
  103|   208k|      const uint32_t offset = prob_data >> 2;
  104|   208k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 30, False: 208k]
  ------------------
  105|     30|        return false;
  106|     30|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  7.28M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 7.08M, False: 208k]
  ------------------
  109|  7.08M|        probability_table_[i + j] = 0;
  110|  7.08M|      }
  111|   208k|      i += offset;
  112|   458k|    } else {
  113|   458k|      const int extra_bytes = token;
  114|   458k|      uint32_t prob = prob_data >> 2;
  115|   761k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 303k, False: 458k]
  ------------------
  116|   303k|        uint8_t eb;
  117|   303k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 31, False: 303k]
  ------------------
  118|     31|          return false;
  119|     31|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|   303k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|   303k|      }
  124|   458k|      probability_table_[i] = prob;
  125|   458k|    }
  126|   667k|  }
  127|    266|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 24, False: 242]
  ------------------
  128|     24|    return false;
  129|     24|  }
  130|    242|  return true;
  131|    266|}
_ZNK5draco17RAnsSymbolDecoderILi7EE11num_symbolsEv:
   38|    257|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi7EE13StartDecodingEPNS_13DecoderBufferE:
  135|    242|    DecoderBuffer* buffer) {
  136|    242|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    242|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    242|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    242|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 25, False: 217]
  ------------------
  140|     25|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 4, False: 21]
  ------------------
  141|      4|      return false;
  142|      4|    }
  143|       |
  144|     25|  } else
  145|    217|#endif
  146|    217|  {
  147|    217|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 1, False: 216]
  ------------------
  148|      1|      return false;
  149|      1|    }
  150|    217|  }
  151|    237|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 51, False: 186]
  ------------------
  152|     51|    return false;
  153|     51|  }
  154|    186|  const uint8_t* const data_head =
  155|    186|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|    186|  buffer->Advance(bytes_encoded);
  158|    186|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 35, False: 151]
  ------------------
  159|     35|    return false;
  160|     35|  }
  161|    151|  return true;
  162|    186|}
_ZN5draco17RAnsSymbolDecoderILi7EE12DecodeSymbolEv:
   43|  13.9M|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi7EE11EndDecodingEv:
  165|    151|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|    151|  ans_.read_end();
  167|    151|}
_ZN5draco17RAnsSymbolDecoderILi8EEC2Ev:
   33|    390|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi8EE6CreateEPNS_13DecoderBufferE:
   59|    390|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    390|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 390]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    390|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    390|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    390|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 16, False: 374]
  ------------------
   67|     16|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 2, False: 14]
  ------------------
   68|      2|      return false;
   69|      2|    }
   70|       |
   71|     16|  } else
   72|    374|#endif
   73|    374|  {
   74|    374|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 21, False: 353]
  ------------------
   75|     21|      return false;
   76|     21|    }
   77|    374|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|    367|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 21, False: 346]
  ------------------
   83|     21|    return false;
   84|     21|  }
   85|    346|  probability_table_.resize(num_symbols_);
   86|    346|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 11, False: 335]
  ------------------
   87|     11|    return true;
   88|     11|  }
   89|       |  // Decode the table.
   90|  14.4k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 14.2k, False: 210]
  ------------------
   91|  14.2k|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|  14.2k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 71, False: 14.1k]
  ------------------
   95|     71|      return false;
   96|     71|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|  14.1k|    const int token = prob_data & 3;
  102|  14.1k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 5.20k, False: 8.94k]
  ------------------
  103|  5.20k|      const uint32_t offset = prob_data >> 2;
  104|  5.20k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 32, False: 5.16k]
  ------------------
  105|     32|        return false;
  106|     32|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|   189k|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 183k, False: 5.16k]
  ------------------
  109|   183k|        probability_table_[i + j] = 0;
  110|   183k|      }
  111|  5.16k|      i += offset;
  112|  8.94k|    } else {
  113|  8.94k|      const int extra_bytes = token;
  114|  8.94k|      uint32_t prob = prob_data >> 2;
  115|  17.1k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 8.25k, False: 8.92k]
  ------------------
  116|  8.25k|        uint8_t eb;
  117|  8.25k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 22, False: 8.23k]
  ------------------
  118|     22|          return false;
  119|     22|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  8.23k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  8.23k|      }
  124|  8.92k|      probability_table_[i] = prob;
  125|  8.92k|    }
  126|  14.1k|  }
  127|    210|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 27, False: 183]
  ------------------
  128|     27|    return false;
  129|     27|  }
  130|    183|  return true;
  131|    210|}
_ZNK5draco17RAnsSymbolDecoderILi8EE11num_symbolsEv:
   38|    194|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi8EE13StartDecodingEPNS_13DecoderBufferE:
  135|    183|    DecoderBuffer* buffer) {
  136|    183|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    183|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    183|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    183|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 9, False: 174]
  ------------------
  140|      9|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 1, False: 8]
  ------------------
  141|      1|      return false;
  142|      1|    }
  143|       |
  144|      9|  } else
  145|    174|#endif
  146|    174|  {
  147|    174|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 2, False: 172]
  ------------------
  148|      2|      return false;
  149|      2|    }
  150|    174|  }
  151|    180|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 51, False: 129]
  ------------------
  152|     51|    return false;
  153|     51|  }
  154|    129|  const uint8_t* const data_head =
  155|    129|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|    129|  buffer->Advance(bytes_encoded);
  158|    129|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 41, False: 88]
  ------------------
  159|     41|    return false;
  160|     41|  }
  161|     88|  return true;
  162|    129|}
_ZN5draco17RAnsSymbolDecoderILi8EE12DecodeSymbolEv:
   43|  4.23M|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi8EE11EndDecodingEv:
  165|     88|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|     88|  ans_.read_end();
  167|     88|}
_ZN5draco17RAnsSymbolDecoderILi9EEC2Ev:
   33|    369|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi9EE6CreateEPNS_13DecoderBufferE:
   59|    369|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    369|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 369]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    369|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    369|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    369|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 13, False: 356]
  ------------------
   67|     13|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 1, False: 12]
  ------------------
   68|      1|      return false;
   69|      1|    }
   70|       |
   71|     13|  } else
   72|    356|#endif
   73|    356|  {
   74|    356|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 8, False: 348]
  ------------------
   75|      8|      return false;
   76|      8|    }
   77|    356|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|    360|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 15, False: 345]
  ------------------
   83|     15|    return false;
   84|     15|  }
   85|    345|  probability_table_.resize(num_symbols_);
   86|    345|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 14, False: 331]
  ------------------
   87|     14|    return true;
   88|     14|  }
   89|       |  // Decode the table.
   90|  21.5k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 21.3k, False: 212]
  ------------------
   91|  21.3k|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|  21.3k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 62, False: 21.3k]
  ------------------
   95|     62|      return false;
   96|     62|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|  21.3k|    const int token = prob_data & 3;
  102|  21.3k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 14.6k, False: 6.68k]
  ------------------
  103|  14.6k|      const uint32_t offset = prob_data >> 2;
  104|  14.6k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 33, False: 14.5k]
  ------------------
  105|     33|        return false;
  106|     33|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|   465k|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 450k, False: 14.5k]
  ------------------
  109|   450k|        probability_table_[i + j] = 0;
  110|   450k|      }
  111|  14.5k|      i += offset;
  112|  14.5k|    } else {
  113|  6.68k|      const int extra_bytes = token;
  114|  6.68k|      uint32_t prob = prob_data >> 2;
  115|  11.1k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 4.49k, False: 6.66k]
  ------------------
  116|  4.49k|        uint8_t eb;
  117|  4.49k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 24, False: 4.47k]
  ------------------
  118|     24|          return false;
  119|     24|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  4.47k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  4.47k|      }
  124|  6.66k|      probability_table_[i] = prob;
  125|  6.66k|    }
  126|  21.3k|  }
  127|    212|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 81, False: 131]
  ------------------
  128|     81|    return false;
  129|     81|  }
  130|    131|  return true;
  131|    212|}
_ZNK5draco17RAnsSymbolDecoderILi9EE11num_symbolsEv:
   38|    145|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi9EE13StartDecodingEPNS_13DecoderBufferE:
  135|    131|    DecoderBuffer* buffer) {
  136|    131|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    131|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    131|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    131|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 0, False: 131]
  ------------------
  140|      0|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 0, False: 0]
  ------------------
  141|      0|      return false;
  142|      0|    }
  143|       |
  144|      0|  } else
  145|    131|#endif
  146|    131|  {
  147|    131|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 1, False: 130]
  ------------------
  148|      1|      return false;
  149|      1|    }
  150|    131|  }
  151|    130|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 33, False: 97]
  ------------------
  152|     33|    return false;
  153|     33|  }
  154|     97|  const uint8_t* const data_head =
  155|     97|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|     97|  buffer->Advance(bytes_encoded);
  158|     97|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 30, False: 67]
  ------------------
  159|     30|    return false;
  160|     30|  }
  161|     67|  return true;
  162|     97|}
_ZN5draco17RAnsSymbolDecoderILi9EE12DecodeSymbolEv:
   43|   131k|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi9EE11EndDecodingEv:
  165|     67|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|     67|  ans_.read_end();
  167|     67|}
_ZN5draco17RAnsSymbolDecoderILi10EEC2Ev:
   33|    438|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi10EE6CreateEPNS_13DecoderBufferE:
   59|    438|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    438|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 438]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    438|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    438|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    438|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 8, False: 430]
  ------------------
   67|      8|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 1, False: 7]
  ------------------
   68|      1|      return false;
   69|      1|    }
   70|       |
   71|      8|  } else
   72|    430|#endif
   73|    430|  {
   74|    430|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 2, False: 428]
  ------------------
   75|      2|      return false;
   76|      2|    }
   77|    430|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|    435|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 15, False: 420]
  ------------------
   83|     15|    return false;
   84|     15|  }
   85|    420|  probability_table_.resize(num_symbols_);
   86|    420|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 8, False: 412]
  ------------------
   87|      8|    return true;
   88|      8|  }
   89|       |  // Decode the table.
   90|   118k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 118k, False: 255]
  ------------------
   91|   118k|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|   118k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 92, False: 118k]
  ------------------
   95|     92|      return false;
   96|     92|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|   118k|    const int token = prob_data & 3;
  102|   118k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 41.8k, False: 76.3k]
  ------------------
  103|  41.8k|      const uint32_t offset = prob_data >> 2;
  104|  41.8k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 40, False: 41.8k]
  ------------------
  105|     40|        return false;
  106|     40|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  1.47M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 1.43M, False: 41.8k]
  ------------------
  109|  1.43M|        probability_table_[i + j] = 0;
  110|  1.43M|      }
  111|  41.8k|      i += offset;
  112|  76.3k|    } else {
  113|  76.3k|      const int extra_bytes = token;
  114|  76.3k|      uint32_t prob = prob_data >> 2;
  115|   135k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 58.8k, False: 76.3k]
  ------------------
  116|  58.8k|        uint8_t eb;
  117|  58.8k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 25, False: 58.8k]
  ------------------
  118|     25|          return false;
  119|     25|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  58.8k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  58.8k|      }
  124|  76.3k|      probability_table_[i] = prob;
  125|  76.3k|    }
  126|   118k|  }
  127|    255|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 75, False: 180]
  ------------------
  128|     75|    return false;
  129|     75|  }
  130|    180|  return true;
  131|    255|}
_ZNK5draco17RAnsSymbolDecoderILi10EE11num_symbolsEv:
   38|    188|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi10EE13StartDecodingEPNS_13DecoderBufferE:
  135|    180|    DecoderBuffer* buffer) {
  136|    180|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    180|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    180|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    180|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 0, False: 180]
  ------------------
  140|      0|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 0, False: 0]
  ------------------
  141|      0|      return false;
  142|      0|    }
  143|       |
  144|      0|  } else
  145|    180|#endif
  146|    180|  {
  147|    180|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 3, False: 177]
  ------------------
  148|      3|      return false;
  149|      3|    }
  150|    180|  }
  151|    177|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 73, False: 104]
  ------------------
  152|     73|    return false;
  153|     73|  }
  154|    104|  const uint8_t* const data_head =
  155|    104|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|    104|  buffer->Advance(bytes_encoded);
  158|    104|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 23, False: 81]
  ------------------
  159|     23|    return false;
  160|     23|  }
  161|     81|  return true;
  162|    104|}
_ZN5draco17RAnsSymbolDecoderILi10EE12DecodeSymbolEv:
   43|   521k|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi10EE11EndDecodingEv:
  165|     81|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|     81|  ans_.read_end();
  167|     81|}
_ZN5draco17RAnsSymbolDecoderILi11EEC2Ev:
   33|    484|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi11EE6CreateEPNS_13DecoderBufferE:
   59|    484|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    484|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 484]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    484|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    484|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    484|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 37, False: 447]
  ------------------
   67|     37|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 1, False: 36]
  ------------------
   68|      1|      return false;
   69|      1|    }
   70|       |
   71|     37|  } else
   72|    447|#endif
   73|    447|  {
   74|    447|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 5, False: 442]
  ------------------
   75|      5|      return false;
   76|      5|    }
   77|    447|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|    478|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 29, False: 449]
  ------------------
   83|     29|    return false;
   84|     29|  }
   85|    449|  probability_table_.resize(num_symbols_);
   86|    449|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 6, False: 443]
  ------------------
   87|      6|    return true;
   88|      6|  }
   89|       |  // Decode the table.
   90|  28.6k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 28.3k, False: 309]
  ------------------
   91|  28.3k|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|  28.3k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 65, False: 28.2k]
  ------------------
   95|     65|      return false;
   96|     65|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|  28.2k|    const int token = prob_data & 3;
  102|  28.2k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 7.79k, False: 20.4k]
  ------------------
  103|  7.79k|      const uint32_t offset = prob_data >> 2;
  104|  7.79k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 45, False: 7.74k]
  ------------------
  105|     45|        return false;
  106|     45|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|   262k|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 255k, False: 7.74k]
  ------------------
  109|   255k|        probability_table_[i + j] = 0;
  110|   255k|      }
  111|  7.74k|      i += offset;
  112|  20.4k|    } else {
  113|  20.4k|      const int extra_bytes = token;
  114|  20.4k|      uint32_t prob = prob_data >> 2;
  115|  39.4k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 18.9k, False: 20.4k]
  ------------------
  116|  18.9k|        uint8_t eb;
  117|  18.9k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 24, False: 18.9k]
  ------------------
  118|     24|          return false;
  119|     24|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  18.9k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  18.9k|      }
  124|  20.4k|      probability_table_[i] = prob;
  125|  20.4k|    }
  126|  28.2k|  }
  127|    309|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 102, False: 207]
  ------------------
  128|    102|    return false;
  129|    102|  }
  130|    207|  return true;
  131|    309|}
_ZNK5draco17RAnsSymbolDecoderILi11EE11num_symbolsEv:
   38|    213|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi11EE13StartDecodingEPNS_13DecoderBufferE:
  135|    207|    DecoderBuffer* buffer) {
  136|    207|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    207|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    207|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    207|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 0, False: 207]
  ------------------
  140|      0|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 0, False: 0]
  ------------------
  141|      0|      return false;
  142|      0|    }
  143|       |
  144|      0|  } else
  145|    207|#endif
  146|    207|  {
  147|    207|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 3, False: 204]
  ------------------
  148|      3|      return false;
  149|      3|    }
  150|    207|  }
  151|    204|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 90, False: 114]
  ------------------
  152|     90|    return false;
  153|     90|  }
  154|    114|  const uint8_t* const data_head =
  155|    114|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|    114|  buffer->Advance(bytes_encoded);
  158|    114|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 57, False: 57]
  ------------------
  159|     57|    return false;
  160|     57|  }
  161|     57|  return true;
  162|    114|}
_ZN5draco17RAnsSymbolDecoderILi11EE12DecodeSymbolEv:
   43|  37.4k|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi11EE11EndDecodingEv:
  165|     57|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|     57|  ans_.read_end();
  167|     57|}
_ZN5draco17RAnsSymbolDecoderILi12EEC2Ev:
   33|    492|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi12EE6CreateEPNS_13DecoderBufferE:
   59|    492|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    492|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 492]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    492|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    492|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    492|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 13, False: 479]
  ------------------
   67|     13|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 1, False: 12]
  ------------------
   68|      1|      return false;
   69|      1|    }
   70|       |
   71|     13|  } else
   72|    479|#endif
   73|    479|  {
   74|    479|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 17, False: 462]
  ------------------
   75|     17|      return false;
   76|     17|    }
   77|    479|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|    474|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 16, False: 458]
  ------------------
   83|     16|    return false;
   84|     16|  }
   85|    458|  probability_table_.resize(num_symbols_);
   86|    458|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 13, False: 445]
  ------------------
   87|     13|    return true;
   88|     13|  }
   89|       |  // Decode the table.
   90|  25.2k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 24.9k, False: 292]
  ------------------
   91|  24.9k|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|  24.9k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 83, False: 24.8k]
  ------------------
   95|     83|      return false;
   96|     83|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|  24.8k|    const int token = prob_data & 3;
  102|  24.8k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 6.30k, False: 18.5k]
  ------------------
  103|  6.30k|      const uint32_t offset = prob_data >> 2;
  104|  6.30k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 46, False: 6.26k]
  ------------------
  105|     46|        return false;
  106|     46|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|   243k|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 236k, False: 6.26k]
  ------------------
  109|   236k|        probability_table_[i + j] = 0;
  110|   236k|      }
  111|  6.26k|      i += offset;
  112|  18.5k|    } else {
  113|  18.5k|      const int extra_bytes = token;
  114|  18.5k|      uint32_t prob = prob_data >> 2;
  115|  35.7k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 17.2k, False: 18.5k]
  ------------------
  116|  17.2k|        uint8_t eb;
  117|  17.2k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 24, False: 17.2k]
  ------------------
  118|     24|          return false;
  119|     24|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  17.2k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  17.2k|      }
  124|  18.5k|      probability_table_[i] = prob;
  125|  18.5k|    }
  126|  24.8k|  }
  127|    292|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 113, False: 179]
  ------------------
  128|    113|    return false;
  129|    113|  }
  130|    179|  return true;
  131|    292|}
_ZNK5draco17RAnsSymbolDecoderILi12EE11num_symbolsEv:
   38|    192|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi12EE13StartDecodingEPNS_13DecoderBufferE:
  135|    179|    DecoderBuffer* buffer) {
  136|    179|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    179|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    179|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    179|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 0, False: 179]
  ------------------
  140|      0|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 0, False: 0]
  ------------------
  141|      0|      return false;
  142|      0|    }
  143|       |
  144|      0|  } else
  145|    179|#endif
  146|    179|  {
  147|    179|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 3, False: 176]
  ------------------
  148|      3|      return false;
  149|      3|    }
  150|    179|  }
  151|    176|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 75, False: 101]
  ------------------
  152|     75|    return false;
  153|     75|  }
  154|    101|  const uint8_t* const data_head =
  155|    101|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|    101|  buffer->Advance(bytes_encoded);
  158|    101|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 40, False: 61]
  ------------------
  159|     40|    return false;
  160|     40|  }
  161|     61|  return true;
  162|    101|}
_ZN5draco17RAnsSymbolDecoderILi12EE12DecodeSymbolEv:
   43|   212k|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi12EE11EndDecodingEv:
  165|     61|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|     61|  ans_.read_end();
  167|     61|}
_ZN5draco17RAnsSymbolDecoderILi13EEC2Ev:
   33|    589|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi13EE6CreateEPNS_13DecoderBufferE:
   59|    589|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    589|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 589]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    589|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    589|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    589|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 25, False: 564]
  ------------------
   67|     25|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 1, False: 24]
  ------------------
   68|      1|      return false;
   69|      1|    }
   70|       |
   71|     25|  } else
   72|    564|#endif
   73|    564|  {
   74|    564|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 6, False: 558]
  ------------------
   75|      6|      return false;
   76|      6|    }
   77|    564|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|    582|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 29, False: 553]
  ------------------
   83|     29|    return false;
   84|     29|  }
   85|    553|  probability_table_.resize(num_symbols_);
   86|    553|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 13, False: 540]
  ------------------
   87|     13|    return true;
   88|     13|  }
   89|       |  // Decode the table.
   90|   389k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 388k, False: 381]
  ------------------
   91|   388k|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|   388k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 73, False: 388k]
  ------------------
   95|     73|      return false;
   96|     73|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|   388k|    const int token = prob_data & 3;
  102|   388k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 71.3k, False: 317k]
  ------------------
  103|  71.3k|      const uint32_t offset = prob_data >> 2;
  104|  71.3k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 50, False: 71.2k]
  ------------------
  105|     50|        return false;
  106|     50|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  2.42M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 2.35M, False: 71.2k]
  ------------------
  109|  2.35M|        probability_table_[i + j] = 0;
  110|  2.35M|      }
  111|  71.2k|      i += offset;
  112|   317k|    } else {
  113|   317k|      const int extra_bytes = token;
  114|   317k|      uint32_t prob = prob_data >> 2;
  115|   579k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 262k, False: 317k]
  ------------------
  116|   262k|        uint8_t eb;
  117|   262k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 36, False: 262k]
  ------------------
  118|     36|          return false;
  119|     36|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|   262k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|   262k|      }
  124|   317k|      probability_table_[i] = prob;
  125|   317k|    }
  126|   388k|  }
  127|    381|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 127, False: 254]
  ------------------
  128|    127|    return false;
  129|    127|  }
  130|    254|  return true;
  131|    381|}
_ZNK5draco17RAnsSymbolDecoderILi13EE11num_symbolsEv:
   38|    267|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi13EE13StartDecodingEPNS_13DecoderBufferE:
  135|    254|    DecoderBuffer* buffer) {
  136|    254|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    254|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    254|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    254|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 0, False: 254]
  ------------------
  140|      0|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 0, False: 0]
  ------------------
  141|      0|      return false;
  142|      0|    }
  143|       |
  144|      0|  } else
  145|    254|#endif
  146|    254|  {
  147|    254|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 6, False: 248]
  ------------------
  148|      6|      return false;
  149|      6|    }
  150|    254|  }
  151|    248|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 101, False: 147]
  ------------------
  152|    101|    return false;
  153|    101|  }
  154|    147|  const uint8_t* const data_head =
  155|    147|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|    147|  buffer->Advance(bytes_encoded);
  158|    147|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 54, False: 93]
  ------------------
  159|     54|    return false;
  160|     54|  }
  161|     93|  return true;
  162|    147|}
_ZN5draco17RAnsSymbolDecoderILi13EE12DecodeSymbolEv:
   43|   714k|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi13EE11EndDecodingEv:
  165|     93|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|     93|  ans_.read_end();
  167|     93|}
_ZN5draco17RAnsSymbolDecoderILi14EEC2Ev:
   33|    476|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi14EE6CreateEPNS_13DecoderBufferE:
   59|    476|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    476|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 476]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    476|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    476|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    476|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 32, False: 444]
  ------------------
   67|     32|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 1, False: 31]
  ------------------
   68|      1|      return false;
   69|      1|    }
   70|       |
   71|     32|  } else
   72|    444|#endif
   73|    444|  {
   74|    444|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 4, False: 440]
  ------------------
   75|      4|      return false;
   76|      4|    }
   77|    444|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|    471|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 42, False: 429]
  ------------------
   83|     42|    return false;
   84|     42|  }
   85|    429|  probability_table_.resize(num_symbols_);
   86|    429|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 11, False: 418]
  ------------------
   87|     11|    return true;
   88|     11|  }
   89|       |  // Decode the table.
   90|   172k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 172k, False: 259]
  ------------------
   91|   172k|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|   172k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 81, False: 172k]
  ------------------
   95|     81|      return false;
   96|     81|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|   172k|    const int token = prob_data & 3;
  102|   172k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 93.9k, False: 78.3k]
  ------------------
  103|  93.9k|      const uint32_t offset = prob_data >> 2;
  104|  93.9k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 42, False: 93.9k]
  ------------------
  105|     42|        return false;
  106|     42|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  4.42M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 4.32M, False: 93.9k]
  ------------------
  109|  4.32M|        probability_table_[i + j] = 0;
  110|  4.32M|      }
  111|  93.9k|      i += offset;
  112|  93.9k|    } else {
  113|  78.3k|      const int extra_bytes = token;
  114|  78.3k|      uint32_t prob = prob_data >> 2;
  115|   124k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 45.9k, False: 78.3k]
  ------------------
  116|  45.9k|        uint8_t eb;
  117|  45.9k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 36, False: 45.9k]
  ------------------
  118|     36|          return false;
  119|     36|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  45.9k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  45.9k|      }
  124|  78.3k|      probability_table_[i] = prob;
  125|  78.3k|    }
  126|   172k|  }
  127|    259|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 45, False: 214]
  ------------------
  128|     45|    return false;
  129|     45|  }
  130|    214|  return true;
  131|    259|}
_ZNK5draco17RAnsSymbolDecoderILi14EE11num_symbolsEv:
   38|    225|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi14EE13StartDecodingEPNS_13DecoderBufferE:
  135|    214|    DecoderBuffer* buffer) {
  136|    214|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    214|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    214|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    214|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 4, False: 210]
  ------------------
  140|      4|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 1, False: 3]
  ------------------
  141|      1|      return false;
  142|      1|    }
  143|       |
  144|      4|  } else
  145|    210|#endif
  146|    210|  {
  147|    210|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 7, False: 203]
  ------------------
  148|      7|      return false;
  149|      7|    }
  150|    210|  }
  151|    206|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 90, False: 116]
  ------------------
  152|     90|    return false;
  153|     90|  }
  154|    116|  const uint8_t* const data_head =
  155|    116|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|    116|  buffer->Advance(bytes_encoded);
  158|    116|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 46, False: 70]
  ------------------
  159|     46|    return false;
  160|     46|  }
  161|     70|  return true;
  162|    116|}
_ZN5draco17RAnsSymbolDecoderILi14EE12DecodeSymbolEv:
   43|  9.93M|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi14EE11EndDecodingEv:
  165|     70|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|     70|  ans_.read_end();
  167|     70|}
_ZN5draco17RAnsSymbolDecoderILi15EEC2Ev:
   33|    494|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi15EE6CreateEPNS_13DecoderBufferE:
   59|    494|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    494|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 494]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    494|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    494|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    494|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 74, False: 420]
  ------------------
   67|     74|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 2, False: 72]
  ------------------
   68|      2|      return false;
   69|      2|    }
   70|       |
   71|     74|  } else
   72|    420|#endif
   73|    420|  {
   74|    420|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 5, False: 415]
  ------------------
   75|      5|      return false;
   76|      5|    }
   77|    420|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|    487|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 27, False: 460]
  ------------------
   83|     27|    return false;
   84|     27|  }
   85|    460|  probability_table_.resize(num_symbols_);
   86|    460|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 21, False: 439]
  ------------------
   87|     21|    return true;
   88|     21|  }
   89|       |  // Decode the table.
   90|   385k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 385k, False: 286]
  ------------------
   91|   385k|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|   385k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 81, False: 385k]
  ------------------
   95|     81|      return false;
   96|     81|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|   385k|    const int token = prob_data & 3;
  102|   385k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 39.6k, False: 345k]
  ------------------
  103|  39.6k|      const uint32_t offset = prob_data >> 2;
  104|  39.6k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 39, False: 39.6k]
  ------------------
  105|     39|        return false;
  106|     39|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  1.78M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 1.74M, False: 39.6k]
  ------------------
  109|  1.74M|        probability_table_[i + j] = 0;
  110|  1.74M|      }
  111|  39.6k|      i += offset;
  112|   345k|    } else {
  113|   345k|      const int extra_bytes = token;
  114|   345k|      uint32_t prob = prob_data >> 2;
  115|   445k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 99.8k, False: 345k]
  ------------------
  116|  99.8k|        uint8_t eb;
  117|  99.8k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 33, False: 99.8k]
  ------------------
  118|     33|          return false;
  119|     33|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  99.8k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  99.8k|      }
  124|   345k|      probability_table_[i] = prob;
  125|   345k|    }
  126|   385k|  }
  127|    286|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 59, False: 227]
  ------------------
  128|     59|    return false;
  129|     59|  }
  130|    227|  return true;
  131|    286|}
_ZNK5draco17RAnsSymbolDecoderILi15EE11num_symbolsEv:
   38|    248|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi15EE13StartDecodingEPNS_13DecoderBufferE:
  135|    227|    DecoderBuffer* buffer) {
  136|    227|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    227|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    227|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    227|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 60, False: 167]
  ------------------
  140|     60|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 2, False: 58]
  ------------------
  141|      2|      return false;
  142|      2|    }
  143|       |
  144|     60|  } else
  145|    167|#endif
  146|    167|  {
  147|    167|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 10, False: 157]
  ------------------
  148|     10|      return false;
  149|     10|    }
  150|    167|  }
  151|    215|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 94, False: 121]
  ------------------
  152|     94|    return false;
  153|     94|  }
  154|    121|  const uint8_t* const data_head =
  155|    121|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|    121|  buffer->Advance(bytes_encoded);
  158|    121|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 51, False: 70]
  ------------------
  159|     51|    return false;
  160|     51|  }
  161|     70|  return true;
  162|    121|}
_ZN5draco17RAnsSymbolDecoderILi15EE12DecodeSymbolEv:
   43|  4.27M|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi15EE11EndDecodingEv:
  165|     70|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|     70|  ans_.read_end();
  167|     70|}
_ZN5draco17RAnsSymbolDecoderILi16EEC2Ev:
   33|    426|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi16EE6CreateEPNS_13DecoderBufferE:
   59|    426|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    426|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 426]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    426|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    426|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    426|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 53, False: 373]
  ------------------
   67|     53|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 1, False: 52]
  ------------------
   68|      1|      return false;
   69|      1|    }
   70|       |
   71|     53|  } else
   72|    373|#endif
   73|    373|  {
   74|    373|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 14, False: 359]
  ------------------
   75|     14|      return false;
   76|     14|    }
   77|    373|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|    411|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 15, False: 396]
  ------------------
   83|     15|    return false;
   84|     15|  }
   85|    396|  probability_table_.resize(num_symbols_);
   86|    396|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 3, False: 393]
  ------------------
   87|      3|    return true;
   88|      3|  }
   89|       |  // Decode the table.
   90|  9.43k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 9.18k, False: 248]
  ------------------
   91|  9.18k|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|  9.18k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 78, False: 9.10k]
  ------------------
   95|     78|      return false;
   96|     78|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|  9.10k|    const int token = prob_data & 3;
  102|  9.10k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 3.87k, False: 5.23k]
  ------------------
  103|  3.87k|      const uint32_t offset = prob_data >> 2;
  104|  3.87k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 42, False: 3.83k]
  ------------------
  105|     42|        return false;
  106|     42|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|   143k|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 139k, False: 3.83k]
  ------------------
  109|   139k|        probability_table_[i + j] = 0;
  110|   139k|      }
  111|  3.83k|      i += offset;
  112|  5.23k|    } else {
  113|  5.23k|      const int extra_bytes = token;
  114|  5.23k|      uint32_t prob = prob_data >> 2;
  115|  9.17k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 3.96k, False: 5.21k]
  ------------------
  116|  3.96k|        uint8_t eb;
  117|  3.96k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 25, False: 3.94k]
  ------------------
  118|     25|          return false;
  119|     25|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  3.94k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  3.94k|      }
  124|  5.21k|      probability_table_[i] = prob;
  125|  5.21k|    }
  126|  9.10k|  }
  127|    248|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 31, False: 217]
  ------------------
  128|     31|    return false;
  129|     31|  }
  130|    217|  return true;
  131|    248|}
_ZNK5draco17RAnsSymbolDecoderILi16EE11num_symbolsEv:
   38|    220|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi16EE13StartDecodingEPNS_13DecoderBufferE:
  135|    217|    DecoderBuffer* buffer) {
  136|    217|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    217|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    217|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    217|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 43, False: 174]
  ------------------
  140|     43|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 2, False: 41]
  ------------------
  141|      2|      return false;
  142|      2|    }
  143|       |
  144|     43|  } else
  145|    174|#endif
  146|    174|  {
  147|    174|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 14, False: 160]
  ------------------
  148|     14|      return false;
  149|     14|    }
  150|    174|  }
  151|    201|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 101, False: 100]
  ------------------
  152|    101|    return false;
  153|    101|  }
  154|    100|  const uint8_t* const data_head =
  155|    100|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|    100|  buffer->Advance(bytes_encoded);
  158|    100|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 33, False: 67]
  ------------------
  159|     33|    return false;
  160|     33|  }
  161|     67|  return true;
  162|    100|}
_ZN5draco17RAnsSymbolDecoderILi16EE12DecodeSymbolEv:
   43|  21.7M|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi16EE11EndDecodingEv:
  165|     67|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|     67|  ans_.read_end();
  167|     67|}
_ZN5draco17RAnsSymbolDecoderILi17EEC2Ev:
   33|    476|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi17EE6CreateEPNS_13DecoderBufferE:
   59|    476|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    476|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 476]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    476|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    476|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    476|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 66, False: 410]
  ------------------
   67|     66|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 2, False: 64]
  ------------------
   68|      2|      return false;
   69|      2|    }
   70|       |
   71|     66|  } else
   72|    410|#endif
   73|    410|  {
   74|    410|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 14, False: 396]
  ------------------
   75|     14|      return false;
   76|     14|    }
   77|    410|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|    460|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 25, False: 435]
  ------------------
   83|     25|    return false;
   84|     25|  }
   85|    435|  probability_table_.resize(num_symbols_);
   86|    435|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 13, False: 422]
  ------------------
   87|     13|    return true;
   88|     13|  }
   89|       |  // Decode the table.
   90|  17.9k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 17.6k, False: 259]
  ------------------
   91|  17.6k|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|  17.6k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 85, False: 17.5k]
  ------------------
   95|     85|      return false;
   96|     85|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|  17.5k|    const int token = prob_data & 3;
  102|  17.5k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 6.97k, False: 10.5k]
  ------------------
  103|  6.97k|      const uint32_t offset = prob_data >> 2;
  104|  6.97k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 42, False: 6.93k]
  ------------------
  105|     42|        return false;
  106|     42|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|   312k|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 305k, False: 6.93k]
  ------------------
  109|   305k|        probability_table_[i + j] = 0;
  110|   305k|      }
  111|  6.93k|      i += offset;
  112|  10.5k|    } else {
  113|  10.5k|      const int extra_bytes = token;
  114|  10.5k|      uint32_t prob = prob_data >> 2;
  115|  17.8k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 7.28k, False: 10.5k]
  ------------------
  116|  7.28k|        uint8_t eb;
  117|  7.28k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 36, False: 7.24k]
  ------------------
  118|     36|          return false;
  119|     36|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  7.24k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  7.24k|      }
  124|  10.5k|      probability_table_[i] = prob;
  125|  10.5k|    }
  126|  17.5k|  }
  127|    259|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 36, False: 223]
  ------------------
  128|     36|    return false;
  129|     36|  }
  130|    223|  return true;
  131|    259|}
_ZNK5draco17RAnsSymbolDecoderILi17EE11num_symbolsEv:
   38|    236|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi17EE13StartDecodingEPNS_13DecoderBufferE:
  135|    223|    DecoderBuffer* buffer) {
  136|    223|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    223|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    223|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    223|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 44, False: 179]
  ------------------
  140|     44|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 5, False: 39]
  ------------------
  141|      5|      return false;
  142|      5|    }
  143|       |
  144|     44|  } else
  145|    179|#endif
  146|    179|  {
  147|    179|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 2, False: 177]
  ------------------
  148|      2|      return false;
  149|      2|    }
  150|    179|  }
  151|    216|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 104, False: 112]
  ------------------
  152|    104|    return false;
  153|    104|  }
  154|    112|  const uint8_t* const data_head =
  155|    112|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|    112|  buffer->Advance(bytes_encoded);
  158|    112|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 33, False: 79]
  ------------------
  159|     33|    return false;
  160|     33|  }
  161|     79|  return true;
  162|    112|}
_ZN5draco17RAnsSymbolDecoderILi17EE12DecodeSymbolEv:
   43|  34.8M|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi17EE11EndDecodingEv:
  165|     79|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|     79|  ans_.read_end();
  167|     79|}
_ZN5draco17RAnsSymbolDecoderILi18EEC2Ev:
   33|    449|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi18EE6CreateEPNS_13DecoderBufferE:
   59|    449|    DecoderBuffer* buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    449|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 449]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    449|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    449|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    449|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 95, False: 354]
  ------------------
   67|     95|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 2, False: 93]
  ------------------
   68|      2|      return false;
   69|      2|    }
   70|       |
   71|     95|  } else
   72|    354|#endif
   73|    354|  {
   74|    354|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 16, False: 338]
  ------------------
   75|     16|      return false;
   76|     16|    }
   77|    354|  }
   78|       |  // Check that decoded number of symbols is not unreasonably high. Remaining
   79|       |  // buffer size must be at least |num_symbols| / 64 bytes to contain the
   80|       |  // probability table. The |prob_data| below is one byte but it can be
   81|       |  // theoretically stored for each 64th symbol.
   82|    431|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 20, False: 411]
  ------------------
   83|     20|    return false;
   84|     20|  }
   85|    411|  probability_table_.resize(num_symbols_);
   86|    411|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 7, False: 404]
  ------------------
   87|      7|    return true;
   88|      7|  }
   89|       |  // Decode the table.
   90|  11.3k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 11.1k, False: 246]
  ------------------
   91|  11.1k|    uint8_t prob_data = 0;
   92|       |    // Decode the first byte and extract the number of extra bytes we need to
   93|       |    // get, or the offset to the next symbol with non-zero probability.
   94|  11.1k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 87, False: 11.0k]
  ------------------
   95|     87|      return false;
   96|     87|    }
   97|       |    // Token is stored in the first two bits of the first byte. Values 0-2 are
   98|       |    // used to indicate the number of extra bytes, and value 3 is a special
   99|       |    // symbol used to denote run-length coding of zero probability entries.
  100|       |    // See rans_symbol_encoder.h for more details.
  101|  11.0k|    const int token = prob_data & 3;
  102|  11.0k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 5.59k, False: 5.46k]
  ------------------
  103|  5.59k|      const uint32_t offset = prob_data >> 2;
  104|  5.59k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 40, False: 5.55k]
  ------------------
  105|     40|        return false;
  106|     40|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|   204k|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 198k, False: 5.55k]
  ------------------
  109|   198k|        probability_table_[i + j] = 0;
  110|   198k|      }
  111|  5.55k|      i += offset;
  112|  5.55k|    } else {
  113|  5.46k|      const int extra_bytes = token;
  114|  5.46k|      uint32_t prob = prob_data >> 2;
  115|  9.27k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 3.83k, False: 5.43k]
  ------------------
  116|  3.83k|        uint8_t eb;
  117|  3.83k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 31, False: 3.80k]
  ------------------
  118|     31|          return false;
  119|     31|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  3.80k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  3.80k|      }
  124|  5.43k|      probability_table_[i] = prob;
  125|  5.43k|    }
  126|  11.0k|  }
  127|    246|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 34, False: 212]
  ------------------
  128|     34|    return false;
  129|     34|  }
  130|    212|  return true;
  131|    246|}
_ZNK5draco17RAnsSymbolDecoderILi18EE11num_symbolsEv:
   38|    219|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi18EE13StartDecodingEPNS_13DecoderBufferE:
  135|    212|    DecoderBuffer* buffer) {
  136|    212|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|    212|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|    212|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    212|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 77, False: 135]
  ------------------
  140|     77|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 3, False: 74]
  ------------------
  141|      3|      return false;
  142|      3|    }
  143|       |
  144|     77|  } else
  145|    135|#endif
  146|    135|  {
  147|    135|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 3, False: 132]
  ------------------
  148|      3|      return false;
  149|      3|    }
  150|    135|  }
  151|    206|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 111, False: 95]
  ------------------
  152|    111|    return false;
  153|    111|  }
  154|     95|  const uint8_t* const data_head =
  155|     95|      reinterpret_cast<const uint8_t*>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|     95|  buffer->Advance(bytes_encoded);
  158|     95|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 9, False: 86]
  ------------------
  159|      9|    return false;
  160|      9|  }
  161|     86|  return true;
  162|     95|}
_ZN5draco17RAnsSymbolDecoderILi18EE12DecodeSymbolEv:
   43|  71.0M|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi18EE11EndDecodingEv:
  165|     86|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|     86|  ans_.read_end();
  167|     86|}

_ZN5draco13DecodeSymbolsEjiPNS_13DecoderBufferEPj:
   33|  13.2k|                   DecoderBuffer* src_buffer, uint32_t* out_values) {
   34|  13.2k|  if (num_values == 0) {
  ------------------
  |  Branch (34:7): [True: 30, False: 13.2k]
  ------------------
   35|     30|    return true;
   36|     30|  }
   37|       |  // Decode which scheme to use.
   38|  13.2k|  uint8_t scheme;
   39|  13.2k|  if (!src_buffer->Decode(&scheme)) {
  ------------------
  |  Branch (39:7): [True: 247, False: 12.9k]
  ------------------
   40|    247|    return false;
   41|    247|  }
   42|  12.9k|  if (scheme == SYMBOL_CODING_TAGGED) {
  ------------------
  |  Branch (42:7): [True: 1.44k, False: 11.5k]
  ------------------
   43|  1.44k|    return DecodeTaggedSymbols<RAnsSymbolDecoder>(num_values, num_components,
   44|  1.44k|                                                  src_buffer, out_values);
   45|  11.5k|  } else if (scheme == SYMBOL_CODING_RAW) {
  ------------------
  |  Branch (45:14): [True: 8.79k, False: 2.76k]
  ------------------
   46|  8.79k|    return DecodeRawSymbols<RAnsSymbolDecoder>(num_values, src_buffer,
   47|  8.79k|                                               out_values);
   48|  8.79k|  }
   49|  2.76k|  return false;
   50|  12.9k|}
_ZN5draco19DecodeTaggedSymbolsINS_17RAnsSymbolDecoderEEEbjiPNS_13DecoderBufferEPj:
   54|  1.44k|                         DecoderBuffer* src_buffer, uint32_t* out_values) {
   55|       |  // Decode the encoded data.
   56|  1.44k|  SymbolDecoderT<5> tag_decoder;
   57|  1.44k|  if (!tag_decoder.Create(src_buffer)) {
  ------------------
  |  Branch (57:7): [True: 631, False: 810]
  ------------------
   58|    631|    return false;
   59|    631|  }
   60|       |
   61|    810|  if (!tag_decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (61:7): [True: 357, False: 453]
  ------------------
   62|    357|    return false;
   63|    357|  }
   64|       |
   65|    453|  if (num_values > 0 && tag_decoder.num_symbols() == 0) {
  ------------------
  |  Branch (65:7): [True: 453, False: 0]
  |  Branch (65:25): [True: 81, False: 372]
  ------------------
   66|     81|    return false;  // Wrong number of symbols.
   67|     81|  }
   68|       |
   69|       |  // src_buffer now points behind the encoded tag data (to the place where the
   70|       |  // values are encoded).
   71|    372|  src_buffer->StartBitDecoding(false, nullptr);
   72|    372|  int value_id = 0;
   73|  6.50M|  for (uint32_t i = 0; i < num_values; i += num_components) {
  ------------------
  |  Branch (73:24): [True: 6.50M, False: 369]
  ------------------
   74|       |    // Decode the tag.
   75|  6.50M|    const uint32_t bit_length = tag_decoder.DecodeSymbol();
   76|       |    // Decode the actual value.
   77|  13.5M|    for (int j = 0; j < num_components; ++j) {
  ------------------
  |  Branch (77:21): [True: 7.04M, False: 6.50M]
  ------------------
   78|  7.04M|      uint32_t val;
   79|  7.04M|      if (!src_buffer->DecodeLeastSignificantBits32(bit_length, &val)) {
  ------------------
  |  Branch (79:11): [True: 3, False: 7.04M]
  ------------------
   80|      3|        return false;
   81|      3|      }
   82|  7.04M|      out_values[value_id++] = val;
   83|  7.04M|    }
   84|  6.50M|  }
   85|    369|  tag_decoder.EndDecoding();
   86|    369|  src_buffer->EndBitDecoding();
   87|    369|  return true;
   88|    372|}
_ZN5draco16DecodeRawSymbolsINS_17RAnsSymbolDecoderEEEbjPNS_13DecoderBufferEPj:
  116|  8.79k|                      uint32_t* out_values) {
  117|  8.79k|  uint8_t max_bit_length;
  118|  8.79k|  if (!src_buffer->Decode(&max_bit_length)) {
  ------------------
  |  Branch (118:7): [True: 43, False: 8.75k]
  ------------------
  119|     43|    return false;
  120|     43|  }
  121|  8.75k|  switch (max_bit_length) {
  122|    743|    case 1:
  ------------------
  |  Branch (122:5): [True: 743, False: 8.00k]
  ------------------
  123|    743|      return DecodeRawSymbolsInternal<SymbolDecoderT<1>>(num_values, src_buffer,
  124|    743|                                                         out_values);
  125|    565|    case 2:
  ------------------
  |  Branch (125:5): [True: 565, False: 8.18k]
  ------------------
  126|    565|      return DecodeRawSymbolsInternal<SymbolDecoderT<2>>(num_values, src_buffer,
  127|    565|                                                         out_values);
  128|    402|    case 3:
  ------------------
  |  Branch (128:5): [True: 402, False: 8.34k]
  ------------------
  129|    402|      return DecodeRawSymbolsInternal<SymbolDecoderT<3>>(num_values, src_buffer,
  130|    402|                                                         out_values);
  131|    396|    case 4:
  ------------------
  |  Branch (131:5): [True: 396, False: 8.35k]
  ------------------
  132|    396|      return DecodeRawSymbolsInternal<SymbolDecoderT<4>>(num_values, src_buffer,
  133|    396|                                                         out_values);
  134|    357|    case 5:
  ------------------
  |  Branch (134:5): [True: 357, False: 8.39k]
  ------------------
  135|    357|      return DecodeRawSymbolsInternal<SymbolDecoderT<5>>(num_values, src_buffer,
  136|    357|                                                         out_values);
  137|    411|    case 6:
  ------------------
  |  Branch (137:5): [True: 411, False: 8.33k]
  ------------------
  138|    411|      return DecodeRawSymbolsInternal<SymbolDecoderT<6>>(num_values, src_buffer,
  139|    411|                                                         out_values);
  140|    454|    case 7:
  ------------------
  |  Branch (140:5): [True: 454, False: 8.29k]
  ------------------
  141|    454|      return DecodeRawSymbolsInternal<SymbolDecoderT<7>>(num_values, src_buffer,
  142|    454|                                                         out_values);
  143|    390|    case 8:
  ------------------
  |  Branch (143:5): [True: 390, False: 8.36k]
  ------------------
  144|    390|      return DecodeRawSymbolsInternal<SymbolDecoderT<8>>(num_values, src_buffer,
  145|    390|                                                         out_values);
  146|    369|    case 9:
  ------------------
  |  Branch (146:5): [True: 369, False: 8.38k]
  ------------------
  147|    369|      return DecodeRawSymbolsInternal<SymbolDecoderT<9>>(num_values, src_buffer,
  148|    369|                                                         out_values);
  149|    438|    case 10:
  ------------------
  |  Branch (149:5): [True: 438, False: 8.31k]
  ------------------
  150|    438|      return DecodeRawSymbolsInternal<SymbolDecoderT<10>>(
  151|    438|          num_values, src_buffer, out_values);
  152|    484|    case 11:
  ------------------
  |  Branch (152:5): [True: 484, False: 8.26k]
  ------------------
  153|    484|      return DecodeRawSymbolsInternal<SymbolDecoderT<11>>(
  154|    484|          num_values, src_buffer, out_values);
  155|    492|    case 12:
  ------------------
  |  Branch (155:5): [True: 492, False: 8.25k]
  ------------------
  156|    492|      return DecodeRawSymbolsInternal<SymbolDecoderT<12>>(
  157|    492|          num_values, src_buffer, out_values);
  158|    589|    case 13:
  ------------------
  |  Branch (158:5): [True: 589, False: 8.16k]
  ------------------
  159|    589|      return DecodeRawSymbolsInternal<SymbolDecoderT<13>>(
  160|    589|          num_values, src_buffer, out_values);
  161|    476|    case 14:
  ------------------
  |  Branch (161:5): [True: 476, False: 8.27k]
  ------------------
  162|    476|      return DecodeRawSymbolsInternal<SymbolDecoderT<14>>(
  163|    476|          num_values, src_buffer, out_values);
  164|    494|    case 15:
  ------------------
  |  Branch (164:5): [True: 494, False: 8.25k]
  ------------------
  165|    494|      return DecodeRawSymbolsInternal<SymbolDecoderT<15>>(
  166|    494|          num_values, src_buffer, out_values);
  167|    426|    case 16:
  ------------------
  |  Branch (167:5): [True: 426, False: 8.32k]
  ------------------
  168|    426|      return DecodeRawSymbolsInternal<SymbolDecoderT<16>>(
  169|    426|          num_values, src_buffer, out_values);
  170|    476|    case 17:
  ------------------
  |  Branch (170:5): [True: 476, False: 8.27k]
  ------------------
  171|    476|      return DecodeRawSymbolsInternal<SymbolDecoderT<17>>(
  172|    476|          num_values, src_buffer, out_values);
  173|    449|    case 18:
  ------------------
  |  Branch (173:5): [True: 449, False: 8.30k]
  ------------------
  174|    449|      return DecodeRawSymbolsInternal<SymbolDecoderT<18>>(
  175|    449|          num_values, src_buffer, out_values);
  176|    339|    default:
  ------------------
  |  Branch (176:5): [True: 339, False: 8.41k]
  ------------------
  177|    339|      return false;
  178|  8.75k|  }
  179|  8.75k|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi1EEEEEbjPNS_13DecoderBufferEPj:
   92|    743|                              uint32_t* out_values) {
   93|    743|  SymbolDecoderT decoder;
   94|    743|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 439, False: 304]
  ------------------
   95|    439|    return false;
   96|    439|  }
   97|       |
   98|    304|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 304, False: 0]
  |  Branch (98:25): [True: 24, False: 280]
  ------------------
   99|     24|    return false;  // Wrong number of symbols.
  100|     24|  }
  101|       |
  102|    280|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 63, False: 217]
  ------------------
  103|     63|    return false;
  104|     63|  }
  105|  67.8M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 67.8M, False: 217]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  67.8M|    const uint32_t value = decoder.DecodeSymbol();
  108|  67.8M|    out_values[i] = value;
  109|  67.8M|  }
  110|    217|  decoder.EndDecoding();
  111|    217|  return true;
  112|    280|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi2EEEEEbjPNS_13DecoderBufferEPj:
   92|    565|                              uint32_t* out_values) {
   93|    565|  SymbolDecoderT decoder;
   94|    565|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 226, False: 339]
  ------------------
   95|    226|    return false;
   96|    226|  }
   97|       |
   98|    339|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 339, False: 0]
  |  Branch (98:25): [True: 15, False: 324]
  ------------------
   99|     15|    return false;  // Wrong number of symbols.
  100|     15|  }
  101|       |
  102|    324|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 85, False: 239]
  ------------------
  103|     85|    return false;
  104|     85|  }
  105|  7.21M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 7.21M, False: 239]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  7.21M|    const uint32_t value = decoder.DecodeSymbol();
  108|  7.21M|    out_values[i] = value;
  109|  7.21M|  }
  110|    239|  decoder.EndDecoding();
  111|    239|  return true;
  112|    324|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi3EEEEEbjPNS_13DecoderBufferEPj:
   92|    402|                              uint32_t* out_values) {
   93|    402|  SymbolDecoderT decoder;
   94|    402|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 196, False: 206]
  ------------------
   95|    196|    return false;
   96|    196|  }
   97|       |
   98|    206|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 206, False: 0]
  |  Branch (98:25): [True: 12, False: 194]
  ------------------
   99|     12|    return false;  // Wrong number of symbols.
  100|     12|  }
  101|       |
  102|    194|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 102, False: 92]
  ------------------
  103|    102|    return false;
  104|    102|  }
  105|  11.9M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 11.9M, False: 92]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  11.9M|    const uint32_t value = decoder.DecodeSymbol();
  108|  11.9M|    out_values[i] = value;
  109|  11.9M|  }
  110|     92|  decoder.EndDecoding();
  111|     92|  return true;
  112|    194|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi4EEEEEbjPNS_13DecoderBufferEPj:
   92|    396|                              uint32_t* out_values) {
   93|    396|  SymbolDecoderT decoder;
   94|    396|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 192, False: 204]
  ------------------
   95|    192|    return false;
   96|    192|  }
   97|       |
   98|    204|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 204, False: 0]
  |  Branch (98:25): [True: 13, False: 191]
  ------------------
   99|     13|    return false;  // Wrong number of symbols.
  100|     13|  }
  101|       |
  102|    191|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 61, False: 130]
  ------------------
  103|     61|    return false;
  104|     61|  }
  105|  2.32M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 2.32M, False: 130]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  2.32M|    const uint32_t value = decoder.DecodeSymbol();
  108|  2.32M|    out_values[i] = value;
  109|  2.32M|  }
  110|    130|  decoder.EndDecoding();
  111|    130|  return true;
  112|    191|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi5EEEEEbjPNS_13DecoderBufferEPj:
   92|    357|                              uint32_t* out_values) {
   93|    357|  SymbolDecoderT decoder;
   94|    357|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 33, False: 324]
  ------------------
   95|     33|    return false;
   96|     33|  }
   97|       |
   98|    324|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 324, False: 0]
  |  Branch (98:25): [True: 189, False: 135]
  ------------------
   99|    189|    return false;  // Wrong number of symbols.
  100|    189|  }
  101|       |
  102|    135|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 20, False: 115]
  ------------------
  103|     20|    return false;
  104|     20|  }
  105|  12.5M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 12.5M, False: 115]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  12.5M|    const uint32_t value = decoder.DecodeSymbol();
  108|  12.5M|    out_values[i] = value;
  109|  12.5M|  }
  110|    115|  decoder.EndDecoding();
  111|    115|  return true;
  112|    135|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi6EEEEEbjPNS_13DecoderBufferEPj:
   92|    411|                              uint32_t* out_values) {
   93|    411|  SymbolDecoderT decoder;
   94|    411|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 170, False: 241]
  ------------------
   95|    170|    return false;
   96|    170|  }
   97|       |
   98|    241|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 241, False: 0]
  |  Branch (98:25): [True: 9, False: 232]
  ------------------
   99|      9|    return false;  // Wrong number of symbols.
  100|      9|  }
  101|       |
  102|    232|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 96, False: 136]
  ------------------
  103|     96|    return false;
  104|     96|  }
  105|  8.34M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 8.34M, False: 136]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  8.34M|    const uint32_t value = decoder.DecodeSymbol();
  108|  8.34M|    out_values[i] = value;
  109|  8.34M|  }
  110|    136|  decoder.EndDecoding();
  111|    136|  return true;
  112|    232|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi7EEEEEbjPNS_13DecoderBufferEPj:
   92|    454|                              uint32_t* out_values) {
   93|    454|  SymbolDecoderT decoder;
   94|    454|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 197, False: 257]
  ------------------
   95|    197|    return false;
   96|    197|  }
   97|       |
   98|    257|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 257, False: 0]
  |  Branch (98:25): [True: 15, False: 242]
  ------------------
   99|     15|    return false;  // Wrong number of symbols.
  100|     15|  }
  101|       |
  102|    242|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 91, False: 151]
  ------------------
  103|     91|    return false;
  104|     91|  }
  105|  13.9M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 13.9M, False: 151]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  13.9M|    const uint32_t value = decoder.DecodeSymbol();
  108|  13.9M|    out_values[i] = value;
  109|  13.9M|  }
  110|    151|  decoder.EndDecoding();
  111|    151|  return true;
  112|    242|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi8EEEEEbjPNS_13DecoderBufferEPj:
   92|    390|                              uint32_t* out_values) {
   93|    390|  SymbolDecoderT decoder;
   94|    390|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 196, False: 194]
  ------------------
   95|    196|    return false;
   96|    196|  }
   97|       |
   98|    194|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 194, False: 0]
  |  Branch (98:25): [True: 11, False: 183]
  ------------------
   99|     11|    return false;  // Wrong number of symbols.
  100|     11|  }
  101|       |
  102|    183|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 95, False: 88]
  ------------------
  103|     95|    return false;
  104|     95|  }
  105|  4.23M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 4.23M, False: 88]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  4.23M|    const uint32_t value = decoder.DecodeSymbol();
  108|  4.23M|    out_values[i] = value;
  109|  4.23M|  }
  110|     88|  decoder.EndDecoding();
  111|     88|  return true;
  112|    183|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi9EEEEEbjPNS_13DecoderBufferEPj:
   92|    369|                              uint32_t* out_values) {
   93|    369|  SymbolDecoderT decoder;
   94|    369|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 224, False: 145]
  ------------------
   95|    224|    return false;
   96|    224|  }
   97|       |
   98|    145|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 145, False: 0]
  |  Branch (98:25): [True: 14, False: 131]
  ------------------
   99|     14|    return false;  // Wrong number of symbols.
  100|     14|  }
  101|       |
  102|    131|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 64, False: 67]
  ------------------
  103|     64|    return false;
  104|     64|  }
  105|   131k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 131k, False: 67]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|   131k|    const uint32_t value = decoder.DecodeSymbol();
  108|   131k|    out_values[i] = value;
  109|   131k|  }
  110|     67|  decoder.EndDecoding();
  111|     67|  return true;
  112|    131|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi10EEEEEbjPNS_13DecoderBufferEPj:
   92|    438|                              uint32_t* out_values) {
   93|    438|  SymbolDecoderT decoder;
   94|    438|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 250, False: 188]
  ------------------
   95|    250|    return false;
   96|    250|  }
   97|       |
   98|    188|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 188, False: 0]
  |  Branch (98:25): [True: 8, False: 180]
  ------------------
   99|      8|    return false;  // Wrong number of symbols.
  100|      8|  }
  101|       |
  102|    180|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 99, False: 81]
  ------------------
  103|     99|    return false;
  104|     99|  }
  105|   521k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 521k, False: 81]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|   521k|    const uint32_t value = decoder.DecodeSymbol();
  108|   521k|    out_values[i] = value;
  109|   521k|  }
  110|     81|  decoder.EndDecoding();
  111|     81|  return true;
  112|    180|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi11EEEEEbjPNS_13DecoderBufferEPj:
   92|    484|                              uint32_t* out_values) {
   93|    484|  SymbolDecoderT decoder;
   94|    484|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 271, False: 213]
  ------------------
   95|    271|    return false;
   96|    271|  }
   97|       |
   98|    213|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 213, False: 0]
  |  Branch (98:25): [True: 6, False: 207]
  ------------------
   99|      6|    return false;  // Wrong number of symbols.
  100|      6|  }
  101|       |
  102|    207|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 150, False: 57]
  ------------------
  103|    150|    return false;
  104|    150|  }
  105|  37.5k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 37.4k, False: 57]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  37.4k|    const uint32_t value = decoder.DecodeSymbol();
  108|  37.4k|    out_values[i] = value;
  109|  37.4k|  }
  110|     57|  decoder.EndDecoding();
  111|     57|  return true;
  112|    207|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi12EEEEEbjPNS_13DecoderBufferEPj:
   92|    492|                              uint32_t* out_values) {
   93|    492|  SymbolDecoderT decoder;
   94|    492|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 300, False: 192]
  ------------------
   95|    300|    return false;
   96|    300|  }
   97|       |
   98|    192|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 192, False: 0]
  |  Branch (98:25): [True: 13, False: 179]
  ------------------
   99|     13|    return false;  // Wrong number of symbols.
  100|     13|  }
  101|       |
  102|    179|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 118, False: 61]
  ------------------
  103|    118|    return false;
  104|    118|  }
  105|   212k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 212k, False: 61]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|   212k|    const uint32_t value = decoder.DecodeSymbol();
  108|   212k|    out_values[i] = value;
  109|   212k|  }
  110|     61|  decoder.EndDecoding();
  111|     61|  return true;
  112|    179|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi13EEEEEbjPNS_13DecoderBufferEPj:
   92|    589|                              uint32_t* out_values) {
   93|    589|  SymbolDecoderT decoder;
   94|    589|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 322, False: 267]
  ------------------
   95|    322|    return false;
   96|    322|  }
   97|       |
   98|    267|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 267, False: 0]
  |  Branch (98:25): [True: 13, False: 254]
  ------------------
   99|     13|    return false;  // Wrong number of symbols.
  100|     13|  }
  101|       |
  102|    254|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 161, False: 93]
  ------------------
  103|    161|    return false;
  104|    161|  }
  105|   714k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 714k, False: 93]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|   714k|    const uint32_t value = decoder.DecodeSymbol();
  108|   714k|    out_values[i] = value;
  109|   714k|  }
  110|     93|  decoder.EndDecoding();
  111|     93|  return true;
  112|    254|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi14EEEEEbjPNS_13DecoderBufferEPj:
   92|    476|                              uint32_t* out_values) {
   93|    476|  SymbolDecoderT decoder;
   94|    476|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 251, False: 225]
  ------------------
   95|    251|    return false;
   96|    251|  }
   97|       |
   98|    225|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 225, False: 0]
  |  Branch (98:25): [True: 11, False: 214]
  ------------------
   99|     11|    return false;  // Wrong number of symbols.
  100|     11|  }
  101|       |
  102|    214|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 144, False: 70]
  ------------------
  103|    144|    return false;
  104|    144|  }
  105|  9.93M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 9.93M, False: 70]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  9.93M|    const uint32_t value = decoder.DecodeSymbol();
  108|  9.93M|    out_values[i] = value;
  109|  9.93M|  }
  110|     70|  decoder.EndDecoding();
  111|     70|  return true;
  112|    214|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi15EEEEEbjPNS_13DecoderBufferEPj:
   92|    494|                              uint32_t* out_values) {
   93|    494|  SymbolDecoderT decoder;
   94|    494|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 246, False: 248]
  ------------------
   95|    246|    return false;
   96|    246|  }
   97|       |
   98|    248|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 248, False: 0]
  |  Branch (98:25): [True: 21, False: 227]
  ------------------
   99|     21|    return false;  // Wrong number of symbols.
  100|     21|  }
  101|       |
  102|    227|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 157, False: 70]
  ------------------
  103|    157|    return false;
  104|    157|  }
  105|  4.27M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 4.27M, False: 70]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  4.27M|    const uint32_t value = decoder.DecodeSymbol();
  108|  4.27M|    out_values[i] = value;
  109|  4.27M|  }
  110|     70|  decoder.EndDecoding();
  111|     70|  return true;
  112|    227|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi16EEEEEbjPNS_13DecoderBufferEPj:
   92|    426|                              uint32_t* out_values) {
   93|    426|  SymbolDecoderT decoder;
   94|    426|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 206, False: 220]
  ------------------
   95|    206|    return false;
   96|    206|  }
   97|       |
   98|    220|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 220, False: 0]
  |  Branch (98:25): [True: 3, False: 217]
  ------------------
   99|      3|    return false;  // Wrong number of symbols.
  100|      3|  }
  101|       |
  102|    217|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 150, False: 67]
  ------------------
  103|    150|    return false;
  104|    150|  }
  105|  21.7M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 21.7M, False: 67]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  21.7M|    const uint32_t value = decoder.DecodeSymbol();
  108|  21.7M|    out_values[i] = value;
  109|  21.7M|  }
  110|     67|  decoder.EndDecoding();
  111|     67|  return true;
  112|    217|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi17EEEEEbjPNS_13DecoderBufferEPj:
   92|    476|                              uint32_t* out_values) {
   93|    476|  SymbolDecoderT decoder;
   94|    476|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 240, False: 236]
  ------------------
   95|    240|    return false;
   96|    240|  }
   97|       |
   98|    236|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 236, False: 0]
  |  Branch (98:25): [True: 13, False: 223]
  ------------------
   99|     13|    return false;  // Wrong number of symbols.
  100|     13|  }
  101|       |
  102|    223|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 144, False: 79]
  ------------------
  103|    144|    return false;
  104|    144|  }
  105|  34.8M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 34.8M, False: 79]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  34.8M|    const uint32_t value = decoder.DecodeSymbol();
  108|  34.8M|    out_values[i] = value;
  109|  34.8M|  }
  110|     79|  decoder.EndDecoding();
  111|     79|  return true;
  112|    223|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi18EEEEEbjPNS_13DecoderBufferEPj:
   92|    449|                              uint32_t* out_values) {
   93|    449|  SymbolDecoderT decoder;
   94|    449|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 230, False: 219]
  ------------------
   95|    230|    return false;
   96|    230|  }
   97|       |
   98|    219|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 219, False: 0]
  |  Branch (98:25): [True: 7, False: 212]
  ------------------
   99|      7|    return false;  // Wrong number of symbols.
  100|      7|  }
  101|       |
  102|    212|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 126, False: 86]
  ------------------
  103|    126|    return false;
  104|    126|  }
  105|  71.0M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 71.0M, False: 86]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  71.0M|    const uint32_t value = decoder.DecodeSymbol();
  108|  71.0M|    out_values[i] = value;
  109|  71.0M|  }
  110|     86|  decoder.EndDecoding();
  111|     86|  return true;
  112|    212|}

_ZN5draco11MeshDecoderC2Ev:
   19|  16.3k|MeshDecoder::MeshDecoder() : mesh_(nullptr) {}
_ZN5draco11MeshDecoder6DecodeERKNS_12DracoOptionsINS_17GeometryAttribute4TypeEEEPNS_13DecoderBufferEPNS_4MeshE:
   22|  16.3k|                           DecoderBuffer* in_buffer, Mesh* out_mesh) {
   23|  16.3k|  mesh_ = out_mesh;
   24|  16.3k|  return PointCloudDecoder::Decode(options, in_buffer, out_mesh);
   25|  16.3k|}
_ZN5draco11MeshDecoder18DecodeGeometryDataEv:
   27|  15.4k|bool MeshDecoder::DecodeGeometryData() {
   28|  15.4k|  if (mesh_ == nullptr) {
  ------------------
  |  Branch (28:7): [True: 0, False: 15.4k]
  ------------------
   29|      0|    return false;
   30|      0|  }
   31|  15.4k|  if (!DecodeConnectivity()) {
  ------------------
  |  Branch (31:7): [True: 9.66k, False: 5.76k]
  ------------------
   32|  9.66k|    return false;
   33|  9.66k|  }
   34|  5.76k|  return PointCloudDecoder::DecodeGeometryData();
   35|  15.4k|}

_ZNK5draco11MeshDecoder15GetGeometryTypeEv:
   31|  28.4k|  EncodedGeometryType GetGeometryType() const override {
   32|  28.4k|    return TRIANGULAR_MESH;
   33|  28.4k|  }
_ZNK5draco11MeshDecoder14GetCornerTableEv:
   41|    348|  virtual const CornerTable* GetCornerTable() const { return nullptr; }
_ZNK5draco11MeshDecoder24GetAttributeEncodingDataEi:
   52|    348|      int /* att_id */) const {
   53|    348|    return nullptr;
   54|    348|  }
_ZNK5draco11MeshDecoder4meshEv:
   56|  30.9M|  Mesh* mesh() const { return mesh_; }

_ZN5draco22MeshEdgebreakerDecoderC2Ev:
   23|  10.7k|MeshEdgebreakerDecoder::MeshEdgebreakerDecoder() = default;
_ZN5draco22MeshEdgebreakerDecoder23CreateAttributesDecoderEi:
   25|  4.91k|bool MeshEdgebreakerDecoder::CreateAttributesDecoder(int32_t att_decoder_id) {
   26|  4.91k|  return impl_->CreateAttributesDecoder(att_decoder_id);
   27|  4.91k|}
_ZN5draco22MeshEdgebreakerDecoder17InitializeDecoderEv:
   29|  10.0k|bool MeshEdgebreakerDecoder::InitializeDecoder() {
   30|  10.0k|  uint8_t traversal_decoder_type;
   31|  10.0k|  if (!buffer()->Decode(&traversal_decoder_type)) {
  ------------------
  |  Branch (31:7): [True: 4, False: 10.0k]
  ------------------
   32|      4|    return false;
   33|      4|  }
   34|  10.0k|  impl_ = nullptr;
   35|  10.0k|  if (traversal_decoder_type == MESH_EDGEBREAKER_STANDARD_ENCODING) {
  ------------------
  |  Branch (35:7): [True: 3.84k, False: 6.24k]
  ------------------
   36|  3.84k|#ifdef DRACO_STANDARD_EDGEBREAKER_SUPPORTED
   37|  3.84k|    impl_ = std::unique_ptr<MeshEdgebreakerDecoderImplInterface>(
   38|  3.84k|        new MeshEdgebreakerDecoderImpl<MeshEdgebreakerTraversalDecoder>());
   39|  3.84k|#endif
   40|  6.24k|  } else if (traversal_decoder_type == MESH_EDGEBREAKER_PREDICTIVE_ENCODING) {
  ------------------
  |  Branch (40:14): [True: 3.18k, False: 3.06k]
  ------------------
   41|  3.18k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   42|  3.18k|#ifdef DRACO_PREDICTIVE_EDGEBREAKER_SUPPORTED
   43|  3.18k|    impl_ = std::unique_ptr<MeshEdgebreakerDecoderImplInterface>(
   44|  3.18k|        new MeshEdgebreakerDecoderImpl<
   45|  3.18k|            MeshEdgebreakerTraversalPredictiveDecoder>());
   46|  3.18k|#endif
   47|  3.18k|#endif
   48|  3.18k|  } else if (traversal_decoder_type == MESH_EDGEBREAKER_VALENCE_ENCODING) {
  ------------------
  |  Branch (48:14): [True: 3.04k, False: 11]
  ------------------
   49|  3.04k|    impl_ = std::unique_ptr<MeshEdgebreakerDecoderImplInterface>(
   50|  3.04k|        new MeshEdgebreakerDecoderImpl<
   51|  3.04k|            MeshEdgebreakerTraversalValenceDecoder>());
   52|  3.04k|  }
   53|  10.0k|  if (!impl_) {
  ------------------
  |  Branch (53:7): [True: 11, False: 10.0k]
  ------------------
   54|     11|    return false;
   55|     11|  }
   56|  10.0k|  if (!impl_->Init(this)) {
  ------------------
  |  Branch (56:7): [True: 0, False: 10.0k]
  ------------------
   57|      0|    return false;
   58|      0|  }
   59|  10.0k|  return true;
   60|  10.0k|}
_ZN5draco22MeshEdgebreakerDecoder18DecodeConnectivityEv:
   62|  10.0k|bool MeshEdgebreakerDecoder::DecodeConnectivity() {
   63|  10.0k|  return impl_->DecodeConnectivity();
   64|  10.0k|}
_ZN5draco22MeshEdgebreakerDecoder19OnAttributesDecodedEv:
   66|  1.52k|bool MeshEdgebreakerDecoder::OnAttributesDecoded() {
   67|  1.52k|  return impl_->OnAttributesDecoded();
   68|  1.52k|}

_ZNK5draco22MeshEdgebreakerDecoder14GetCornerTableEv:
   29|  5.52k|  const CornerTable* GetCornerTable() const override {
   30|  5.52k|    return impl_->GetCornerTable();
   31|  5.52k|  }
_ZNK5draco22MeshEdgebreakerDecoder23GetAttributeCornerTableEi:
   34|  5.52k|      int att_id) const override {
   35|  5.52k|    return impl_->GetAttributeCornerTable(att_id);
   36|  5.52k|  }
_ZNK5draco22MeshEdgebreakerDecoder24GetAttributeEncodingDataEi:
   39|  5.52k|      int att_id) const override {
   40|  5.52k|    return impl_->GetAttributeEncodingData(att_id);
   41|  5.52k|  }

_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEEC2Ev:
   48|  3.84k|    : decoder_(nullptr),
   49|  3.84k|      last_symbol_id_(-1),
   50|  3.84k|      last_vert_id_(-1),
   51|  3.84k|      last_face_id_(-1),
   52|  3.84k|      num_new_vertices_(0),
   53|  3.84k|      num_encoded_vertices_(0),
   54|  3.84k|      pos_data_decoder_id_(-1) {}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE4InitEPNS_22MeshEdgebreakerDecoderE:
   58|  3.84k|    MeshEdgebreakerDecoder* decoder) {
   59|  3.84k|  decoder_ = decoder;
   60|  3.84k|  return true;
   61|  3.84k|}
_ZNK5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE23GetAttributeCornerTableEi:
   66|  3.01k|    int att_id) const {
   67|  5.24k|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (67:24): [True: 4.32k, False: 926]
  ------------------
   68|  4.32k|    const int decoder_id = attribute_data_[i].decoder_id;
   69|  4.32k|    if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) {
  ------------------
  |  Branch (69:9): [True: 2.23k, False: 2.08k]
  |  Branch (69:27): [True: 0, False: 2.08k]
  ------------------
   70|  2.23k|      continue;
   71|  2.23k|    }
   72|  2.08k|    const AttributesDecoderInterface* const dec =
   73|  2.08k|        decoder_->attributes_decoder(decoder_id);
   74|  4.98k|    for (int j = 0; j < dec->GetNumAttributes(); ++j) {
  ------------------
  |  Branch (74:21): [True: 4.98k, False: 0]
  ------------------
   75|  4.98k|      if (dec->GetAttributeId(j) == att_id) {
  ------------------
  |  Branch (75:11): [True: 2.08k, False: 2.90k]
  ------------------
   76|  2.08k|        if (attribute_data_[i].is_connectivity_used) {
  ------------------
  |  Branch (76:13): [True: 1.53k, False: 553]
  ------------------
   77|  1.53k|          return &attribute_data_[i].connectivity_data;
   78|  1.53k|        }
   79|    553|        return nullptr;
   80|  2.08k|      }
   81|  4.98k|    }
   82|  2.08k|  }
   83|    926|  return nullptr;
   84|  3.01k|}
_ZNK5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE24GetAttributeEncodingDataEi:
   89|  3.01k|    int att_id) const {
   90|  5.24k|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (90:24): [True: 4.32k, False: 926]
  ------------------
   91|  4.32k|    const int decoder_id = attribute_data_[i].decoder_id;
   92|  4.32k|    if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) {
  ------------------
  |  Branch (92:9): [True: 2.23k, False: 2.08k]
  |  Branch (92:27): [True: 0, False: 2.08k]
  ------------------
   93|  2.23k|      continue;
   94|  2.23k|    }
   95|  2.08k|    const AttributesDecoderInterface* const dec =
   96|  2.08k|        decoder_->attributes_decoder(decoder_id);
   97|  4.98k|    for (int j = 0; j < dec->GetNumAttributes(); ++j) {
  ------------------
  |  Branch (97:21): [True: 4.98k, False: 0]
  ------------------
   98|  4.98k|      if (dec->GetAttributeId(j) == att_id) {
  ------------------
  |  Branch (98:11): [True: 2.08k, False: 2.90k]
  ------------------
   99|  2.08k|        return &attribute_data_[i].encoding_data;
  100|  2.08k|      }
  101|  4.98k|    }
  102|  2.08k|  }
  103|    926|  return &pos_encoding_data_;
  104|  3.01k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE23CreateAttributesDecoderEi:
  130|  2.60k|    int32_t att_decoder_id) {
  131|  2.60k|  int8_t att_data_id;
  132|  2.60k|  if (!decoder_->buffer()->Decode(&att_data_id)) {
  ------------------
  |  Branch (132:7): [True: 37, False: 2.56k]
  ------------------
  133|     37|    return false;
  134|     37|  }
  135|  2.56k|  uint8_t decoder_type;
  136|  2.56k|  if (!decoder_->buffer()->Decode(&decoder_type)) {
  ------------------
  |  Branch (136:7): [True: 12, False: 2.55k]
  ------------------
  137|     12|    return false;
  138|     12|  }
  139|       |
  140|  2.55k|  if (att_data_id >= 0) {
  ------------------
  |  Branch (140:7): [True: 1.70k, False: 847]
  ------------------
  141|  1.70k|    if (att_data_id >= attribute_data_.size()) {
  ------------------
  |  Branch (141:9): [True: 84, False: 1.62k]
  ------------------
  142|     84|      return false;  // Unexpected attribute data.
  143|     84|    }
  144|       |
  145|       |    // Ensure that the attribute data is not mapped to a different attributes
  146|       |    // decoder already.
  147|  1.62k|    if (attribute_data_[att_data_id].decoder_id >= 0) {
  ------------------
  |  Branch (147:9): [True: 11, False: 1.61k]
  ------------------
  148|     11|      return false;
  149|     11|    }
  150|       |
  151|  1.61k|    attribute_data_[att_data_id].decoder_id = att_decoder_id;
  152|  1.61k|  } else {
  153|       |    // Assign the attributes decoder to |pos_encoding_data_|.
  154|    847|    if (pos_data_decoder_id_ >= 0) {
  ------------------
  |  Branch (154:9): [True: 2, False: 845]
  ------------------
  155|      2|      return false;  // Some other decoder is already using the data. Error.
  156|      2|    }
  157|    845|    pos_data_decoder_id_ = att_decoder_id;
  158|    845|  }
  159|       |
  160|  2.45k|  MeshTraversalMethod traversal_method = MESH_TRAVERSAL_DEPTH_FIRST;
  161|  2.45k|  if (decoder_->bitstream_version() >= DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|  2.45k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (161:7): [True: 2.45k, False: 1]
  ------------------
  162|  2.45k|    uint8_t traversal_method_encoded;
  163|  2.45k|    if (!decoder_->buffer()->Decode(&traversal_method_encoded)) {
  ------------------
  |  Branch (163:9): [True: 12, False: 2.44k]
  ------------------
  164|     12|      return false;
  165|     12|    }
  166|       |    // Check that decoded traversal method is valid.
  167|  2.44k|    if (traversal_method_encoded >= NUM_TRAVERSAL_METHODS) {
  ------------------
  |  Branch (167:9): [True: 77, False: 2.36k]
  ------------------
  168|     77|      return false;
  169|     77|    }
  170|  2.36k|    traversal_method =
  171|  2.36k|        static_cast<MeshTraversalMethod>(traversal_method_encoded);
  172|  2.36k|  }
  173|       |
  174|  2.36k|  const Mesh* mesh = decoder_->mesh();
  175|  2.36k|  std::unique_ptr<PointsSequencer> sequencer;
  176|       |
  177|  2.36k|  if (decoder_type == MESH_VERTEX_ATTRIBUTE) {
  ------------------
  |  Branch (177:7): [True: 1.19k, False: 1.16k]
  ------------------
  178|       |    // Per-vertex attribute decoder.
  179|       |
  180|  1.19k|    MeshAttributeIndicesEncodingData* encoding_data = nullptr;
  181|  1.19k|    if (att_data_id < 0) {
  ------------------
  |  Branch (181:9): [True: 780, False: 419]
  ------------------
  182|    780|      encoding_data = &pos_encoding_data_;
  183|    780|    } else {
  184|    419|      encoding_data = &attribute_data_[att_data_id].encoding_data;
  185|       |      // Mark the attribute connectivity data invalid to ensure it's not used
  186|       |      // later on.
  187|    419|      attribute_data_[att_data_id].is_connectivity_used = false;
  188|    419|    }
  189|       |    // Defining sequencer via a traversal scheme.
  190|  1.19k|    if (traversal_method == MESH_TRAVERSAL_PREDICTION_DEGREE) {
  ------------------
  |  Branch (190:9): [True: 195, False: 1.00k]
  ------------------
  191|    195|      typedef MeshAttributeIndicesEncodingObserver<CornerTable> AttObserver;
  192|    195|      typedef MaxPredictionDegreeTraverser<CornerTable, AttObserver>
  193|    195|          AttTraverser;
  194|    195|      sequencer = CreateVertexTraversalSequencer<AttTraverser>(encoding_data);
  195|  1.00k|    } else if (traversal_method == MESH_TRAVERSAL_DEPTH_FIRST) {
  ------------------
  |  Branch (195:16): [True: 1.00k, False: 0]
  ------------------
  196|  1.00k|      typedef MeshAttributeIndicesEncodingObserver<CornerTable> AttObserver;
  197|  1.00k|      typedef DepthFirstTraverser<CornerTable, AttObserver> AttTraverser;
  198|  1.00k|      sequencer = CreateVertexTraversalSequencer<AttTraverser>(encoding_data);
  199|  1.00k|    } else {
  200|      0|      return false;  // Unsupported method
  201|      0|    }
  202|  1.19k|  } else {
  203|  1.16k|    if (traversal_method != MESH_TRAVERSAL_DEPTH_FIRST) {
  ------------------
  |  Branch (203:9): [True: 14, False: 1.15k]
  ------------------
  204|     14|      return false;  // Unsupported method.
  205|     14|    }
  206|  1.15k|    if (att_data_id < 0) {
  ------------------
  |  Branch (206:9): [True: 5, False: 1.14k]
  ------------------
  207|      5|      return false;  // Attribute data must be specified.
  208|      5|    }
  209|       |
  210|       |    // Per-corner attribute decoder.
  211|       |
  212|  1.14k|    typedef MeshAttributeIndicesEncodingObserver<MeshAttributeCornerTable>
  213|  1.14k|        AttObserver;
  214|  1.14k|    typedef DepthFirstTraverser<MeshAttributeCornerTable, AttObserver>
  215|  1.14k|        AttTraverser;
  216|       |
  217|  1.14k|    MeshAttributeIndicesEncodingData* const encoding_data =
  218|  1.14k|        &attribute_data_[att_data_id].encoding_data;
  219|  1.14k|    const MeshAttributeCornerTable* const corner_table =
  220|  1.14k|        &attribute_data_[att_data_id].connectivity_data;
  221|       |
  222|  1.14k|    std::unique_ptr<MeshTraversalSequencer<AttTraverser>> traversal_sequencer(
  223|  1.14k|        new MeshTraversalSequencer<AttTraverser>(mesh, encoding_data));
  224|       |
  225|  1.14k|    AttObserver att_observer(corner_table, mesh, traversal_sequencer.get(),
  226|  1.14k|                             encoding_data);
  227|       |
  228|  1.14k|    AttTraverser att_traverser;
  229|  1.14k|    att_traverser.Init(corner_table, att_observer);
  230|       |
  231|  1.14k|    traversal_sequencer->SetTraverser(att_traverser);
  232|  1.14k|    sequencer = std::move(traversal_sequencer);
  233|  1.14k|  }
  234|       |
  235|  2.34k|  if (!sequencer) {
  ------------------
  |  Branch (235:7): [True: 0, False: 2.34k]
  ------------------
  236|      0|    return false;
  237|      0|  }
  238|       |
  239|  2.34k|  std::unique_ptr<SequentialAttributeDecodersController> att_controller(
  240|  2.34k|      new SequentialAttributeDecodersController(std::move(sequencer)));
  241|       |
  242|  2.34k|  return decoder_->SetAttributesDecoder(att_decoder_id,
  243|  2.34k|                                        std::move(att_controller));
  244|  2.34k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE18DecodeConnectivityEv:
  247|  3.84k|bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
  248|  3.84k|  num_new_vertices_ = 0;
  249|  3.84k|  new_to_parent_vertex_map_.clear();
  250|  3.84k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  251|  3.84k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  3.84k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (251:7): [True: 781, False: 3.06k]
  ------------------
  252|    781|    uint32_t num_new_verts;
  253|    781|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    781|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (253:9): [True: 286, False: 495]
  ------------------
  254|    286|      if (!decoder_->buffer()->Decode(&num_new_verts)) {
  ------------------
  |  Branch (254:11): [True: 10, False: 276]
  ------------------
  255|     10|        return false;
  256|     10|      }
  257|    495|    } else {
  258|    495|      if (!DecodeVarint(&num_new_verts, decoder_->buffer())) {
  ------------------
  |  Branch (258:11): [True: 2, False: 493]
  ------------------
  259|      2|        return false;
  260|      2|      }
  261|    495|    }
  262|    769|    num_new_vertices_ = num_new_verts;
  263|    769|  }
  264|  3.82k|#endif
  265|       |
  266|  3.82k|  uint32_t num_encoded_vertices;
  267|  3.82k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  268|  3.82k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  3.82k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (268:7): [True: 276, False: 3.55k]
  ------------------
  269|    276|    if (!decoder_->buffer()->Decode(&num_encoded_vertices)) {
  ------------------
  |  Branch (269:9): [True: 2, False: 274]
  ------------------
  270|      2|      return false;
  271|      2|    }
  272|       |
  273|    276|  } else
  274|  3.55k|#endif
  275|  3.55k|  {
  276|  3.55k|    if (!DecodeVarint(&num_encoded_vertices, decoder_->buffer())) {
  ------------------
  |  Branch (276:9): [True: 5, False: 3.54k]
  ------------------
  277|      5|      return false;
  278|      5|    }
  279|  3.55k|  }
  280|  3.82k|  num_encoded_vertices_ = num_encoded_vertices;
  281|       |
  282|  3.82k|  uint32_t num_faces;
  283|  3.82k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  284|  3.82k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  3.82k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (284:7): [True: 274, False: 3.54k]
  ------------------
  285|    274|    if (!decoder_->buffer()->Decode(&num_faces)) {
  ------------------
  |  Branch (285:9): [True: 4, False: 270]
  ------------------
  286|      4|      return false;
  287|      4|    }
  288|       |
  289|    274|  } else
  290|  3.54k|#endif
  291|  3.54k|  {
  292|  3.54k|    if (!DecodeVarint(&num_faces, decoder_->buffer())) {
  ------------------
  |  Branch (292:9): [True: 4, False: 3.54k]
  ------------------
  293|      4|      return false;
  294|      4|    }
  295|  3.54k|  }
  296|  3.81k|  if (num_faces > std::numeric_limits<CornerIndex::ValueType>::max() / 3) {
  ------------------
  |  Branch (296:7): [True: 4, False: 3.81k]
  ------------------
  297|      4|    return false;  // Draco cannot handle this many faces.
  298|      4|  }
  299|       |
  300|  3.81k|  if (static_cast<uint32_t>(num_encoded_vertices_) > num_faces * 3) {
  ------------------
  |  Branch (300:7): [True: 37, False: 3.77k]
  ------------------
  301|     37|    return false;  // There cannot be more vertices than 3 * num_faces.
  302|     37|  }
  303|       |
  304|       |  // Minimum number of edges of the mesh assuming each edge is shared between
  305|       |  // two faces.
  306|  3.77k|  const uint32_t min_num_face_edges = 3 * num_faces / 2;
  307|       |
  308|       |  // Maximum number of edges that can exist between |num_encoded_vertices_|.
  309|       |  // This is based on graph theory assuming simple connected graph.
  310|  3.77k|  const uint64_t num_encoded_vertices_64 =
  311|  3.77k|      static_cast<uint64_t>(num_encoded_vertices_);
  312|  3.77k|  const uint64_t max_num_vertex_edges =
  313|  3.77k|      num_encoded_vertices_64 * (num_encoded_vertices_64 - 1) / 2;
  314|  3.77k|  if (max_num_vertex_edges < min_num_face_edges) {
  ------------------
  |  Branch (314:7): [True: 24, False: 3.74k]
  ------------------
  315|       |    // It is impossible to construct a manifold mesh with these properties.
  316|     24|    return false;
  317|     24|  }
  318|       |
  319|  3.74k|  uint8_t num_attribute_data;
  320|  3.74k|  if (!decoder_->buffer()->Decode(&num_attribute_data)) {
  ------------------
  |  Branch (320:7): [True: 52, False: 3.69k]
  ------------------
  321|     52|    return false;
  322|     52|  }
  323|       |
  324|  3.69k|  uint32_t num_encoded_symbols;
  325|  3.69k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  326|  3.69k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  3.69k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (326:7): [True: 241, False: 3.45k]
  ------------------
  327|    241|    if (!decoder_->buffer()->Decode(&num_encoded_symbols)) {
  ------------------
  |  Branch (327:9): [True: 16, False: 225]
  ------------------
  328|     16|      return false;
  329|     16|    }
  330|       |
  331|    241|  } else
  332|  3.45k|#endif
  333|  3.45k|  {
  334|  3.45k|    if (!DecodeVarint(&num_encoded_symbols, decoder_->buffer())) {
  ------------------
  |  Branch (334:9): [True: 6, False: 3.45k]
  ------------------
  335|      6|      return false;
  336|      6|    }
  337|  3.45k|  }
  338|       |
  339|  3.67k|  if (num_faces < num_encoded_symbols) {
  ------------------
  |  Branch (339:7): [True: 22, False: 3.65k]
  ------------------
  340|       |    // Number of faces needs to be the same or greater than the number of
  341|       |    // symbols (it can be greater because the initial face may not be encoded as
  342|       |    // a symbol).
  343|     22|    return false;
  344|     22|  }
  345|  3.65k|  const uint32_t max_encoded_faces =
  346|  3.65k|      num_encoded_symbols + (num_encoded_symbols / 3);
  347|  3.65k|  if (num_faces > max_encoded_faces) {
  ------------------
  |  Branch (347:7): [True: 58, False: 3.59k]
  ------------------
  348|       |    // Faces can only be 1 1/3 times bigger than number of encoded symbols. This
  349|       |    // could only happen if all new encoded components started with interior
  350|       |    // triangles. E.g. A mesh with multiple tetrahedrons.
  351|     58|    return false;
  352|     58|  }
  353|       |
  354|  3.59k|  uint32_t num_encoded_split_symbols;
  355|  3.59k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  356|  3.59k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  3.59k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (356:7): [True: 205, False: 3.39k]
  ------------------
  357|    205|    if (!decoder_->buffer()->Decode(&num_encoded_split_symbols)) {
  ------------------
  |  Branch (357:9): [True: 1, False: 204]
  ------------------
  358|      1|      return false;
  359|      1|    }
  360|       |
  361|    205|  } else
  362|  3.39k|#endif
  363|  3.39k|  {
  364|  3.39k|    if (!DecodeVarint(&num_encoded_split_symbols, decoder_->buffer())) {
  ------------------
  |  Branch (364:9): [True: 6, False: 3.38k]
  ------------------
  365|      6|      return false;
  366|      6|    }
  367|  3.39k|  }
  368|       |
  369|  3.58k|  if (num_encoded_split_symbols > num_encoded_symbols) {
  ------------------
  |  Branch (369:7): [True: 48, False: 3.54k]
  ------------------
  370|     48|    return false;  // Split symbols are a sub-set of all symbols.
  371|     48|  }
  372|       |
  373|       |  // Decode topology (connectivity).
  374|  3.54k|  vertex_traversal_length_.clear();
  375|  3.54k|  corner_table_ = std::unique_ptr<CornerTable>(new CornerTable());
  376|  3.54k|  if (corner_table_ == nullptr) {
  ------------------
  |  Branch (376:7): [True: 0, False: 3.54k]
  ------------------
  377|      0|    return false;
  378|      0|  }
  379|  3.54k|  processed_corner_ids_.clear();
  380|  3.54k|  processed_corner_ids_.reserve(num_faces);
  381|  3.54k|  processed_connectivity_corners_.clear();
  382|  3.54k|  processed_connectivity_corners_.reserve(num_faces);
  383|  3.54k|  topology_split_data_.clear();
  384|  3.54k|  hole_event_data_.clear();
  385|  3.54k|  init_face_configurations_.clear();
  386|  3.54k|  init_corners_.clear();
  387|       |
  388|  3.54k|  last_symbol_id_ = -1;
  389|  3.54k|  last_face_id_ = -1;
  390|  3.54k|  last_vert_id_ = -1;
  391|       |
  392|  3.54k|  attribute_data_.clear();
  393|       |  // Add one attribute data for each attribute decoder.
  394|  3.54k|  attribute_data_.resize(num_attribute_data);
  395|       |
  396|  3.54k|  if (!corner_table_->Reset(
  ------------------
  |  Branch (396:7): [True: 1, False: 3.53k]
  ------------------
  397|  3.54k|          num_faces, num_encoded_vertices_ + num_encoded_split_symbols)) {
  398|      1|    return false;
  399|      1|  }
  400|       |
  401|       |  // Start with all vertices marked as holes (boundaries).
  402|       |  // Only vertices decoded with TOPOLOGY_C symbol (and the initial face) will
  403|       |  // be marked as non hole vertices. We need to allocate the array larger
  404|       |  // because split symbols can create extra vertices during the decoding
  405|       |  // process (these extra vertices are then eliminated during deduplication).
  406|  3.53k|  is_vert_hole_.assign(num_encoded_vertices_ + num_encoded_split_symbols, true);
  407|       |
  408|  3.53k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  409|  3.53k|  int32_t topology_split_decoded_bytes = -1;
  410|  3.53k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  3.53k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (410:7): [True: 672, False: 2.86k]
  ------------------
  411|    672|    uint32_t encoded_connectivity_size;
  412|    672|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    672|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (412:9): [True: 199, False: 473]
  ------------------
  413|    199|      if (!decoder_->buffer()->Decode(&encoded_connectivity_size)) {
  ------------------
  |  Branch (413:11): [True: 10, False: 189]
  ------------------
  414|     10|        return false;
  415|     10|      }
  416|    473|    } else {
  417|    473|      if (!DecodeVarint(&encoded_connectivity_size, decoder_->buffer())) {
  ------------------
  |  Branch (417:11): [True: 3, False: 470]
  ------------------
  418|      3|        return false;
  419|      3|      }
  420|    473|    }
  421|    659|    if (encoded_connectivity_size == 0 ||
  ------------------
  |  Branch (421:9): [True: 5, False: 654]
  ------------------
  422|    654|        encoded_connectivity_size > decoder_->buffer()->remaining_size()) {
  ------------------
  |  Branch (422:9): [True: 69, False: 585]
  ------------------
  423|     74|      return false;
  424|     74|    }
  425|    585|    DecoderBuffer event_buffer;
  426|    585|    event_buffer.Init(
  427|    585|        decoder_->buffer()->data_head() + encoded_connectivity_size,
  428|    585|        decoder_->buffer()->remaining_size() - encoded_connectivity_size,
  429|    585|        decoder_->buffer()->bitstream_version());
  430|       |    // Decode hole and topology split events.
  431|    585|    topology_split_decoded_bytes =
  432|    585|        DecodeHoleAndTopologySplitEvents(&event_buffer);
  433|    585|    if (topology_split_decoded_bytes == -1) {
  ------------------
  |  Branch (433:9): [True: 169, False: 416]
  ------------------
  434|    169|      return false;
  435|    169|    }
  436|       |
  437|    585|  } else
  438|  2.86k|#endif
  439|  2.86k|  {
  440|  2.86k|    if (DecodeHoleAndTopologySplitEvents(decoder_->buffer()) == -1) {
  ------------------
  |  Branch (440:9): [True: 121, False: 2.74k]
  ------------------
  441|    121|      return false;
  442|    121|    }
  443|  2.86k|  }
  444|       |
  445|  3.16k|  traversal_decoder_.Init(this);
  446|       |  // Add one extra vertex for each split symbol.
  447|  3.16k|  traversal_decoder_.SetNumEncodedVertices(num_encoded_vertices_ +
  448|  3.16k|                                           num_encoded_split_symbols);
  449|  3.16k|  traversal_decoder_.SetNumAttributeData(num_attribute_data);
  450|       |
  451|  3.16k|  DecoderBuffer traversal_end_buffer;
  452|  3.16k|  if (!traversal_decoder_.Start(&traversal_end_buffer)) {
  ------------------
  |  Branch (452:7): [True: 255, False: 2.90k]
  ------------------
  453|    255|    return false;
  454|    255|  }
  455|       |
  456|  2.90k|  const int num_connectivity_verts = DecodeConnectivity(num_encoded_symbols);
  457|  2.90k|  if (num_connectivity_verts == -1) {
  ------------------
  |  Branch (457:7): [True: 311, False: 2.59k]
  ------------------
  458|    311|    return false;
  459|    311|  }
  460|       |
  461|       |  // Set the main buffer to the end of the traversal.
  462|  2.59k|  decoder_->buffer()->Init(traversal_end_buffer.data_head(),
  463|  2.59k|                           traversal_end_buffer.remaining_size(),
  464|  2.59k|                           decoder_->buffer()->bitstream_version());
  465|       |
  466|  2.59k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  467|  2.59k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  2.59k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (467:7): [True: 280, False: 2.31k]
  ------------------
  468|       |    // Skip topology split data that was already decoded earlier.
  469|    280|    decoder_->buffer()->Advance(topology_split_decoded_bytes);
  470|    280|  }
  471|  2.59k|#endif
  472|       |
  473|       |  // Decode connectivity of non-position attributes.
  474|  2.59k|  if (!attribute_data_.empty()) {
  ------------------
  |  Branch (474:7): [True: 2.48k, False: 107]
  ------------------
  475|  2.48k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  476|  2.48k|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
  ------------------
  |  |  115|  2.48k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (476:9): [True: 271, False: 2.21k]
  ------------------
  477|  1.86k|      for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
  ------------------
  |  Branch (477:31): [True: 1.59k, False: 271]
  ------------------
  478|  1.59k|        if (!DecodeAttributeConnectivitiesOnFaceLegacy(ci)) {
  ------------------
  |  Branch (478:13): [True: 0, False: 1.59k]
  ------------------
  479|      0|          return false;
  480|      0|        }
  481|  1.59k|      }
  482|       |
  483|    271|    } else
  484|  2.21k|#endif
  485|  2.21k|    {
  486|   302k|      for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
  ------------------
  |  Branch (486:31): [True: 300k, False: 2.21k]
  ------------------
  487|   300k|        if (!DecodeAttributeConnectivitiesOnFace(ci)) {
  ------------------
  |  Branch (487:13): [True: 0, False: 300k]
  ------------------
  488|      0|          return false;
  489|      0|        }
  490|   300k|      }
  491|  2.21k|    }
  492|  2.48k|  }
  493|  2.59k|  traversal_decoder_.Done();
  494|       |
  495|       |  // Decode attribute connectivity.
  496|       |  // Prepare data structure for decoding non-position attribute connectivity.
  497|  8.89k|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (497:24): [True: 6.29k, False: 2.59k]
  ------------------
  498|  6.29k|    attribute_data_[i].connectivity_data.InitEmpty(corner_table_.get());
  499|       |    // Add all seams.
  500|  2.42M|    for (int32_t c : attribute_data_[i].attribute_seam_corners) {
  ------------------
  |  Branch (500:20): [True: 2.42M, False: 6.29k]
  ------------------
  501|  2.42M|      attribute_data_[i].connectivity_data.AddSeamEdge(CornerIndex(c));
  502|  2.42M|    }
  503|       |    // Recompute vertices from the newly added seam edges.
  504|  6.29k|    if (!attribute_data_[i].connectivity_data.RecomputeVertices(nullptr,
  ------------------
  |  Branch (504:9): [True: 0, False: 6.29k]
  ------------------
  505|  6.29k|                                                                nullptr)) {
  506|      0|      return false;
  507|      0|    }
  508|  6.29k|  }
  509|       |
  510|  2.59k|  pos_encoding_data_.Init(corner_table_->num_vertices());
  511|  8.89k|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (511:24): [True: 6.29k, False: 2.59k]
  ------------------
  512|       |    // For non-position attributes, preallocate the vertex to value mapping
  513|       |    // using the maximum number of vertices from the base corner table and the
  514|       |    // attribute corner table (since the attribute decoder may use either of
  515|       |    // it).
  516|  6.29k|    int32_t att_connectivity_verts =
  517|  6.29k|        attribute_data_[i].connectivity_data.num_vertices();
  518|  6.29k|    if (att_connectivity_verts < corner_table_->num_vertices()) {
  ------------------
  |  Branch (518:9): [True: 428, False: 5.86k]
  ------------------
  519|    428|      att_connectivity_verts = corner_table_->num_vertices();
  520|    428|    }
  521|  6.29k|    attribute_data_[i].encoding_data.Init(att_connectivity_verts);
  522|  6.29k|  }
  523|  2.59k|  if (!AssignPointsToCorners(num_connectivity_verts)) {
  ------------------
  |  Branch (523:7): [True: 9, False: 2.58k]
  ------------------
  524|      9|    return false;
  525|      9|  }
  526|  2.58k|  return true;
  527|  2.59k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE19OnAttributesDecodedEv:
  530|    735|bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::OnAttributesDecoded() {
  531|    735|  return true;
  532|    735|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE18DecodeConnectivityEi:
  536|  2.90k|    int num_symbols) {
  537|       |  // Algorithm does the reverse decoding of the symbols encoded with the
  538|       |  // edgebreaker method. The reverse decoding always keeps track of the active
  539|       |  // edge identified by its opposite corner (active corner). New faces are
  540|       |  // always added to this active edge. There may be multiple active corners at
  541|       |  // one time that either correspond to separate mesh components or to
  542|       |  // sub-components of one mesh that are going to be merged together using the
  543|       |  // TOPOLOGY_S symbol. We can store these active edges on a stack, because the
  544|       |  // decoder always processes only the latest active edge. TOPOLOGY_S then
  545|       |  // removes the top edge from the stack and TOPOLOGY_E adds a new edge to the
  546|       |  // stack.
  547|  2.90k|  std::vector<CornerIndex> active_corner_stack;
  548|       |
  549|       |  // Additional active edges may be added as a result of topology split events.
  550|       |  // They can be added in arbitrary order, but we always know the split symbol
  551|       |  // id they belong to, so we can address them using this symbol id.
  552|  2.90k|  std::unordered_map<int, CornerIndex> topology_split_active_corners;
  553|       |
  554|       |  // Vector used for storing vertices that were marked as isolated during the
  555|       |  // decoding process. Currently used only when the mesh doesn't contain any
  556|       |  // non-position connectivity data.
  557|  2.90k|  std::vector<VertexIndex> invalid_vertices;
  558|  2.90k|  const bool remove_invalid_vertices = attribute_data_.empty();
  559|       |
  560|  2.90k|  int max_num_vertices = static_cast<int>(is_vert_hole_.size());
  561|  2.90k|  int num_faces = 0;
  562|  10.3M|  for (int symbol_id = 0; symbol_id < num_symbols; ++symbol_id) {
  ------------------
  |  Branch (562:27): [True: 10.3M, False: 2.64k]
  ------------------
  563|  10.3M|    const FaceIndex face(num_faces++);
  564|       |    // Used to flag cases where we need to look for topology split events.
  565|  10.3M|    bool check_topology_split = false;
  566|  10.3M|    const uint32_t symbol = traversal_decoder_.DecodeSymbol();
  567|  10.3M|    if (symbol == TOPOLOGY_C) {
  ------------------
  |  Branch (567:9): [True: 4.40M, False: 5.95M]
  ------------------
  568|       |      // Create a new face between two edges on the open boundary.
  569|       |      // The first edge is opposite to the corner "a" from the image below.
  570|       |      // The other edge is opposite to the corner "b" that can be reached
  571|       |      // through a CCW traversal around the vertex "v".
  572|       |      // One new active boundary edge is created, opposite to the new corner
  573|       |      // "x".
  574|       |      //
  575|       |      //     *-------*
  576|       |      //    / \     / \
  577|       |      //   /   \   /   \
  578|       |      //  /     \ /     \
  579|       |      // *-------v-------*
  580|       |      //  \b    /x\    a/
  581|       |      //   \   /   \   /
  582|       |      //    \ /  C  \ /
  583|       |      //     *.......*
  584|       |
  585|       |      // Find the corner "b" from the corner "a" which is the corner on the
  586|       |      // top of the active stack.
  587|  4.40M|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (587:11): [True: 2, False: 4.40M]
  ------------------
  588|      2|        return -1;
  589|      2|      }
  590|       |
  591|  4.40M|      const CornerIndex corner_a = active_corner_stack.back();
  592|  4.40M|      const VertexIndex vertex_x =
  593|  4.40M|          corner_table_->Vertex(corner_table_->Next(corner_a));
  594|  4.40M|      const CornerIndex corner_b =
  595|  4.40M|          corner_table_->Next(corner_table_->LeftMostCorner(vertex_x));
  596|       |
  597|  4.40M|      if (corner_a == corner_b) {
  ------------------
  |  Branch (597:11): [True: 183, False: 4.40M]
  ------------------
  598|       |        // All matched corners must be different.
  599|    183|        return -1;
  600|    183|      }
  601|  4.40M|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex ||
  ------------------
  |  Branch (601:11): [True: 0, False: 4.40M]
  |  Branch (601:11): [True: 0, False: 4.40M]
  ------------------
  602|  4.40M|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex) {
  ------------------
  |  Branch (602:11): [True: 0, False: 4.40M]
  ------------------
  603|       |        // One of the corners is already opposite to an existing face, which
  604|       |        // should not happen unless the input was tampered with.
  605|      0|        return -1;
  606|      0|      }
  607|       |
  608|       |      // New tip corner.
  609|  4.40M|      const CornerIndex corner(3 * face.value());
  610|       |      // Update opposite corner mappings.
  611|  4.40M|      SetOppositeCorners(corner_a, corner + 1);
  612|  4.40M|      SetOppositeCorners(corner_b, corner + 2);
  613|       |
  614|       |      // Update vertex mapping.
  615|  4.40M|      const VertexIndex vert_a_prev =
  616|  4.40M|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  617|  4.40M|      const VertexIndex vert_b_next =
  618|  4.40M|          corner_table_->Vertex(corner_table_->Next(corner_b));
  619|  4.40M|      if (vertex_x == vert_a_prev || vertex_x == vert_b_next) {
  ------------------
  |  Branch (619:11): [True: 0, False: 4.40M]
  |  Branch (619:38): [True: 0, False: 4.40M]
  ------------------
  620|       |        // Encoding is invalid, because face vertices are degenerate.
  621|      0|        return -1;
  622|      0|      }
  623|  4.40M|      corner_table_->MapCornerToVertex(corner, vertex_x);
  624|  4.40M|      corner_table_->MapCornerToVertex(corner + 1, vert_b_next);
  625|  4.40M|      corner_table_->MapCornerToVertex(corner + 2, vert_a_prev);
  626|  4.40M|      corner_table_->SetLeftMostCorner(vert_a_prev, corner + 2);
  627|       |      // Mark the vertex |x| as interior.
  628|  4.40M|      is_vert_hole_[vertex_x.value()] = false;
  629|       |      // Update the corner on the active stack.
  630|  4.40M|      active_corner_stack.back() = corner;
  631|  5.95M|    } else if (symbol == TOPOLOGY_R || symbol == TOPOLOGY_L) {
  ------------------
  |  Branch (631:16): [True: 1.96M, False: 3.99M]
  |  Branch (631:40): [True: 704k, False: 3.29M]
  ------------------
  632|       |      // Create a new face extending from the open boundary edge opposite to the
  633|       |      // corner "a" from the image below. Two new boundary edges are created
  634|       |      // opposite to corners "r" and "l". New active corner is set to either "r"
  635|       |      // or "l" depending on the decoded symbol. One new vertex is created
  636|       |      // at the opposite corner to corner "a".
  637|       |      //     *-------*
  638|       |      //    /a\     / \
  639|       |      //   /   \   /   \
  640|       |      //  /     \ /     \
  641|       |      // *-------v-------*
  642|       |      //  .l   r.
  643|       |      //   .   .
  644|       |      //    . .
  645|       |      //     *
  646|  2.66M|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (646:11): [True: 2, False: 2.66M]
  ------------------
  647|      2|        return -1;
  648|      2|      }
  649|  2.66M|      const CornerIndex corner_a = active_corner_stack.back();
  650|  2.66M|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex) {
  ------------------
  |  Branch (650:11): [True: 0, False: 2.66M]
  ------------------
  651|       |        // Active corner is already opposite to an existing face, which should
  652|       |        // not happen unless the input was tampered with.
  653|      0|        return -1;
  654|      0|      }
  655|       |
  656|       |      // First corner on the new face is either corner "l" or "r".
  657|  2.66M|      const CornerIndex corner(3 * face.value());
  658|  2.66M|      CornerIndex opp_corner, corner_l, corner_r;
  659|  2.66M|      if (symbol == TOPOLOGY_R) {
  ------------------
  |  Branch (659:11): [True: 1.96M, False: 704k]
  ------------------
  660|       |        // "r" is the new first corner.
  661|  1.96M|        opp_corner = corner + 2;
  662|  1.96M|        corner_l = corner + 1;
  663|  1.96M|        corner_r = corner;
  664|  1.96M|      } else {
  665|       |        // "l" is the new first corner.
  666|   704k|        opp_corner = corner + 1;
  667|   704k|        corner_l = corner;
  668|   704k|        corner_r = corner + 2;
  669|   704k|      }
  670|  2.66M|      SetOppositeCorners(opp_corner, corner_a);
  671|       |      // Update vertex mapping.
  672|  2.66M|      const VertexIndex new_vert_index = corner_table_->AddNewVertex();
  673|       |
  674|  2.66M|      if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (674:11): [True: 1, False: 2.66M]
  ------------------
  675|      1|        return -1;  // Unexpected number of decoded vertices.
  676|      1|      }
  677|       |
  678|  2.66M|      corner_table_->MapCornerToVertex(opp_corner, new_vert_index);
  679|  2.66M|      corner_table_->SetLeftMostCorner(new_vert_index, opp_corner);
  680|       |
  681|  2.66M|      const VertexIndex vertex_r =
  682|  2.66M|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  683|  2.66M|      corner_table_->MapCornerToVertex(corner_r, vertex_r);
  684|       |      // Update left-most corner on the vertex on the |corner_r|.
  685|  2.66M|      corner_table_->SetLeftMostCorner(vertex_r, corner_r);
  686|       |
  687|  2.66M|      corner_table_->MapCornerToVertex(
  688|  2.66M|          corner_l, corner_table_->Vertex(corner_table_->Next(corner_a)));
  689|  2.66M|      active_corner_stack.back() = corner;
  690|  2.66M|      check_topology_split = true;
  691|  3.29M|    } else if (symbol == TOPOLOGY_S) {
  ------------------
  |  Branch (691:16): [True: 1.11M, False: 2.17M]
  ------------------
  692|       |      // Create a new face that merges two last active edges from the active
  693|       |      // stack. No new vertex is created, but two vertices at corners "p" and
  694|       |      // "n" need to be merged into a single vertex.
  695|       |      //
  696|       |      // *-------v-------*
  697|       |      //  \a   p/x\n   b/
  698|       |      //   \   /   \   /
  699|       |      //    \ /  S  \ /
  700|       |      //     *.......*
  701|       |      //
  702|  1.11M|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (702:11): [True: 1, False: 1.11M]
  ------------------
  703|      1|        return -1;
  704|      1|      }
  705|  1.11M|      const CornerIndex corner_b = active_corner_stack.back();
  706|  1.11M|      active_corner_stack.pop_back();
  707|       |
  708|       |      // Corner "a" can correspond either to a normal active edge, or to an edge
  709|       |      // created from the topology split event.
  710|  1.11M|      const auto it = topology_split_active_corners.find(symbol_id);
  711|  1.11M|      if (it != topology_split_active_corners.end()) {
  ------------------
  |  Branch (711:11): [True: 73, False: 1.11M]
  ------------------
  712|       |        // Topology split event. Move the retrieved edge to the stack.
  713|     73|        active_corner_stack.push_back(it->second);
  714|     73|      }
  715|  1.11M|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (715:11): [True: 17, False: 1.11M]
  ------------------
  716|     17|        return -1;
  717|     17|      }
  718|  1.11M|      const CornerIndex corner_a = active_corner_stack.back();
  719|       |
  720|  1.11M|      if (corner_a == corner_b) {
  ------------------
  |  Branch (720:11): [True: 0, False: 1.11M]
  ------------------
  721|       |        // All matched corners must be different.
  722|      0|        return -1;
  723|      0|      }
  724|  1.11M|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex ||
  ------------------
  |  Branch (724:11): [True: 9, False: 1.11M]
  |  Branch (724:11): [True: 9, False: 1.11M]
  ------------------
  725|  1.11M|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex) {
  ------------------
  |  Branch (725:11): [True: 0, False: 1.11M]
  ------------------
  726|       |        // One of the corners is already opposite to an existing face, which
  727|       |        // should not happen unless the input was tampered with.
  728|      9|        return -1;
  729|      9|      }
  730|       |
  731|       |      // First corner on the new face is corner "x" from the image above.
  732|  1.11M|      const CornerIndex corner(3 * face.value());
  733|       |      // Update the opposite corner mapping.
  734|  1.11M|      SetOppositeCorners(corner_a, corner + 2);
  735|  1.11M|      SetOppositeCorners(corner_b, corner + 1);
  736|       |      // Update vertices. For the vertex at corner "x", use the vertex id from
  737|       |      // the corner "p".
  738|  1.11M|      const VertexIndex vertex_p =
  739|  1.11M|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  740|  1.11M|      corner_table_->MapCornerToVertex(corner, vertex_p);
  741|  1.11M|      corner_table_->MapCornerToVertex(
  742|  1.11M|          corner + 1, corner_table_->Vertex(corner_table_->Next(corner_a)));
  743|  1.11M|      const VertexIndex vert_b_prev =
  744|  1.11M|          corner_table_->Vertex(corner_table_->Previous(corner_b));
  745|  1.11M|      corner_table_->MapCornerToVertex(corner + 2, vert_b_prev);
  746|  1.11M|      corner_table_->SetLeftMostCorner(vert_b_prev, corner + 2);
  747|  1.11M|      CornerIndex corner_n = corner_table_->Next(corner_b);
  748|  1.11M|      const VertexIndex vertex_n = corner_table_->Vertex(corner_n);
  749|  1.11M|      traversal_decoder_.MergeVertices(vertex_p, vertex_n);
  750|       |      // Update the left most corner on the newly merged vertex.
  751|  1.11M|      corner_table_->SetLeftMostCorner(vertex_p,
  752|  1.11M|                                       corner_table_->LeftMostCorner(vertex_n));
  753|       |
  754|       |      // Also update the vertex id at corner "n" and all corners that are
  755|       |      // connected to it in the CCW direction.
  756|  1.11M|      const CornerIndex first_corner = corner_n;
  757|  7.33M|      while (corner_n != kInvalidCornerIndex) {
  ------------------
  |  Branch (757:14): [True: 6.21M, False: 1.11M]
  ------------------
  758|  6.21M|        corner_table_->MapCornerToVertex(corner_n, vertex_p);
  759|  6.21M|        corner_n = corner_table_->SwingLeft(corner_n);
  760|  6.21M|        if (corner_n == first_corner) {
  ------------------
  |  Branch (760:13): [True: 2, False: 6.21M]
  ------------------
  761|       |          // We reached the start again which should not happen for split
  762|       |          // symbols.
  763|      2|          return -1;
  764|      2|        }
  765|  6.21M|      }
  766|       |      // Make sure the old vertex n is now mapped to an invalid corner (make it
  767|       |      // isolated).
  768|  1.11M|      corner_table_->MakeVertexIsolated(vertex_n);
  769|  1.11M|      if (remove_invalid_vertices) {
  ------------------
  |  Branch (769:11): [True: 18.4k, False: 1.09M]
  ------------------
  770|  18.4k|        invalid_vertices.push_back(vertex_n);
  771|  18.4k|      }
  772|  1.11M|      active_corner_stack.back() = corner;
  773|  2.17M|    } else if (symbol == TOPOLOGY_E) {
  ------------------
  |  Branch (773:16): [True: 2.17M, False: 0]
  ------------------
  774|  2.17M|      const CornerIndex corner(3 * face.value());
  775|  2.17M|      const VertexIndex first_vert_index = corner_table_->AddNewVertex();
  776|       |      // Create three new vertices at the corners of the new face.
  777|  2.17M|      corner_table_->MapCornerToVertex(corner, first_vert_index);
  778|  2.17M|      corner_table_->MapCornerToVertex(corner + 1,
  779|  2.17M|                                       corner_table_->AddNewVertex());
  780|  2.17M|      corner_table_->MapCornerToVertex(corner + 2,
  781|  2.17M|                                       corner_table_->AddNewVertex());
  782|       |
  783|  2.17M|      if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (783:11): [True: 4, False: 2.17M]
  ------------------
  784|      4|        return -1;  // Unexpected number of decoded vertices.
  785|      4|      }
  786|       |
  787|  2.17M|      corner_table_->SetLeftMostCorner(first_vert_index, corner);
  788|  2.17M|      corner_table_->SetLeftMostCorner(first_vert_index + 1, corner + 1);
  789|  2.17M|      corner_table_->SetLeftMostCorner(first_vert_index + 2, corner + 2);
  790|       |      // Add the tip corner to the active stack.
  791|  2.17M|      active_corner_stack.push_back(corner);
  792|  2.17M|      check_topology_split = true;
  793|  2.17M|    } else {
  794|       |      // Error. Unknown symbol decoded.
  795|      0|      return -1;
  796|      0|    }
  797|       |    // Inform the traversal decoder that a new corner has been reached.
  798|  10.3M|    traversal_decoder_.NewActiveCornerReached(active_corner_stack.back());
  799|       |
  800|  10.3M|    if (check_topology_split) {
  ------------------
  |  Branch (800:9): [True: 4.84M, False: 5.52M]
  ------------------
  801|       |      // Check for topology splits happens only for TOPOLOGY_L, TOPOLOGY_R and
  802|       |      // TOPOLOGY_E symbols because those are the symbols that correspond to
  803|       |      // faces that can be directly connected a TOPOLOGY_S face through the
  804|       |      // topology split event.
  805|       |      // If a topology split is detected, we need to add a new active edge
  806|       |      // onto the active_corner_stack because it will be used later when the
  807|       |      // corresponding TOPOLOGY_S event is decoded.
  808|       |
  809|       |      // Symbol id used by the encoder (reverse).
  810|  4.84M|      const int encoder_symbol_id = num_symbols - symbol_id - 1;
  811|  4.84M|      EdgeFaceName split_edge;
  812|  4.84M|      int encoder_split_symbol_id;
  813|  4.84M|      while (IsTopologySplit(encoder_symbol_id, &split_edge,
  ------------------
  |  Branch (813:14): [True: 2.02k, False: 4.84M]
  ------------------
  814|  4.84M|                             &encoder_split_symbol_id)) {
  815|  2.02k|        if (encoder_split_symbol_id < 0) {
  ------------------
  |  Branch (815:13): [True: 37, False: 1.99k]
  ------------------
  816|     37|          return -1;  // Wrong split symbol id.
  817|     37|        }
  818|       |        // Symbol was part of a topology split. Now we need to determine which
  819|       |        // edge should be added to the active edges stack.
  820|  1.99k|        const CornerIndex act_top_corner = active_corner_stack.back();
  821|       |        // The current symbol has one active edge (stored in act_top_corner) and
  822|       |        // two remaining inactive edges that are attached to it.
  823|       |        //              *
  824|       |        //             / \
  825|       |        //  left_edge /   \ right_edge
  826|       |        //           /     \
  827|       |        //          *.......*
  828|       |        //         active_edge
  829|       |
  830|  1.99k|        CornerIndex new_active_corner;
  831|  1.99k|        if (split_edge == RIGHT_FACE_EDGE) {
  ------------------
  |  Branch (831:13): [True: 628, False: 1.36k]
  ------------------
  832|    628|          new_active_corner = corner_table_->Next(act_top_corner);
  833|  1.36k|        } else {
  834|  1.36k|          new_active_corner = corner_table_->Previous(act_top_corner);
  835|  1.36k|        }
  836|       |        // Add the new active edge.
  837|       |        // Convert the encoder split symbol id to decoder symbol id.
  838|  1.99k|        const int decoder_split_symbol_id =
  839|  1.99k|            num_symbols - encoder_split_symbol_id - 1;
  840|  1.99k|        topology_split_active_corners[decoder_split_symbol_id] =
  841|  1.99k|            new_active_corner;
  842|  1.99k|      }
  843|  4.84M|    }
  844|  10.3M|  }
  845|  2.64k|  if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (845:7): [True: 0, False: 2.64k]
  ------------------
  846|      0|    return -1;  // Unexpected number of decoded vertices.
  847|      0|  }
  848|       |  // Decode start faces and connect them to the faces from the active stack.
  849|  43.5k|  while (!active_corner_stack.empty()) {
  ------------------
  |  Branch (849:10): [True: 40.9k, False: 2.61k]
  ------------------
  850|  40.9k|    const CornerIndex corner = active_corner_stack.back();
  851|  40.9k|    active_corner_stack.pop_back();
  852|  40.9k|    const bool interior_face =
  853|  40.9k|        traversal_decoder_.DecodeStartFaceConfiguration();
  854|  40.9k|    if (interior_face) {
  ------------------
  |  Branch (854:9): [True: 30.6k, False: 10.2k]
  ------------------
  855|       |      // The start face is interior, we need to find three corners that are
  856|       |      // opposite to it. The first opposite corner "a" is the corner from the
  857|       |      // top of the active corner stack and the remaining two corners "b" and
  858|       |      // "c" are then the next corners from the left-most corners of vertices
  859|       |      // "n" and "x" respectively.
  860|       |      //
  861|       |      //           *-------*
  862|       |      //          / \     / \
  863|       |      //         /   \   /   \
  864|       |      //        /     \ /     \
  865|       |      //       *-------p-------*
  866|       |      //      / \a    . .    c/ \
  867|       |      //     /   \   .   .   /   \
  868|       |      //    /     \ .  I  . /     \
  869|       |      //   *-------n.......x------*
  870|       |      //    \     / \     / \     /
  871|       |      //     \   /   \   /   \   /
  872|       |      //      \ /     \b/     \ /
  873|       |      //       *-------*-------*
  874|       |      //
  875|       |
  876|  30.6k|      if (num_faces >= corner_table_->num_faces()) {
  ------------------
  |  Branch (876:11): [True: 5, False: 30.6k]
  ------------------
  877|      5|        return -1;  // More faces than expected added to the mesh.
  878|      5|      }
  879|       |
  880|  30.6k|      const CornerIndex corner_a = corner;
  881|  30.6k|      const VertexIndex vert_n =
  882|  30.6k|          corner_table_->Vertex(corner_table_->Next(corner_a));
  883|  30.6k|      const CornerIndex corner_b =
  884|  30.6k|          corner_table_->Next(corner_table_->LeftMostCorner(vert_n));
  885|       |
  886|  30.6k|      const VertexIndex vert_x =
  887|  30.6k|          corner_table_->Vertex(corner_table_->Next(corner_b));
  888|  30.6k|      const CornerIndex corner_c =
  889|  30.6k|          corner_table_->Next(corner_table_->LeftMostCorner(vert_x));
  890|       |
  891|  30.6k|      if (corner == corner_b || corner == corner_c || corner_b == corner_c) {
  ------------------
  |  Branch (891:11): [True: 17, False: 30.6k]
  |  Branch (891:33): [True: 11, False: 30.6k]
  |  Branch (891:55): [True: 0, False: 30.6k]
  ------------------
  892|       |        // All matched corners must be different.
  893|     28|        return -1;
  894|     28|      }
  895|  30.6k|      if (corner_table_->Opposite(corner) != kInvalidCornerIndex ||
  ------------------
  |  Branch (895:11): [True: 1, False: 30.6k]
  |  Branch (895:11): [True: 1, False: 30.6k]
  ------------------
  896|  30.6k|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex ||
  ------------------
  |  Branch (896:11): [True: 0, False: 30.6k]
  ------------------
  897|  30.6k|          corner_table_->Opposite(corner_c) != kInvalidCornerIndex) {
  ------------------
  |  Branch (897:11): [True: 0, False: 30.6k]
  ------------------
  898|       |        // One of the corners is already opposite to an existing face, which
  899|       |        // should not happen unless the input was tampered with.
  900|      1|        return -1;
  901|      1|      }
  902|       |
  903|  30.6k|      const VertexIndex vert_p =
  904|  30.6k|          corner_table_->Vertex(corner_table_->Next(corner_c));
  905|       |
  906|  30.6k|      const FaceIndex face(num_faces++);
  907|       |      // The first corner of the initial face is the corner opposite to "a".
  908|  30.6k|      const CornerIndex new_corner(3 * face.value());
  909|  30.6k|      SetOppositeCorners(new_corner, corner);
  910|  30.6k|      SetOppositeCorners(new_corner + 1, corner_b);
  911|  30.6k|      SetOppositeCorners(new_corner + 2, corner_c);
  912|       |
  913|       |      // Map new corners to existing vertices.
  914|  30.6k|      corner_table_->MapCornerToVertex(new_corner, vert_x);
  915|  30.6k|      corner_table_->MapCornerToVertex(new_corner + 1, vert_p);
  916|  30.6k|      corner_table_->MapCornerToVertex(new_corner + 2, vert_n);
  917|       |
  918|       |      // Mark all three vertices as interior.
  919|   122k|      for (int ci = 0; ci < 3; ++ci) {
  ------------------
  |  Branch (919:24): [True: 91.9k, False: 30.6k]
  ------------------
  920|  91.9k|        is_vert_hole_[corner_table_->Vertex(new_corner + ci).value()] = false;
  921|  91.9k|      }
  922|       |
  923|  30.6k|      init_face_configurations_.push_back(true);
  924|  30.6k|      init_corners_.push_back(new_corner);
  925|  30.6k|    } else {
  926|       |      // The initial face wasn't interior and the traversal had to start from
  927|       |      // an open boundary. In this case no new face is added, but we need to
  928|       |      // keep record about the first opposite corner to this boundary.
  929|  10.2k|      init_face_configurations_.push_back(false);
  930|  10.2k|      init_corners_.push_back(corner);
  931|  10.2k|    }
  932|  40.9k|  }
  933|  2.61k|  if (num_faces != corner_table_->num_faces()) {
  ------------------
  |  Branch (933:7): [True: 18, False: 2.59k]
  ------------------
  934|     18|    return -1;  // Unexpected number of decoded faces.
  935|     18|  }
  936|       |
  937|  2.59k|  int num_vertices = corner_table_->num_vertices();
  938|       |  // If any vertex was marked as isolated, we want to remove it from the corner
  939|       |  // table to ensure that all vertices in range <0, num_vertices> are valid.
  940|  2.59k|  for (const VertexIndex invalid_vert : invalid_vertices) {
  ------------------
  |  Branch (940:39): [True: 754, False: 2.59k]
  ------------------
  941|       |    // Find the last valid vertex and swap it with the isolated vertex.
  942|    754|    VertexIndex src_vert(num_vertices - 1);
  943|    898|    while (corner_table_->LeftMostCorner(src_vert) == kInvalidCornerIndex) {
  ------------------
  |  Branch (943:12): [True: 144, False: 754]
  ------------------
  944|       |      // The last vertex is invalid, proceed to the previous one.
  945|    144|      src_vert = VertexIndex(--num_vertices - 1);
  946|    144|    }
  947|    754|    if (src_vert < invalid_vert) {
  ------------------
  |  Branch (947:9): [True: 144, False: 610]
  ------------------
  948|    144|      continue;  // No need to swap anything.
  949|    144|    }
  950|       |
  951|       |    // Remap all corners mapped to |src_vert| to |invalid_vert|.
  952|    610|    VertexCornersIterator<CornerTable> vcit(corner_table_.get(), src_vert);
  953|  4.01k|    for (; !vcit.End(); ++vcit) {
  ------------------
  |  Branch (953:12): [True: 3.40k, False: 609]
  ------------------
  954|  3.40k|      const CornerIndex cid = vcit.Corner();
  955|  3.40k|      if (corner_table_->Vertex(cid) != src_vert) {
  ------------------
  |  Branch (955:11): [True: 1, False: 3.40k]
  ------------------
  956|       |        // Vertex mapped to |cid| was not |src_vert|. This indicates corrupted
  957|       |        // data and we should terminate the decoding.
  958|      1|        return -1;
  959|      1|      }
  960|  3.40k|      corner_table_->MapCornerToVertex(cid, invalid_vert);
  961|  3.40k|    }
  962|    609|    corner_table_->SetLeftMostCorner(invalid_vert,
  963|    609|                                     corner_table_->LeftMostCorner(src_vert));
  964|       |
  965|       |    // Make the |src_vert| invalid.
  966|    609|    corner_table_->MakeVertexIsolated(src_vert);
  967|    609|    is_vert_hole_[invalid_vert.value()] = is_vert_hole_[src_vert.value()];
  968|    609|    is_vert_hole_[src_vert.value()] = false;
  969|       |
  970|       |    // The last vertex is now invalid.
  971|    609|    num_vertices--;
  972|    609|  }
  973|  2.59k|  return num_vertices;
  974|  2.59k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE32DecodeHoleAndTopologySplitEventsEPNS_13DecoderBufferE:
  979|  3.45k|    DecoderBuffer* decoder_buffer) {
  980|       |  // Prepare a new decoder from the provided buffer offset.
  981|  3.45k|  uint32_t num_topology_splits;
  982|  3.45k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  983|  3.45k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  3.45k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (983:7): [True: 149, False: 3.30k]
  ------------------
  984|    149|    if (!decoder_buffer->Decode(&num_topology_splits)) {
  ------------------
  |  Branch (984:9): [True: 1, False: 148]
  ------------------
  985|      1|      return -1;
  986|      1|    }
  987|       |
  988|    149|  } else
  989|  3.30k|#endif
  990|  3.30k|  {
  991|  3.30k|    if (!DecodeVarint(&num_topology_splits, decoder_buffer)) {
  ------------------
  |  Branch (991:9): [True: 9, False: 3.29k]
  ------------------
  992|      9|      return -1;
  993|      9|    }
  994|  3.30k|  }
  995|  3.44k|  if (num_topology_splits > 0) {
  ------------------
  |  Branch (995:7): [True: 1.69k, False: 1.74k]
  ------------------
  996|  1.69k|    if (num_topology_splits >
  ------------------
  |  Branch (996:9): [True: 72, False: 1.62k]
  ------------------
  997|  1.69k|        static_cast<uint32_t>(corner_table_->num_faces())) {
  998|     72|      return -1;
  999|     72|    }
 1000|  1.62k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1001|  1.62k|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|  1.62k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1001:9): [True: 65, False: 1.55k]
  ------------------
 1002|  51.4k|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1002:28): [True: 51.4k, False: 26]
  ------------------
 1003|  51.4k|        TopologySplitEventData event_data;
 1004|  51.4k|        if (!decoder_buffer->Decode(&event_data.split_symbol_id)) {
  ------------------
  |  Branch (1004:13): [True: 25, False: 51.4k]
  ------------------
 1005|     25|          return -1;
 1006|     25|        }
 1007|  51.4k|        if (!decoder_buffer->Decode(&event_data.source_symbol_id)) {
  ------------------
  |  Branch (1007:13): [True: 10, False: 51.4k]
  ------------------
 1008|     10|          return -1;
 1009|     10|        }
 1010|  51.4k|        uint8_t edge_data;
 1011|  51.4k|        if (!decoder_buffer->Decode(&edge_data)) {
  ------------------
  |  Branch (1011:13): [True: 4, False: 51.4k]
  ------------------
 1012|      4|          return -1;
 1013|      4|        }
 1014|  51.4k|        event_data.source_edge = edge_data & 1;
 1015|  51.4k|        topology_split_data_.push_back(event_data);
 1016|  51.4k|      }
 1017|       |
 1018|     65|    } else
 1019|  1.55k|#endif
 1020|  1.55k|    {
 1021|       |      // Decode source and split symbol ids using delta and varint coding. See
 1022|       |      // description in mesh_edgebreaker_encoder_impl.cc for more details.
 1023|  1.55k|      int last_source_symbol_id = 0;
 1024|  7.27k|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1024:28): [True: 5.78k, False: 1.49k]
  ------------------
 1025|  5.78k|        TopologySplitEventData event_data;
 1026|  5.78k|        uint32_t delta;
 1027|  5.78k|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1027:13): [True: 20, False: 5.76k]
  ------------------
 1028|     20|          return -1;
 1029|     20|        }
 1030|  5.76k|        event_data.source_symbol_id = delta + last_source_symbol_id;
 1031|  5.76k|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1031:13): [True: 12, False: 5.74k]
  ------------------
 1032|     12|          return -1;
 1033|     12|        }
 1034|  5.74k|        if (delta > event_data.source_symbol_id) {
  ------------------
  |  Branch (1034:13): [True: 32, False: 5.71k]
  ------------------
 1035|     32|          return -1;
 1036|     32|        }
 1037|  5.71k|        event_data.split_symbol_id =
 1038|  5.71k|            event_data.source_symbol_id - static_cast<int32_t>(delta);
 1039|  5.71k|        last_source_symbol_id = event_data.source_symbol_id;
 1040|  5.71k|        topology_split_data_.push_back(event_data);
 1041|  5.71k|      }
 1042|       |      // Split edges are decoded from a direct bit decoder.
 1043|  1.49k|      decoder_buffer->StartBitDecoding(false, nullptr);
 1044|  6.73k|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1044:28): [True: 5.23k, False: 1.49k]
  ------------------
 1045|  5.23k|        uint32_t edge_data;
 1046|  5.23k|        if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  5.23k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1046:13): [True: 1.44k, False: 3.79k]
  ------------------
 1047|  1.44k|          decoder_buffer->DecodeLeastSignificantBits32(2, &edge_data);
 1048|  3.79k|        } else {
 1049|  3.79k|          decoder_buffer->DecodeLeastSignificantBits32(1, &edge_data);
 1050|  3.79k|        }
 1051|  5.23k|        TopologySplitEventData& event_data = topology_split_data_[i];
 1052|  5.23k|        event_data.source_edge = edge_data & 1;
 1053|  5.23k|      }
 1054|  1.49k|      decoder_buffer->EndBitDecoding();
 1055|  1.49k|    }
 1056|  1.62k|  }
 1057|  3.26k|  uint32_t num_hole_events = 0;
 1058|  3.26k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1059|  3.26k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  3.26k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1059:7): [True: 89, False: 3.17k]
  ------------------
 1060|     89|    if (!decoder_buffer->Decode(&num_hole_events)) {
  ------------------
  |  Branch (1060:9): [True: 7, False: 82]
  ------------------
 1061|      7|      return -1;
 1062|      7|    }
 1063|  3.17k|  } else if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
  ------------------
  |  |  115|  3.17k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1063:14): [True: 417, False: 2.76k]
  ------------------
 1064|    417|    if (!DecodeVarint(&num_hole_events, decoder_buffer)) {
  ------------------
  |  Branch (1064:9): [True: 12, False: 405]
  ------------------
 1065|     12|      return -1;
 1066|     12|    }
 1067|    417|  }
 1068|  3.24k|#endif
 1069|  3.24k|  if (num_hole_events > 0) {
  ------------------
  |  Branch (1069:7): [True: 107, False: 3.14k]
  ------------------
 1070|    107|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1071|    107|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|    107|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1071:9): [True: 60, False: 47]
  ------------------
 1072|   211k|      for (uint32_t i = 0; i < num_hole_events; ++i) {
  ------------------
  |  Branch (1072:28): [True: 211k, False: 11]
  ------------------
 1073|   211k|        HoleEventData event_data;
 1074|   211k|        if (!decoder_buffer->Decode(&event_data)) {
  ------------------
  |  Branch (1074:13): [True: 49, False: 211k]
  ------------------
 1075|     49|          return -1;
 1076|     49|        }
 1077|   211k|        hole_event_data_.push_back(event_data);
 1078|   211k|      }
 1079|       |
 1080|     60|    } else
 1081|     47|#endif
 1082|     47|    {
 1083|       |      // Decode hole symbol ids using delta and varint coding.
 1084|     47|      int last_symbol_id = 0;
 1085|  88.1k|      for (uint32_t i = 0; i < num_hole_events; ++i) {
  ------------------
  |  Branch (1085:28): [True: 88.1k, False: 10]
  ------------------
 1086|  88.1k|        HoleEventData event_data;
 1087|  88.1k|        uint32_t delta;
 1088|  88.1k|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1088:13): [True: 37, False: 88.1k]
  ------------------
 1089|     37|          return -1;
 1090|     37|        }
 1091|  88.1k|        event_data.symbol_id = delta + last_symbol_id;
 1092|  88.1k|        last_symbol_id = event_data.symbol_id;
 1093|  88.1k|        hole_event_data_.push_back(event_data);
 1094|  88.1k|      }
 1095|     47|    }
 1096|    107|  }
 1097|  3.16k|  return static_cast<int32_t>(decoder_buffer->decoded_size());
 1098|  3.24k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE41DecodeAttributeConnectivitiesOnFaceLegacyENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
 1103|  1.59k|    DecodeAttributeConnectivitiesOnFaceLegacy(CornerIndex corner) {
 1104|       |  // Three corners of the face.
 1105|  1.59k|  const CornerIndex corners[3] = {corner, corner_table_->Next(corner),
 1106|  1.59k|                                  corner_table_->Previous(corner)};
 1107|       |
 1108|  6.36k|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1108:19): [True: 4.77k, False: 1.59k]
  ------------------
 1109|  4.77k|    const CornerIndex opp_corner = corner_table_->Opposite(corners[c]);
 1110|  4.77k|    if (opp_corner == kInvalidCornerIndex) {
  ------------------
  |  Branch (1110:9): [True: 1.44k, False: 3.32k]
  ------------------
 1111|       |      // Don't decode attribute seams on boundary edges (every boundary edge
 1112|       |      // is automatically an attribute seam).
 1113|  2.88k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1113:28): [True: 1.44k, False: 1.44k]
  ------------------
 1114|  1.44k|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1115|  1.44k|      }
 1116|  1.44k|      continue;
 1117|  1.44k|    }
 1118|       |
 1119|  6.65k|    for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1119:26): [True: 3.32k, False: 3.32k]
  ------------------
 1120|  3.32k|      const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i);
 1121|  3.32k|      if (is_seam) {
  ------------------
  |  Branch (1121:11): [True: 2.68k, False: 644]
  ------------------
 1122|  2.68k|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1123|  2.68k|      }
 1124|  3.32k|    }
 1125|  3.32k|  }
 1126|  1.59k|  return true;
 1127|  1.59k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE35DecodeAttributeConnectivitiesOnFaceENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
 1132|   300k|    TraversalDecoder>::DecodeAttributeConnectivitiesOnFace(CornerIndex corner) {
 1133|       |  // Three corners of the face.
 1134|   300k|  const CornerIndex corners[3] = {corner, corner_table_->Next(corner),
 1135|   300k|                                  corner_table_->Previous(corner)};
 1136|       |
 1137|   300k|  const FaceIndex src_face_id = corner_table_->Face(corner);
 1138|  1.20M|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1138:19): [True: 900k, False: 300k]
  ------------------
 1139|   900k|    const CornerIndex opp_corner = corner_table_->Opposite(corners[c]);
 1140|   900k|    if (opp_corner == kInvalidCornerIndex) {
  ------------------
  |  Branch (1140:9): [True: 42.2k, False: 857k]
  ------------------
 1141|       |      // Don't decode attribute seams on boundary edges (every boundary edge
 1142|       |      // is automatically an attribute seam).
 1143|   240k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1143:28): [True: 198k, False: 42.2k]
  ------------------
 1144|   198k|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1145|   198k|      }
 1146|  42.2k|      continue;
 1147|  42.2k|    }
 1148|   857k|    const FaceIndex opp_face_id = corner_table_->Face(opp_corner);
 1149|       |    // Don't decode edges when the opposite face has been already processed.
 1150|   857k|    if (opp_face_id < src_face_id) {
  ------------------
  |  Branch (1150:9): [True: 428k, False: 428k]
  ------------------
 1151|   428k|      continue;
 1152|   428k|    }
 1153|       |
 1154|  3.00M|    for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1154:26): [True: 2.57M, False: 428k]
  ------------------
 1155|  2.57M|      const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i);
 1156|  2.57M|      if (is_seam) {
  ------------------
  |  Branch (1156:11): [True: 2.22M, False: 349k]
  ------------------
 1157|  2.22M|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1158|  2.22M|      }
 1159|  2.57M|    }
 1160|   428k|  }
 1161|   300k|  return true;
 1162|   300k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE21AssignPointsToCornersEi:
 1166|  2.59k|    int num_connectivity_verts) {
 1167|       |  // Map between the existing and deduplicated point ids.
 1168|       |  // Note that at this point we have one point id for each corner of the
 1169|       |  // mesh so there is corner_table_->num_corners() point ids.
 1170|  2.59k|  decoder_->mesh()->SetNumFaces(corner_table_->num_faces());
 1171|       |
 1172|  2.59k|  if (attribute_data_.empty()) {
  ------------------
  |  Branch (1172:7): [True: 107, False: 2.48k]
  ------------------
 1173|       |    // We have connectivity for position only. In this case all vertex indices
 1174|       |    // are equal to point indices.
 1175|  6.66k|    for (FaceIndex f(0); f < decoder_->mesh()->num_faces(); ++f) {
  ------------------
  |  Branch (1175:26): [True: 6.55k, False: 107]
  ------------------
 1176|  6.55k|      Mesh::Face face;
 1177|  6.55k|      const CornerIndex start_corner(3 * f.value());
 1178|  26.2k|      for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1178:23): [True: 19.6k, False: 6.55k]
  ------------------
 1179|       |        // Get the vertex index on the corner and use it as a point index.
 1180|  19.6k|        const int32_t vert_id = corner_table_->Vertex(start_corner + c).value();
 1181|  19.6k|        face[c] = vert_id;
 1182|  19.6k|      }
 1183|  6.55k|      decoder_->mesh()->SetFace(f, face);
 1184|  6.55k|    }
 1185|    107|    decoder_->point_cloud()->set_num_points(num_connectivity_verts);
 1186|    107|    return true;
 1187|    107|  }
 1188|       |  // Else we need to deduplicate multiple attributes.
 1189|       |
 1190|       |  // Map between point id and an associated corner id. Only one corner for
 1191|       |  // each point is stored. The corners are used to sample the attribute values
 1192|       |  // in the last stage of the deduplication.
 1193|  2.48k|  std::vector<int32_t> point_to_corner_map;
 1194|       |  // Map between every corner and their new point ids.
 1195|  2.48k|  std::vector<int32_t> corner_to_point_map(corner_table_->num_corners());
 1196|   199k|  for (int v = 0; v < corner_table_->num_vertices(); ++v) {
  ------------------
  |  Branch (1196:19): [True: 196k, False: 2.48k]
  ------------------
 1197|   196k|    CornerIndex c = corner_table_->LeftMostCorner(VertexIndex(v));
 1198|   196k|    if (c == kInvalidCornerIndex) {
  ------------------
  |  Branch (1198:9): [True: 11.9k, False: 184k]
  ------------------
 1199|  11.9k|      continue;  // Isolated vertex.
 1200|  11.9k|    }
 1201|   184k|    CornerIndex deduplication_first_corner = c;
 1202|   184k|    if (is_vert_hole_[v]) {
  ------------------
  |  Branch (1202:9): [True: 43.6k, False: 141k]
  ------------------
 1203|       |      // If the vertex is on a boundary, start deduplication from the left most
 1204|       |      // corner that is guaranteed to lie on the boundary.
 1205|  43.6k|      deduplication_first_corner = c;
 1206|   141k|    } else {
 1207|       |      // If we are not on the boundary we need to find the first seam (of any
 1208|       |      // attribute).
 1209|   153k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1209:28): [True: 150k, False: 3.41k]
  ------------------
 1210|   150k|        if (!attribute_data_[i].connectivity_data.IsCornerOnSeam(c)) {
  ------------------
  |  Branch (1210:13): [True: 6.92k, False: 143k]
  ------------------
 1211|  6.92k|          continue;  // No seam for this attribute, ignore it.
 1212|  6.92k|        }
 1213|       |        // Else there needs to be at least one seam edge.
 1214|       |
 1215|       |        // At this point, we use identity mapping between corners and point ids.
 1216|   143k|        const VertexIndex vert_id =
 1217|   143k|            attribute_data_[i].connectivity_data.Vertex(c);
 1218|   143k|        CornerIndex act_c = corner_table_->SwingRight(c);
 1219|   143k|        bool seam_found = false;
 1220|   153k|        while (act_c != c) {
  ------------------
  |  Branch (1220:16): [True: 147k, False: 5.52k]
  ------------------
 1221|   147k|          if (act_c == kInvalidCornerIndex) {
  ------------------
  |  Branch (1221:15): [True: 9, False: 147k]
  ------------------
 1222|      9|            return false;
 1223|      9|          }
 1224|   147k|          if (attribute_data_[i].connectivity_data.Vertex(act_c) != vert_id) {
  ------------------
  |  Branch (1224:15): [True: 137k, False: 10.2k]
  ------------------
 1225|       |            // Attribute seam found. Stop.
 1226|   137k|            deduplication_first_corner = act_c;
 1227|   137k|            seam_found = true;
 1228|   137k|            break;
 1229|   137k|          }
 1230|  10.2k|          act_c = corner_table_->SwingRight(act_c);
 1231|  10.2k|        }
 1232|   143k|        if (seam_found) {
  ------------------
  |  Branch (1232:13): [True: 137k, False: 5.52k]
  ------------------
 1233|   137k|          break;  // No reason to process other attributes if we found a seam.
 1234|   137k|        }
 1235|   143k|      }
 1236|   141k|    }
 1237|       |
 1238|       |    // Do a deduplication pass over the corners on the processed vertex.
 1239|       |    // At this point each corner corresponds to one point id and our goal is to
 1240|       |    // merge similar points into a single point id.
 1241|       |    // We do a single pass in a clockwise direction over the corners and we add
 1242|       |    // a new point id whenever one of the attributes change.
 1243|   184k|    c = deduplication_first_corner;
 1244|       |    // Create a new point.
 1245|   184k|    corner_to_point_map[c.value()] =
 1246|   184k|        static_cast<uint32_t>(point_to_corner_map.size());
 1247|   184k|    point_to_corner_map.push_back(c.value());
 1248|       |    // Traverse in CW direction.
 1249|   184k|    CornerIndex prev_c = c;
 1250|   184k|    c = corner_table_->SwingRight(c);
 1251|   961k|    while (c != kInvalidCornerIndex && c != deduplication_first_corner) {
  ------------------
  |  Branch (1251:12): [True: 918k, False: 43.8k]
  |  Branch (1251:40): [True: 777k, False: 140k]
  ------------------
 1252|   777k|      bool attribute_seam = false;
 1253|   834k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1253:28): [True: 816k, False: 18.0k]
  ------------------
 1254|   816k|        if (attribute_data_[i].connectivity_data.Vertex(c) !=
  ------------------
  |  Branch (1254:13): [True: 758k, False: 57.0k]
  ------------------
 1255|   816k|            attribute_data_[i].connectivity_data.Vertex(prev_c)) {
 1256|       |          // Attribute index changed from the previous corner. We need to add a
 1257|       |          // new point here.
 1258|   758k|          attribute_seam = true;
 1259|   758k|          break;
 1260|   758k|        }
 1261|   816k|      }
 1262|   777k|      if (attribute_seam) {
  ------------------
  |  Branch (1262:11): [True: 758k, False: 18.0k]
  ------------------
 1263|   758k|        corner_to_point_map[c.value()] =
 1264|   758k|            static_cast<uint32_t>(point_to_corner_map.size());
 1265|   758k|        point_to_corner_map.push_back(c.value());
 1266|   758k|      } else {
 1267|  18.0k|        corner_to_point_map[c.value()] = corner_to_point_map[prev_c.value()];
 1268|  18.0k|      }
 1269|   777k|      prev_c = c;
 1270|   777k|      c = corner_table_->SwingRight(c);
 1271|   777k|    }
 1272|   184k|  }
 1273|       |  // Add faces.
 1274|   303k|  for (FaceIndex f(0); f < decoder_->mesh()->num_faces(); ++f) {
  ------------------
  |  Branch (1274:24): [True: 301k, False: 2.48k]
  ------------------
 1275|   301k|    Mesh::Face face;
 1276|  1.20M|    for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1276:21): [True: 903k, False: 301k]
  ------------------
 1277|       |      // Remap old points to the new ones.
 1278|   903k|      face[c] = corner_to_point_map[3 * f.value() + c];
 1279|   903k|    }
 1280|   301k|    decoder_->mesh()->SetFace(f, face);
 1281|   301k|  }
 1282|  2.48k|  decoder_->point_cloud()->set_num_points(
 1283|  2.48k|      static_cast<uint32_t>(point_to_corner_map.size()));
 1284|  2.48k|  return true;
 1285|  2.48k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEEC2Ev:
   48|  3.18k|    : decoder_(nullptr),
   49|  3.18k|      last_symbol_id_(-1),
   50|  3.18k|      last_vert_id_(-1),
   51|  3.18k|      last_face_id_(-1),
   52|  3.18k|      num_new_vertices_(0),
   53|  3.18k|      num_encoded_vertices_(0),
   54|  3.18k|      pos_data_decoder_id_(-1) {}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE4InitEPNS_22MeshEdgebreakerDecoderE:
   58|  3.18k|    MeshEdgebreakerDecoder* decoder) {
   59|  3.18k|  decoder_ = decoder;
   60|  3.18k|  return true;
   61|  3.18k|}
_ZNK5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE23GetAttributeCornerTableEi:
   66|  2.27k|    int att_id) const {
   67|  3.46k|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (67:24): [True: 2.77k, False: 693]
  ------------------
   68|  2.77k|    const int decoder_id = attribute_data_[i].decoder_id;
   69|  2.77k|    if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) {
  ------------------
  |  Branch (69:9): [True: 1.18k, False: 1.58k]
  |  Branch (69:27): [True: 0, False: 1.58k]
  ------------------
   70|  1.18k|      continue;
   71|  1.18k|    }
   72|  1.58k|    const AttributesDecoderInterface* const dec =
   73|  1.58k|        decoder_->attributes_decoder(decoder_id);
   74|  3.72k|    for (int j = 0; j < dec->GetNumAttributes(); ++j) {
  ------------------
  |  Branch (74:21): [True: 3.72k, False: 0]
  ------------------
   75|  3.72k|      if (dec->GetAttributeId(j) == att_id) {
  ------------------
  |  Branch (75:11): [True: 1.58k, False: 2.13k]
  ------------------
   76|  1.58k|        if (attribute_data_[i].is_connectivity_used) {
  ------------------
  |  Branch (76:13): [True: 1.03k, False: 554]
  ------------------
   77|  1.03k|          return &attribute_data_[i].connectivity_data;
   78|  1.03k|        }
   79|    554|        return nullptr;
   80|  1.58k|      }
   81|  3.72k|    }
   82|  1.58k|  }
   83|    693|  return nullptr;
   84|  2.27k|}
_ZNK5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE24GetAttributeEncodingDataEi:
   89|  2.27k|    int att_id) const {
   90|  3.46k|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (90:24): [True: 2.77k, False: 693]
  ------------------
   91|  2.77k|    const int decoder_id = attribute_data_[i].decoder_id;
   92|  2.77k|    if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) {
  ------------------
  |  Branch (92:9): [True: 1.18k, False: 1.58k]
  |  Branch (92:27): [True: 0, False: 1.58k]
  ------------------
   93|  1.18k|      continue;
   94|  1.18k|    }
   95|  1.58k|    const AttributesDecoderInterface* const dec =
   96|  1.58k|        decoder_->attributes_decoder(decoder_id);
   97|  3.72k|    for (int j = 0; j < dec->GetNumAttributes(); ++j) {
  ------------------
  |  Branch (97:21): [True: 3.72k, False: 0]
  ------------------
   98|  3.72k|      if (dec->GetAttributeId(j) == att_id) {
  ------------------
  |  Branch (98:11): [True: 1.58k, False: 2.13k]
  ------------------
   99|  1.58k|        return &attribute_data_[i].encoding_data;
  100|  1.58k|      }
  101|  3.72k|    }
  102|  1.58k|  }
  103|    693|  return &pos_encoding_data_;
  104|  2.27k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE23CreateAttributesDecoderEi:
  130|  2.09k|    int32_t att_decoder_id) {
  131|  2.09k|  int8_t att_data_id;
  132|  2.09k|  if (!decoder_->buffer()->Decode(&att_data_id)) {
  ------------------
  |  Branch (132:7): [True: 55, False: 2.03k]
  ------------------
  133|     55|    return false;
  134|     55|  }
  135|  2.03k|  uint8_t decoder_type;
  136|  2.03k|  if (!decoder_->buffer()->Decode(&decoder_type)) {
  ------------------
  |  Branch (136:7): [True: 21, False: 2.01k]
  ------------------
  137|     21|    return false;
  138|     21|  }
  139|       |
  140|  2.01k|  if (att_data_id >= 0) {
  ------------------
  |  Branch (140:7): [True: 1.43k, False: 585]
  ------------------
  141|  1.43k|    if (att_data_id >= attribute_data_.size()) {
  ------------------
  |  Branch (141:9): [True: 52, False: 1.38k]
  ------------------
  142|     52|      return false;  // Unexpected attribute data.
  143|     52|    }
  144|       |
  145|       |    // Ensure that the attribute data is not mapped to a different attributes
  146|       |    // decoder already.
  147|  1.38k|    if (attribute_data_[att_data_id].decoder_id >= 0) {
  ------------------
  |  Branch (147:9): [True: 10, False: 1.37k]
  ------------------
  148|     10|      return false;
  149|     10|    }
  150|       |
  151|  1.37k|    attribute_data_[att_data_id].decoder_id = att_decoder_id;
  152|  1.37k|  } else {
  153|       |    // Assign the attributes decoder to |pos_encoding_data_|.
  154|    585|    if (pos_data_decoder_id_ >= 0) {
  ------------------
  |  Branch (154:9): [True: 1, False: 584]
  ------------------
  155|      1|      return false;  // Some other decoder is already using the data. Error.
  156|      1|    }
  157|    584|    pos_data_decoder_id_ = att_decoder_id;
  158|    584|  }
  159|       |
  160|  1.95k|  MeshTraversalMethod traversal_method = MESH_TRAVERSAL_DEPTH_FIRST;
  161|  1.95k|  if (decoder_->bitstream_version() >= DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|  1.95k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (161:7): [True: 1.95k, False: 0]
  ------------------
  162|  1.95k|    uint8_t traversal_method_encoded;
  163|  1.95k|    if (!decoder_->buffer()->Decode(&traversal_method_encoded)) {
  ------------------
  |  Branch (163:9): [True: 15, False: 1.94k]
  ------------------
  164|     15|      return false;
  165|     15|    }
  166|       |    // Check that decoded traversal method is valid.
  167|  1.94k|    if (traversal_method_encoded >= NUM_TRAVERSAL_METHODS) {
  ------------------
  |  Branch (167:9): [True: 21, False: 1.91k]
  ------------------
  168|     21|      return false;
  169|     21|    }
  170|  1.91k|    traversal_method =
  171|  1.91k|        static_cast<MeshTraversalMethod>(traversal_method_encoded);
  172|  1.91k|  }
  173|       |
  174|  1.91k|  const Mesh* mesh = decoder_->mesh();
  175|  1.91k|  std::unique_ptr<PointsSequencer> sequencer;
  176|       |
  177|  1.91k|  if (decoder_type == MESH_VERTEX_ATTRIBUTE) {
  ------------------
  |  Branch (177:7): [True: 973, False: 946]
  ------------------
  178|       |    // Per-vertex attribute decoder.
  179|       |
  180|    973|    MeshAttributeIndicesEncodingData* encoding_data = nullptr;
  181|    973|    if (att_data_id < 0) {
  ------------------
  |  Branch (181:9): [True: 558, False: 415]
  ------------------
  182|    558|      encoding_data = &pos_encoding_data_;
  183|    558|    } else {
  184|    415|      encoding_data = &attribute_data_[att_data_id].encoding_data;
  185|       |      // Mark the attribute connectivity data invalid to ensure it's not used
  186|       |      // later on.
  187|    415|      attribute_data_[att_data_id].is_connectivity_used = false;
  188|    415|    }
  189|       |    // Defining sequencer via a traversal scheme.
  190|    973|    if (traversal_method == MESH_TRAVERSAL_PREDICTION_DEGREE) {
  ------------------
  |  Branch (190:9): [True: 236, False: 737]
  ------------------
  191|    236|      typedef MeshAttributeIndicesEncodingObserver<CornerTable> AttObserver;
  192|    236|      typedef MaxPredictionDegreeTraverser<CornerTable, AttObserver>
  193|    236|          AttTraverser;
  194|    236|      sequencer = CreateVertexTraversalSequencer<AttTraverser>(encoding_data);
  195|    737|    } else if (traversal_method == MESH_TRAVERSAL_DEPTH_FIRST) {
  ------------------
  |  Branch (195:16): [True: 737, False: 0]
  ------------------
  196|    737|      typedef MeshAttributeIndicesEncodingObserver<CornerTable> AttObserver;
  197|    737|      typedef DepthFirstTraverser<CornerTable, AttObserver> AttTraverser;
  198|    737|      sequencer = CreateVertexTraversalSequencer<AttTraverser>(encoding_data);
  199|    737|    } else {
  200|      0|      return false;  // Unsupported method
  201|      0|    }
  202|    973|  } else {
  203|    946|    if (traversal_method != MESH_TRAVERSAL_DEPTH_FIRST) {
  ------------------
  |  Branch (203:9): [True: 2, False: 944]
  ------------------
  204|      2|      return false;  // Unsupported method.
  205|      2|    }
  206|    944|    if (att_data_id < 0) {
  ------------------
  |  Branch (206:9): [True: 8, False: 936]
  ------------------
  207|      8|      return false;  // Attribute data must be specified.
  208|      8|    }
  209|       |
  210|       |    // Per-corner attribute decoder.
  211|       |
  212|    936|    typedef MeshAttributeIndicesEncodingObserver<MeshAttributeCornerTable>
  213|    936|        AttObserver;
  214|    936|    typedef DepthFirstTraverser<MeshAttributeCornerTable, AttObserver>
  215|    936|        AttTraverser;
  216|       |
  217|    936|    MeshAttributeIndicesEncodingData* const encoding_data =
  218|    936|        &attribute_data_[att_data_id].encoding_data;
  219|    936|    const MeshAttributeCornerTable* const corner_table =
  220|    936|        &attribute_data_[att_data_id].connectivity_data;
  221|       |
  222|    936|    std::unique_ptr<MeshTraversalSequencer<AttTraverser>> traversal_sequencer(
  223|    936|        new MeshTraversalSequencer<AttTraverser>(mesh, encoding_data));
  224|       |
  225|    936|    AttObserver att_observer(corner_table, mesh, traversal_sequencer.get(),
  226|    936|                             encoding_data);
  227|       |
  228|    936|    AttTraverser att_traverser;
  229|    936|    att_traverser.Init(corner_table, att_observer);
  230|       |
  231|    936|    traversal_sequencer->SetTraverser(att_traverser);
  232|    936|    sequencer = std::move(traversal_sequencer);
  233|    936|  }
  234|       |
  235|  1.90k|  if (!sequencer) {
  ------------------
  |  Branch (235:7): [True: 0, False: 1.90k]
  ------------------
  236|      0|    return false;
  237|      0|  }
  238|       |
  239|  1.90k|  std::unique_ptr<SequentialAttributeDecodersController> att_controller(
  240|  1.90k|      new SequentialAttributeDecodersController(std::move(sequencer)));
  241|       |
  242|  1.90k|  return decoder_->SetAttributesDecoder(att_decoder_id,
  243|  1.90k|                                        std::move(att_controller));
  244|  1.90k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE18DecodeConnectivityEv:
  247|  3.18k|bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
  248|  3.18k|  num_new_vertices_ = 0;
  249|  3.18k|  new_to_parent_vertex_map_.clear();
  250|  3.18k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  251|  3.18k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  3.18k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (251:7): [True: 368, False: 2.82k]
  ------------------
  252|    368|    uint32_t num_new_verts;
  253|    368|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    368|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (253:9): [True: 258, False: 110]
  ------------------
  254|    258|      if (!decoder_->buffer()->Decode(&num_new_verts)) {
  ------------------
  |  Branch (254:11): [True: 9, False: 249]
  ------------------
  255|      9|        return false;
  256|      9|      }
  257|    258|    } else {
  258|    110|      if (!DecodeVarint(&num_new_verts, decoder_->buffer())) {
  ------------------
  |  Branch (258:11): [True: 2, False: 108]
  ------------------
  259|      2|        return false;
  260|      2|      }
  261|    110|    }
  262|    357|    num_new_vertices_ = num_new_verts;
  263|    357|  }
  264|  3.17k|#endif
  265|       |
  266|  3.17k|  uint32_t num_encoded_vertices;
  267|  3.17k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  268|  3.17k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  3.17k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (268:7): [True: 249, False: 2.92k]
  ------------------
  269|    249|    if (!decoder_->buffer()->Decode(&num_encoded_vertices)) {
  ------------------
  |  Branch (269:9): [True: 5, False: 244]
  ------------------
  270|      5|      return false;
  271|      5|    }
  272|       |
  273|    249|  } else
  274|  2.92k|#endif
  275|  2.92k|  {
  276|  2.92k|    if (!DecodeVarint(&num_encoded_vertices, decoder_->buffer())) {
  ------------------
  |  Branch (276:9): [True: 6, False: 2.92k]
  ------------------
  277|      6|      return false;
  278|      6|    }
  279|  2.92k|  }
  280|  3.16k|  num_encoded_vertices_ = num_encoded_vertices;
  281|       |
  282|  3.16k|  uint32_t num_faces;
  283|  3.16k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  284|  3.16k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  3.16k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (284:7): [True: 244, False: 2.92k]
  ------------------
  285|    244|    if (!decoder_->buffer()->Decode(&num_faces)) {
  ------------------
  |  Branch (285:9): [True: 3, False: 241]
  ------------------
  286|      3|      return false;
  287|      3|    }
  288|       |
  289|    244|  } else
  290|  2.92k|#endif
  291|  2.92k|  {
  292|  2.92k|    if (!DecodeVarint(&num_faces, decoder_->buffer())) {
  ------------------
  |  Branch (292:9): [True: 1, False: 2.92k]
  ------------------
  293|      1|      return false;
  294|      1|    }
  295|  2.92k|  }
  296|  3.16k|  if (num_faces > std::numeric_limits<CornerIndex::ValueType>::max() / 3) {
  ------------------
  |  Branch (296:7): [True: 3, False: 3.15k]
  ------------------
  297|      3|    return false;  // Draco cannot handle this many faces.
  298|      3|  }
  299|       |
  300|  3.15k|  if (static_cast<uint32_t>(num_encoded_vertices_) > num_faces * 3) {
  ------------------
  |  Branch (300:7): [True: 36, False: 3.12k]
  ------------------
  301|     36|    return false;  // There cannot be more vertices than 3 * num_faces.
  302|     36|  }
  303|       |
  304|       |  // Minimum number of edges of the mesh assuming each edge is shared between
  305|       |  // two faces.
  306|  3.12k|  const uint32_t min_num_face_edges = 3 * num_faces / 2;
  307|       |
  308|       |  // Maximum number of edges that can exist between |num_encoded_vertices_|.
  309|       |  // This is based on graph theory assuming simple connected graph.
  310|  3.12k|  const uint64_t num_encoded_vertices_64 =
  311|  3.12k|      static_cast<uint64_t>(num_encoded_vertices_);
  312|  3.12k|  const uint64_t max_num_vertex_edges =
  313|  3.12k|      num_encoded_vertices_64 * (num_encoded_vertices_64 - 1) / 2;
  314|  3.12k|  if (max_num_vertex_edges < min_num_face_edges) {
  ------------------
  |  Branch (314:7): [True: 23, False: 3.10k]
  ------------------
  315|       |    // It is impossible to construct a manifold mesh with these properties.
  316|     23|    return false;
  317|     23|  }
  318|       |
  319|  3.10k|  uint8_t num_attribute_data;
  320|  3.10k|  if (!decoder_->buffer()->Decode(&num_attribute_data)) {
  ------------------
  |  Branch (320:7): [True: 46, False: 3.05k]
  ------------------
  321|     46|    return false;
  322|     46|  }
  323|       |
  324|  3.05k|  uint32_t num_encoded_symbols;
  325|  3.05k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  326|  3.05k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  3.05k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (326:7): [True: 211, False: 2.84k]
  ------------------
  327|    211|    if (!decoder_->buffer()->Decode(&num_encoded_symbols)) {
  ------------------
  |  Branch (327:9): [True: 19, False: 192]
  ------------------
  328|     19|      return false;
  329|     19|    }
  330|       |
  331|    211|  } else
  332|  2.84k|#endif
  333|  2.84k|  {
  334|  2.84k|    if (!DecodeVarint(&num_encoded_symbols, decoder_->buffer())) {
  ------------------
  |  Branch (334:9): [True: 5, False: 2.83k]
  ------------------
  335|      5|      return false;
  336|      5|    }
  337|  2.84k|  }
  338|       |
  339|  3.03k|  if (num_faces < num_encoded_symbols) {
  ------------------
  |  Branch (339:7): [True: 33, False: 2.99k]
  ------------------
  340|       |    // Number of faces needs to be the same or greater than the number of
  341|       |    // symbols (it can be greater because the initial face may not be encoded as
  342|       |    // a symbol).
  343|     33|    return false;
  344|     33|  }
  345|  2.99k|  const uint32_t max_encoded_faces =
  346|  2.99k|      num_encoded_symbols + (num_encoded_symbols / 3);
  347|  2.99k|  if (num_faces > max_encoded_faces) {
  ------------------
  |  Branch (347:7): [True: 51, False: 2.94k]
  ------------------
  348|       |    // Faces can only be 1 1/3 times bigger than number of encoded symbols. This
  349|       |    // could only happen if all new encoded components started with interior
  350|       |    // triangles. E.g. A mesh with multiple tetrahedrons.
  351|     51|    return false;
  352|     51|  }
  353|       |
  354|  2.94k|  uint32_t num_encoded_split_symbols;
  355|  2.94k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  356|  2.94k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  2.94k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (356:7): [True: 163, False: 2.78k]
  ------------------
  357|    163|    if (!decoder_->buffer()->Decode(&num_encoded_split_symbols)) {
  ------------------
  |  Branch (357:9): [True: 6, False: 157]
  ------------------
  358|      6|      return false;
  359|      6|    }
  360|       |
  361|    163|  } else
  362|  2.78k|#endif
  363|  2.78k|  {
  364|  2.78k|    if (!DecodeVarint(&num_encoded_split_symbols, decoder_->buffer())) {
  ------------------
  |  Branch (364:9): [True: 6, False: 2.77k]
  ------------------
  365|      6|      return false;
  366|      6|    }
  367|  2.78k|  }
  368|       |
  369|  2.93k|  if (num_encoded_split_symbols > num_encoded_symbols) {
  ------------------
  |  Branch (369:7): [True: 41, False: 2.89k]
  ------------------
  370|     41|    return false;  // Split symbols are a sub-set of all symbols.
  371|     41|  }
  372|       |
  373|       |  // Decode topology (connectivity).
  374|  2.89k|  vertex_traversal_length_.clear();
  375|  2.89k|  corner_table_ = std::unique_ptr<CornerTable>(new CornerTable());
  376|  2.89k|  if (corner_table_ == nullptr) {
  ------------------
  |  Branch (376:7): [True: 0, False: 2.89k]
  ------------------
  377|      0|    return false;
  378|      0|  }
  379|  2.89k|  processed_corner_ids_.clear();
  380|  2.89k|  processed_corner_ids_.reserve(num_faces);
  381|  2.89k|  processed_connectivity_corners_.clear();
  382|  2.89k|  processed_connectivity_corners_.reserve(num_faces);
  383|  2.89k|  topology_split_data_.clear();
  384|  2.89k|  hole_event_data_.clear();
  385|  2.89k|  init_face_configurations_.clear();
  386|  2.89k|  init_corners_.clear();
  387|       |
  388|  2.89k|  last_symbol_id_ = -1;
  389|  2.89k|  last_face_id_ = -1;
  390|  2.89k|  last_vert_id_ = -1;
  391|       |
  392|  2.89k|  attribute_data_.clear();
  393|       |  // Add one attribute data for each attribute decoder.
  394|  2.89k|  attribute_data_.resize(num_attribute_data);
  395|       |
  396|  2.89k|  if (!corner_table_->Reset(
  ------------------
  |  Branch (396:7): [True: 0, False: 2.89k]
  ------------------
  397|  2.89k|          num_faces, num_encoded_vertices_ + num_encoded_split_symbols)) {
  398|      0|    return false;
  399|      0|  }
  400|       |
  401|       |  // Start with all vertices marked as holes (boundaries).
  402|       |  // Only vertices decoded with TOPOLOGY_C symbol (and the initial face) will
  403|       |  // be marked as non hole vertices. We need to allocate the array larger
  404|       |  // because split symbols can create extra vertices during the decoding
  405|       |  // process (these extra vertices are then eliminated during deduplication).
  406|  2.89k|  is_vert_hole_.assign(num_encoded_vertices_ + num_encoded_split_symbols, true);
  407|       |
  408|  2.89k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  409|  2.89k|  int32_t topology_split_decoded_bytes = -1;
  410|  2.89k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  2.89k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (410:7): [True: 253, False: 2.64k]
  ------------------
  411|    253|    uint32_t encoded_connectivity_size;
  412|    253|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    253|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (412:9): [True: 156, False: 97]
  ------------------
  413|    156|      if (!decoder_->buffer()->Decode(&encoded_connectivity_size)) {
  ------------------
  |  Branch (413:11): [True: 4, False: 152]
  ------------------
  414|      4|        return false;
  415|      4|      }
  416|    156|    } else {
  417|     97|      if (!DecodeVarint(&encoded_connectivity_size, decoder_->buffer())) {
  ------------------
  |  Branch (417:11): [True: 2, False: 95]
  ------------------
  418|      2|        return false;
  419|      2|      }
  420|     97|    }
  421|    247|    if (encoded_connectivity_size == 0 ||
  ------------------
  |  Branch (421:9): [True: 2, False: 245]
  ------------------
  422|    245|        encoded_connectivity_size > decoder_->buffer()->remaining_size()) {
  ------------------
  |  Branch (422:9): [True: 45, False: 200]
  ------------------
  423|     47|      return false;
  424|     47|    }
  425|    200|    DecoderBuffer event_buffer;
  426|    200|    event_buffer.Init(
  427|    200|        decoder_->buffer()->data_head() + encoded_connectivity_size,
  428|    200|        decoder_->buffer()->remaining_size() - encoded_connectivity_size,
  429|    200|        decoder_->buffer()->bitstream_version());
  430|       |    // Decode hole and topology split events.
  431|    200|    topology_split_decoded_bytes =
  432|    200|        DecodeHoleAndTopologySplitEvents(&event_buffer);
  433|    200|    if (topology_split_decoded_bytes == -1) {
  ------------------
  |  Branch (433:9): [True: 151, False: 49]
  ------------------
  434|    151|      return false;
  435|    151|    }
  436|       |
  437|    200|  } else
  438|  2.64k|#endif
  439|  2.64k|  {
  440|  2.64k|    if (DecodeHoleAndTopologySplitEvents(decoder_->buffer()) == -1) {
  ------------------
  |  Branch (440:9): [True: 127, False: 2.51k]
  ------------------
  441|    127|      return false;
  442|    127|    }
  443|  2.64k|  }
  444|       |
  445|  2.56k|  traversal_decoder_.Init(this);
  446|       |  // Add one extra vertex for each split symbol.
  447|  2.56k|  traversal_decoder_.SetNumEncodedVertices(num_encoded_vertices_ +
  448|  2.56k|                                           num_encoded_split_symbols);
  449|  2.56k|  traversal_decoder_.SetNumAttributeData(num_attribute_data);
  450|       |
  451|  2.56k|  DecoderBuffer traversal_end_buffer;
  452|  2.56k|  if (!traversal_decoder_.Start(&traversal_end_buffer)) {
  ------------------
  |  Branch (452:7): [True: 181, False: 2.38k]
  ------------------
  453|    181|    return false;
  454|    181|  }
  455|       |
  456|  2.38k|  const int num_connectivity_verts = DecodeConnectivity(num_encoded_symbols);
  457|  2.38k|  if (num_connectivity_verts == -1) {
  ------------------
  |  Branch (457:7): [True: 191, False: 2.19k]
  ------------------
  458|    191|    return false;
  459|    191|  }
  460|       |
  461|       |  // Set the main buffer to the end of the traversal.
  462|  2.19k|  decoder_->buffer()->Init(traversal_end_buffer.data_head(),
  463|  2.19k|                           traversal_end_buffer.remaining_size(),
  464|  2.19k|                           decoder_->buffer()->bitstream_version());
  465|       |
  466|  2.19k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  467|  2.19k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  2.19k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (467:7): [True: 19, False: 2.17k]
  ------------------
  468|       |    // Skip topology split data that was already decoded earlier.
  469|     19|    decoder_->buffer()->Advance(topology_split_decoded_bytes);
  470|     19|  }
  471|  2.19k|#endif
  472|       |
  473|       |  // Decode connectivity of non-position attributes.
  474|  2.19k|  if (!attribute_data_.empty()) {
  ------------------
  |  Branch (474:7): [True: 2.16k, False: 27]
  ------------------
  475|  2.16k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  476|  2.16k|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
  ------------------
  |  |  115|  2.16k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (476:9): [True: 19, False: 2.14k]
  ------------------
  477|  2.05k|      for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
  ------------------
  |  Branch (477:31): [True: 2.03k, False: 19]
  ------------------
  478|  2.03k|        if (!DecodeAttributeConnectivitiesOnFaceLegacy(ci)) {
  ------------------
  |  Branch (478:13): [True: 0, False: 2.03k]
  ------------------
  479|      0|          return false;
  480|      0|        }
  481|  2.03k|      }
  482|       |
  483|     19|    } else
  484|  2.14k|#endif
  485|  2.14k|    {
  486|  15.0M|      for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
  ------------------
  |  Branch (486:31): [True: 15.0M, False: 2.14k]
  ------------------
  487|  15.0M|        if (!DecodeAttributeConnectivitiesOnFace(ci)) {
  ------------------
  |  Branch (487:13): [True: 0, False: 15.0M]
  ------------------
  488|      0|          return false;
  489|      0|        }
  490|  15.0M|      }
  491|  2.14k|    }
  492|  2.16k|  }
  493|  2.19k|  traversal_decoder_.Done();
  494|       |
  495|       |  // Decode attribute connectivity.
  496|       |  // Prepare data structure for decoding non-position attribute connectivity.
  497|  4.84k|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (497:24): [True: 2.65k, False: 2.19k]
  ------------------
  498|  2.65k|    attribute_data_[i].connectivity_data.InitEmpty(corner_table_.get());
  499|       |    // Add all seams.
  500|  20.7M|    for (int32_t c : attribute_data_[i].attribute_seam_corners) {
  ------------------
  |  Branch (500:20): [True: 20.7M, False: 2.65k]
  ------------------
  501|  20.7M|      attribute_data_[i].connectivity_data.AddSeamEdge(CornerIndex(c));
  502|  20.7M|    }
  503|       |    // Recompute vertices from the newly added seam edges.
  504|  2.65k|    if (!attribute_data_[i].connectivity_data.RecomputeVertices(nullptr,
  ------------------
  |  Branch (504:9): [True: 0, False: 2.65k]
  ------------------
  505|  2.65k|                                                                nullptr)) {
  506|      0|      return false;
  507|      0|    }
  508|  2.65k|  }
  509|       |
  510|  2.19k|  pos_encoding_data_.Init(corner_table_->num_vertices());
  511|  4.84k|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (511:24): [True: 2.65k, False: 2.19k]
  ------------------
  512|       |    // For non-position attributes, preallocate the vertex to value mapping
  513|       |    // using the maximum number of vertices from the base corner table and the
  514|       |    // attribute corner table (since the attribute decoder may use either of
  515|       |    // it).
  516|  2.65k|    int32_t att_connectivity_verts =
  517|  2.65k|        attribute_data_[i].connectivity_data.num_vertices();
  518|  2.65k|    if (att_connectivity_verts < corner_table_->num_vertices()) {
  ------------------
  |  Branch (518:9): [True: 191, False: 2.45k]
  ------------------
  519|    191|      att_connectivity_verts = corner_table_->num_vertices();
  520|    191|    }
  521|  2.65k|    attribute_data_[i].encoding_data.Init(att_connectivity_verts);
  522|  2.65k|  }
  523|  2.19k|  if (!AssignPointsToCorners(num_connectivity_verts)) {
  ------------------
  |  Branch (523:7): [True: 17, False: 2.17k]
  ------------------
  524|     17|    return false;
  525|     17|  }
  526|  2.17k|  return true;
  527|  2.19k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE19OnAttributesDecodedEv:
  530|    767|bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::OnAttributesDecoded() {
  531|    767|  return true;
  532|    767|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE18DecodeConnectivityEi:
  536|  2.38k|    int num_symbols) {
  537|       |  // Algorithm does the reverse decoding of the symbols encoded with the
  538|       |  // edgebreaker method. The reverse decoding always keeps track of the active
  539|       |  // edge identified by its opposite corner (active corner). New faces are
  540|       |  // always added to this active edge. There may be multiple active corners at
  541|       |  // one time that either correspond to separate mesh components or to
  542|       |  // sub-components of one mesh that are going to be merged together using the
  543|       |  // TOPOLOGY_S symbol. We can store these active edges on a stack, because the
  544|       |  // decoder always processes only the latest active edge. TOPOLOGY_S then
  545|       |  // removes the top edge from the stack and TOPOLOGY_E adds a new edge to the
  546|       |  // stack.
  547|  2.38k|  std::vector<CornerIndex> active_corner_stack;
  548|       |
  549|       |  // Additional active edges may be added as a result of topology split events.
  550|       |  // They can be added in arbitrary order, but we always know the split symbol
  551|       |  // id they belong to, so we can address them using this symbol id.
  552|  2.38k|  std::unordered_map<int, CornerIndex> topology_split_active_corners;
  553|       |
  554|       |  // Vector used for storing vertices that were marked as isolated during the
  555|       |  // decoding process. Currently used only when the mesh doesn't contain any
  556|       |  // non-position connectivity data.
  557|  2.38k|  std::vector<VertexIndex> invalid_vertices;
  558|  2.38k|  const bool remove_invalid_vertices = attribute_data_.empty();
  559|       |
  560|  2.38k|  int max_num_vertices = static_cast<int>(is_vert_hole_.size());
  561|  2.38k|  int num_faces = 0;
  562|  59.4M|  for (int symbol_id = 0; symbol_id < num_symbols; ++symbol_id) {
  ------------------
  |  Branch (562:27): [True: 59.4M, False: 2.27k]
  ------------------
  563|  59.4M|    const FaceIndex face(num_faces++);
  564|       |    // Used to flag cases where we need to look for topology split events.
  565|  59.4M|    bool check_topology_split = false;
  566|  59.4M|    const uint32_t symbol = traversal_decoder_.DecodeSymbol();
  567|  59.4M|    if (symbol == TOPOLOGY_C) {
  ------------------
  |  Branch (567:9): [True: 29.5M, False: 29.8M]
  ------------------
  568|       |      // Create a new face between two edges on the open boundary.
  569|       |      // The first edge is opposite to the corner "a" from the image below.
  570|       |      // The other edge is opposite to the corner "b" that can be reached
  571|       |      // through a CCW traversal around the vertex "v".
  572|       |      // One new active boundary edge is created, opposite to the new corner
  573|       |      // "x".
  574|       |      //
  575|       |      //     *-------*
  576|       |      //    / \     / \
  577|       |      //   /   \   /   \
  578|       |      //  /     \ /     \
  579|       |      // *-------v-------*
  580|       |      //  \b    /x\    a/
  581|       |      //   \   /   \   /
  582|       |      //    \ /  C  \ /
  583|       |      //     *.......*
  584|       |
  585|       |      // Find the corner "b" from the corner "a" which is the corner on the
  586|       |      // top of the active stack.
  587|  29.5M|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (587:11): [True: 1, False: 29.5M]
  ------------------
  588|      1|        return -1;
  589|      1|      }
  590|       |
  591|  29.5M|      const CornerIndex corner_a = active_corner_stack.back();
  592|  29.5M|      const VertexIndex vertex_x =
  593|  29.5M|          corner_table_->Vertex(corner_table_->Next(corner_a));
  594|  29.5M|      const CornerIndex corner_b =
  595|  29.5M|          corner_table_->Next(corner_table_->LeftMostCorner(vertex_x));
  596|       |
  597|  29.5M|      if (corner_a == corner_b) {
  ------------------
  |  Branch (597:11): [True: 36, False: 29.5M]
  ------------------
  598|       |        // All matched corners must be different.
  599|     36|        return -1;
  600|     36|      }
  601|  29.5M|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex ||
  ------------------
  |  Branch (601:11): [True: 0, False: 29.5M]
  |  Branch (601:11): [True: 0, False: 29.5M]
  ------------------
  602|  29.5M|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex) {
  ------------------
  |  Branch (602:11): [True: 0, False: 29.5M]
  ------------------
  603|       |        // One of the corners is already opposite to an existing face, which
  604|       |        // should not happen unless the input was tampered with.
  605|      0|        return -1;
  606|      0|      }
  607|       |
  608|       |      // New tip corner.
  609|  29.5M|      const CornerIndex corner(3 * face.value());
  610|       |      // Update opposite corner mappings.
  611|  29.5M|      SetOppositeCorners(corner_a, corner + 1);
  612|  29.5M|      SetOppositeCorners(corner_b, corner + 2);
  613|       |
  614|       |      // Update vertex mapping.
  615|  29.5M|      const VertexIndex vert_a_prev =
  616|  29.5M|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  617|  29.5M|      const VertexIndex vert_b_next =
  618|  29.5M|          corner_table_->Vertex(corner_table_->Next(corner_b));
  619|  29.5M|      if (vertex_x == vert_a_prev || vertex_x == vert_b_next) {
  ------------------
  |  Branch (619:11): [True: 0, False: 29.5M]
  |  Branch (619:38): [True: 0, False: 29.5M]
  ------------------
  620|       |        // Encoding is invalid, because face vertices are degenerate.
  621|      0|        return -1;
  622|      0|      }
  623|  29.5M|      corner_table_->MapCornerToVertex(corner, vertex_x);
  624|  29.5M|      corner_table_->MapCornerToVertex(corner + 1, vert_b_next);
  625|  29.5M|      corner_table_->MapCornerToVertex(corner + 2, vert_a_prev);
  626|  29.5M|      corner_table_->SetLeftMostCorner(vert_a_prev, corner + 2);
  627|       |      // Mark the vertex |x| as interior.
  628|  29.5M|      is_vert_hole_[vertex_x.value()] = false;
  629|       |      // Update the corner on the active stack.
  630|  29.5M|      active_corner_stack.back() = corner;
  631|  29.8M|    } else if (symbol == TOPOLOGY_R || symbol == TOPOLOGY_L) {
  ------------------
  |  Branch (631:16): [True: 29.8M, False: 35.9k]
  |  Branch (631:40): [True: 6.97k, False: 29.0k]
  ------------------
  632|       |      // Create a new face extending from the open boundary edge opposite to the
  633|       |      // corner "a" from the image below. Two new boundary edges are created
  634|       |      // opposite to corners "r" and "l". New active corner is set to either "r"
  635|       |      // or "l" depending on the decoded symbol. One new vertex is created
  636|       |      // at the opposite corner to corner "a".
  637|       |      //     *-------*
  638|       |      //    /a\     / \
  639|       |      //   /   \   /   \
  640|       |      //  /     \ /     \
  641|       |      // *-------v-------*
  642|       |      //  .l   r.
  643|       |      //   .   .
  644|       |      //    . .
  645|       |      //     *
  646|  29.8M|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (646:11): [True: 1, False: 29.8M]
  ------------------
  647|      1|        return -1;
  648|      1|      }
  649|  29.8M|      const CornerIndex corner_a = active_corner_stack.back();
  650|  29.8M|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex) {
  ------------------
  |  Branch (650:11): [True: 0, False: 29.8M]
  ------------------
  651|       |        // Active corner is already opposite to an existing face, which should
  652|       |        // not happen unless the input was tampered with.
  653|      0|        return -1;
  654|      0|      }
  655|       |
  656|       |      // First corner on the new face is either corner "l" or "r".
  657|  29.8M|      const CornerIndex corner(3 * face.value());
  658|  29.8M|      CornerIndex opp_corner, corner_l, corner_r;
  659|  29.8M|      if (symbol == TOPOLOGY_R) {
  ------------------
  |  Branch (659:11): [True: 29.8M, False: 6.97k]
  ------------------
  660|       |        // "r" is the new first corner.
  661|  29.8M|        opp_corner = corner + 2;
  662|  29.8M|        corner_l = corner + 1;
  663|  29.8M|        corner_r = corner;
  664|  29.8M|      } else {
  665|       |        // "l" is the new first corner.
  666|  6.97k|        opp_corner = corner + 1;
  667|  6.97k|        corner_l = corner;
  668|  6.97k|        corner_r = corner + 2;
  669|  6.97k|      }
  670|  29.8M|      SetOppositeCorners(opp_corner, corner_a);
  671|       |      // Update vertex mapping.
  672|  29.8M|      const VertexIndex new_vert_index = corner_table_->AddNewVertex();
  673|       |
  674|  29.8M|      if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (674:11): [True: 14, False: 29.8M]
  ------------------
  675|     14|        return -1;  // Unexpected number of decoded vertices.
  676|     14|      }
  677|       |
  678|  29.8M|      corner_table_->MapCornerToVertex(opp_corner, new_vert_index);
  679|  29.8M|      corner_table_->SetLeftMostCorner(new_vert_index, opp_corner);
  680|       |
  681|  29.8M|      const VertexIndex vertex_r =
  682|  29.8M|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  683|  29.8M|      corner_table_->MapCornerToVertex(corner_r, vertex_r);
  684|       |      // Update left-most corner on the vertex on the |corner_r|.
  685|  29.8M|      corner_table_->SetLeftMostCorner(vertex_r, corner_r);
  686|       |
  687|  29.8M|      corner_table_->MapCornerToVertex(
  688|  29.8M|          corner_l, corner_table_->Vertex(corner_table_->Next(corner_a)));
  689|  29.8M|      active_corner_stack.back() = corner;
  690|  29.8M|      check_topology_split = true;
  691|  29.8M|    } else if (symbol == TOPOLOGY_S) {
  ------------------
  |  Branch (691:16): [True: 9.11k, False: 19.8k]
  ------------------
  692|       |      // Create a new face that merges two last active edges from the active
  693|       |      // stack. No new vertex is created, but two vertices at corners "p" and
  694|       |      // "n" need to be merged into a single vertex.
  695|       |      //
  696|       |      // *-------v-------*
  697|       |      //  \a   p/x\n   b/
  698|       |      //   \   /   \   /
  699|       |      //    \ /  S  \ /
  700|       |      //     *.......*
  701|       |      //
  702|  9.11k|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (702:11): [True: 1, False: 9.11k]
  ------------------
  703|      1|        return -1;
  704|      1|      }
  705|  9.11k|      const CornerIndex corner_b = active_corner_stack.back();
  706|  9.11k|      active_corner_stack.pop_back();
  707|       |
  708|       |      // Corner "a" can correspond either to a normal active edge, or to an edge
  709|       |      // created from the topology split event.
  710|  9.11k|      const auto it = topology_split_active_corners.find(symbol_id);
  711|  9.11k|      if (it != topology_split_active_corners.end()) {
  ------------------
  |  Branch (711:11): [True: 35, False: 9.07k]
  ------------------
  712|       |        // Topology split event. Move the retrieved edge to the stack.
  713|     35|        active_corner_stack.push_back(it->second);
  714|     35|      }
  715|  9.11k|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (715:11): [True: 13, False: 9.10k]
  ------------------
  716|     13|        return -1;
  717|     13|      }
  718|  9.10k|      const CornerIndex corner_a = active_corner_stack.back();
  719|       |
  720|  9.10k|      if (corner_a == corner_b) {
  ------------------
  |  Branch (720:11): [True: 0, False: 9.10k]
  ------------------
  721|       |        // All matched corners must be different.
  722|      0|        return -1;
  723|      0|      }
  724|  9.10k|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex ||
  ------------------
  |  Branch (724:11): [True: 7, False: 9.09k]
  |  Branch (724:11): [True: 7, False: 9.09k]
  ------------------
  725|  9.09k|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex) {
  ------------------
  |  Branch (725:11): [True: 0, False: 9.09k]
  ------------------
  726|       |        // One of the corners is already opposite to an existing face, which
  727|       |        // should not happen unless the input was tampered with.
  728|      7|        return -1;
  729|      7|      }
  730|       |
  731|       |      // First corner on the new face is corner "x" from the image above.
  732|  9.09k|      const CornerIndex corner(3 * face.value());
  733|       |      // Update the opposite corner mapping.
  734|  9.09k|      SetOppositeCorners(corner_a, corner + 2);
  735|  9.09k|      SetOppositeCorners(corner_b, corner + 1);
  736|       |      // Update vertices. For the vertex at corner "x", use the vertex id from
  737|       |      // the corner "p".
  738|  9.09k|      const VertexIndex vertex_p =
  739|  9.09k|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  740|  9.09k|      corner_table_->MapCornerToVertex(corner, vertex_p);
  741|  9.09k|      corner_table_->MapCornerToVertex(
  742|  9.09k|          corner + 1, corner_table_->Vertex(corner_table_->Next(corner_a)));
  743|  9.09k|      const VertexIndex vert_b_prev =
  744|  9.09k|          corner_table_->Vertex(corner_table_->Previous(corner_b));
  745|  9.09k|      corner_table_->MapCornerToVertex(corner + 2, vert_b_prev);
  746|  9.09k|      corner_table_->SetLeftMostCorner(vert_b_prev, corner + 2);
  747|  9.09k|      CornerIndex corner_n = corner_table_->Next(corner_b);
  748|  9.09k|      const VertexIndex vertex_n = corner_table_->Vertex(corner_n);
  749|  9.09k|      traversal_decoder_.MergeVertices(vertex_p, vertex_n);
  750|       |      // Update the left most corner on the newly merged vertex.
  751|  9.09k|      corner_table_->SetLeftMostCorner(vertex_p,
  752|  9.09k|                                       corner_table_->LeftMostCorner(vertex_n));
  753|       |
  754|       |      // Also update the vertex id at corner "n" and all corners that are
  755|       |      // connected to it in the CCW direction.
  756|  9.09k|      const CornerIndex first_corner = corner_n;
  757|  35.7k|      while (corner_n != kInvalidCornerIndex) {
  ------------------
  |  Branch (757:14): [True: 26.6k, False: 9.09k]
  ------------------
  758|  26.6k|        corner_table_->MapCornerToVertex(corner_n, vertex_p);
  759|  26.6k|        corner_n = corner_table_->SwingLeft(corner_n);
  760|  26.6k|        if (corner_n == first_corner) {
  ------------------
  |  Branch (760:13): [True: 1, False: 26.6k]
  ------------------
  761|       |          // We reached the start again which should not happen for split
  762|       |          // symbols.
  763|      1|          return -1;
  764|      1|        }
  765|  26.6k|      }
  766|       |      // Make sure the old vertex n is now mapped to an invalid corner (make it
  767|       |      // isolated).
  768|  9.09k|      corner_table_->MakeVertexIsolated(vertex_n);
  769|  9.09k|      if (remove_invalid_vertices) {
  ------------------
  |  Branch (769:11): [True: 3.23k, False: 5.85k]
  ------------------
  770|  3.23k|        invalid_vertices.push_back(vertex_n);
  771|  3.23k|      }
  772|  9.09k|      active_corner_stack.back() = corner;
  773|  19.8k|    } else if (symbol == TOPOLOGY_E) {
  ------------------
  |  Branch (773:16): [True: 19.8k, False: 0]
  ------------------
  774|  19.8k|      const CornerIndex corner(3 * face.value());
  775|  19.8k|      const VertexIndex first_vert_index = corner_table_->AddNewVertex();
  776|       |      // Create three new vertices at the corners of the new face.
  777|  19.8k|      corner_table_->MapCornerToVertex(corner, first_vert_index);
  778|  19.8k|      corner_table_->MapCornerToVertex(corner + 1,
  779|  19.8k|                                       corner_table_->AddNewVertex());
  780|  19.8k|      corner_table_->MapCornerToVertex(corner + 2,
  781|  19.8k|                                       corner_table_->AddNewVertex());
  782|       |
  783|  19.8k|      if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (783:11): [True: 5, False: 19.8k]
  ------------------
  784|      5|        return -1;  // Unexpected number of decoded vertices.
  785|      5|      }
  786|       |
  787|  19.8k|      corner_table_->SetLeftMostCorner(first_vert_index, corner);
  788|  19.8k|      corner_table_->SetLeftMostCorner(first_vert_index + 1, corner + 1);
  789|  19.8k|      corner_table_->SetLeftMostCorner(first_vert_index + 2, corner + 2);
  790|       |      // Add the tip corner to the active stack.
  791|  19.8k|      active_corner_stack.push_back(corner);
  792|  19.8k|      check_topology_split = true;
  793|  19.8k|    } else {
  794|       |      // Error. Unknown symbol decoded.
  795|      0|      return -1;
  796|      0|    }
  797|       |    // Inform the traversal decoder that a new corner has been reached.
  798|  59.4M|    traversal_decoder_.NewActiveCornerReached(active_corner_stack.back());
  799|       |
  800|  59.4M|    if (check_topology_split) {
  ------------------
  |  Branch (800:9): [True: 29.8M, False: 29.5M]
  ------------------
  801|       |      // Check for topology splits happens only for TOPOLOGY_L, TOPOLOGY_R and
  802|       |      // TOPOLOGY_E symbols because those are the symbols that correspond to
  803|       |      // faces that can be directly connected a TOPOLOGY_S face through the
  804|       |      // topology split event.
  805|       |      // If a topology split is detected, we need to add a new active edge
  806|       |      // onto the active_corner_stack because it will be used later when the
  807|       |      // corresponding TOPOLOGY_S event is decoded.
  808|       |
  809|       |      // Symbol id used by the encoder (reverse).
  810|  29.8M|      const int encoder_symbol_id = num_symbols - symbol_id - 1;
  811|  29.8M|      EdgeFaceName split_edge;
  812|  29.8M|      int encoder_split_symbol_id;
  813|  29.8M|      while (IsTopologySplit(encoder_symbol_id, &split_edge,
  ------------------
  |  Branch (813:14): [True: 1.32k, False: 29.8M]
  ------------------
  814|  29.8M|                             &encoder_split_symbol_id)) {
  815|  1.32k|        if (encoder_split_symbol_id < 0) {
  ------------------
  |  Branch (815:13): [True: 24, False: 1.30k]
  ------------------
  816|     24|          return -1;  // Wrong split symbol id.
  817|     24|        }
  818|       |        // Symbol was part of a topology split. Now we need to determine which
  819|       |        // edge should be added to the active edges stack.
  820|  1.30k|        const CornerIndex act_top_corner = active_corner_stack.back();
  821|       |        // The current symbol has one active edge (stored in act_top_corner) and
  822|       |        // two remaining inactive edges that are attached to it.
  823|       |        //              *
  824|       |        //             / \
  825|       |        //  left_edge /   \ right_edge
  826|       |        //           /     \
  827|       |        //          *.......*
  828|       |        //         active_edge
  829|       |
  830|  1.30k|        CornerIndex new_active_corner;
  831|  1.30k|        if (split_edge == RIGHT_FACE_EDGE) {
  ------------------
  |  Branch (831:13): [True: 502, False: 803]
  ------------------
  832|    502|          new_active_corner = corner_table_->Next(act_top_corner);
  833|    803|        } else {
  834|    803|          new_active_corner = corner_table_->Previous(act_top_corner);
  835|    803|        }
  836|       |        // Add the new active edge.
  837|       |        // Convert the encoder split symbol id to decoder symbol id.
  838|  1.30k|        const int decoder_split_symbol_id =
  839|  1.30k|            num_symbols - encoder_split_symbol_id - 1;
  840|  1.30k|        topology_split_active_corners[decoder_split_symbol_id] =
  841|  1.30k|            new_active_corner;
  842|  1.30k|      }
  843|  29.8M|    }
  844|  59.4M|  }
  845|  2.27k|  if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (845:7): [True: 0, False: 2.27k]
  ------------------
  846|      0|    return -1;  // Unexpected number of decoded vertices.
  847|      0|  }
  848|       |  // Decode start faces and connect them to the faces from the active stack.
  849|  11.0k|  while (!active_corner_stack.empty()) {
  ------------------
  |  Branch (849:10): [True: 8.82k, False: 2.25k]
  ------------------
  850|  8.82k|    const CornerIndex corner = active_corner_stack.back();
  851|  8.82k|    active_corner_stack.pop_back();
  852|  8.82k|    const bool interior_face =
  853|  8.82k|        traversal_decoder_.DecodeStartFaceConfiguration();
  854|  8.82k|    if (interior_face) {
  ------------------
  |  Branch (854:9): [True: 4.80k, False: 4.01k]
  ------------------
  855|       |      // The start face is interior, we need to find three corners that are
  856|       |      // opposite to it. The first opposite corner "a" is the corner from the
  857|       |      // top of the active corner stack and the remaining two corners "b" and
  858|       |      // "c" are then the next corners from the left-most corners of vertices
  859|       |      // "n" and "x" respectively.
  860|       |      //
  861|       |      //           *-------*
  862|       |      //          / \     / \
  863|       |      //         /   \   /   \
  864|       |      //        /     \ /     \
  865|       |      //       *-------p-------*
  866|       |      //      / \a    . .    c/ \
  867|       |      //     /   \   .   .   /   \
  868|       |      //    /     \ .  I  . /     \
  869|       |      //   *-------n.......x------*
  870|       |      //    \     / \     / \     /
  871|       |      //     \   /   \   /   \   /
  872|       |      //      \ /     \b/     \ /
  873|       |      //       *-------*-------*
  874|       |      //
  875|       |
  876|  4.80k|      if (num_faces >= corner_table_->num_faces()) {
  ------------------
  |  Branch (876:11): [True: 14, False: 4.79k]
  ------------------
  877|     14|        return -1;  // More faces than expected added to the mesh.
  878|     14|      }
  879|       |
  880|  4.79k|      const CornerIndex corner_a = corner;
  881|  4.79k|      const VertexIndex vert_n =
  882|  4.79k|          corner_table_->Vertex(corner_table_->Next(corner_a));
  883|  4.79k|      const CornerIndex corner_b =
  884|  4.79k|          corner_table_->Next(corner_table_->LeftMostCorner(vert_n));
  885|       |
  886|  4.79k|      const VertexIndex vert_x =
  887|  4.79k|          corner_table_->Vertex(corner_table_->Next(corner_b));
  888|  4.79k|      const CornerIndex corner_c =
  889|  4.79k|          corner_table_->Next(corner_table_->LeftMostCorner(vert_x));
  890|       |
  891|  4.79k|      if (corner == corner_b || corner == corner_c || corner_b == corner_c) {
  ------------------
  |  Branch (891:11): [True: 2, False: 4.79k]
  |  Branch (891:33): [True: 9, False: 4.78k]
  |  Branch (891:55): [True: 0, False: 4.78k]
  ------------------
  892|       |        // All matched corners must be different.
  893|     11|        return -1;
  894|     11|      }
  895|  4.78k|      if (corner_table_->Opposite(corner) != kInvalidCornerIndex ||
  ------------------
  |  Branch (895:11): [True: 3, False: 4.77k]
  |  Branch (895:11): [True: 3, False: 4.77k]
  ------------------
  896|  4.77k|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex ||
  ------------------
  |  Branch (896:11): [True: 0, False: 4.77k]
  ------------------
  897|  4.77k|          corner_table_->Opposite(corner_c) != kInvalidCornerIndex) {
  ------------------
  |  Branch (897:11): [True: 0, False: 4.77k]
  ------------------
  898|       |        // One of the corners is already opposite to an existing face, which
  899|       |        // should not happen unless the input was tampered with.
  900|      3|        return -1;
  901|      3|      }
  902|       |
  903|  4.77k|      const VertexIndex vert_p =
  904|  4.77k|          corner_table_->Vertex(corner_table_->Next(corner_c));
  905|       |
  906|  4.77k|      const FaceIndex face(num_faces++);
  907|       |      // The first corner of the initial face is the corner opposite to "a".
  908|  4.77k|      const CornerIndex new_corner(3 * face.value());
  909|  4.77k|      SetOppositeCorners(new_corner, corner);
  910|  4.77k|      SetOppositeCorners(new_corner + 1, corner_b);
  911|  4.77k|      SetOppositeCorners(new_corner + 2, corner_c);
  912|       |
  913|       |      // Map new corners to existing vertices.
  914|  4.77k|      corner_table_->MapCornerToVertex(new_corner, vert_x);
  915|  4.77k|      corner_table_->MapCornerToVertex(new_corner + 1, vert_p);
  916|  4.77k|      corner_table_->MapCornerToVertex(new_corner + 2, vert_n);
  917|       |
  918|       |      // Mark all three vertices as interior.
  919|  19.1k|      for (int ci = 0; ci < 3; ++ci) {
  ------------------
  |  Branch (919:24): [True: 14.3k, False: 4.77k]
  ------------------
  920|  14.3k|        is_vert_hole_[corner_table_->Vertex(new_corner + ci).value()] = false;
  921|  14.3k|      }
  922|       |
  923|  4.77k|      init_face_configurations_.push_back(true);
  924|  4.77k|      init_corners_.push_back(new_corner);
  925|  4.77k|    } else {
  926|       |      // The initial face wasn't interior and the traversal had to start from
  927|       |      // an open boundary. In this case no new face is added, but we need to
  928|       |      // keep record about the first opposite corner to this boundary.
  929|  4.01k|      init_face_configurations_.push_back(false);
  930|  4.01k|      init_corners_.push_back(corner);
  931|  4.01k|    }
  932|  8.82k|  }
  933|  2.25k|  if (num_faces != corner_table_->num_faces()) {
  ------------------
  |  Branch (933:7): [True: 55, False: 2.19k]
  ------------------
  934|     55|    return -1;  // Unexpected number of decoded faces.
  935|     55|  }
  936|       |
  937|  2.19k|  int num_vertices = corner_table_->num_vertices();
  938|       |  // If any vertex was marked as isolated, we want to remove it from the corner
  939|       |  // table to ensure that all vertices in range <0, num_vertices> are valid.
  940|  2.19k|  for (const VertexIndex invalid_vert : invalid_vertices) {
  ------------------
  |  Branch (940:39): [True: 233, False: 2.19k]
  ------------------
  941|       |    // Find the last valid vertex and swap it with the isolated vertex.
  942|    233|    VertexIndex src_vert(num_vertices - 1);
  943|    270|    while (corner_table_->LeftMostCorner(src_vert) == kInvalidCornerIndex) {
  ------------------
  |  Branch (943:12): [True: 37, False: 233]
  ------------------
  944|       |      // The last vertex is invalid, proceed to the previous one.
  945|     37|      src_vert = VertexIndex(--num_vertices - 1);
  946|     37|    }
  947|    233|    if (src_vert < invalid_vert) {
  ------------------
  |  Branch (947:9): [True: 37, False: 196]
  ------------------
  948|     37|      continue;  // No need to swap anything.
  949|     37|    }
  950|       |
  951|       |    // Remap all corners mapped to |src_vert| to |invalid_vert|.
  952|    196|    VertexCornersIterator<CornerTable> vcit(corner_table_.get(), src_vert);
  953|  1.01k|    for (; !vcit.End(); ++vcit) {
  ------------------
  |  Branch (953:12): [True: 827, False: 191]
  ------------------
  954|    827|      const CornerIndex cid = vcit.Corner();
  955|    827|      if (corner_table_->Vertex(cid) != src_vert) {
  ------------------
  |  Branch (955:11): [True: 5, False: 822]
  ------------------
  956|       |        // Vertex mapped to |cid| was not |src_vert|. This indicates corrupted
  957|       |        // data and we should terminate the decoding.
  958|      5|        return -1;
  959|      5|      }
  960|    822|      corner_table_->MapCornerToVertex(cid, invalid_vert);
  961|    822|    }
  962|    191|    corner_table_->SetLeftMostCorner(invalid_vert,
  963|    191|                                     corner_table_->LeftMostCorner(src_vert));
  964|       |
  965|       |    // Make the |src_vert| invalid.
  966|    191|    corner_table_->MakeVertexIsolated(src_vert);
  967|    191|    is_vert_hole_[invalid_vert.value()] = is_vert_hole_[src_vert.value()];
  968|    191|    is_vert_hole_[src_vert.value()] = false;
  969|       |
  970|       |    // The last vertex is now invalid.
  971|    191|    num_vertices--;
  972|    191|  }
  973|  2.19k|  return num_vertices;
  974|  2.19k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE32DecodeHoleAndTopologySplitEventsEPNS_13DecoderBufferE:
  979|  2.84k|    DecoderBuffer* decoder_buffer) {
  980|       |  // Prepare a new decoder from the provided buffer offset.
  981|  2.84k|  uint32_t num_topology_splits;
  982|  2.84k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  983|  2.84k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  2.84k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (983:7): [True: 116, False: 2.72k]
  ------------------
  984|    116|    if (!decoder_buffer->Decode(&num_topology_splits)) {
  ------------------
  |  Branch (984:9): [True: 1, False: 115]
  ------------------
  985|      1|      return -1;
  986|      1|    }
  987|       |
  988|    116|  } else
  989|  2.72k|#endif
  990|  2.72k|  {
  991|  2.72k|    if (!DecodeVarint(&num_topology_splits, decoder_buffer)) {
  ------------------
  |  Branch (991:9): [True: 16, False: 2.70k]
  ------------------
  992|     16|      return -1;
  993|     16|    }
  994|  2.72k|  }
  995|  2.82k|  if (num_topology_splits > 0) {
  ------------------
  |  Branch (995:7): [True: 809, False: 2.01k]
  ------------------
  996|    809|    if (num_topology_splits >
  ------------------
  |  Branch (996:9): [True: 72, False: 737]
  ------------------
  997|    809|        static_cast<uint32_t>(corner_table_->num_faces())) {
  998|     72|      return -1;
  999|     72|    }
 1000|    737|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1001|    737|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|    737|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1001:9): [True: 57, False: 680]
  ------------------
 1002|   131k|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1002:28): [True: 131k, False: 14]
  ------------------
 1003|   131k|        TopologySplitEventData event_data;
 1004|   131k|        if (!decoder_buffer->Decode(&event_data.split_symbol_id)) {
  ------------------
  |  Branch (1004:13): [True: 23, False: 131k]
  ------------------
 1005|     23|          return -1;
 1006|     23|        }
 1007|   131k|        if (!decoder_buffer->Decode(&event_data.source_symbol_id)) {
  ------------------
  |  Branch (1007:13): [True: 17, False: 131k]
  ------------------
 1008|     17|          return -1;
 1009|     17|        }
 1010|   131k|        uint8_t edge_data;
 1011|   131k|        if (!decoder_buffer->Decode(&edge_data)) {
  ------------------
  |  Branch (1011:13): [True: 3, False: 131k]
  ------------------
 1012|      3|          return -1;
 1013|      3|        }
 1014|   131k|        event_data.source_edge = edge_data & 1;
 1015|   131k|        topology_split_data_.push_back(event_data);
 1016|   131k|      }
 1017|       |
 1018|     57|    } else
 1019|    680|#endif
 1020|    680|    {
 1021|       |      // Decode source and split symbol ids using delta and varint coding. See
 1022|       |      // description in mesh_edgebreaker_encoder_impl.cc for more details.
 1023|    680|      int last_source_symbol_id = 0;
 1024|  3.75k|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1024:28): [True: 3.14k, False: 614]
  ------------------
 1025|  3.14k|        TopologySplitEventData event_data;
 1026|  3.14k|        uint32_t delta;
 1027|  3.14k|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1027:13): [True: 25, False: 3.11k]
  ------------------
 1028|     25|          return -1;
 1029|     25|        }
 1030|  3.11k|        event_data.source_symbol_id = delta + last_source_symbol_id;
 1031|  3.11k|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1031:13): [True: 9, False: 3.11k]
  ------------------
 1032|      9|          return -1;
 1033|      9|        }
 1034|  3.11k|        if (delta > event_data.source_symbol_id) {
  ------------------
  |  Branch (1034:13): [True: 32, False: 3.07k]
  ------------------
 1035|     32|          return -1;
 1036|     32|        }
 1037|  3.07k|        event_data.split_symbol_id =
 1038|  3.07k|            event_data.source_symbol_id - static_cast<int32_t>(delta);
 1039|  3.07k|        last_source_symbol_id = event_data.source_symbol_id;
 1040|  3.07k|        topology_split_data_.push_back(event_data);
 1041|  3.07k|      }
 1042|       |      // Split edges are decoded from a direct bit decoder.
 1043|    614|      decoder_buffer->StartBitDecoding(false, nullptr);
 1044|  3.08k|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1044:28): [True: 2.47k, False: 614]
  ------------------
 1045|  2.47k|        uint32_t edge_data;
 1046|  2.47k|        if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  2.47k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1046:13): [True: 390, False: 2.08k]
  ------------------
 1047|    390|          decoder_buffer->DecodeLeastSignificantBits32(2, &edge_data);
 1048|  2.08k|        } else {
 1049|  2.08k|          decoder_buffer->DecodeLeastSignificantBits32(1, &edge_data);
 1050|  2.08k|        }
 1051|  2.47k|        TopologySplitEventData& event_data = topology_split_data_[i];
 1052|  2.47k|        event_data.source_edge = edge_data & 1;
 1053|  2.47k|      }
 1054|    614|      decoder_buffer->EndBitDecoding();
 1055|    614|    }
 1056|    737|  }
 1057|  2.64k|  uint32_t num_hole_events = 0;
 1058|  2.64k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1059|  2.64k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  2.64k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1059:7): [True: 55, False: 2.58k]
  ------------------
 1060|     55|    if (!decoder_buffer->Decode(&num_hole_events)) {
  ------------------
  |  Branch (1060:9): [True: 5, False: 50]
  ------------------
 1061|      5|      return -1;
 1062|      5|    }
 1063|  2.58k|  } else if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
  ------------------
  |  |  115|  2.58k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1063:14): [True: 66, False: 2.52k]
  ------------------
 1064|     66|    if (!DecodeVarint(&num_hole_events, decoder_buffer)) {
  ------------------
  |  Branch (1064:9): [True: 11, False: 55]
  ------------------
 1065|     11|      return -1;
 1066|     11|    }
 1067|     66|  }
 1068|  2.62k|#endif
 1069|  2.62k|  if (num_hole_events > 0) {
  ------------------
  |  Branch (1069:7): [True: 71, False: 2.55k]
  ------------------
 1070|     71|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1071|     71|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|     71|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1071:9): [True: 41, False: 30]
  ------------------
 1072|  82.6k|      for (uint32_t i = 0; i < num_hole_events; ++i) {
  ------------------
  |  Branch (1072:28): [True: 82.6k, False: 3]
  ------------------
 1073|  82.6k|        HoleEventData event_data;
 1074|  82.6k|        if (!decoder_buffer->Decode(&event_data)) {
  ------------------
  |  Branch (1074:13): [True: 38, False: 82.6k]
  ------------------
 1075|     38|          return -1;
 1076|     38|        }
 1077|  82.6k|        hole_event_data_.push_back(event_data);
 1078|  82.6k|      }
 1079|       |
 1080|     41|    } else
 1081|     30|#endif
 1082|     30|    {
 1083|       |      // Decode hole symbol ids using delta and varint coding.
 1084|     30|      int last_symbol_id = 0;
 1085|  17.8k|      for (uint32_t i = 0; i < num_hole_events; ++i) {
  ------------------
  |  Branch (1085:28): [True: 17.8k, False: 4]
  ------------------
 1086|  17.8k|        HoleEventData event_data;
 1087|  17.8k|        uint32_t delta;
 1088|  17.8k|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1088:13): [True: 26, False: 17.8k]
  ------------------
 1089|     26|          return -1;
 1090|     26|        }
 1091|  17.8k|        event_data.symbol_id = delta + last_symbol_id;
 1092|  17.8k|        last_symbol_id = event_data.symbol_id;
 1093|  17.8k|        hole_event_data_.push_back(event_data);
 1094|  17.8k|      }
 1095|     30|    }
 1096|     71|  }
 1097|  2.56k|  return static_cast<int32_t>(decoder_buffer->decoded_size());
 1098|  2.62k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE41DecodeAttributeConnectivitiesOnFaceLegacyENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
 1103|  2.03k|    DecodeAttributeConnectivitiesOnFaceLegacy(CornerIndex corner) {
 1104|       |  // Three corners of the face.
 1105|  2.03k|  const CornerIndex corners[3] = {corner, corner_table_->Next(corner),
 1106|  2.03k|                                  corner_table_->Previous(corner)};
 1107|       |
 1108|  8.13k|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1108:19): [True: 6.09k, False: 2.03k]
  ------------------
 1109|  6.09k|    const CornerIndex opp_corner = corner_table_->Opposite(corners[c]);
 1110|  6.09k|    if (opp_corner == kInvalidCornerIndex) {
  ------------------
  |  Branch (1110:9): [True: 841, False: 5.25k]
  ------------------
 1111|       |      // Don't decode attribute seams on boundary edges (every boundary edge
 1112|       |      // is automatically an attribute seam).
 1113|  1.68k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1113:28): [True: 841, False: 841]
  ------------------
 1114|    841|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1115|    841|      }
 1116|    841|      continue;
 1117|    841|    }
 1118|       |
 1119|  10.5k|    for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1119:26): [True: 5.25k, False: 5.25k]
  ------------------
 1120|  5.25k|      const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i);
 1121|  5.25k|      if (is_seam) {
  ------------------
  |  Branch (1121:11): [True: 5.16k, False: 90]
  ------------------
 1122|  5.16k|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1123|  5.16k|      }
 1124|  5.25k|    }
 1125|  5.25k|  }
 1126|  2.03k|  return true;
 1127|  2.03k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE35DecodeAttributeConnectivitiesOnFaceENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
 1132|  15.0M|    TraversalDecoder>::DecodeAttributeConnectivitiesOnFace(CornerIndex corner) {
 1133|       |  // Three corners of the face.
 1134|  15.0M|  const CornerIndex corners[3] = {corner, corner_table_->Next(corner),
 1135|  15.0M|                                  corner_table_->Previous(corner)};
 1136|       |
 1137|  15.0M|  const FaceIndex src_face_id = corner_table_->Face(corner);
 1138|  60.2M|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1138:19): [True: 45.1M, False: 15.0M]
  ------------------
 1139|  45.1M|    const CornerIndex opp_corner = corner_table_->Opposite(corners[c]);
 1140|  45.1M|    if (opp_corner == kInvalidCornerIndex) {
  ------------------
  |  Branch (1140:9): [True: 205k, False: 44.9M]
  ------------------
 1141|       |      // Don't decode attribute seams on boundary edges (every boundary edge
 1142|       |      // is automatically an attribute seam).
 1143|   421k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1143:28): [True: 216k, False: 205k]
  ------------------
 1144|   216k|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1145|   216k|      }
 1146|   205k|      continue;
 1147|   205k|    }
 1148|  44.9M|    const FaceIndex opp_face_id = corner_table_->Face(opp_corner);
 1149|       |    // Don't decode edges when the opposite face has been already processed.
 1150|  44.9M|    if (opp_face_id < src_face_id) {
  ------------------
  |  Branch (1150:9): [True: 22.4M, False: 22.4M]
  ------------------
 1151|  22.4M|      continue;
 1152|  22.4M|    }
 1153|       |
 1154|  45.8M|    for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1154:26): [True: 23.3M, False: 22.4M]
  ------------------
 1155|  23.3M|      const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i);
 1156|  23.3M|      if (is_seam) {
  ------------------
  |  Branch (1156:11): [True: 20.4M, False: 2.83M]
  ------------------
 1157|  20.4M|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1158|  20.4M|      }
 1159|  23.3M|    }
 1160|  22.4M|  }
 1161|  15.0M|  return true;
 1162|  15.0M|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE21AssignPointsToCornersEi:
 1166|  2.19k|    int num_connectivity_verts) {
 1167|       |  // Map between the existing and deduplicated point ids.
 1168|       |  // Note that at this point we have one point id for each corner of the
 1169|       |  // mesh so there is corner_table_->num_corners() point ids.
 1170|  2.19k|  decoder_->mesh()->SetNumFaces(corner_table_->num_faces());
 1171|       |
 1172|  2.19k|  if (attribute_data_.empty()) {
  ------------------
  |  Branch (1172:7): [True: 27, False: 2.16k]
  ------------------
 1173|       |    // We have connectivity for position only. In this case all vertex indices
 1174|       |    // are equal to point indices.
 1175|  16.1k|    for (FaceIndex f(0); f < decoder_->mesh()->num_faces(); ++f) {
  ------------------
  |  Branch (1175:26): [True: 16.0k, False: 27]
  ------------------
 1176|  16.0k|      Mesh::Face face;
 1177|  16.0k|      const CornerIndex start_corner(3 * f.value());
 1178|  64.3k|      for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1178:23): [True: 48.2k, False: 16.0k]
  ------------------
 1179|       |        // Get the vertex index on the corner and use it as a point index.
 1180|  48.2k|        const int32_t vert_id = corner_table_->Vertex(start_corner + c).value();
 1181|  48.2k|        face[c] = vert_id;
 1182|  48.2k|      }
 1183|  16.0k|      decoder_->mesh()->SetFace(f, face);
 1184|  16.0k|    }
 1185|     27|    decoder_->point_cloud()->set_num_points(num_connectivity_verts);
 1186|     27|    return true;
 1187|     27|  }
 1188|       |  // Else we need to deduplicate multiple attributes.
 1189|       |
 1190|       |  // Map between point id and an associated corner id. Only one corner for
 1191|       |  // each point is stored. The corners are used to sample the attribute values
 1192|       |  // in the last stage of the deduplication.
 1193|  2.16k|  std::vector<int32_t> point_to_corner_map;
 1194|       |  // Map between every corner and their new point ids.
 1195|  2.16k|  std::vector<int32_t> corner_to_point_map(corner_table_->num_corners());
 1196|  7.63M|  for (int v = 0; v < corner_table_->num_vertices(); ++v) {
  ------------------
  |  Branch (1196:19): [True: 7.63M, False: 2.14k]
  ------------------
 1197|  7.63M|    CornerIndex c = corner_table_->LeftMostCorner(VertexIndex(v));
 1198|  7.63M|    if (c == kInvalidCornerIndex) {
  ------------------
  |  Branch (1198:9): [True: 4.19k, False: 7.62M]
  ------------------
 1199|  4.19k|      continue;  // Isolated vertex.
 1200|  4.19k|    }
 1201|  7.62M|    CornerIndex deduplication_first_corner = c;
 1202|  7.62M|    if (is_vert_hole_[v]) {
  ------------------
  |  Branch (1202:9): [True: 205k, False: 7.42M]
  ------------------
 1203|       |      // If the vertex is on a boundary, start deduplication from the left most
 1204|       |      // corner that is guaranteed to lie on the boundary.
 1205|   205k|      deduplication_first_corner = c;
 1206|  7.42M|    } else {
 1207|       |      // If we are not on the boundary we need to find the first seam (of any
 1208|       |      // attribute).
 1209|  8.25M|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1209:28): [True: 7.42M, False: 828k]
  ------------------
 1210|  7.42M|        if (!attribute_data_[i].connectivity_data.IsCornerOnSeam(c)) {
  ------------------
  |  Branch (1210:13): [True: 807k, False: 6.61M]
  ------------------
 1211|   807k|          continue;  // No seam for this attribute, ignore it.
 1212|   807k|        }
 1213|       |        // Else there needs to be at least one seam edge.
 1214|       |
 1215|       |        // At this point, we use identity mapping between corners and point ids.
 1216|  6.61M|        const VertexIndex vert_id =
 1217|  6.61M|            attribute_data_[i].connectivity_data.Vertex(c);
 1218|  6.61M|        CornerIndex act_c = corner_table_->SwingRight(c);
 1219|  6.61M|        bool seam_found = false;
 1220|  6.86M|        while (act_c != c) {
  ------------------
  |  Branch (1220:16): [True: 6.84M, False: 23.9k]
  ------------------
 1221|  6.84M|          if (act_c == kInvalidCornerIndex) {
  ------------------
  |  Branch (1221:15): [True: 17, False: 6.84M]
  ------------------
 1222|     17|            return false;
 1223|     17|          }
 1224|  6.84M|          if (attribute_data_[i].connectivity_data.Vertex(act_c) != vert_id) {
  ------------------
  |  Branch (1224:15): [True: 6.59M, False: 248k]
  ------------------
 1225|       |            // Attribute seam found. Stop.
 1226|  6.59M|            deduplication_first_corner = act_c;
 1227|  6.59M|            seam_found = true;
 1228|  6.59M|            break;
 1229|  6.59M|          }
 1230|   248k|          act_c = corner_table_->SwingRight(act_c);
 1231|   248k|        }
 1232|  6.61M|        if (seam_found) {
  ------------------
  |  Branch (1232:13): [True: 6.59M, False: 23.9k]
  ------------------
 1233|  6.59M|          break;  // No reason to process other attributes if we found a seam.
 1234|  6.59M|        }
 1235|  6.61M|      }
 1236|  7.42M|    }
 1237|       |
 1238|       |    // Do a deduplication pass over the corners on the processed vertex.
 1239|       |    // At this point each corner corresponds to one point id and our goal is to
 1240|       |    // merge similar points into a single point id.
 1241|       |    // We do a single pass in a clockwise direction over the corners and we add
 1242|       |    // a new point id whenever one of the attributes change.
 1243|  7.62M|    c = deduplication_first_corner;
 1244|       |    // Create a new point.
 1245|  7.62M|    corner_to_point_map[c.value()] =
 1246|  7.62M|        static_cast<uint32_t>(point_to_corner_map.size());
 1247|  7.62M|    point_to_corner_map.push_back(c.value());
 1248|       |    // Traverse in CW direction.
 1249|  7.62M|    CornerIndex prev_c = c;
 1250|  7.62M|    c = corner_table_->SwingRight(c);
 1251|  45.1M|    while (c != kInvalidCornerIndex && c != deduplication_first_corner) {
  ------------------
  |  Branch (1251:12): [True: 44.9M, False: 208k]
  |  Branch (1251:40): [True: 37.4M, False: 7.42M]
  ------------------
 1252|  37.4M|      bool attribute_seam = false;
 1253|  41.8M|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1253:28): [True: 37.5M, False: 4.34M]
  ------------------
 1254|  37.5M|        if (attribute_data_[i].connectivity_data.Vertex(c) !=
  ------------------
  |  Branch (1254:13): [True: 33.1M, False: 4.36M]
  ------------------
 1255|  37.5M|            attribute_data_[i].connectivity_data.Vertex(prev_c)) {
 1256|       |          // Attribute index changed from the previous corner. We need to add a
 1257|       |          // new point here.
 1258|  33.1M|          attribute_seam = true;
 1259|  33.1M|          break;
 1260|  33.1M|        }
 1261|  37.5M|      }
 1262|  37.4M|      if (attribute_seam) {
  ------------------
  |  Branch (1262:11): [True: 33.1M, False: 4.34M]
  ------------------
 1263|  33.1M|        corner_to_point_map[c.value()] =
 1264|  33.1M|            static_cast<uint32_t>(point_to_corner_map.size());
 1265|  33.1M|        point_to_corner_map.push_back(c.value());
 1266|  33.1M|      } else {
 1267|  4.34M|        corner_to_point_map[c.value()] = corner_to_point_map[prev_c.value()];
 1268|  4.34M|      }
 1269|  37.4M|      prev_c = c;
 1270|  37.4M|      c = corner_table_->SwingRight(c);
 1271|  37.4M|    }
 1272|  7.62M|  }
 1273|       |  // Add faces.
 1274|  14.9M|  for (FaceIndex f(0); f < decoder_->mesh()->num_faces(); ++f) {
  ------------------
  |  Branch (1274:24): [True: 14.9M, False: 2.14k]
  ------------------
 1275|  14.9M|    Mesh::Face face;
 1276|  59.8M|    for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1276:21): [True: 44.9M, False: 14.9M]
  ------------------
 1277|       |      // Remap old points to the new ones.
 1278|  44.9M|      face[c] = corner_to_point_map[3 * f.value() + c];
 1279|  44.9M|    }
 1280|  14.9M|    decoder_->mesh()->SetFace(f, face);
 1281|  14.9M|  }
 1282|  2.14k|  decoder_->point_cloud()->set_num_points(
 1283|  2.14k|      static_cast<uint32_t>(point_to_corner_map.size()));
 1284|  2.14k|  return true;
 1285|  2.16k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEEC2Ev:
   48|  3.04k|    : decoder_(nullptr),
   49|  3.04k|      last_symbol_id_(-1),
   50|  3.04k|      last_vert_id_(-1),
   51|  3.04k|      last_face_id_(-1),
   52|  3.04k|      num_new_vertices_(0),
   53|  3.04k|      num_encoded_vertices_(0),
   54|  3.04k|      pos_data_decoder_id_(-1) {}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE4InitEPNS_22MeshEdgebreakerDecoderE:
   58|  3.04k|    MeshEdgebreakerDecoder* decoder) {
   59|  3.04k|  decoder_ = decoder;
   60|  3.04k|  return true;
   61|  3.04k|}
_ZNK5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE23GetAttributeCornerTableEi:
   66|    234|    int att_id) const {
   67|    363|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (67:24): [True: 269, False: 94]
  ------------------
   68|    269|    const int decoder_id = attribute_data_[i].decoder_id;
   69|    269|    if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) {
  ------------------
  |  Branch (69:9): [True: 129, False: 140]
  |  Branch (69:27): [True: 0, False: 140]
  ------------------
   70|    129|      continue;
   71|    129|    }
   72|    140|    const AttributesDecoderInterface* const dec =
   73|    140|        decoder_->attributes_decoder(decoder_id);
   74|  1.58k|    for (int j = 0; j < dec->GetNumAttributes(); ++j) {
  ------------------
  |  Branch (74:21): [True: 1.58k, False: 0]
  ------------------
   75|  1.58k|      if (dec->GetAttributeId(j) == att_id) {
  ------------------
  |  Branch (75:11): [True: 140, False: 1.44k]
  ------------------
   76|    140|        if (attribute_data_[i].is_connectivity_used) {
  ------------------
  |  Branch (76:13): [True: 110, False: 30]
  ------------------
   77|    110|          return &attribute_data_[i].connectivity_data;
   78|    110|        }
   79|     30|        return nullptr;
   80|    140|      }
   81|  1.58k|    }
   82|    140|  }
   83|     94|  return nullptr;
   84|    234|}
_ZNK5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE24GetAttributeEncodingDataEi:
   89|    234|    int att_id) const {
   90|    363|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (90:24): [True: 269, False: 94]
  ------------------
   91|    269|    const int decoder_id = attribute_data_[i].decoder_id;
   92|    269|    if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) {
  ------------------
  |  Branch (92:9): [True: 129, False: 140]
  |  Branch (92:27): [True: 0, False: 140]
  ------------------
   93|    129|      continue;
   94|    129|    }
   95|    140|    const AttributesDecoderInterface* const dec =
   96|    140|        decoder_->attributes_decoder(decoder_id);
   97|  1.58k|    for (int j = 0; j < dec->GetNumAttributes(); ++j) {
  ------------------
  |  Branch (97:21): [True: 1.58k, False: 0]
  ------------------
   98|  1.58k|      if (dec->GetAttributeId(j) == att_id) {
  ------------------
  |  Branch (98:11): [True: 140, False: 1.44k]
  ------------------
   99|    140|        return &attribute_data_[i].encoding_data;
  100|    140|      }
  101|  1.58k|    }
  102|    140|  }
  103|     94|  return &pos_encoding_data_;
  104|    234|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE23CreateAttributesDecoderEi:
  130|    216|    int32_t att_decoder_id) {
  131|    216|  int8_t att_data_id;
  132|    216|  if (!decoder_->buffer()->Decode(&att_data_id)) {
  ------------------
  |  Branch (132:7): [True: 8, False: 208]
  ------------------
  133|      8|    return false;
  134|      8|  }
  135|    208|  uint8_t decoder_type;
  136|    208|  if (!decoder_->buffer()->Decode(&decoder_type)) {
  ------------------
  |  Branch (136:7): [True: 7, False: 201]
  ------------------
  137|      7|    return false;
  138|      7|  }
  139|       |
  140|    201|  if (att_data_id >= 0) {
  ------------------
  |  Branch (140:7): [True: 115, False: 86]
  ------------------
  141|    115|    if (att_data_id >= attribute_data_.size()) {
  ------------------
  |  Branch (141:9): [True: 29, False: 86]
  ------------------
  142|     29|      return false;  // Unexpected attribute data.
  143|     29|    }
  144|       |
  145|       |    // Ensure that the attribute data is not mapped to a different attributes
  146|       |    // decoder already.
  147|     86|    if (attribute_data_[att_data_id].decoder_id >= 0) {
  ------------------
  |  Branch (147:9): [True: 5, False: 81]
  ------------------
  148|      5|      return false;
  149|      5|    }
  150|       |
  151|     81|    attribute_data_[att_data_id].decoder_id = att_decoder_id;
  152|     86|  } else {
  153|       |    // Assign the attributes decoder to |pos_encoding_data_|.
  154|     86|    if (pos_data_decoder_id_ >= 0) {
  ------------------
  |  Branch (154:9): [True: 4, False: 82]
  ------------------
  155|      4|      return false;  // Some other decoder is already using the data. Error.
  156|      4|    }
  157|     82|    pos_data_decoder_id_ = att_decoder_id;
  158|     82|  }
  159|       |
  160|    163|  MeshTraversalMethod traversal_method = MESH_TRAVERSAL_DEPTH_FIRST;
  161|    163|  if (decoder_->bitstream_version() >= DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|    163|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (161:7): [True: 163, False: 0]
  ------------------
  162|    163|    uint8_t traversal_method_encoded;
  163|    163|    if (!decoder_->buffer()->Decode(&traversal_method_encoded)) {
  ------------------
  |  Branch (163:9): [True: 8, False: 155]
  ------------------
  164|      8|      return false;
  165|      8|    }
  166|       |    // Check that decoded traversal method is valid.
  167|    155|    if (traversal_method_encoded >= NUM_TRAVERSAL_METHODS) {
  ------------------
  |  Branch (167:9): [True: 18, False: 137]
  ------------------
  168|     18|      return false;
  169|     18|    }
  170|    137|    traversal_method =
  171|    137|        static_cast<MeshTraversalMethod>(traversal_method_encoded);
  172|    137|  }
  173|       |
  174|    137|  const Mesh* mesh = decoder_->mesh();
  175|    137|  std::unique_ptr<PointsSequencer> sequencer;
  176|       |
  177|    137|  if (decoder_type == MESH_VERTEX_ATTRIBUTE) {
  ------------------
  |  Branch (177:7): [True: 72, False: 65]
  ------------------
  178|       |    // Per-vertex attribute decoder.
  179|       |
  180|     72|    MeshAttributeIndicesEncodingData* encoding_data = nullptr;
  181|     72|    if (att_data_id < 0) {
  ------------------
  |  Branch (181:9): [True: 56, False: 16]
  ------------------
  182|     56|      encoding_data = &pos_encoding_data_;
  183|     56|    } else {
  184|     16|      encoding_data = &attribute_data_[att_data_id].encoding_data;
  185|       |      // Mark the attribute connectivity data invalid to ensure it's not used
  186|       |      // later on.
  187|     16|      attribute_data_[att_data_id].is_connectivity_used = false;
  188|     16|    }
  189|       |    // Defining sequencer via a traversal scheme.
  190|     72|    if (traversal_method == MESH_TRAVERSAL_PREDICTION_DEGREE) {
  ------------------
  |  Branch (190:9): [True: 29, False: 43]
  ------------------
  191|     29|      typedef MeshAttributeIndicesEncodingObserver<CornerTable> AttObserver;
  192|     29|      typedef MaxPredictionDegreeTraverser<CornerTable, AttObserver>
  193|     29|          AttTraverser;
  194|     29|      sequencer = CreateVertexTraversalSequencer<AttTraverser>(encoding_data);
  195|     43|    } else if (traversal_method == MESH_TRAVERSAL_DEPTH_FIRST) {
  ------------------
  |  Branch (195:16): [True: 43, False: 0]
  ------------------
  196|     43|      typedef MeshAttributeIndicesEncodingObserver<CornerTable> AttObserver;
  197|     43|      typedef DepthFirstTraverser<CornerTable, AttObserver> AttTraverser;
  198|     43|      sequencer = CreateVertexTraversalSequencer<AttTraverser>(encoding_data);
  199|     43|    } else {
  200|      0|      return false;  // Unsupported method
  201|      0|    }
  202|     72|  } else {
  203|     65|    if (traversal_method != MESH_TRAVERSAL_DEPTH_FIRST) {
  ------------------
  |  Branch (203:9): [True: 3, False: 62]
  ------------------
  204|      3|      return false;  // Unsupported method.
  205|      3|    }
  206|     62|    if (att_data_id < 0) {
  ------------------
  |  Branch (206:9): [True: 3, False: 59]
  ------------------
  207|      3|      return false;  // Attribute data must be specified.
  208|      3|    }
  209|       |
  210|       |    // Per-corner attribute decoder.
  211|       |
  212|     59|    typedef MeshAttributeIndicesEncodingObserver<MeshAttributeCornerTable>
  213|     59|        AttObserver;
  214|     59|    typedef DepthFirstTraverser<MeshAttributeCornerTable, AttObserver>
  215|     59|        AttTraverser;
  216|       |
  217|     59|    MeshAttributeIndicesEncodingData* const encoding_data =
  218|     59|        &attribute_data_[att_data_id].encoding_data;
  219|     59|    const MeshAttributeCornerTable* const corner_table =
  220|     59|        &attribute_data_[att_data_id].connectivity_data;
  221|       |
  222|     59|    std::unique_ptr<MeshTraversalSequencer<AttTraverser>> traversal_sequencer(
  223|     59|        new MeshTraversalSequencer<AttTraverser>(mesh, encoding_data));
  224|       |
  225|     59|    AttObserver att_observer(corner_table, mesh, traversal_sequencer.get(),
  226|     59|                             encoding_data);
  227|       |
  228|     59|    AttTraverser att_traverser;
  229|     59|    att_traverser.Init(corner_table, att_observer);
  230|       |
  231|     59|    traversal_sequencer->SetTraverser(att_traverser);
  232|     59|    sequencer = std::move(traversal_sequencer);
  233|     59|  }
  234|       |
  235|    131|  if (!sequencer) {
  ------------------
  |  Branch (235:7): [True: 0, False: 131]
  ------------------
  236|      0|    return false;
  237|      0|  }
  238|       |
  239|    131|  std::unique_ptr<SequentialAttributeDecodersController> att_controller(
  240|    131|      new SequentialAttributeDecodersController(std::move(sequencer)));
  241|       |
  242|    131|  return decoder_->SetAttributesDecoder(att_decoder_id,
  243|    131|                                        std::move(att_controller));
  244|    131|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE18DecodeConnectivityEv:
  247|  3.04k|bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
  248|  3.04k|  num_new_vertices_ = 0;
  249|  3.04k|  new_to_parent_vertex_map_.clear();
  250|  3.04k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  251|  3.04k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  3.04k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (251:7): [True: 548, False: 2.50k]
  ------------------
  252|    548|    uint32_t num_new_verts;
  253|    548|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    548|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (253:9): [True: 287, False: 261]
  ------------------
  254|    287|      if (!decoder_->buffer()->Decode(&num_new_verts)) {
  ------------------
  |  Branch (254:11): [True: 9, False: 278]
  ------------------
  255|      9|        return false;
  256|      9|      }
  257|    287|    } else {
  258|    261|      if (!DecodeVarint(&num_new_verts, decoder_->buffer())) {
  ------------------
  |  Branch (258:11): [True: 1, False: 260]
  ------------------
  259|      1|        return false;
  260|      1|      }
  261|    261|    }
  262|    538|    num_new_vertices_ = num_new_verts;
  263|    538|  }
  264|  3.03k|#endif
  265|       |
  266|  3.03k|  uint32_t num_encoded_vertices;
  267|  3.03k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  268|  3.03k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  3.03k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (268:7): [True: 278, False: 2.76k]
  ------------------
  269|    278|    if (!decoder_->buffer()->Decode(&num_encoded_vertices)) {
  ------------------
  |  Branch (269:9): [True: 5, False: 273]
  ------------------
  270|      5|      return false;
  271|      5|    }
  272|       |
  273|    278|  } else
  274|  2.76k|#endif
  275|  2.76k|  {
  276|  2.76k|    if (!DecodeVarint(&num_encoded_vertices, decoder_->buffer())) {
  ------------------
  |  Branch (276:9): [True: 6, False: 2.75k]
  ------------------
  277|      6|      return false;
  278|      6|    }
  279|  2.76k|  }
  280|  3.02k|  num_encoded_vertices_ = num_encoded_vertices;
  281|       |
  282|  3.02k|  uint32_t num_faces;
  283|  3.02k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  284|  3.02k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  3.02k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (284:7): [True: 273, False: 2.75k]
  ------------------
  285|    273|    if (!decoder_->buffer()->Decode(&num_faces)) {
  ------------------
  |  Branch (285:9): [True: 4, False: 269]
  ------------------
  286|      4|      return false;
  287|      4|    }
  288|       |
  289|    273|  } else
  290|  2.75k|#endif
  291|  2.75k|  {
  292|  2.75k|    if (!DecodeVarint(&num_faces, decoder_->buffer())) {
  ------------------
  |  Branch (292:9): [True: 3, False: 2.75k]
  ------------------
  293|      3|      return false;
  294|      3|    }
  295|  2.75k|  }
  296|  3.02k|  if (num_faces > std::numeric_limits<CornerIndex::ValueType>::max() / 3) {
  ------------------
  |  Branch (296:7): [True: 2, False: 3.01k]
  ------------------
  297|      2|    return false;  // Draco cannot handle this many faces.
  298|      2|  }
  299|       |
  300|  3.01k|  if (static_cast<uint32_t>(num_encoded_vertices_) > num_faces * 3) {
  ------------------
  |  Branch (300:7): [True: 29, False: 2.99k]
  ------------------
  301|     29|    return false;  // There cannot be more vertices than 3 * num_faces.
  302|     29|  }
  303|       |
  304|       |  // Minimum number of edges of the mesh assuming each edge is shared between
  305|       |  // two faces.
  306|  2.99k|  const uint32_t min_num_face_edges = 3 * num_faces / 2;
  307|       |
  308|       |  // Maximum number of edges that can exist between |num_encoded_vertices_|.
  309|       |  // This is based on graph theory assuming simple connected graph.
  310|  2.99k|  const uint64_t num_encoded_vertices_64 =
  311|  2.99k|      static_cast<uint64_t>(num_encoded_vertices_);
  312|  2.99k|  const uint64_t max_num_vertex_edges =
  313|  2.99k|      num_encoded_vertices_64 * (num_encoded_vertices_64 - 1) / 2;
  314|  2.99k|  if (max_num_vertex_edges < min_num_face_edges) {
  ------------------
  |  Branch (314:7): [True: 21, False: 2.96k]
  ------------------
  315|       |    // It is impossible to construct a manifold mesh with these properties.
  316|     21|    return false;
  317|     21|  }
  318|       |
  319|  2.96k|  uint8_t num_attribute_data;
  320|  2.96k|  if (!decoder_->buffer()->Decode(&num_attribute_data)) {
  ------------------
  |  Branch (320:7): [True: 35, False: 2.93k]
  ------------------
  321|     35|    return false;
  322|     35|  }
  323|       |
  324|  2.93k|  uint32_t num_encoded_symbols;
  325|  2.93k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  326|  2.93k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  2.93k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (326:7): [True: 255, False: 2.67k]
  ------------------
  327|    255|    if (!decoder_->buffer()->Decode(&num_encoded_symbols)) {
  ------------------
  |  Branch (327:9): [True: 15, False: 240]
  ------------------
  328|     15|      return false;
  329|     15|    }
  330|       |
  331|    255|  } else
  332|  2.67k|#endif
  333|  2.67k|  {
  334|  2.67k|    if (!DecodeVarint(&num_encoded_symbols, decoder_->buffer())) {
  ------------------
  |  Branch (334:9): [True: 9, False: 2.67k]
  ------------------
  335|      9|      return false;
  336|      9|    }
  337|  2.67k|  }
  338|       |
  339|  2.91k|  if (num_faces < num_encoded_symbols) {
  ------------------
  |  Branch (339:7): [True: 23, False: 2.88k]
  ------------------
  340|       |    // Number of faces needs to be the same or greater than the number of
  341|       |    // symbols (it can be greater because the initial face may not be encoded as
  342|       |    // a symbol).
  343|     23|    return false;
  344|     23|  }
  345|  2.88k|  const uint32_t max_encoded_faces =
  346|  2.88k|      num_encoded_symbols + (num_encoded_symbols / 3);
  347|  2.88k|  if (num_faces > max_encoded_faces) {
  ------------------
  |  Branch (347:7): [True: 54, False: 2.83k]
  ------------------
  348|       |    // Faces can only be 1 1/3 times bigger than number of encoded symbols. This
  349|       |    // could only happen if all new encoded components started with interior
  350|       |    // triangles. E.g. A mesh with multiple tetrahedrons.
  351|     54|    return false;
  352|     54|  }
  353|       |
  354|  2.83k|  uint32_t num_encoded_split_symbols;
  355|  2.83k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  356|  2.83k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  2.83k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (356:7): [True: 218, False: 2.61k]
  ------------------
  357|    218|    if (!decoder_->buffer()->Decode(&num_encoded_split_symbols)) {
  ------------------
  |  Branch (357:9): [True: 2, False: 216]
  ------------------
  358|      2|      return false;
  359|      2|    }
  360|       |
  361|    218|  } else
  362|  2.61k|#endif
  363|  2.61k|  {
  364|  2.61k|    if (!DecodeVarint(&num_encoded_split_symbols, decoder_->buffer())) {
  ------------------
  |  Branch (364:9): [True: 5, False: 2.61k]
  ------------------
  365|      5|      return false;
  366|      5|    }
  367|  2.61k|  }
  368|       |
  369|  2.82k|  if (num_encoded_split_symbols > num_encoded_symbols) {
  ------------------
  |  Branch (369:7): [True: 49, False: 2.77k]
  ------------------
  370|     49|    return false;  // Split symbols are a sub-set of all symbols.
  371|     49|  }
  372|       |
  373|       |  // Decode topology (connectivity).
  374|  2.77k|  vertex_traversal_length_.clear();
  375|  2.77k|  corner_table_ = std::unique_ptr<CornerTable>(new CornerTable());
  376|  2.77k|  if (corner_table_ == nullptr) {
  ------------------
  |  Branch (376:7): [True: 0, False: 2.77k]
  ------------------
  377|      0|    return false;
  378|      0|  }
  379|  2.77k|  processed_corner_ids_.clear();
  380|  2.77k|  processed_corner_ids_.reserve(num_faces);
  381|  2.77k|  processed_connectivity_corners_.clear();
  382|  2.77k|  processed_connectivity_corners_.reserve(num_faces);
  383|  2.77k|  topology_split_data_.clear();
  384|  2.77k|  hole_event_data_.clear();
  385|  2.77k|  init_face_configurations_.clear();
  386|  2.77k|  init_corners_.clear();
  387|       |
  388|  2.77k|  last_symbol_id_ = -1;
  389|  2.77k|  last_face_id_ = -1;
  390|  2.77k|  last_vert_id_ = -1;
  391|       |
  392|  2.77k|  attribute_data_.clear();
  393|       |  // Add one attribute data for each attribute decoder.
  394|  2.77k|  attribute_data_.resize(num_attribute_data);
  395|       |
  396|  2.77k|  if (!corner_table_->Reset(
  ------------------
  |  Branch (396:7): [True: 0, False: 2.77k]
  ------------------
  397|  2.77k|          num_faces, num_encoded_vertices_ + num_encoded_split_symbols)) {
  398|      0|    return false;
  399|      0|  }
  400|       |
  401|       |  // Start with all vertices marked as holes (boundaries).
  402|       |  // Only vertices decoded with TOPOLOGY_C symbol (and the initial face) will
  403|       |  // be marked as non hole vertices. We need to allocate the array larger
  404|       |  // because split symbols can create extra vertices during the decoding
  405|       |  // process (these extra vertices are then eliminated during deduplication).
  406|  2.77k|  is_vert_hole_.assign(num_encoded_vertices_ + num_encoded_split_symbols, true);
  407|       |
  408|  2.77k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  409|  2.77k|  int32_t topology_split_decoded_bytes = -1;
  410|  2.77k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  2.77k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (410:7): [True: 455, False: 2.32k]
  ------------------
  411|    455|    uint32_t encoded_connectivity_size;
  412|    455|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    455|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (412:9): [True: 206, False: 249]
  ------------------
  413|    206|      if (!decoder_->buffer()->Decode(&encoded_connectivity_size)) {
  ------------------
  |  Branch (413:11): [True: 2, False: 204]
  ------------------
  414|      2|        return false;
  415|      2|      }
  416|    249|    } else {
  417|    249|      if (!DecodeVarint(&encoded_connectivity_size, decoder_->buffer())) {
  ------------------
  |  Branch (417:11): [True: 4, False: 245]
  ------------------
  418|      4|        return false;
  419|      4|      }
  420|    249|    }
  421|    449|    if (encoded_connectivity_size == 0 ||
  ------------------
  |  Branch (421:9): [True: 1, False: 448]
  ------------------
  422|    448|        encoded_connectivity_size > decoder_->buffer()->remaining_size()) {
  ------------------
  |  Branch (422:9): [True: 30, False: 418]
  ------------------
  423|     31|      return false;
  424|     31|    }
  425|    418|    DecoderBuffer event_buffer;
  426|    418|    event_buffer.Init(
  427|    418|        decoder_->buffer()->data_head() + encoded_connectivity_size,
  428|    418|        decoder_->buffer()->remaining_size() - encoded_connectivity_size,
  429|    418|        decoder_->buffer()->bitstream_version());
  430|       |    // Decode hole and topology split events.
  431|    418|    topology_split_decoded_bytes =
  432|    418|        DecodeHoleAndTopologySplitEvents(&event_buffer);
  433|    418|    if (topology_split_decoded_bytes == -1) {
  ------------------
  |  Branch (433:9): [True: 130, False: 288]
  ------------------
  434|    130|      return false;
  435|    130|    }
  436|       |
  437|    418|  } else
  438|  2.32k|#endif
  439|  2.32k|  {
  440|  2.32k|    if (DecodeHoleAndTopologySplitEvents(decoder_->buffer()) == -1) {
  ------------------
  |  Branch (440:9): [True: 102, False: 2.22k]
  ------------------
  441|    102|      return false;
  442|    102|    }
  443|  2.32k|  }
  444|       |
  445|  2.50k|  traversal_decoder_.Init(this);
  446|       |  // Add one extra vertex for each split symbol.
  447|  2.50k|  traversal_decoder_.SetNumEncodedVertices(num_encoded_vertices_ +
  448|  2.50k|                                           num_encoded_split_symbols);
  449|  2.50k|  traversal_decoder_.SetNumAttributeData(num_attribute_data);
  450|       |
  451|  2.50k|  DecoderBuffer traversal_end_buffer;
  452|  2.50k|  if (!traversal_decoder_.Start(&traversal_end_buffer)) {
  ------------------
  |  Branch (452:7): [True: 1.38k, False: 1.12k]
  ------------------
  453|  1.38k|    return false;
  454|  1.38k|  }
  455|       |
  456|  1.12k|  const int num_connectivity_verts = DecodeConnectivity(num_encoded_symbols);
  457|  1.12k|  if (num_connectivity_verts == -1) {
  ------------------
  |  Branch (457:7): [True: 883, False: 237]
  ------------------
  458|    883|    return false;
  459|    883|  }
  460|       |
  461|       |  // Set the main buffer to the end of the traversal.
  462|    237|  decoder_->buffer()->Init(traversal_end_buffer.data_head(),
  463|    237|                           traversal_end_buffer.remaining_size(),
  464|    237|                           decoder_->buffer()->bitstream_version());
  465|       |
  466|    237|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  467|    237|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    237|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (467:7): [True: 7, False: 230]
  ------------------
  468|       |    // Skip topology split data that was already decoded earlier.
  469|      7|    decoder_->buffer()->Advance(topology_split_decoded_bytes);
  470|      7|  }
  471|    237|#endif
  472|       |
  473|       |  // Decode connectivity of non-position attributes.
  474|    237|  if (!attribute_data_.empty()) {
  ------------------
  |  Branch (474:7): [True: 200, False: 37]
  ------------------
  475|    200|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  476|    200|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
  ------------------
  |  |  115|    200|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (476:9): [True: 6, False: 194]
  ------------------
  477|     18|      for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
  ------------------
  |  Branch (477:31): [True: 12, False: 6]
  ------------------
  478|     12|        if (!DecodeAttributeConnectivitiesOnFaceLegacy(ci)) {
  ------------------
  |  Branch (478:13): [True: 0, False: 12]
  ------------------
  479|      0|          return false;
  480|      0|        }
  481|     12|      }
  482|       |
  483|      6|    } else
  484|    194|#endif
  485|    194|    {
  486|   341k|      for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
  ------------------
  |  Branch (486:31): [True: 341k, False: 194]
  ------------------
  487|   341k|        if (!DecodeAttributeConnectivitiesOnFace(ci)) {
  ------------------
  |  Branch (487:13): [True: 0, False: 341k]
  ------------------
  488|      0|          return false;
  489|      0|        }
  490|   341k|      }
  491|    194|    }
  492|    200|  }
  493|    237|  traversal_decoder_.Done();
  494|       |
  495|       |  // Decode attribute connectivity.
  496|       |  // Prepare data structure for decoding non-position attribute connectivity.
  497|    600|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (497:24): [True: 363, False: 237]
  ------------------
  498|    363|    attribute_data_[i].connectivity_data.InitEmpty(corner_table_.get());
  499|       |    // Add all seams.
  500|   387k|    for (int32_t c : attribute_data_[i].attribute_seam_corners) {
  ------------------
  |  Branch (500:20): [True: 387k, False: 363]
  ------------------
  501|   387k|      attribute_data_[i].connectivity_data.AddSeamEdge(CornerIndex(c));
  502|   387k|    }
  503|       |    // Recompute vertices from the newly added seam edges.
  504|    363|    if (!attribute_data_[i].connectivity_data.RecomputeVertices(nullptr,
  ------------------
  |  Branch (504:9): [True: 0, False: 363]
  ------------------
  505|    363|                                                                nullptr)) {
  506|      0|      return false;
  507|      0|    }
  508|    363|  }
  509|       |
  510|    237|  pos_encoding_data_.Init(corner_table_->num_vertices());
  511|    600|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (511:24): [True: 363, False: 237]
  ------------------
  512|       |    // For non-position attributes, preallocate the vertex to value mapping
  513|       |    // using the maximum number of vertices from the base corner table and the
  514|       |    // attribute corner table (since the attribute decoder may use either of
  515|       |    // it).
  516|    363|    int32_t att_connectivity_verts =
  517|    363|        attribute_data_[i].connectivity_data.num_vertices();
  518|    363|    if (att_connectivity_verts < corner_table_->num_vertices()) {
  ------------------
  |  Branch (518:9): [True: 4, False: 359]
  ------------------
  519|      4|      att_connectivity_verts = corner_table_->num_vertices();
  520|      4|    }
  521|    363|    attribute_data_[i].encoding_data.Init(att_connectivity_verts);
  522|    363|  }
  523|    237|  if (!AssignPointsToCorners(num_connectivity_verts)) {
  ------------------
  |  Branch (523:7): [True: 21, False: 216]
  ------------------
  524|     21|    return false;
  525|     21|  }
  526|    216|  return true;
  527|    237|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE19OnAttributesDecodedEv:
  530|     23|bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::OnAttributesDecoded() {
  531|     23|  return true;
  532|     23|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE18DecodeConnectivityEi:
  536|  1.12k|    int num_symbols) {
  537|       |  // Algorithm does the reverse decoding of the symbols encoded with the
  538|       |  // edgebreaker method. The reverse decoding always keeps track of the active
  539|       |  // edge identified by its opposite corner (active corner). New faces are
  540|       |  // always added to this active edge. There may be multiple active corners at
  541|       |  // one time that either correspond to separate mesh components or to
  542|       |  // sub-components of one mesh that are going to be merged together using the
  543|       |  // TOPOLOGY_S symbol. We can store these active edges on a stack, because the
  544|       |  // decoder always processes only the latest active edge. TOPOLOGY_S then
  545|       |  // removes the top edge from the stack and TOPOLOGY_E adds a new edge to the
  546|       |  // stack.
  547|  1.12k|  std::vector<CornerIndex> active_corner_stack;
  548|       |
  549|       |  // Additional active edges may be added as a result of topology split events.
  550|       |  // They can be added in arbitrary order, but we always know the split symbol
  551|       |  // id they belong to, so we can address them using this symbol id.
  552|  1.12k|  std::unordered_map<int, CornerIndex> topology_split_active_corners;
  553|       |
  554|       |  // Vector used for storing vertices that were marked as isolated during the
  555|       |  // decoding process. Currently used only when the mesh doesn't contain any
  556|       |  // non-position connectivity data.
  557|  1.12k|  std::vector<VertexIndex> invalid_vertices;
  558|  1.12k|  const bool remove_invalid_vertices = attribute_data_.empty();
  559|       |
  560|  1.12k|  int max_num_vertices = static_cast<int>(is_vert_hole_.size());
  561|  1.12k|  int num_faces = 0;
  562|  60.0M|  for (int symbol_id = 0; symbol_id < num_symbols; ++symbol_id) {
  ------------------
  |  Branch (562:27): [True: 60.0M, False: 359]
  ------------------
  563|  60.0M|    const FaceIndex face(num_faces++);
  564|       |    // Used to flag cases where we need to look for topology split events.
  565|  60.0M|    bool check_topology_split = false;
  566|  60.0M|    const uint32_t symbol = traversal_decoder_.DecodeSymbol();
  567|  60.0M|    if (symbol == TOPOLOGY_C) {
  ------------------
  |  Branch (567:9): [True: 6.06M, False: 53.9M]
  ------------------
  568|       |      // Create a new face between two edges on the open boundary.
  569|       |      // The first edge is opposite to the corner "a" from the image below.
  570|       |      // The other edge is opposite to the corner "b" that can be reached
  571|       |      // through a CCW traversal around the vertex "v".
  572|       |      // One new active boundary edge is created, opposite to the new corner
  573|       |      // "x".
  574|       |      //
  575|       |      //     *-------*
  576|       |      //    / \     / \
  577|       |      //   /   \   /   \
  578|       |      //  /     \ /     \
  579|       |      // *-------v-------*
  580|       |      //  \b    /x\    a/
  581|       |      //   \   /   \   /
  582|       |      //    \ /  C  \ /
  583|       |      //     *.......*
  584|       |
  585|       |      // Find the corner "b" from the corner "a" which is the corner on the
  586|       |      // top of the active stack.
  587|  6.06M|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (587:11): [True: 54, False: 6.06M]
  ------------------
  588|     54|        return -1;
  589|     54|      }
  590|       |
  591|  6.06M|      const CornerIndex corner_a = active_corner_stack.back();
  592|  6.06M|      const VertexIndex vertex_x =
  593|  6.06M|          corner_table_->Vertex(corner_table_->Next(corner_a));
  594|  6.06M|      const CornerIndex corner_b =
  595|  6.06M|          corner_table_->Next(corner_table_->LeftMostCorner(vertex_x));
  596|       |
  597|  6.06M|      if (corner_a == corner_b) {
  ------------------
  |  Branch (597:11): [True: 314, False: 6.06M]
  ------------------
  598|       |        // All matched corners must be different.
  599|    314|        return -1;
  600|    314|      }
  601|  6.06M|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex ||
  ------------------
  |  Branch (601:11): [True: 0, False: 6.06M]
  |  Branch (601:11): [True: 0, False: 6.06M]
  ------------------
  602|  6.06M|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex) {
  ------------------
  |  Branch (602:11): [True: 0, False: 6.06M]
  ------------------
  603|       |        // One of the corners is already opposite to an existing face, which
  604|       |        // should not happen unless the input was tampered with.
  605|      0|        return -1;
  606|      0|      }
  607|       |
  608|       |      // New tip corner.
  609|  6.06M|      const CornerIndex corner(3 * face.value());
  610|       |      // Update opposite corner mappings.
  611|  6.06M|      SetOppositeCorners(corner_a, corner + 1);
  612|  6.06M|      SetOppositeCorners(corner_b, corner + 2);
  613|       |
  614|       |      // Update vertex mapping.
  615|  6.06M|      const VertexIndex vert_a_prev =
  616|  6.06M|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  617|  6.06M|      const VertexIndex vert_b_next =
  618|  6.06M|          corner_table_->Vertex(corner_table_->Next(corner_b));
  619|  6.06M|      if (vertex_x == vert_a_prev || vertex_x == vert_b_next) {
  ------------------
  |  Branch (619:11): [True: 0, False: 6.06M]
  |  Branch (619:38): [True: 0, False: 6.06M]
  ------------------
  620|       |        // Encoding is invalid, because face vertices are degenerate.
  621|      0|        return -1;
  622|      0|      }
  623|  6.06M|      corner_table_->MapCornerToVertex(corner, vertex_x);
  624|  6.06M|      corner_table_->MapCornerToVertex(corner + 1, vert_b_next);
  625|  6.06M|      corner_table_->MapCornerToVertex(corner + 2, vert_a_prev);
  626|  6.06M|      corner_table_->SetLeftMostCorner(vert_a_prev, corner + 2);
  627|       |      // Mark the vertex |x| as interior.
  628|  6.06M|      is_vert_hole_[vertex_x.value()] = false;
  629|       |      // Update the corner on the active stack.
  630|  6.06M|      active_corner_stack.back() = corner;
  631|  53.9M|    } else if (symbol == TOPOLOGY_R || symbol == TOPOLOGY_L) {
  ------------------
  |  Branch (631:16): [True: 2.99k, False: 53.9M]
  |  Branch (631:40): [True: 47.9M, False: 5.97M]
  ------------------
  632|       |      // Create a new face extending from the open boundary edge opposite to the
  633|       |      // corner "a" from the image below. Two new boundary edges are created
  634|       |      // opposite to corners "r" and "l". New active corner is set to either "r"
  635|       |      // or "l" depending on the decoded symbol. One new vertex is created
  636|       |      // at the opposite corner to corner "a".
  637|       |      //     *-------*
  638|       |      //    /a\     / \
  639|       |      //   /   \   /   \
  640|       |      //  /     \ /     \
  641|       |      // *-------v-------*
  642|       |      //  .l   r.
  643|       |      //   .   .
  644|       |      //    . .
  645|       |      //     *
  646|  47.9M|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (646:11): [True: 0, False: 47.9M]
  ------------------
  647|      0|        return -1;
  648|      0|      }
  649|  47.9M|      const CornerIndex corner_a = active_corner_stack.back();
  650|  47.9M|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex) {
  ------------------
  |  Branch (650:11): [True: 0, False: 47.9M]
  ------------------
  651|       |        // Active corner is already opposite to an existing face, which should
  652|       |        // not happen unless the input was tampered with.
  653|      0|        return -1;
  654|      0|      }
  655|       |
  656|       |      // First corner on the new face is either corner "l" or "r".
  657|  47.9M|      const CornerIndex corner(3 * face.value());
  658|  47.9M|      CornerIndex opp_corner, corner_l, corner_r;
  659|  47.9M|      if (symbol == TOPOLOGY_R) {
  ------------------
  |  Branch (659:11): [True: 2.99k, False: 47.9M]
  ------------------
  660|       |        // "r" is the new first corner.
  661|  2.99k|        opp_corner = corner + 2;
  662|  2.99k|        corner_l = corner + 1;
  663|  2.99k|        corner_r = corner;
  664|  47.9M|      } else {
  665|       |        // "l" is the new first corner.
  666|  47.9M|        opp_corner = corner + 1;
  667|  47.9M|        corner_l = corner;
  668|  47.9M|        corner_r = corner + 2;
  669|  47.9M|      }
  670|  47.9M|      SetOppositeCorners(opp_corner, corner_a);
  671|       |      // Update vertex mapping.
  672|  47.9M|      const VertexIndex new_vert_index = corner_table_->AddNewVertex();
  673|       |
  674|  47.9M|      if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (674:11): [True: 17, False: 47.9M]
  ------------------
  675|     17|        return -1;  // Unexpected number of decoded vertices.
  676|     17|      }
  677|       |
  678|  47.9M|      corner_table_->MapCornerToVertex(opp_corner, new_vert_index);
  679|  47.9M|      corner_table_->SetLeftMostCorner(new_vert_index, opp_corner);
  680|       |
  681|  47.9M|      const VertexIndex vertex_r =
  682|  47.9M|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  683|  47.9M|      corner_table_->MapCornerToVertex(corner_r, vertex_r);
  684|       |      // Update left-most corner on the vertex on the |corner_r|.
  685|  47.9M|      corner_table_->SetLeftMostCorner(vertex_r, corner_r);
  686|       |
  687|  47.9M|      corner_table_->MapCornerToVertex(
  688|  47.9M|          corner_l, corner_table_->Vertex(corner_table_->Next(corner_a)));
  689|  47.9M|      active_corner_stack.back() = corner;
  690|  47.9M|      check_topology_split = true;
  691|  47.9M|    } else if (symbol == TOPOLOGY_S) {
  ------------------
  |  Branch (691:16): [True: 44.9k, False: 5.93M]
  ------------------
  692|       |      // Create a new face that merges two last active edges from the active
  693|       |      // stack. No new vertex is created, but two vertices at corners "p" and
  694|       |      // "n" need to be merged into a single vertex.
  695|       |      //
  696|       |      // *-------v-------*
  697|       |      //  \a   p/x\n   b/
  698|       |      //   \   /   \   /
  699|       |      //    \ /  S  \ /
  700|       |      //     *.......*
  701|       |      //
  702|  44.9k|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (702:11): [True: 1, False: 44.9k]
  ------------------
  703|      1|        return -1;
  704|      1|      }
  705|  44.9k|      const CornerIndex corner_b = active_corner_stack.back();
  706|  44.9k|      active_corner_stack.pop_back();
  707|       |
  708|       |      // Corner "a" can correspond either to a normal active edge, or to an edge
  709|       |      // created from the topology split event.
  710|  44.9k|      const auto it = topology_split_active_corners.find(symbol_id);
  711|  44.9k|      if (it != topology_split_active_corners.end()) {
  ------------------
  |  Branch (711:11): [True: 26, False: 44.9k]
  ------------------
  712|       |        // Topology split event. Move the retrieved edge to the stack.
  713|     26|        active_corner_stack.push_back(it->second);
  714|     26|      }
  715|  44.9k|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (715:11): [True: 69, False: 44.9k]
  ------------------
  716|     69|        return -1;
  717|     69|      }
  718|  44.9k|      const CornerIndex corner_a = active_corner_stack.back();
  719|       |
  720|  44.9k|      if (corner_a == corner_b) {
  ------------------
  |  Branch (720:11): [True: 0, False: 44.9k]
  ------------------
  721|       |        // All matched corners must be different.
  722|      0|        return -1;
  723|      0|      }
  724|  44.9k|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex ||
  ------------------
  |  Branch (724:11): [True: 3, False: 44.9k]
  |  Branch (724:11): [True: 3, False: 44.9k]
  ------------------
  725|  44.9k|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex) {
  ------------------
  |  Branch (725:11): [True: 0, False: 44.9k]
  ------------------
  726|       |        // One of the corners is already opposite to an existing face, which
  727|       |        // should not happen unless the input was tampered with.
  728|      3|        return -1;
  729|      3|      }
  730|       |
  731|       |      // First corner on the new face is corner "x" from the image above.
  732|  44.9k|      const CornerIndex corner(3 * face.value());
  733|       |      // Update the opposite corner mapping.
  734|  44.9k|      SetOppositeCorners(corner_a, corner + 2);
  735|  44.9k|      SetOppositeCorners(corner_b, corner + 1);
  736|       |      // Update vertices. For the vertex at corner "x", use the vertex id from
  737|       |      // the corner "p".
  738|  44.9k|      const VertexIndex vertex_p =
  739|  44.9k|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  740|  44.9k|      corner_table_->MapCornerToVertex(corner, vertex_p);
  741|  44.9k|      corner_table_->MapCornerToVertex(
  742|  44.9k|          corner + 1, corner_table_->Vertex(corner_table_->Next(corner_a)));
  743|  44.9k|      const VertexIndex vert_b_prev =
  744|  44.9k|          corner_table_->Vertex(corner_table_->Previous(corner_b));
  745|  44.9k|      corner_table_->MapCornerToVertex(corner + 2, vert_b_prev);
  746|  44.9k|      corner_table_->SetLeftMostCorner(vert_b_prev, corner + 2);
  747|  44.9k|      CornerIndex corner_n = corner_table_->Next(corner_b);
  748|  44.9k|      const VertexIndex vertex_n = corner_table_->Vertex(corner_n);
  749|  44.9k|      traversal_decoder_.MergeVertices(vertex_p, vertex_n);
  750|       |      // Update the left most corner on the newly merged vertex.
  751|  44.9k|      corner_table_->SetLeftMostCorner(vertex_p,
  752|  44.9k|                                       corner_table_->LeftMostCorner(vertex_n));
  753|       |
  754|       |      // Also update the vertex id at corner "n" and all corners that are
  755|       |      // connected to it in the CCW direction.
  756|  44.9k|      const CornerIndex first_corner = corner_n;
  757|  10.3M|      while (corner_n != kInvalidCornerIndex) {
  ------------------
  |  Branch (757:14): [True: 10.2M, False: 44.9k]
  ------------------
  758|  10.2M|        corner_table_->MapCornerToVertex(corner_n, vertex_p);
  759|  10.2M|        corner_n = corner_table_->SwingLeft(corner_n);
  760|  10.2M|        if (corner_n == first_corner) {
  ------------------
  |  Branch (760:13): [True: 1, False: 10.2M]
  ------------------
  761|       |          // We reached the start again which should not happen for split
  762|       |          // symbols.
  763|      1|          return -1;
  764|      1|        }
  765|  10.2M|      }
  766|       |      // Make sure the old vertex n is now mapped to an invalid corner (make it
  767|       |      // isolated).
  768|  44.9k|      corner_table_->MakeVertexIsolated(vertex_n);
  769|  44.9k|      if (remove_invalid_vertices) {
  ------------------
  |  Branch (769:11): [True: 44.8k, False: 95]
  ------------------
  770|  44.8k|        invalid_vertices.push_back(vertex_n);
  771|  44.8k|      }
  772|  44.9k|      active_corner_stack.back() = corner;
  773|  5.93M|    } else if (symbol == TOPOLOGY_E) {
  ------------------
  |  Branch (773:16): [True: 5.93M, False: 255]
  ------------------
  774|  5.93M|      const CornerIndex corner(3 * face.value());
  775|  5.93M|      const VertexIndex first_vert_index = corner_table_->AddNewVertex();
  776|       |      // Create three new vertices at the corners of the new face.
  777|  5.93M|      corner_table_->MapCornerToVertex(corner, first_vert_index);
  778|  5.93M|      corner_table_->MapCornerToVertex(corner + 1,
  779|  5.93M|                                       corner_table_->AddNewVertex());
  780|  5.93M|      corner_table_->MapCornerToVertex(corner + 2,
  781|  5.93M|                                       corner_table_->AddNewVertex());
  782|       |
  783|  5.93M|      if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (783:11): [True: 8, False: 5.93M]
  ------------------
  784|      8|        return -1;  // Unexpected number of decoded vertices.
  785|      8|      }
  786|       |
  787|  5.93M|      corner_table_->SetLeftMostCorner(first_vert_index, corner);
  788|  5.93M|      corner_table_->SetLeftMostCorner(first_vert_index + 1, corner + 1);
  789|  5.93M|      corner_table_->SetLeftMostCorner(first_vert_index + 2, corner + 2);
  790|       |      // Add the tip corner to the active stack.
  791|  5.93M|      active_corner_stack.push_back(corner);
  792|  5.93M|      check_topology_split = true;
  793|  5.93M|    } else {
  794|       |      // Error. Unknown symbol decoded.
  795|    255|      return -1;
  796|    255|    }
  797|       |    // Inform the traversal decoder that a new corner has been reached.
  798|  60.0M|    traversal_decoder_.NewActiveCornerReached(active_corner_stack.back());
  799|       |
  800|  60.0M|    if (check_topology_split) {
  ------------------
  |  Branch (800:9): [True: 53.8M, False: 6.11M]
  ------------------
  801|       |      // Check for topology splits happens only for TOPOLOGY_L, TOPOLOGY_R and
  802|       |      // TOPOLOGY_E symbols because those are the symbols that correspond to
  803|       |      // faces that can be directly connected a TOPOLOGY_S face through the
  804|       |      // topology split event.
  805|       |      // If a topology split is detected, we need to add a new active edge
  806|       |      // onto the active_corner_stack because it will be used later when the
  807|       |      // corresponding TOPOLOGY_S event is decoded.
  808|       |
  809|       |      // Symbol id used by the encoder (reverse).
  810|  53.8M|      const int encoder_symbol_id = num_symbols - symbol_id - 1;
  811|  53.8M|      EdgeFaceName split_edge;
  812|  53.8M|      int encoder_split_symbol_id;
  813|  53.8M|      while (IsTopologySplit(encoder_symbol_id, &split_edge,
  ------------------
  |  Branch (813:14): [True: 1.25k, False: 53.8M]
  ------------------
  814|  53.8M|                             &encoder_split_symbol_id)) {
  815|  1.25k|        if (encoder_split_symbol_id < 0) {
  ------------------
  |  Branch (815:13): [True: 39, False: 1.21k]
  ------------------
  816|     39|          return -1;  // Wrong split symbol id.
  817|     39|        }
  818|       |        // Symbol was part of a topology split. Now we need to determine which
  819|       |        // edge should be added to the active edges stack.
  820|  1.21k|        const CornerIndex act_top_corner = active_corner_stack.back();
  821|       |        // The current symbol has one active edge (stored in act_top_corner) and
  822|       |        // two remaining inactive edges that are attached to it.
  823|       |        //              *
  824|       |        //             / \
  825|       |        //  left_edge /   \ right_edge
  826|       |        //           /     \
  827|       |        //          *.......*
  828|       |        //         active_edge
  829|       |
  830|  1.21k|        CornerIndex new_active_corner;
  831|  1.21k|        if (split_edge == RIGHT_FACE_EDGE) {
  ------------------
  |  Branch (831:13): [True: 410, False: 802]
  ------------------
  832|    410|          new_active_corner = corner_table_->Next(act_top_corner);
  833|    802|        } else {
  834|    802|          new_active_corner = corner_table_->Previous(act_top_corner);
  835|    802|        }
  836|       |        // Add the new active edge.
  837|       |        // Convert the encoder split symbol id to decoder symbol id.
  838|  1.21k|        const int decoder_split_symbol_id =
  839|  1.21k|            num_symbols - encoder_split_symbol_id - 1;
  840|  1.21k|        topology_split_active_corners[decoder_split_symbol_id] =
  841|  1.21k|            new_active_corner;
  842|  1.21k|      }
  843|  53.8M|    }
  844|  60.0M|  }
  845|    359|  if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (845:7): [True: 0, False: 359]
  ------------------
  846|      0|    return -1;  // Unexpected number of decoded vertices.
  847|      0|  }
  848|       |  // Decode start faces and connect them to the faces from the active stack.
  849|  4.29M|  while (!active_corner_stack.empty()) {
  ------------------
  |  Branch (849:10): [True: 4.29M, False: 318]
  ------------------
  850|  4.29M|    const CornerIndex corner = active_corner_stack.back();
  851|  4.29M|    active_corner_stack.pop_back();
  852|  4.29M|    const bool interior_face =
  853|  4.29M|        traversal_decoder_.DecodeStartFaceConfiguration();
  854|  4.29M|    if (interior_face) {
  ------------------
  |  Branch (854:9): [True: 4.26M, False: 26.5k]
  ------------------
  855|       |      // The start face is interior, we need to find three corners that are
  856|       |      // opposite to it. The first opposite corner "a" is the corner from the
  857|       |      // top of the active corner stack and the remaining two corners "b" and
  858|       |      // "c" are then the next corners from the left-most corners of vertices
  859|       |      // "n" and "x" respectively.
  860|       |      //
  861|       |      //           *-------*
  862|       |      //          / \     / \
  863|       |      //         /   \   /   \
  864|       |      //        /     \ /     \
  865|       |      //       *-------p-------*
  866|       |      //      / \a    . .    c/ \
  867|       |      //     /   \   .   .   /   \
  868|       |      //    /     \ .  I  . /     \
  869|       |      //   *-------n.......x------*
  870|       |      //    \     / \     / \     /
  871|       |      //     \   /   \   /   \   /
  872|       |      //      \ /     \b/     \ /
  873|       |      //       *-------*-------*
  874|       |      //
  875|       |
  876|  4.26M|      if (num_faces >= corner_table_->num_faces()) {
  ------------------
  |  Branch (876:11): [True: 35, False: 4.26M]
  ------------------
  877|     35|        return -1;  // More faces than expected added to the mesh.
  878|     35|      }
  879|       |
  880|  4.26M|      const CornerIndex corner_a = corner;
  881|  4.26M|      const VertexIndex vert_n =
  882|  4.26M|          corner_table_->Vertex(corner_table_->Next(corner_a));
  883|  4.26M|      const CornerIndex corner_b =
  884|  4.26M|          corner_table_->Next(corner_table_->LeftMostCorner(vert_n));
  885|       |
  886|  4.26M|      const VertexIndex vert_x =
  887|  4.26M|          corner_table_->Vertex(corner_table_->Next(corner_b));
  888|  4.26M|      const CornerIndex corner_c =
  889|  4.26M|          corner_table_->Next(corner_table_->LeftMostCorner(vert_x));
  890|       |
  891|  4.26M|      if (corner == corner_b || corner == corner_c || corner_b == corner_c) {
  ------------------
  |  Branch (891:11): [True: 4, False: 4.26M]
  |  Branch (891:33): [True: 2, False: 4.26M]
  |  Branch (891:55): [True: 0, False: 4.26M]
  ------------------
  892|       |        // All matched corners must be different.
  893|      6|        return -1;
  894|      6|      }
  895|  4.26M|      if (corner_table_->Opposite(corner) != kInvalidCornerIndex ||
  ------------------
  |  Branch (895:11): [True: 0, False: 4.26M]
  |  Branch (895:11): [True: 0, False: 4.26M]
  ------------------
  896|  4.26M|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex ||
  ------------------
  |  Branch (896:11): [True: 0, False: 4.26M]
  ------------------
  897|  4.26M|          corner_table_->Opposite(corner_c) != kInvalidCornerIndex) {
  ------------------
  |  Branch (897:11): [True: 0, False: 4.26M]
  ------------------
  898|       |        // One of the corners is already opposite to an existing face, which
  899|       |        // should not happen unless the input was tampered with.
  900|      0|        return -1;
  901|      0|      }
  902|       |
  903|  4.26M|      const VertexIndex vert_p =
  904|  4.26M|          corner_table_->Vertex(corner_table_->Next(corner_c));
  905|       |
  906|  4.26M|      const FaceIndex face(num_faces++);
  907|       |      // The first corner of the initial face is the corner opposite to "a".
  908|  4.26M|      const CornerIndex new_corner(3 * face.value());
  909|  4.26M|      SetOppositeCorners(new_corner, corner);
  910|  4.26M|      SetOppositeCorners(new_corner + 1, corner_b);
  911|  4.26M|      SetOppositeCorners(new_corner + 2, corner_c);
  912|       |
  913|       |      // Map new corners to existing vertices.
  914|  4.26M|      corner_table_->MapCornerToVertex(new_corner, vert_x);
  915|  4.26M|      corner_table_->MapCornerToVertex(new_corner + 1, vert_p);
  916|  4.26M|      corner_table_->MapCornerToVertex(new_corner + 2, vert_n);
  917|       |
  918|       |      // Mark all three vertices as interior.
  919|  17.0M|      for (int ci = 0; ci < 3; ++ci) {
  ------------------
  |  Branch (919:24): [True: 12.7M, False: 4.26M]
  ------------------
  920|  12.7M|        is_vert_hole_[corner_table_->Vertex(new_corner + ci).value()] = false;
  921|  12.7M|      }
  922|       |
  923|  4.26M|      init_face_configurations_.push_back(true);
  924|  4.26M|      init_corners_.push_back(new_corner);
  925|  4.26M|    } else {
  926|       |      // The initial face wasn't interior and the traversal had to start from
  927|       |      // an open boundary. In this case no new face is added, but we need to
  928|       |      // keep record about the first opposite corner to this boundary.
  929|  26.5k|      init_face_configurations_.push_back(false);
  930|  26.5k|      init_corners_.push_back(corner);
  931|  26.5k|    }
  932|  4.29M|  }
  933|    318|  if (num_faces != corner_table_->num_faces()) {
  ------------------
  |  Branch (933:7): [True: 78, False: 240]
  ------------------
  934|     78|    return -1;  // Unexpected number of decoded faces.
  935|     78|  }
  936|       |
  937|    240|  int num_vertices = corner_table_->num_vertices();
  938|       |  // If any vertex was marked as isolated, we want to remove it from the corner
  939|       |  // table to ensure that all vertices in range <0, num_vertices> are valid.
  940|  2.86k|  for (const VertexIndex invalid_vert : invalid_vertices) {
  ------------------
  |  Branch (940:39): [True: 2.86k, False: 237]
  ------------------
  941|       |    // Find the last valid vertex and swap it with the isolated vertex.
  942|  2.86k|    VertexIndex src_vert(num_vertices - 1);
  943|  3.57k|    while (corner_table_->LeftMostCorner(src_vert) == kInvalidCornerIndex) {
  ------------------
  |  Branch (943:12): [True: 709, False: 2.86k]
  ------------------
  944|       |      // The last vertex is invalid, proceed to the previous one.
  945|    709|      src_vert = VertexIndex(--num_vertices - 1);
  946|    709|    }
  947|  2.86k|    if (src_vert < invalid_vert) {
  ------------------
  |  Branch (947:9): [True: 592, False: 2.27k]
  ------------------
  948|    592|      continue;  // No need to swap anything.
  949|    592|    }
  950|       |
  951|       |    // Remap all corners mapped to |src_vert| to |invalid_vert|.
  952|  2.27k|    VertexCornersIterator<CornerTable> vcit(corner_table_.get(), src_vert);
  953|  9.13k|    for (; !vcit.End(); ++vcit) {
  ------------------
  |  Branch (953:12): [True: 6.86k, False: 2.27k]
  ------------------
  954|  6.86k|      const CornerIndex cid = vcit.Corner();
  955|  6.86k|      if (corner_table_->Vertex(cid) != src_vert) {
  ------------------
  |  Branch (955:11): [True: 3, False: 6.86k]
  ------------------
  956|       |        // Vertex mapped to |cid| was not |src_vert|. This indicates corrupted
  957|       |        // data and we should terminate the decoding.
  958|      3|        return -1;
  959|      3|      }
  960|  6.86k|      corner_table_->MapCornerToVertex(cid, invalid_vert);
  961|  6.86k|    }
  962|  2.27k|    corner_table_->SetLeftMostCorner(invalid_vert,
  963|  2.27k|                                     corner_table_->LeftMostCorner(src_vert));
  964|       |
  965|       |    // Make the |src_vert| invalid.
  966|  2.27k|    corner_table_->MakeVertexIsolated(src_vert);
  967|  2.27k|    is_vert_hole_[invalid_vert.value()] = is_vert_hole_[src_vert.value()];
  968|  2.27k|    is_vert_hole_[src_vert.value()] = false;
  969|       |
  970|       |    // The last vertex is now invalid.
  971|  2.27k|    num_vertices--;
  972|  2.27k|  }
  973|    237|  return num_vertices;
  974|    240|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE32DecodeHoleAndTopologySplitEventsEPNS_13DecoderBufferE:
  979|  2.74k|    DecoderBuffer* decoder_buffer) {
  980|       |  // Prepare a new decoder from the provided buffer offset.
  981|  2.74k|  uint32_t num_topology_splits;
  982|  2.74k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  983|  2.74k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  2.74k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (983:7): [True: 188, False: 2.55k]
  ------------------
  984|    188|    if (!decoder_buffer->Decode(&num_topology_splits)) {
  ------------------
  |  Branch (984:9): [True: 1, False: 187]
  ------------------
  985|      1|      return -1;
  986|      1|    }
  987|       |
  988|    188|  } else
  989|  2.55k|#endif
  990|  2.55k|  {
  991|  2.55k|    if (!DecodeVarint(&num_topology_splits, decoder_buffer)) {
  ------------------
  |  Branch (991:9): [True: 20, False: 2.53k]
  ------------------
  992|     20|      return -1;
  993|     20|    }
  994|  2.55k|  }
  995|  2.71k|  if (num_topology_splits > 0) {
  ------------------
  |  Branch (995:7): [True: 486, False: 2.23k]
  ------------------
  996|    486|    if (num_topology_splits >
  ------------------
  |  Branch (996:9): [True: 53, False: 433]
  ------------------
  997|    486|        static_cast<uint32_t>(corner_table_->num_faces())) {
  998|     53|      return -1;
  999|     53|    }
 1000|    433|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1001|    433|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|    433|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1001:9): [True: 64, False: 369]
  ------------------
 1002|   104k|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1002:28): [True: 104k, False: 32]
  ------------------
 1003|   104k|        TopologySplitEventData event_data;
 1004|   104k|        if (!decoder_buffer->Decode(&event_data.split_symbol_id)) {
  ------------------
  |  Branch (1004:13): [True: 23, False: 104k]
  ------------------
 1005|     23|          return -1;
 1006|     23|        }
 1007|   104k|        if (!decoder_buffer->Decode(&event_data.source_symbol_id)) {
  ------------------
  |  Branch (1007:13): [True: 7, False: 104k]
  ------------------
 1008|      7|          return -1;
 1009|      7|        }
 1010|   104k|        uint8_t edge_data;
 1011|   104k|        if (!decoder_buffer->Decode(&edge_data)) {
  ------------------
  |  Branch (1011:13): [True: 2, False: 104k]
  ------------------
 1012|      2|          return -1;
 1013|      2|        }
 1014|   104k|        event_data.source_edge = edge_data & 1;
 1015|   104k|        topology_split_data_.push_back(event_data);
 1016|   104k|      }
 1017|       |
 1018|     64|    } else
 1019|    369|#endif
 1020|    369|    {
 1021|       |      // Decode source and split symbol ids using delta and varint coding. See
 1022|       |      // description in mesh_edgebreaker_encoder_impl.cc for more details.
 1023|    369|      int last_source_symbol_id = 0;
 1024|  3.73k|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1024:28): [True: 3.40k, False: 327]
  ------------------
 1025|  3.40k|        TopologySplitEventData event_data;
 1026|  3.40k|        uint32_t delta;
 1027|  3.40k|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1027:13): [True: 20, False: 3.38k]
  ------------------
 1028|     20|          return -1;
 1029|     20|        }
 1030|  3.38k|        event_data.source_symbol_id = delta + last_source_symbol_id;
 1031|  3.38k|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1031:13): [True: 9, False: 3.37k]
  ------------------
 1032|      9|          return -1;
 1033|      9|        }
 1034|  3.37k|        if (delta > event_data.source_symbol_id) {
  ------------------
  |  Branch (1034:13): [True: 13, False: 3.36k]
  ------------------
 1035|     13|          return -1;
 1036|     13|        }
 1037|  3.36k|        event_data.split_symbol_id =
 1038|  3.36k|            event_data.source_symbol_id - static_cast<int32_t>(delta);
 1039|  3.36k|        last_source_symbol_id = event_data.source_symbol_id;
 1040|  3.36k|        topology_split_data_.push_back(event_data);
 1041|  3.36k|      }
 1042|       |      // Split edges are decoded from a direct bit decoder.
 1043|    327|      decoder_buffer->StartBitDecoding(false, nullptr);
 1044|  3.05k|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1044:28): [True: 2.72k, False: 327]
  ------------------
 1045|  2.72k|        uint32_t edge_data;
 1046|  2.72k|        if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  2.72k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1046:13): [True: 192, False: 2.53k]
  ------------------
 1047|    192|          decoder_buffer->DecodeLeastSignificantBits32(2, &edge_data);
 1048|  2.53k|        } else {
 1049|  2.53k|          decoder_buffer->DecodeLeastSignificantBits32(1, &edge_data);
 1050|  2.53k|        }
 1051|  2.72k|        TopologySplitEventData& event_data = topology_split_data_[i];
 1052|  2.72k|        event_data.source_edge = edge_data & 1;
 1053|  2.72k|      }
 1054|    327|      decoder_buffer->EndBitDecoding();
 1055|    327|    }
 1056|    433|  }
 1057|  2.59k|  uint32_t num_hole_events = 0;
 1058|  2.59k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1059|  2.59k|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  2.59k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1059:7): [True: 146, False: 2.44k]
  ------------------
 1060|    146|    if (!decoder_buffer->Decode(&num_hole_events)) {
  ------------------
  |  Branch (1060:9): [True: 3, False: 143]
  ------------------
 1061|      3|      return -1;
 1062|      3|    }
 1063|  2.44k|  } else if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
  ------------------
  |  |  115|  2.44k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1063:14): [True: 222, False: 2.22k]
  ------------------
 1064|    222|    if (!DecodeVarint(&num_hole_events, decoder_buffer)) {
  ------------------
  |  Branch (1064:9): [True: 12, False: 210]
  ------------------
 1065|     12|      return -1;
 1066|     12|    }
 1067|    222|  }
 1068|  2.57k|#endif
 1069|  2.57k|  if (num_hole_events > 0) {
  ------------------
  |  Branch (1069:7): [True: 96, False: 2.48k]
  ------------------
 1070|     96|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1071|     96|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|     96|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1071:9): [True: 57, False: 39]
  ------------------
 1072|  1.43M|      for (uint32_t i = 0; i < num_hole_events; ++i) {
  ------------------
  |  Branch (1072:28): [True: 1.43M, False: 5]
  ------------------
 1073|  1.43M|        HoleEventData event_data;
 1074|  1.43M|        if (!decoder_buffer->Decode(&event_data)) {
  ------------------
  |  Branch (1074:13): [True: 52, False: 1.43M]
  ------------------
 1075|     52|          return -1;
 1076|     52|        }
 1077|  1.43M|        hole_event_data_.push_back(event_data);
 1078|  1.43M|      }
 1079|       |
 1080|     57|    } else
 1081|     39|#endif
 1082|     39|    {
 1083|       |      // Decode hole symbol ids using delta and varint coding.
 1084|     39|      int last_symbol_id = 0;
 1085|    726|      for (uint32_t i = 0; i < num_hole_events; ++i) {
  ------------------
  |  Branch (1085:28): [True: 704, False: 22]
  ------------------
 1086|    704|        HoleEventData event_data;
 1087|    704|        uint32_t delta;
 1088|    704|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1088:13): [True: 17, False: 687]
  ------------------
 1089|     17|          return -1;
 1090|     17|        }
 1091|    687|        event_data.symbol_id = delta + last_symbol_id;
 1092|    687|        last_symbol_id = event_data.symbol_id;
 1093|    687|        hole_event_data_.push_back(event_data);
 1094|    687|      }
 1095|     39|    }
 1096|     96|  }
 1097|  2.50k|  return static_cast<int32_t>(decoder_buffer->decoded_size());
 1098|  2.57k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE41DecodeAttributeConnectivitiesOnFaceLegacyENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
 1103|     12|    DecodeAttributeConnectivitiesOnFaceLegacy(CornerIndex corner) {
 1104|       |  // Three corners of the face.
 1105|     12|  const CornerIndex corners[3] = {corner, corner_table_->Next(corner),
 1106|     12|                                  corner_table_->Previous(corner)};
 1107|       |
 1108|     48|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1108:19): [True: 36, False: 12]
  ------------------
 1109|     36|    const CornerIndex opp_corner = corner_table_->Opposite(corners[c]);
 1110|     36|    if (opp_corner == kInvalidCornerIndex) {
  ------------------
  |  Branch (1110:9): [True: 12, False: 24]
  ------------------
 1111|       |      // Don't decode attribute seams on boundary edges (every boundary edge
 1112|       |      // is automatically an attribute seam).
 1113|     24|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1113:28): [True: 12, False: 12]
  ------------------
 1114|     12|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1115|     12|      }
 1116|     12|      continue;
 1117|     12|    }
 1118|       |
 1119|     48|    for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1119:26): [True: 24, False: 24]
  ------------------
 1120|     24|      const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i);
 1121|     24|      if (is_seam) {
  ------------------
  |  Branch (1121:11): [True: 11, False: 13]
  ------------------
 1122|     11|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1123|     11|      }
 1124|     24|    }
 1125|     24|  }
 1126|     12|  return true;
 1127|     12|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE35DecodeAttributeConnectivitiesOnFaceENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
 1132|   341k|    TraversalDecoder>::DecodeAttributeConnectivitiesOnFace(CornerIndex corner) {
 1133|       |  // Three corners of the face.
 1134|   341k|  const CornerIndex corners[3] = {corner, corner_table_->Next(corner),
 1135|   341k|                                  corner_table_->Previous(corner)};
 1136|       |
 1137|   341k|  const FaceIndex src_face_id = corner_table_->Face(corner);
 1138|  1.36M|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1138:19): [True: 1.02M, False: 341k]
  ------------------
 1139|  1.02M|    const CornerIndex opp_corner = corner_table_->Opposite(corners[c]);
 1140|  1.02M|    if (opp_corner == kInvalidCornerIndex) {
  ------------------
  |  Branch (1140:9): [True: 199k, False: 825k]
  ------------------
 1141|       |      // Don't decode attribute seams on boundary edges (every boundary edge
 1142|       |      // is automatically an attribute seam).
 1143|   400k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1143:28): [True: 200k, False: 199k]
  ------------------
 1144|   200k|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1145|   200k|      }
 1146|   199k|      continue;
 1147|   199k|    }
 1148|   825k|    const FaceIndex opp_face_id = corner_table_->Face(opp_corner);
 1149|       |    // Don't decode edges when the opposite face has been already processed.
 1150|   825k|    if (opp_face_id < src_face_id) {
  ------------------
  |  Branch (1150:9): [True: 412k, False: 412k]
  ------------------
 1151|   412k|      continue;
 1152|   412k|    }
 1153|       |
 1154|   825k|    for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1154:26): [True: 413k, False: 412k]
  ------------------
 1155|   413k|      const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i);
 1156|   413k|      if (is_seam) {
  ------------------
  |  Branch (1156:11): [True: 186k, False: 226k]
  ------------------
 1157|   186k|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1158|   186k|      }
 1159|   413k|    }
 1160|   412k|  }
 1161|   341k|  return true;
 1162|   341k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE21AssignPointsToCornersEi:
 1166|    237|    int num_connectivity_verts) {
 1167|       |  // Map between the existing and deduplicated point ids.
 1168|       |  // Note that at this point we have one point id for each corner of the
 1169|       |  // mesh so there is corner_table_->num_corners() point ids.
 1170|    237|  decoder_->mesh()->SetNumFaces(corner_table_->num_faces());
 1171|       |
 1172|    237|  if (attribute_data_.empty()) {
  ------------------
  |  Branch (1172:7): [True: 37, False: 200]
  ------------------
 1173|       |    // We have connectivity for position only. In this case all vertex indices
 1174|       |    // are equal to point indices.
 1175|  94.4k|    for (FaceIndex f(0); f < decoder_->mesh()->num_faces(); ++f) {
  ------------------
  |  Branch (1175:26): [True: 94.3k, False: 37]
  ------------------
 1176|  94.3k|      Mesh::Face face;
 1177|  94.3k|      const CornerIndex start_corner(3 * f.value());
 1178|   377k|      for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1178:23): [True: 283k, False: 94.3k]
  ------------------
 1179|       |        // Get the vertex index on the corner and use it as a point index.
 1180|   283k|        const int32_t vert_id = corner_table_->Vertex(start_corner + c).value();
 1181|   283k|        face[c] = vert_id;
 1182|   283k|      }
 1183|  94.3k|      decoder_->mesh()->SetFace(f, face);
 1184|  94.3k|    }
 1185|     37|    decoder_->point_cloud()->set_num_points(num_connectivity_verts);
 1186|     37|    return true;
 1187|     37|  }
 1188|       |  // Else we need to deduplicate multiple attributes.
 1189|       |
 1190|       |  // Map between point id and an associated corner id. Only one corner for
 1191|       |  // each point is stored. The corners are used to sample the attribute values
 1192|       |  // in the last stage of the deduplication.
 1193|    200|  std::vector<int32_t> point_to_corner_map;
 1194|       |  // Map between every corner and their new point ids.
 1195|    200|  std::vector<int32_t> corner_to_point_map(corner_table_->num_corners());
 1196|   255k|  for (int v = 0; v < corner_table_->num_vertices(); ++v) {
  ------------------
  |  Branch (1196:19): [True: 255k, False: 179]
  ------------------
 1197|   255k|    CornerIndex c = corner_table_->LeftMostCorner(VertexIndex(v));
 1198|   255k|    if (c == kInvalidCornerIndex) {
  ------------------
  |  Branch (1198:9): [True: 79, False: 255k]
  ------------------
 1199|     79|      continue;  // Isolated vertex.
 1200|     79|    }
 1201|   255k|    CornerIndex deduplication_first_corner = c;
 1202|   255k|    if (is_vert_hole_[v]) {
  ------------------
  |  Branch (1202:9): [True: 198k, False: 56.9k]
  ------------------
 1203|       |      // If the vertex is on a boundary, start deduplication from the left most
 1204|       |      // corner that is guaranteed to lie on the boundary.
 1205|   198k|      deduplication_first_corner = c;
 1206|   198k|    } else {
 1207|       |      // If we are not on the boundary we need to find the first seam (of any
 1208|       |      // attribute).
 1209|  66.4k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1209:28): [True: 57.0k, False: 9.43k]
  ------------------
 1210|  57.0k|        if (!attribute_data_[i].connectivity_data.IsCornerOnSeam(c)) {
  ------------------
  |  Branch (1210:13): [True: 9.21k, False: 47.8k]
  ------------------
 1211|  9.21k|          continue;  // No seam for this attribute, ignore it.
 1212|  9.21k|        }
 1213|       |        // Else there needs to be at least one seam edge.
 1214|       |
 1215|       |        // At this point, we use identity mapping between corners and point ids.
 1216|  47.8k|        const VertexIndex vert_id =
 1217|  47.8k|            attribute_data_[i].connectivity_data.Vertex(c);
 1218|  47.8k|        CornerIndex act_c = corner_table_->SwingRight(c);
 1219|  47.8k|        bool seam_found = false;
 1220|  55.7k|        while (act_c != c) {
  ------------------
  |  Branch (1220:16): [True: 55.4k, False: 289]
  ------------------
 1221|  55.4k|          if (act_c == kInvalidCornerIndex) {
  ------------------
  |  Branch (1221:15): [True: 21, False: 55.4k]
  ------------------
 1222|     21|            return false;
 1223|     21|          }
 1224|  55.4k|          if (attribute_data_[i].connectivity_data.Vertex(act_c) != vert_id) {
  ------------------
  |  Branch (1224:15): [True: 47.5k, False: 7.92k]
  ------------------
 1225|       |            // Attribute seam found. Stop.
 1226|  47.5k|            deduplication_first_corner = act_c;
 1227|  47.5k|            seam_found = true;
 1228|  47.5k|            break;
 1229|  47.5k|          }
 1230|  7.92k|          act_c = corner_table_->SwingRight(act_c);
 1231|  7.92k|        }
 1232|  47.8k|        if (seam_found) {
  ------------------
  |  Branch (1232:13): [True: 47.5k, False: 289]
  ------------------
 1233|  47.5k|          break;  // No reason to process other attributes if we found a seam.
 1234|  47.5k|        }
 1235|  47.8k|      }
 1236|  56.9k|    }
 1237|       |
 1238|       |    // Do a deduplication pass over the corners on the processed vertex.
 1239|       |    // At this point each corner corresponds to one point id and our goal is to
 1240|       |    // merge similar points into a single point id.
 1241|       |    // We do a single pass in a clockwise direction over the corners and we add
 1242|       |    // a new point id whenever one of the attributes change.
 1243|   255k|    c = deduplication_first_corner;
 1244|       |    // Create a new point.
 1245|   255k|    corner_to_point_map[c.value()] =
 1246|   255k|        static_cast<uint32_t>(point_to_corner_map.size());
 1247|   255k|    point_to_corner_map.push_back(c.value());
 1248|       |    // Traverse in CW direction.
 1249|   255k|    CornerIndex prev_c = c;
 1250|   255k|    c = corner_table_->SwingRight(c);
 1251|   900k|    while (c != kInvalidCornerIndex && c != deduplication_first_corner) {
  ------------------
  |  Branch (1251:12): [True: 702k, False: 198k]
  |  Branch (1251:40): [True: 645k, False: 56.6k]
  ------------------
 1252|   645k|      bool attribute_seam = false;
 1253|  1.20M|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1253:28): [True: 645k, False: 559k]
  ------------------
 1254|   645k|        if (attribute_data_[i].connectivity_data.Vertex(c) !=
  ------------------
  |  Branch (1254:13): [True: 86.5k, False: 559k]
  ------------------
 1255|   645k|            attribute_data_[i].connectivity_data.Vertex(prev_c)) {
 1256|       |          // Attribute index changed from the previous corner. We need to add a
 1257|       |          // new point here.
 1258|  86.5k|          attribute_seam = true;
 1259|  86.5k|          break;
 1260|  86.5k|        }
 1261|   645k|      }
 1262|   645k|      if (attribute_seam) {
  ------------------
  |  Branch (1262:11): [True: 86.5k, False: 559k]
  ------------------
 1263|  86.5k|        corner_to_point_map[c.value()] =
 1264|  86.5k|            static_cast<uint32_t>(point_to_corner_map.size());
 1265|  86.5k|        point_to_corner_map.push_back(c.value());
 1266|   559k|      } else {
 1267|   559k|        corner_to_point_map[c.value()] = corner_to_point_map[prev_c.value()];
 1268|   559k|      }
 1269|   645k|      prev_c = c;
 1270|   645k|      c = corner_table_->SwingRight(c);
 1271|   645k|    }
 1272|   255k|  }
 1273|       |  // Add faces.
 1274|  79.1k|  for (FaceIndex f(0); f < decoder_->mesh()->num_faces(); ++f) {
  ------------------
  |  Branch (1274:24): [True: 78.9k, False: 179]
  ------------------
 1275|  78.9k|    Mesh::Face face;
 1276|   315k|    for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1276:21): [True: 236k, False: 78.9k]
  ------------------
 1277|       |      // Remap old points to the new ones.
 1278|   236k|      face[c] = corner_to_point_map[3 * f.value() + c];
 1279|   236k|    }
 1280|  78.9k|    decoder_->mesh()->SetFace(f, face);
 1281|  78.9k|  }
 1282|    179|  decoder_->point_cloud()->set_num_points(
 1283|    179|      static_cast<uint32_t>(point_to_corner_map.size()));
 1284|    179|  return true;
 1285|    200|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE30CreateVertexTraversalSequencerINS_28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS5_EEEEEENSt3__110unique_ptrINS_15PointsSequencerENS9_14default_deleteISB_EEEEPNS_32MeshAttributeIndicesEncodingDataE:
  110|    195|    MeshAttributeIndicesEncodingData* encoding_data) {
  111|    195|  typedef typename TraverserT::TraversalObserver AttObserver;
  112|    195|  typedef typename TraverserT::CornerTable CornerTable;
  113|       |
  114|    195|  const Mesh* mesh = decoder_->mesh();
  115|    195|  std::unique_ptr<MeshTraversalSequencer<TraverserT>> traversal_sequencer(
  116|    195|      new MeshTraversalSequencer<TraverserT>(mesh, encoding_data));
  117|       |
  118|    195|  AttObserver att_observer(corner_table_.get(), mesh, traversal_sequencer.get(),
  119|    195|                           encoding_data);
  120|       |
  121|    195|  TraverserT att_traverser;
  122|    195|  att_traverser.Init(corner_table_.get(), att_observer);
  123|       |
  124|    195|  traversal_sequencer->SetTraverser(att_traverser);
  125|    195|  return std::move(traversal_sequencer);
  126|    195|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE30CreateVertexTraversalSequencerINS_19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS5_EEEEEENSt3__110unique_ptrINS_15PointsSequencerENS9_14default_deleteISB_EEEEPNS_32MeshAttributeIndicesEncodingDataE:
  110|  1.00k|    MeshAttributeIndicesEncodingData* encoding_data) {
  111|  1.00k|  typedef typename TraverserT::TraversalObserver AttObserver;
  112|  1.00k|  typedef typename TraverserT::CornerTable CornerTable;
  113|       |
  114|  1.00k|  const Mesh* mesh = decoder_->mesh();
  115|  1.00k|  std::unique_ptr<MeshTraversalSequencer<TraverserT>> traversal_sequencer(
  116|  1.00k|      new MeshTraversalSequencer<TraverserT>(mesh, encoding_data));
  117|       |
  118|  1.00k|  AttObserver att_observer(corner_table_.get(), mesh, traversal_sequencer.get(),
  119|  1.00k|                           encoding_data);
  120|       |
  121|  1.00k|  TraverserT att_traverser;
  122|  1.00k|  att_traverser.Init(corner_table_.get(), att_observer);
  123|       |
  124|  1.00k|  traversal_sequencer->SetTraverser(att_traverser);
  125|  1.00k|  return std::move(traversal_sequencer);
  126|  1.00k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE30CreateVertexTraversalSequencerINS_28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS5_EEEEEENSt3__110unique_ptrINS_15PointsSequencerENS9_14default_deleteISB_EEEEPNS_32MeshAttributeIndicesEncodingDataE:
  110|    236|    MeshAttributeIndicesEncodingData* encoding_data) {
  111|    236|  typedef typename TraverserT::TraversalObserver AttObserver;
  112|    236|  typedef typename TraverserT::CornerTable CornerTable;
  113|       |
  114|    236|  const Mesh* mesh = decoder_->mesh();
  115|    236|  std::unique_ptr<MeshTraversalSequencer<TraverserT>> traversal_sequencer(
  116|    236|      new MeshTraversalSequencer<TraverserT>(mesh, encoding_data));
  117|       |
  118|    236|  AttObserver att_observer(corner_table_.get(), mesh, traversal_sequencer.get(),
  119|    236|                           encoding_data);
  120|       |
  121|    236|  TraverserT att_traverser;
  122|    236|  att_traverser.Init(corner_table_.get(), att_observer);
  123|       |
  124|    236|  traversal_sequencer->SetTraverser(att_traverser);
  125|    236|  return std::move(traversal_sequencer);
  126|    236|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE30CreateVertexTraversalSequencerINS_19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS5_EEEEEENSt3__110unique_ptrINS_15PointsSequencerENS9_14default_deleteISB_EEEEPNS_32MeshAttributeIndicesEncodingDataE:
  110|    737|    MeshAttributeIndicesEncodingData* encoding_data) {
  111|    737|  typedef typename TraverserT::TraversalObserver AttObserver;
  112|    737|  typedef typename TraverserT::CornerTable CornerTable;
  113|       |
  114|    737|  const Mesh* mesh = decoder_->mesh();
  115|    737|  std::unique_ptr<MeshTraversalSequencer<TraverserT>> traversal_sequencer(
  116|    737|      new MeshTraversalSequencer<TraverserT>(mesh, encoding_data));
  117|       |
  118|    737|  AttObserver att_observer(corner_table_.get(), mesh, traversal_sequencer.get(),
  119|    737|                           encoding_data);
  120|       |
  121|    737|  TraverserT att_traverser;
  122|    737|  att_traverser.Init(corner_table_.get(), att_observer);
  123|       |
  124|    737|  traversal_sequencer->SetTraverser(att_traverser);
  125|    737|  return std::move(traversal_sequencer);
  126|    737|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE30CreateVertexTraversalSequencerINS_28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS5_EEEEEENSt3__110unique_ptrINS_15PointsSequencerENS9_14default_deleteISB_EEEEPNS_32MeshAttributeIndicesEncodingDataE:
  110|     29|    MeshAttributeIndicesEncodingData* encoding_data) {
  111|     29|  typedef typename TraverserT::TraversalObserver AttObserver;
  112|     29|  typedef typename TraverserT::CornerTable CornerTable;
  113|       |
  114|     29|  const Mesh* mesh = decoder_->mesh();
  115|     29|  std::unique_ptr<MeshTraversalSequencer<TraverserT>> traversal_sequencer(
  116|     29|      new MeshTraversalSequencer<TraverserT>(mesh, encoding_data));
  117|       |
  118|     29|  AttObserver att_observer(corner_table_.get(), mesh, traversal_sequencer.get(),
  119|     29|                           encoding_data);
  120|       |
  121|     29|  TraverserT att_traverser;
  122|     29|  att_traverser.Init(corner_table_.get(), att_observer);
  123|       |
  124|     29|  traversal_sequencer->SetTraverser(att_traverser);
  125|     29|  return std::move(traversal_sequencer);
  126|     29|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE30CreateVertexTraversalSequencerINS_19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS5_EEEEEENSt3__110unique_ptrINS_15PointsSequencerENS9_14default_deleteISB_EEEEPNS_32MeshAttributeIndicesEncodingDataE:
  110|     43|    MeshAttributeIndicesEncodingData* encoding_data) {
  111|     43|  typedef typename TraverserT::TraversalObserver AttObserver;
  112|     43|  typedef typename TraverserT::CornerTable CornerTable;
  113|       |
  114|     43|  const Mesh* mesh = decoder_->mesh();
  115|     43|  std::unique_ptr<MeshTraversalSequencer<TraverserT>> traversal_sequencer(
  116|     43|      new MeshTraversalSequencer<TraverserT>(mesh, encoding_data));
  117|       |
  118|     43|  AttObserver att_observer(corner_table_.get(), mesh, traversal_sequencer.get(),
  119|     43|                           encoding_data);
  120|       |
  121|     43|  TraverserT att_traverser;
  122|     43|  att_traverser.Init(corner_table_.get(), att_observer);
  123|       |
  124|     43|  traversal_sequencer->SetTraverser(att_traverser);
  125|     43|  return std::move(traversal_sequencer);
  126|     43|}

_ZNK5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE10GetDecoderEv:
   65|  9.48k|  MeshEdgebreakerDecoder* GetDecoder() const override { return decoder_; }
_ZNK5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE14GetCornerTableEv:
   66|  3.01k|  const CornerTable* GetCornerTable() const override {
   67|  3.01k|    return corner_table_.get();
   68|  3.01k|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE15IsTopologySplitEiPNS_12EdgeFaceNameEPi:
   86|  4.84M|                       int* out_encoder_split_symbol_id) {
   87|  4.84M|    if (topology_split_data_.size() == 0) {
  ------------------
  |  Branch (87:9): [True: 29.6k, False: 4.81M]
  ------------------
   88|  29.6k|      return false;
   89|  29.6k|    }
   90|  4.81M|    if (topology_split_data_.back().source_symbol_id >
  ------------------
  |  Branch (90:9): [True: 37, False: 4.81M]
  ------------------
   91|  4.81M|        static_cast<uint32_t>(encoder_symbol_id)) {
   92|       |      // Something is wrong; if the desired source symbol is greater than the
   93|       |      // current encoder_symbol_id, we missed it, or the input was tampered
   94|       |      // (|encoder_symbol_id| keeps decreasing).
   95|       |      // Return invalid symbol id to notify the decoder that there was an
   96|       |      // error.
   97|     37|      *out_encoder_split_symbol_id = -1;
   98|     37|      return true;
   99|     37|    }
  100|  4.81M|    if (topology_split_data_.back().source_symbol_id != encoder_symbol_id) {
  ------------------
  |  Branch (100:9): [True: 4.81M, False: 1.99k]
  ------------------
  101|  4.81M|      return false;
  102|  4.81M|    }
  103|  1.99k|    *out_face_edge =
  104|  1.99k|        static_cast<EdgeFaceName>(topology_split_data_.back().source_edge);
  105|  1.99k|    *out_encoder_split_symbol_id = topology_split_data_.back().split_symbol_id;
  106|       |    // Remove the latest split event.
  107|  1.99k|    topology_split_data_.pop_back();
  108|  1.99k|    return true;
  109|  4.81M|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE18SetOppositeCornersENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEES5_:
  133|  13.8M|  void SetOppositeCorners(CornerIndex corner_0, CornerIndex corner_1) {
  134|  13.8M|    corner_table_->SetOppositeCorner(corner_0, corner_1);
  135|  13.8M|    corner_table_->SetOppositeCorner(corner_1, corner_0);
  136|  13.8M|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE13AttributeDataC2Ev:
  210|  19.7k|    AttributeData() : decoder_id(-1), is_connectivity_used(true) {}
_ZNK5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE10GetDecoderEv:
   65|  7.68k|  MeshEdgebreakerDecoder* GetDecoder() const override { return decoder_; }
_ZNK5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE14GetCornerTableEv:
   66|  4.84k|  const CornerTable* GetCornerTable() const override {
   67|  4.84k|    return corner_table_.get();
   68|  4.84k|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE15IsTopologySplitEiPNS_12EdgeFaceNameEPi:
   86|  29.8M|                       int* out_encoder_split_symbol_id) {
   87|  29.8M|    if (topology_split_data_.size() == 0) {
  ------------------
  |  Branch (87:9): [True: 29.8M, False: 53.7k]
  ------------------
   88|  29.8M|      return false;
   89|  29.8M|    }
   90|  53.7k|    if (topology_split_data_.back().source_symbol_id >
  ------------------
  |  Branch (90:9): [True: 24, False: 53.6k]
  ------------------
   91|  53.7k|        static_cast<uint32_t>(encoder_symbol_id)) {
   92|       |      // Something is wrong; if the desired source symbol is greater than the
   93|       |      // current encoder_symbol_id, we missed it, or the input was tampered
   94|       |      // (|encoder_symbol_id| keeps decreasing).
   95|       |      // Return invalid symbol id to notify the decoder that there was an
   96|       |      // error.
   97|     24|      *out_encoder_split_symbol_id = -1;
   98|     24|      return true;
   99|     24|    }
  100|  53.6k|    if (topology_split_data_.back().source_symbol_id != encoder_symbol_id) {
  ------------------
  |  Branch (100:9): [True: 52.3k, False: 1.30k]
  ------------------
  101|  52.3k|      return false;
  102|  52.3k|    }
  103|  1.30k|    *out_face_edge =
  104|  1.30k|        static_cast<EdgeFaceName>(topology_split_data_.back().source_edge);
  105|  1.30k|    *out_encoder_split_symbol_id = topology_split_data_.back().split_symbol_id;
  106|       |    // Remove the latest split event.
  107|  1.30k|    topology_split_data_.pop_back();
  108|  1.30k|    return true;
  109|  53.6k|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE18SetOppositeCornersENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEES5_:
  133|  88.9M|  void SetOppositeCorners(CornerIndex corner_0, CornerIndex corner_1) {
  134|  88.9M|    corner_table_->SetOppositeCorner(corner_0, corner_1);
  135|  88.9M|    corner_table_->SetOppositeCorner(corner_1, corner_0);
  136|  88.9M|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE13AttributeDataC2Ev:
  210|  15.0k|    AttributeData() : decoder_id(-1), is_connectivity_used(true) {}
_ZNK5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE10GetDecoderEv:
   65|  13.4k|  MeshEdgebreakerDecoder* GetDecoder() const override { return decoder_; }
_ZNK5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE14GetCornerTableEv:
   66|  2.74k|  const CornerTable* GetCornerTable() const override {
   67|  2.74k|    return corner_table_.get();
   68|  2.74k|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE15IsTopologySplitEiPNS_12EdgeFaceNameEPi:
   86|  53.8M|                       int* out_encoder_split_symbol_id) {
   87|  53.8M|    if (topology_split_data_.size() == 0) {
  ------------------
  |  Branch (87:9): [True: 53.3M, False: 508k]
  ------------------
   88|  53.3M|      return false;
   89|  53.3M|    }
   90|   508k|    if (topology_split_data_.back().source_symbol_id >
  ------------------
  |  Branch (90:9): [True: 39, False: 508k]
  ------------------
   91|   508k|        static_cast<uint32_t>(encoder_symbol_id)) {
   92|       |      // Something is wrong; if the desired source symbol is greater than the
   93|       |      // current encoder_symbol_id, we missed it, or the input was tampered
   94|       |      // (|encoder_symbol_id| keeps decreasing).
   95|       |      // Return invalid symbol id to notify the decoder that there was an
   96|       |      // error.
   97|     39|      *out_encoder_split_symbol_id = -1;
   98|     39|      return true;
   99|     39|    }
  100|   508k|    if (topology_split_data_.back().source_symbol_id != encoder_symbol_id) {
  ------------------
  |  Branch (100:9): [True: 507k, False: 1.21k]
  ------------------
  101|   507k|      return false;
  102|   507k|    }
  103|  1.21k|    *out_face_edge =
  104|  1.21k|        static_cast<EdgeFaceName>(topology_split_data_.back().source_edge);
  105|  1.21k|    *out_encoder_split_symbol_id = topology_split_data_.back().split_symbol_id;
  106|       |    // Remove the latest split event.
  107|  1.21k|    topology_split_data_.pop_back();
  108|  1.21k|    return true;
  109|   508k|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE18SetOppositeCornersENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEES5_:
  133|  72.9M|  void SetOppositeCorners(CornerIndex corner_0, CornerIndex corner_1) {
  134|  72.9M|    corner_table_->SetOppositeCorner(corner_0, corner_1);
  135|  72.9M|    corner_table_->SetOppositeCorner(corner_1, corner_0);
  136|  72.9M|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE13AttributeDataC2Ev:
  210|  11.8k|    AttributeData() : decoder_id(-1), is_connectivity_used(true) {}

_ZN5draco35MeshEdgebreakerDecoderImplInterfaceD2Ev:
   30|  10.0k|  virtual ~MeshEdgebreakerDecoderImplInterface() = default;

_ZN5draco13HoleEventDataC2Ev:
  118|  1.84M|  HoleEventData() : symbol_id(0) {}

_ZN5draco31MeshEdgebreakerTraversalDecoderC2Ev:
   33|  10.0k|      : attribute_connectivity_decoders_(nullptr),
   34|  10.0k|        num_attribute_data_(0),
   35|  10.0k|        decoder_impl_(nullptr) {}
_ZN5draco31MeshEdgebreakerTraversalDecoder4InitEPNS_35MeshEdgebreakerDecoderImplInterfaceE:
   36|  8.23k|  void Init(MeshEdgebreakerDecoderImplInterface* decoder) {
   37|  8.23k|    decoder_impl_ = decoder;
   38|  8.23k|    buffer_.Init(decoder->GetDecoder()->buffer()->data_head(),
   39|  8.23k|                 decoder->GetDecoder()->buffer()->remaining_size(),
   40|  8.23k|                 decoder->GetDecoder()->buffer()->bitstream_version());
   41|  8.23k|  }
_ZNK5draco31MeshEdgebreakerTraversalDecoder16BitstreamVersionEv:
   44|  5.93k|  uint16_t BitstreamVersion() const {
   45|  5.93k|    return decoder_impl_->GetDecoder()->bitstream_version();
   46|  5.93k|  }
_ZN5draco31MeshEdgebreakerTraversalDecoder21SetNumEncodedVerticesEi:
   50|  3.16k|  void SetNumEncodedVertices(int /* num_vertices */) {}
_ZN5draco31MeshEdgebreakerTraversalDecoder19SetNumAttributeDataEi:
   54|  8.23k|  void SetNumAttributeData(int num_data) { num_attribute_data_ = num_data; }
_ZN5draco31MeshEdgebreakerTraversalDecoder5StartEPNS_13DecoderBufferE:
   59|  5.72k|  bool Start(DecoderBuffer* out_buffer) {
   60|       |    // Decode symbols from the main buffer decoder and face configurations from
   61|       |    // the start_face_buffer decoder.
   62|  5.72k|    if (!DecodeTraversalSymbols()) {
  ------------------
  |  Branch (62:9): [True: 181, False: 5.54k]
  ------------------
   63|    181|      return false;
   64|    181|    }
   65|       |
   66|  5.54k|    if (!DecodeStartFaces()) {
  ------------------
  |  Branch (66:9): [True: 134, False: 5.40k]
  ------------------
   67|    134|      return false;
   68|    134|    }
   69|       |
   70|  5.40k|    if (!DecodeAttributeSeams()) {
  ------------------
  |  Branch (70:9): [True: 32, False: 5.37k]
  ------------------
   71|     32|      return false;
   72|     32|    }
   73|  5.37k|    *out_buffer = buffer_;
   74|  5.37k|    return true;
   75|  5.40k|  }
_ZN5draco31MeshEdgebreakerTraversalDecoder28DecodeStartFaceConfigurationEv:
   78|  4.34M|  inline bool DecodeStartFaceConfiguration() {
   79|  4.34M|    uint32_t face_configuration;
   80|  4.34M|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   81|  4.34M|    if (buffer_.bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  4.34M|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (81:9): [True: 598, False: 4.34M]
  ------------------
   82|    598|      start_face_buffer_.DecodeLeastSignificantBits32(1, &face_configuration);
   83|       |
   84|    598|    } else
   85|  4.34M|#endif
   86|  4.34M|    {
   87|  4.34M|      face_configuration = start_face_decoder_.DecodeNextBit();
   88|  4.34M|    }
   89|  4.34M|    return face_configuration;
   90|  4.34M|  }
_ZN5draco31MeshEdgebreakerTraversalDecoder12DecodeSymbolEv:
   93|  10.4M|  inline uint32_t DecodeSymbol() {
   94|  10.4M|    uint32_t symbol;
   95|  10.4M|    symbol_buffer_.DecodeLeastSignificantBits32(1, &symbol);
   96|  10.4M|    if (symbol == TOPOLOGY_C) {
  ------------------
  |  Branch (96:9): [True: 4.45M, False: 6.00M]
  ------------------
   97|  4.45M|      return symbol;
   98|  4.45M|    }
   99|       |    // Else decode two additional bits.
  100|  6.00M|    uint32_t symbol_suffix;
  101|  6.00M|    symbol_buffer_.DecodeLeastSignificantBits32(2, &symbol_suffix);
  102|  6.00M|    symbol |= (symbol_suffix << 1);
  103|  6.00M|    return symbol;
  104|  10.4M|  }
_ZN5draco31MeshEdgebreakerTraversalDecoder22NewActiveCornerReachedENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  107|  10.3M|  inline void NewActiveCornerReached(CornerIndex /* corner */) {}
_ZN5draco31MeshEdgebreakerTraversalDecoder13MergeVerticesENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEES3_:
  111|  1.11M|  inline void MergeVertices(VertexIndex /* dest */, VertexIndex /* source */) {}
_ZN5draco31MeshEdgebreakerTraversalDecoder19DecodeAttributeSeamEi:
  117|  26.3M|  inline bool DecodeAttributeSeam(int attribute) {
  118|  26.3M|    return attribute_connectivity_decoders_[attribute].DecodeNextBit();
  119|  26.3M|  }
_ZN5draco31MeshEdgebreakerTraversalDecoder4DoneEv:
  122|  5.02k|  void Done() {
  123|  5.02k|    if (symbol_buffer_.bit_decoder_active()) {
  ------------------
  |  Branch (123:9): [True: 4.79k, False: 230]
  ------------------
  124|  4.79k|      symbol_buffer_.EndBitDecoding();
  125|  4.79k|    }
  126|  5.02k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  127|  5.02k|    if (buffer_.bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  5.02k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (127:9): [True: 306, False: 4.71k]
  ------------------
  128|    306|      start_face_buffer_.EndBitDecoding();
  129|       |
  130|    306|    } else
  131|  4.71k|#endif
  132|  4.71k|    {
  133|  4.71k|      start_face_decoder_.EndDecoding();
  134|  4.71k|    }
  135|  5.02k|  }
_ZN5draco31MeshEdgebreakerTraversalDecoder6bufferEv:
  138|  2.23k|  DecoderBuffer* buffer() { return &buffer_; }
_ZN5draco31MeshEdgebreakerTraversalDecoder22DecodeTraversalSymbolsEv:
  140|  6.01k|  bool DecodeTraversalSymbols() {
  141|  6.01k|    uint64_t traversal_size;
  142|  6.01k|    symbol_buffer_ = buffer_;
  143|  6.01k|    if (!symbol_buffer_.StartBitDecoding(true, &traversal_size)) {
  ------------------
  |  Branch (143:9): [True: 63, False: 5.94k]
  ------------------
  144|     63|      return false;
  145|     63|    }
  146|  5.94k|    buffer_ = symbol_buffer_;
  147|  5.94k|    if (traversal_size > static_cast<uint64_t>(buffer_.remaining_size())) {
  ------------------
  |  Branch (147:9): [True: 223, False: 5.72k]
  ------------------
  148|    223|      return false;
  149|    223|    }
  150|  5.72k|    buffer_.Advance(traversal_size);
  151|  5.72k|    return true;
  152|  5.94k|  }
_ZN5draco31MeshEdgebreakerTraversalDecoder16DecodeStartFacesEv:
  154|  7.94k|  bool DecodeStartFaces() {
  155|       |    // Create a decoder that is set to the end of the encoded traversal data.
  156|  7.94k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  157|  7.94k|    if (buffer_.bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  7.94k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (157:9): [True: 607, False: 7.33k]
  ------------------
  158|    607|      start_face_buffer_ = buffer_;
  159|    607|      uint64_t traversal_size;
  160|    607|      if (!start_face_buffer_.StartBitDecoding(true, &traversal_size)) {
  ------------------
  |  Branch (160:11): [True: 5, False: 602]
  ------------------
  161|      5|        return false;
  162|      5|      }
  163|    602|      buffer_ = start_face_buffer_;
  164|    602|      if (traversal_size > static_cast<uint64_t>(buffer_.remaining_size())) {
  ------------------
  |  Branch (164:11): [True: 198, False: 404]
  ------------------
  165|    198|        return false;
  166|    198|      }
  167|    404|      buffer_.Advance(traversal_size);
  168|    404|      return true;
  169|    602|    }
  170|  7.33k|#endif
  171|  7.33k|    return start_face_decoder_.StartDecoding(&buffer_);
  172|  7.94k|  }
_ZN5draco31MeshEdgebreakerTraversalDecoder20DecodeAttributeSeamsEv:
  174|  7.67k|  bool DecodeAttributeSeams() {
  175|       |    // Prepare attribute decoding.
  176|  7.67k|    if (num_attribute_data_ > 0) {
  ------------------
  |  Branch (176:9): [True: 5.22k, False: 2.45k]
  ------------------
  177|  5.22k|      attribute_connectivity_decoders_ = std::unique_ptr<BinaryDecoder[]>(
  178|  5.22k|          new BinaryDecoder[num_attribute_data_]);
  179|  15.3k|      for (int i = 0; i < num_attribute_data_; ++i) {
  ------------------
  |  Branch (179:23): [True: 10.1k, False: 5.15k]
  ------------------
  180|  10.1k|        if (!attribute_connectivity_decoders_[i].StartDecoding(&buffer_)) {
  ------------------
  |  Branch (180:13): [True: 62, False: 10.0k]
  ------------------
  181|     62|          return false;
  182|     62|        }
  183|  10.1k|      }
  184|  5.22k|    }
  185|  7.61k|    return true;
  186|  7.67k|  }

_ZN5draco41MeshEdgebreakerTraversalPredictiveDecoderC2Ev:
   32|  3.18k|      : corner_table_(nullptr),
   33|  3.18k|        num_vertices_(0),
   34|  3.18k|        last_symbol_(-1),
   35|  3.18k|        predicted_symbol_(-1) {}
_ZN5draco41MeshEdgebreakerTraversalPredictiveDecoder4InitEPNS_35MeshEdgebreakerDecoderImplInterfaceE:
   36|  2.56k|  void Init(MeshEdgebreakerDecoderImplInterface* decoder) {
   37|  2.56k|    MeshEdgebreakerTraversalDecoder::Init(decoder);
   38|  2.56k|    corner_table_ = decoder->GetCornerTable();
   39|  2.56k|  }
_ZN5draco41MeshEdgebreakerTraversalPredictiveDecoder21SetNumEncodedVerticesEi:
   40|  2.56k|  void SetNumEncodedVertices(int num_vertices) { num_vertices_ = num_vertices; }
_ZN5draco41MeshEdgebreakerTraversalPredictiveDecoder5StartEPNS_13DecoderBufferE:
   42|  2.56k|  bool Start(DecoderBuffer* out_buffer) {
   43|  2.56k|    if (!MeshEdgebreakerTraversalDecoder::Start(out_buffer)) {
  ------------------
  |  Branch (43:9): [True: 92, False: 2.47k]
  ------------------
   44|     92|      return false;
   45|     92|    }
   46|  2.47k|    int32_t num_split_symbols;
   47|  2.47k|    if (!out_buffer->Decode(&num_split_symbols) || num_split_symbols < 0)
  ------------------
  |  Branch (47:9): [True: 1, False: 2.46k]
  |  Branch (47:52): [True: 38, False: 2.43k]
  ------------------
   48|     39|      return false;
   49|  2.43k|    if (num_split_symbols >= num_vertices_) {
  ------------------
  |  Branch (49:9): [True: 40, False: 2.39k]
  ------------------
   50|     40|      return false;
   51|     40|    }
   52|       |    // Set the valences of all initial vertices to 0.
   53|  2.39k|    vertex_valences_.resize(num_vertices_, 0);
   54|  2.39k|    if (!prediction_decoder_.StartDecoding(out_buffer)) {
  ------------------
  |  Branch (54:9): [True: 10, False: 2.38k]
  ------------------
   55|     10|      return false;
   56|     10|    }
   57|  2.38k|    return true;
   58|  2.39k|  }
_ZN5draco41MeshEdgebreakerTraversalPredictiveDecoder12DecodeSymbolEv:
   60|  59.4M|  inline uint32_t DecodeSymbol() {
   61|       |    // First check if we have a predicted symbol.
   62|  59.4M|    if (predicted_symbol_ != -1) {
  ------------------
  |  Branch (62:9): [True: 59.3M, False: 38.3k]
  ------------------
   63|       |      // Double check that the predicted symbol was predicted correctly.
   64|  59.3M|      if (prediction_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (64:11): [True: 59.3M, False: 52.1k]
  ------------------
   65|  59.3M|        last_symbol_ = predicted_symbol_;
   66|  59.3M|        return predicted_symbol_;
   67|  59.3M|      }
   68|  59.3M|    }
   69|       |    // We don't have a predicted symbol or the symbol was mis-predicted.
   70|       |    // Decode it directly.
   71|  90.4k|    last_symbol_ = MeshEdgebreakerTraversalDecoder::DecodeSymbol();
   72|  90.4k|    return last_symbol_;
   73|  59.4M|  }
_ZN5draco41MeshEdgebreakerTraversalPredictiveDecoder22NewActiveCornerReachedENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   75|  59.4M|  inline void NewActiveCornerReached(CornerIndex corner) {
   76|  59.4M|    const CornerIndex next = corner_table_->Next(corner);
   77|  59.4M|    const CornerIndex prev = corner_table_->Previous(corner);
   78|       |    // Update valences.
   79|  59.4M|    switch (last_symbol_) {
   80|  29.5M|      case TOPOLOGY_C:
  ------------------
  |  Branch (80:7): [True: 29.5M, False: 29.8M]
  ------------------
   81|  29.5M|      case TOPOLOGY_S:
  ------------------
  |  Branch (81:7): [True: 9.09k, False: 59.4M]
  ------------------
   82|  29.5M|        vertex_valences_[corner_table_->Vertex(next).value()] += 1;
   83|  29.5M|        vertex_valences_[corner_table_->Vertex(prev).value()] += 1;
   84|  29.5M|        break;
   85|  29.8M|      case TOPOLOGY_R:
  ------------------
  |  Branch (85:7): [True: 29.8M, False: 29.5M]
  ------------------
   86|  29.8M|        vertex_valences_[corner_table_->Vertex(corner).value()] += 1;
   87|  29.8M|        vertex_valences_[corner_table_->Vertex(next).value()] += 1;
   88|  29.8M|        vertex_valences_[corner_table_->Vertex(prev).value()] += 2;
   89|  29.8M|        break;
   90|  6.97k|      case TOPOLOGY_L:
  ------------------
  |  Branch (90:7): [True: 6.97k, False: 59.4M]
  ------------------
   91|  6.97k|        vertex_valences_[corner_table_->Vertex(corner).value()] += 1;
   92|  6.97k|        vertex_valences_[corner_table_->Vertex(next).value()] += 2;
   93|  6.97k|        vertex_valences_[corner_table_->Vertex(prev).value()] += 1;
   94|  6.97k|        break;
   95|  19.8k|      case TOPOLOGY_E:
  ------------------
  |  Branch (95:7): [True: 19.8k, False: 59.4M]
  ------------------
   96|  19.8k|        vertex_valences_[corner_table_->Vertex(corner).value()] += 2;
   97|  19.8k|        vertex_valences_[corner_table_->Vertex(next).value()] += 2;
   98|  19.8k|        vertex_valences_[corner_table_->Vertex(prev).value()] += 2;
   99|  19.8k|        break;
  100|      0|      default:
  ------------------
  |  Branch (100:7): [True: 0, False: 59.4M]
  ------------------
  101|      0|        break;
  102|  59.4M|    }
  103|       |    // Compute the new predicted symbol.
  104|  59.4M|    if (last_symbol_ == TOPOLOGY_C || last_symbol_ == TOPOLOGY_R) {
  ------------------
  |  Branch (104:9): [True: 29.5M, False: 29.8M]
  |  Branch (104:39): [True: 29.8M, False: 35.9k]
  ------------------
  105|  59.3M|      const VertexIndex pivot =
  106|  59.3M|          corner_table_->Vertex(corner_table_->Next(corner));
  107|  59.3M|      if (vertex_valences_[pivot.value()] < 6) {
  ------------------
  |  Branch (107:11): [True: 29.8M, False: 29.5M]
  ------------------
  108|  29.8M|        predicted_symbol_ = TOPOLOGY_R;
  109|  29.8M|      } else {
  110|  29.5M|        predicted_symbol_ = TOPOLOGY_C;
  111|  29.5M|      }
  112|  59.3M|    } else {
  113|  35.9k|      predicted_symbol_ = -1;
  114|  35.9k|    }
  115|  59.4M|  }
_ZN5draco41MeshEdgebreakerTraversalPredictiveDecoder13MergeVerticesENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEES3_:
  117|  9.09k|  inline void MergeVertices(VertexIndex dest, VertexIndex source) {
  118|       |    // Update valences on the merged vertices.
  119|  9.09k|    vertex_valences_[dest.value()] += vertex_valences_[source.value()];
  120|  9.09k|  }

_ZN5draco38MeshEdgebreakerTraversalValenceDecoderC2Ev:
   33|  3.04k|      : corner_table_(nullptr),
   34|  3.04k|        num_vertices_(0),
   35|  3.04k|        last_symbol_(-1),
   36|  3.04k|        active_context_(-1),
   37|  3.04k|        min_valence_(2),
   38|  3.04k|        max_valence_(7) {}
_ZN5draco38MeshEdgebreakerTraversalValenceDecoder4InitEPNS_35MeshEdgebreakerDecoderImplInterfaceE:
   39|  2.50k|  void Init(MeshEdgebreakerDecoderImplInterface* decoder) {
   40|  2.50k|    MeshEdgebreakerTraversalDecoder::Init(decoder);
   41|  2.50k|    corner_table_ = decoder->GetCornerTable();
   42|  2.50k|  }
_ZN5draco38MeshEdgebreakerTraversalValenceDecoder21SetNumEncodedVerticesEi:
   43|  2.50k|  void SetNumEncodedVertices(int num_vertices) { num_vertices_ = num_vertices; }
_ZN5draco38MeshEdgebreakerTraversalValenceDecoder5StartEPNS_13DecoderBufferE:
   45|  2.50k|  bool Start(DecoderBuffer* out_buffer) {
   46|  2.50k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   47|  2.50k|    if (BitstreamVersion() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  2.50k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (47:9): [True: 288, False: 2.22k]
  ------------------
   48|    288|      if (!MeshEdgebreakerTraversalDecoder::DecodeTraversalSymbols()) {
  ------------------
  |  Branch (48:11): [True: 105, False: 183]
  ------------------
   49|    105|        return false;
   50|    105|      }
   51|    288|    }
   52|  2.40k|#endif
   53|  2.40k|    if (!MeshEdgebreakerTraversalDecoder::DecodeStartFaces()) {
  ------------------
  |  Branch (53:9): [True: 138, False: 2.26k]
  ------------------
   54|    138|      return false;
   55|    138|    }
   56|  2.26k|    if (!MeshEdgebreakerTraversalDecoder::DecodeAttributeSeams()) {
  ------------------
  |  Branch (56:9): [True: 30, False: 2.23k]
  ------------------
   57|     30|      return false;
   58|     30|    }
   59|  2.23k|    *out_buffer = *buffer();
   60|       |
   61|  2.23k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   62|  2.23k|    if (BitstreamVersion() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  2.23k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (62:9): [True: 89, False: 2.14k]
  ------------------
   63|     89|      uint32_t num_split_symbols;
   64|     89|      if (BitstreamVersion() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     89|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (64:11): [True: 71, False: 18]
  ------------------
   65|     71|        if (!out_buffer->Decode(&num_split_symbols)) {
  ------------------
  |  Branch (65:13): [True: 1, False: 70]
  ------------------
   66|      1|          return false;
   67|      1|        }
   68|     71|      } else {
   69|     18|        if (!DecodeVarint(&num_split_symbols, out_buffer)) {
  ------------------
  |  Branch (69:13): [True: 1, False: 17]
  ------------------
   70|      1|          return false;
   71|      1|        }
   72|     18|      }
   73|     87|      if (num_split_symbols >= static_cast<uint32_t>(num_vertices_)) {
  ------------------
  |  Branch (73:11): [True: 4, False: 83]
  ------------------
   74|      4|        return false;
   75|      4|      }
   76|       |
   77|     83|      int8_t mode;
   78|     83|      if (!out_buffer->Decode(&mode)) {
  ------------------
  |  Branch (78:11): [True: 1, False: 82]
  ------------------
   79|      1|        return false;
   80|      1|      }
   81|     82|      if (mode == EDGEBREAKER_VALENCE_MODE_2_7) {
  ------------------
  |  Branch (81:11): [True: 80, False: 2]
  ------------------
   82|     80|        min_valence_ = 2;
   83|     80|        max_valence_ = 7;
   84|     80|      } else {
   85|       |        // Unsupported mode.
   86|      2|        return false;
   87|      2|      }
   88|       |
   89|     82|    } else
   90|  2.14k|#endif
   91|  2.14k|    {
   92|  2.14k|      min_valence_ = 2;
   93|  2.14k|      max_valence_ = 7;
   94|  2.14k|    }
   95|       |
   96|  2.22k|    if (num_vertices_ < 0) {
  ------------------
  |  Branch (96:9): [True: 0, False: 2.22k]
  ------------------
   97|      0|      return false;
   98|      0|    }
   99|       |    // Set the valences of all initial vertices to 0.
  100|  2.22k|    vertex_valences_.resize(num_vertices_, 0);
  101|       |
  102|  2.22k|    const int num_unique_valences = max_valence_ - min_valence_ + 1;
  103|       |
  104|       |    // Decode all symbols for all contexts.
  105|  2.22k|    context_symbols_.resize(num_unique_valences);
  106|  2.22k|    context_counters_.resize(context_symbols_.size());
  107|  12.2k|    for (int i = 0; i < context_symbols_.size(); ++i) {
  ------------------
  |  Branch (107:21): [True: 11.1k, False: 1.12k]
  ------------------
  108|  11.1k|      uint32_t num_symbols;
  109|  11.1k|      if (!DecodeVarint<uint32_t>(&num_symbols, out_buffer)) {
  ------------------
  |  Branch (109:11): [True: 973, False: 10.1k]
  ------------------
  110|    973|        return false;
  111|    973|      }
  112|  10.1k|      if (num_symbols > static_cast<uint32_t>(corner_table_->num_faces())) {
  ------------------
  |  Branch (112:11): [True: 133, False: 10.0k]
  ------------------
  113|    133|        return false;
  114|    133|      }
  115|  10.0k|      if (num_symbols > 0) {
  ------------------
  |  Branch (115:11): [True: 8.32k, False: 1.68k]
  ------------------
  116|  8.32k|        context_symbols_[i].resize(num_symbols);
  117|  8.32k|        DecodeSymbols(num_symbols, 1, out_buffer, context_symbols_[i].data());
  118|       |        // All symbols are going to be processed from the back.
  119|  8.32k|        context_counters_[i] = num_symbols;
  120|  8.32k|      }
  121|  10.0k|    }
  122|  1.12k|    return true;
  123|  2.22k|  }
_ZN5draco38MeshEdgebreakerTraversalValenceDecoder12DecodeSymbolEv:
  125|  60.0M|  inline uint32_t DecodeSymbol() {
  126|       |    // First check if we have a valid context.
  127|  60.0M|    if (active_context_ != -1) {
  ------------------
  |  Branch (127:9): [True: 60.0M, False: 1.10k]
  ------------------
  128|  60.0M|      const int context_counter = --context_counters_[active_context_];
  129|  60.0M|      if (context_counter < 0) {
  ------------------
  |  Branch (129:11): [True: 253, False: 60.0M]
  ------------------
  130|    253|        return TOPOLOGY_INVALID;
  131|    253|      }
  132|  60.0M|      const uint32_t symbol_id =
  133|  60.0M|          context_symbols_[active_context_][context_counter];
  134|  60.0M|      if (symbol_id > 4) {
  ------------------
  |  Branch (134:11): [True: 2, False: 60.0M]
  ------------------
  135|      2|        return TOPOLOGY_INVALID;
  136|      2|      }
  137|  60.0M|      last_symbol_ = edge_breaker_symbol_to_topology_id[symbol_id];
  138|  60.0M|    } else {
  139|  1.10k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  140|  1.10k|      if (BitstreamVersion() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  1.10k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (140:11): [True: 64, False: 1.03k]
  ------------------
  141|       |        // We don't have a predicted symbol or the symbol was mis-predicted.
  142|       |        // Decode it directly.
  143|     64|        last_symbol_ = MeshEdgebreakerTraversalDecoder::DecodeSymbol();
  144|       |
  145|     64|      } else
  146|  1.03k|#endif
  147|  1.03k|      {
  148|       |        // The first symbol must be E.
  149|  1.03k|        last_symbol_ = TOPOLOGY_E;
  150|  1.03k|      }
  151|  1.10k|    }
  152|  60.0M|    return last_symbol_;
  153|  60.0M|  }
_ZN5draco38MeshEdgebreakerTraversalValenceDecoder22NewActiveCornerReachedENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  155|  60.0M|  inline void NewActiveCornerReached(CornerIndex corner) {
  156|  60.0M|    const CornerIndex next = corner_table_->Next(corner);
  157|  60.0M|    const CornerIndex prev = corner_table_->Previous(corner);
  158|       |    // Update valences.
  159|  60.0M|    switch (last_symbol_) {
  160|  6.06M|      case TOPOLOGY_C:
  ------------------
  |  Branch (160:7): [True: 6.06M, False: 53.9M]
  ------------------
  161|  6.11M|      case TOPOLOGY_S:
  ------------------
  |  Branch (161:7): [True: 44.9k, False: 59.9M]
  ------------------
  162|  6.11M|        vertex_valences_[corner_table_->Vertex(next)] += 1;
  163|  6.11M|        vertex_valences_[corner_table_->Vertex(prev)] += 1;
  164|  6.11M|        break;
  165|  2.99k|      case TOPOLOGY_R:
  ------------------
  |  Branch (165:7): [True: 2.99k, False: 60.0M]
  ------------------
  166|  2.99k|        vertex_valences_[corner_table_->Vertex(corner)] += 1;
  167|  2.99k|        vertex_valences_[corner_table_->Vertex(next)] += 1;
  168|  2.99k|        vertex_valences_[corner_table_->Vertex(prev)] += 2;
  169|  2.99k|        break;
  170|  47.9M|      case TOPOLOGY_L:
  ------------------
  |  Branch (170:7): [True: 47.9M, False: 12.0M]
  ------------------
  171|  47.9M|        vertex_valences_[corner_table_->Vertex(corner)] += 1;
  172|  47.9M|        vertex_valences_[corner_table_->Vertex(next)] += 2;
  173|  47.9M|        vertex_valences_[corner_table_->Vertex(prev)] += 1;
  174|  47.9M|        break;
  175|  5.93M|      case TOPOLOGY_E:
  ------------------
  |  Branch (175:7): [True: 5.93M, False: 54.0M]
  ------------------
  176|  5.93M|        vertex_valences_[corner_table_->Vertex(corner)] += 2;
  177|  5.93M|        vertex_valences_[corner_table_->Vertex(next)] += 2;
  178|  5.93M|        vertex_valences_[corner_table_->Vertex(prev)] += 2;
  179|  5.93M|        break;
  180|      0|      default:
  ------------------
  |  Branch (180:7): [True: 0, False: 60.0M]
  ------------------
  181|      0|        break;
  182|  60.0M|    }
  183|       |    // Compute the new context that is going to be used to decode the next
  184|       |    // symbol.
  185|  60.0M|    const int active_valence = vertex_valences_[corner_table_->Vertex(next)];
  186|  60.0M|    int clamped_valence;
  187|  60.0M|    if (active_valence < min_valence_) {
  ------------------
  |  Branch (187:9): [True: 0, False: 60.0M]
  ------------------
  188|      0|      clamped_valence = min_valence_;
  189|  60.0M|    } else if (active_valence > max_valence_) {
  ------------------
  |  Branch (189:16): [True: 6.04M, False: 53.9M]
  ------------------
  190|  6.04M|      clamped_valence = max_valence_;
  191|  53.9M|    } else {
  192|  53.9M|      clamped_valence = active_valence;
  193|  53.9M|    }
  194|       |
  195|  60.0M|    active_context_ = (clamped_valence - min_valence_);
  196|  60.0M|  }
_ZN5draco38MeshEdgebreakerTraversalValenceDecoder13MergeVerticesENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEES3_:
  198|  44.9k|  inline void MergeVertices(VertexIndex dest, VertexIndex source) {
  199|       |    // Update valences on the merged vertices.
  200|  44.9k|    vertex_valences_[dest] += vertex_valences_[source];
  201|  44.9k|  }

_ZN5draco21MeshSequentialDecoderC2Ev:
   27|  5.59k|MeshSequentialDecoder::MeshSequentialDecoder() = default;
_ZN5draco21MeshSequentialDecoder18DecodeConnectivityEv:
   29|  5.34k|bool MeshSequentialDecoder::DecodeConnectivity() {
   30|  5.34k|  uint32_t num_faces;
   31|  5.34k|  uint32_t num_points;
   32|  5.34k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   33|  5.34k|  if (bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  5.34k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (33:7): [True: 739, False: 4.61k]
  ------------------
   34|    739|    if (!buffer()->Decode(&num_faces)) {
  ------------------
  |  Branch (34:9): [True: 11, False: 728]
  ------------------
   35|     11|      return false;
   36|     11|    }
   37|    728|    if (!buffer()->Decode(&num_points)) {
  ------------------
  |  Branch (37:9): [True: 3, False: 725]
  ------------------
   38|      3|      return false;
   39|      3|    }
   40|       |
   41|    728|  } else
   42|  4.61k|#endif
   43|  4.61k|  {
   44|  4.61k|    if (!DecodeVarint(&num_faces, buffer())) {
  ------------------
  |  Branch (44:9): [True: 15, False: 4.59k]
  ------------------
   45|     15|      return false;
   46|     15|    }
   47|  4.59k|    if (!DecodeVarint(&num_points, buffer())) {
  ------------------
  |  Branch (47:9): [True: 10, False: 4.58k]
  ------------------
   48|     10|      return false;
   49|     10|    }
   50|  4.59k|  }
   51|       |
   52|       |  // Check that num_faces and num_points are valid values.
   53|  5.31k|  const uint64_t faces_64 = static_cast<uint64_t>(num_faces);
   54|       |  // Compressed sequential encoding can only handle (2^32 - 1) / 3 indices.
   55|  5.31k|  if (faces_64 > 0xffffffff / 3) {
  ------------------
  |  Branch (55:7): [True: 9, False: 5.30k]
  ------------------
   56|      9|    return false;
   57|      9|  }
   58|  5.30k|  if (faces_64 > buffer()->remaining_size() / 3) {
  ------------------
  |  Branch (58:7): [True: 56, False: 5.24k]
  ------------------
   59|       |    // The number of faces is unreasonably high, because face indices do not
   60|       |    // fit in the remaining size of the buffer.
   61|     56|    return false;
   62|     56|  }
   63|  5.24k|  uint8_t connectivity_method;
   64|  5.24k|  if (!buffer()->Decode(&connectivity_method)) {
  ------------------
  |  Branch (64:7): [True: 4, False: 5.24k]
  ------------------
   65|      4|    return false;
   66|      4|  }
   67|  5.24k|  if (connectivity_method == 0) {
  ------------------
  |  Branch (67:7): [True: 4.27k, False: 964]
  ------------------
   68|  4.27k|    if (!DecodeAndDecompressIndices(num_faces, num_points)) {
  ------------------
  |  Branch (68:9): [True: 4.14k, False: 136]
  ------------------
   69|  4.14k|      return false;
   70|  4.14k|    }
   71|  4.27k|  } else {
   72|    964|    if (num_points < 256) {
  ------------------
  |  Branch (72:9): [True: 557, False: 407]
  ------------------
   73|       |      // Decode indices as uint8_t.
   74|  1.25k|      for (uint32_t i = 0; i < num_faces; ++i) {
  ------------------
  |  Branch (74:28): [True: 728, False: 523]
  ------------------
   75|    728|        Mesh::Face face;
   76|  2.85k|        for (int j = 0; j < 3; ++j) {
  ------------------
  |  Branch (76:25): [True: 2.16k, False: 694]
  ------------------
   77|  2.16k|          uint8_t val;
   78|  2.16k|          if (!buffer()->Decode(&val)) {
  ------------------
  |  Branch (78:15): [True: 14, False: 2.14k]
  ------------------
   79|     14|            return false;
   80|     14|          }
   81|  2.14k|          if (val >= num_points) {
  ------------------
  |  Branch (81:15): [True: 20, False: 2.12k]
  ------------------
   82|     20|            return false;
   83|     20|          }
   84|  2.12k|          face[j] = val;
   85|  2.12k|        }
   86|    694|        mesh()->AddFace(face);
   87|    694|      }
   88|    557|    } else if (num_points < (1 << 16)) {
  ------------------
  |  Branch (88:16): [True: 92, False: 315]
  ------------------
   89|       |      // Decode indices as uint16_t.
   90|    384|      for (uint32_t i = 0; i < num_faces; ++i) {
  ------------------
  |  Branch (90:28): [True: 359, False: 25]
  ------------------
   91|    359|        Mesh::Face face;
   92|  1.29k|        for (int j = 0; j < 3; ++j) {
  ------------------
  |  Branch (92:25): [True: 1.00k, False: 292]
  ------------------
   93|  1.00k|          uint16_t val;
   94|  1.00k|          if (!buffer()->Decode(&val)) {
  ------------------
  |  Branch (94:15): [True: 38, False: 966]
  ------------------
   95|     38|            return false;
   96|     38|          }
   97|    966|          if (val >= num_points) {
  ------------------
  |  Branch (97:15): [True: 29, False: 937]
  ------------------
   98|     29|            return false;
   99|     29|          }
  100|    937|          face[j] = val;
  101|    937|        }
  102|    292|        mesh()->AddFace(face);
  103|    292|      }
  104|    315|    } else if (num_points < (1 << 21) &&
  ------------------
  |  Branch (104:16): [True: 141, False: 174]
  ------------------
  105|    141|               bitstream_version() >= DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    141|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (105:16): [True: 131, False: 10]
  ------------------
  106|       |      // Decode indices as uint32_t.
  107|  1.68k|      for (uint32_t i = 0; i < num_faces; ++i) {
  ------------------
  |  Branch (107:28): [True: 1.63k, False: 44]
  ------------------
  108|  1.63k|        Mesh::Face face;
  109|  6.38k|        for (int j = 0; j < 3; ++j) {
  ------------------
  |  Branch (109:25): [True: 4.82k, False: 1.55k]
  ------------------
  110|  4.82k|          uint32_t val;
  111|  4.82k|          if (!DecodeVarint(&val, buffer())) {
  ------------------
  |  Branch (111:15): [True: 33, False: 4.79k]
  ------------------
  112|     33|            return false;
  113|     33|          }
  114|  4.79k|          if (val >= num_points) {
  ------------------
  |  Branch (114:15): [True: 54, False: 4.74k]
  ------------------
  115|     54|            return false;
  116|     54|          }
  117|  4.74k|          face[j] = val;
  118|  4.74k|        }
  119|  1.55k|        mesh()->AddFace(face);
  120|  1.55k|      }
  121|    184|    } else {
  122|       |      // Decode faces as uint32_t (default).
  123|  1.24k|      for (uint32_t i = 0; i < num_faces; ++i) {
  ------------------
  |  Branch (123:28): [True: 1.18k, False: 56]
  ------------------
  124|  1.18k|        Mesh::Face face;
  125|  4.45k|        for (int j = 0; j < 3; ++j) {
  ------------------
  |  Branch (125:25): [True: 3.39k, False: 1.05k]
  ------------------
  126|  3.39k|          uint32_t val;
  127|  3.39k|          if (!buffer()->Decode(&val)) {
  ------------------
  |  Branch (127:15): [True: 72, False: 3.32k]
  ------------------
  128|     72|            return false;
  129|     72|          }
  130|  3.32k|          if (val >= num_points) {
  ------------------
  |  Branch (130:15): [True: 56, False: 3.27k]
  ------------------
  131|     56|            return false;
  132|     56|          }
  133|  3.27k|          face[j] = val;
  134|  3.27k|        }
  135|  1.05k|        mesh()->AddFace(face);
  136|  1.05k|      }
  137|    184|    }
  138|    964|  }
  139|    784|  point_cloud()->set_num_points(num_points);
  140|    784|  return true;
  141|  5.24k|}
_ZN5draco21MeshSequentialDecoder23CreateAttributesDecoderEi:
  143|  17.3k|bool MeshSequentialDecoder::CreateAttributesDecoder(int32_t att_decoder_id) {
  144|       |  // Always create the basic attribute decoder.
  145|  17.3k|  return SetAttributesDecoder(
  146|  17.3k|      att_decoder_id,
  147|  17.3k|      std::unique_ptr<AttributesDecoder>(
  148|  17.3k|          new SequentialAttributeDecodersController(
  149|  17.3k|              std::unique_ptr<PointsSequencer>(
  150|  17.3k|                  new LinearSequencer(point_cloud()->num_points())))));
  151|  17.3k|}
_ZN5draco21MeshSequentialDecoder26DecodeAndDecompressIndicesEjj:
  154|  4.27k|                                                       uint32_t num_points) {
  155|       |  // Get decoded indices differences that were encoded with an entropy code.
  156|  4.27k|  std::vector<uint32_t> indices_buffer(num_faces * 3);
  157|  4.27k|  if (!DecodeSymbols(num_faces * 3, 1, buffer(), indices_buffer.data())) {
  ------------------
  |  Branch (157:7): [True: 3.97k, False: 306]
  ------------------
  158|  3.97k|    return false;
  159|  3.97k|  }
  160|       |  // Reconstruct the indices from the differences.
  161|       |  // See MeshSequentialEncoder::CompressAndEncodeIndices() for more details.
  162|    306|  int32_t last_index_value = 0;  // This will always be >= 0.
  163|    306|  int vertex_index = 0;
  164|    886|  for (uint32_t i = 0; i < num_faces; ++i) {
  ------------------
  |  Branch (164:24): [True: 750, False: 136]
  ------------------
  165|    750|    Mesh::Face face;
  166|  2.56k|    for (int j = 0; j < 3; ++j) {
  ------------------
  |  Branch (166:21): [True: 1.98k, False: 580]
  ------------------
  167|  1.98k|      const uint32_t encoded_val = indices_buffer[vertex_index++];
  168|  1.98k|      int32_t index_diff = (encoded_val >> 1);
  169|  1.98k|      if (encoded_val & 1) {
  ------------------
  |  Branch (169:11): [True: 977, False: 1.00k]
  ------------------
  170|    977|        if (index_diff > last_index_value) {
  ------------------
  |  Branch (170:13): [True: 51, False: 926]
  ------------------
  171|       |          // Subtracting index_diff would result in a negative index.
  172|     51|          return false;
  173|     51|        }
  174|    926|        index_diff = -index_diff;
  175|  1.00k|      } else {
  176|  1.00k|        if (index_diff >
  ------------------
  |  Branch (176:13): [True: 0, False: 1.00k]
  ------------------
  177|  1.00k|            (std::numeric_limits<int32_t>::max() - last_index_value)) {
  178|       |          // Adding index_diff to last_index_value would overflow.
  179|      0|          return false;
  180|      0|        }
  181|  1.00k|      }
  182|  1.92k|      const int32_t index_value = index_diff + last_index_value;
  183|  1.92k|      if (index_value < 0 || static_cast<uint32_t>(index_value) >= num_points) {
  ------------------
  |  Branch (183:11): [True: 0, False: 1.92k]
  |  Branch (183:30): [True: 119, False: 1.81k]
  ------------------
  184|    119|        return false;
  185|    119|      }
  186|  1.81k|      face[j] = index_value;
  187|  1.81k|      last_index_value = index_value;
  188|  1.81k|    }
  189|    580|    mesh()->AddFace(face);
  190|    580|  }
  191|    136|  return true;
  192|    306|}

_ZN5draco19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE16OnTraversalStartEv:
   54|  1.70k|  void OnTraversalStart() {}
_ZN5draco19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE18TraverseFromCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   59|  3.90M|  bool TraverseFromCorner(CornerIndex corner_id) {
   60|  3.90M|    if (this->IsFaceVisited(corner_id)) {
  ------------------
  |  Branch (60:9): [True: 3.90M, False: 5.37k]
  ------------------
   61|  3.90M|      return true;  // Already traversed.
   62|  3.90M|    }
   63|       |
   64|  5.37k|    corner_traversal_stack_.clear();
   65|  5.37k|    corner_traversal_stack_.push_back(corner_id);
   66|       |    // For the first face, check the remaining corners as they may not be
   67|       |    // processed yet.
   68|  5.37k|    const VertexIndex next_vert =
   69|  5.37k|        this->corner_table()->Vertex(this->corner_table()->Next(corner_id));
   70|  5.37k|    const VertexIndex prev_vert =
   71|  5.37k|        this->corner_table()->Vertex(this->corner_table()->Previous(corner_id));
   72|  5.37k|    if (next_vert == kInvalidVertexIndex || prev_vert == kInvalidVertexIndex) {
  ------------------
  |  Branch (72:9): [True: 0, False: 5.37k]
  |  Branch (72:45): [True: 0, False: 5.37k]
  ------------------
   73|      0|      return false;
   74|      0|    }
   75|  5.37k|    if (!this->IsVertexVisited(next_vert)) {
  ------------------
  |  Branch (75:9): [True: 3.77k, False: 1.59k]
  ------------------
   76|  3.77k|      this->MarkVertexVisited(next_vert);
   77|  3.77k|      this->traversal_observer().OnNewVertexVisited(
   78|  3.77k|          next_vert, this->corner_table()->Next(corner_id));
   79|  3.77k|    }
   80|  5.37k|    if (!this->IsVertexVisited(prev_vert)) {
  ------------------
  |  Branch (80:9): [True: 4.42k, False: 944]
  ------------------
   81|  4.42k|      this->MarkVertexVisited(prev_vert);
   82|  4.42k|      this->traversal_observer().OnNewVertexVisited(
   83|  4.42k|          prev_vert, this->corner_table()->Previous(corner_id));
   84|  4.42k|    }
   85|       |
   86|       |    // Start the actual traversal.
   87|  31.9k|    while (!corner_traversal_stack_.empty()) {
  ------------------
  |  Branch (87:12): [True: 26.5k, False: 5.37k]
  ------------------
   88|       |      // Currently processed corner.
   89|  26.5k|      corner_id = corner_traversal_stack_.back();
   90|  26.5k|      FaceIndex face_id(corner_id.value() / 3);
   91|       |      // Make sure the face hasn't been visited yet.
   92|  26.5k|      if (corner_id == kInvalidCornerIndex || this->IsFaceVisited(face_id)) {
  ------------------
  |  Branch (92:11): [True: 0, False: 26.5k]
  |  Branch (92:47): [True: 1.04k, False: 25.5k]
  ------------------
   93|       |        // This face has been already traversed.
   94|  1.04k|        corner_traversal_stack_.pop_back();
   95|  1.04k|        continue;
   96|  1.04k|      }
   97|  3.90M|      while (true) {
  ------------------
  |  Branch (97:14): [True: 3.90M, Folded]
  ------------------
   98|  3.90M|        this->MarkFaceVisited(face_id);
   99|  3.90M|        this->traversal_observer().OnNewFaceVisited(face_id);
  100|  3.90M|        const VertexIndex vert_id = this->corner_table()->Vertex(corner_id);
  101|  3.90M|        if (vert_id == kInvalidVertexIndex) {
  ------------------
  |  Branch (101:13): [True: 0, False: 3.90M]
  ------------------
  102|      0|          return false;
  103|      0|        }
  104|  3.90M|        if (!this->IsVertexVisited(vert_id)) {
  ------------------
  |  Branch (104:13): [True: 1.97M, False: 1.93M]
  ------------------
  105|  1.97M|          const bool on_boundary = this->corner_table()->IsOnBoundary(vert_id);
  106|  1.97M|          this->MarkVertexVisited(vert_id);
  107|  1.97M|          this->traversal_observer().OnNewVertexVisited(vert_id, corner_id);
  108|  1.97M|          if (!on_boundary) {
  ------------------
  |  Branch (108:15): [True: 1.92M, False: 51.3k]
  ------------------
  109|  1.92M|            corner_id = this->corner_table()->GetRightCorner(corner_id);
  110|  1.92M|            face_id = FaceIndex(corner_id.value() / 3);
  111|  1.92M|            continue;
  112|  1.92M|          }
  113|  1.97M|        }
  114|       |        // The current vertex has been already visited or it was on a boundary.
  115|       |        // We need to determine whether we can visit any of it's neighboring
  116|       |        // faces.
  117|  1.98M|        const CornerIndex right_corner_id =
  118|  1.98M|            this->corner_table()->GetRightCorner(corner_id);
  119|  1.98M|        const CornerIndex left_corner_id =
  120|  1.98M|            this->corner_table()->GetLeftCorner(corner_id);
  121|  1.98M|        const FaceIndex right_face_id(
  122|  1.98M|            (right_corner_id == kInvalidCornerIndex
  ------------------
  |  Branch (122:14): [True: 37.7k, False: 1.94M]
  ------------------
  123|  1.98M|                 ? kInvalidFaceIndex
  124|  1.98M|                 : FaceIndex(right_corner_id.value() / 3)));
  125|  1.98M|        const FaceIndex left_face_id(
  126|  1.98M|            (left_corner_id == kInvalidCornerIndex
  ------------------
  |  Branch (126:14): [True: 17.2k, False: 1.96M]
  ------------------
  127|  1.98M|                 ? kInvalidFaceIndex
  128|  1.98M|                 : FaceIndex(left_corner_id.value() / 3)));
  129|  1.98M|        if (this->IsFaceVisited(right_face_id)) {
  ------------------
  |  Branch (129:13): [True: 1.93M, False: 50.8k]
  ------------------
  130|       |          // Right face has been already visited.
  131|  1.93M|          if (this->IsFaceVisited(left_face_id)) {
  ------------------
  |  Branch (131:15): [True: 14.9k, False: 1.91M]
  ------------------
  132|       |            // Both neighboring faces are visited. End reached.
  133|  14.9k|            corner_traversal_stack_.pop_back();
  134|  14.9k|            break;  // Break from the while (true) loop.
  135|  1.91M|          } else {
  136|       |            // Go to the left face.
  137|  1.91M|            corner_id = left_corner_id;
  138|  1.91M|            face_id = left_face_id;
  139|  1.91M|          }
  140|  1.93M|        } else {
  141|       |          // Right face was not visited.
  142|  50.8k|          if (this->IsFaceVisited(left_face_id)) {
  ------------------
  |  Branch (142:15): [True: 40.2k, False: 10.5k]
  ------------------
  143|       |            // Left face visited, go to the right one.
  144|  40.2k|            corner_id = right_corner_id;
  145|  40.2k|            face_id = right_face_id;
  146|  40.2k|          } else {
  147|       |            // Both neighboring faces are unvisited, we need to visit both of
  148|       |            // them.
  149|       |
  150|       |            // Split the traversal.
  151|       |            // First make the top of the current corner stack point to the left
  152|       |            // face (this one will be processed second).
  153|  10.5k|            corner_traversal_stack_.back() = left_corner_id;
  154|       |            // Add a new corner to the top of the stack (right face needs to
  155|       |            // be traversed first).
  156|  10.5k|            corner_traversal_stack_.push_back(right_corner_id);
  157|       |            // Break from the while (true) loop.
  158|  10.5k|            break;
  159|  10.5k|          }
  160|  50.8k|        }
  161|  1.98M|      }
  162|  25.5k|    }
  163|  5.37k|    return true;
  164|  5.37k|  }
_ZN5draco19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE14OnTraversalEndEv:
   57|  1.70k|  void OnTraversalEnd() {}
_ZN5draco19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEEC2Ev:
   51|  3.56k|  DepthFirstTraverser() {}
_ZN5draco19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE16OnTraversalStartEv:
   54|  2.07k|  void OnTraversalStart() {}
_ZN5draco19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE18TraverseFromCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   59|  5.86M|  bool TraverseFromCorner(CornerIndex corner_id) {
   60|  5.86M|    if (this->IsFaceVisited(corner_id)) {
  ------------------
  |  Branch (60:9): [True: 1.31M, False: 4.54M]
  ------------------
   61|  1.31M|      return true;  // Already traversed.
   62|  1.31M|    }
   63|       |
   64|  4.54M|    corner_traversal_stack_.clear();
   65|  4.54M|    corner_traversal_stack_.push_back(corner_id);
   66|       |    // For the first face, check the remaining corners as they may not be
   67|       |    // processed yet.
   68|  4.54M|    const VertexIndex next_vert =
   69|  4.54M|        this->corner_table()->Vertex(this->corner_table()->Next(corner_id));
   70|  4.54M|    const VertexIndex prev_vert =
   71|  4.54M|        this->corner_table()->Vertex(this->corner_table()->Previous(corner_id));
   72|  4.54M|    if (next_vert == kInvalidVertexIndex || prev_vert == kInvalidVertexIndex) {
  ------------------
  |  Branch (72:9): [True: 0, False: 4.54M]
  |  Branch (72:45): [True: 0, False: 4.54M]
  ------------------
   73|      0|      return false;
   74|      0|    }
   75|  4.54M|    if (!this->IsVertexVisited(next_vert)) {
  ------------------
  |  Branch (75:9): [True: 4.54M, False: 1.82k]
  ------------------
   76|  4.54M|      this->MarkVertexVisited(next_vert);
   77|  4.54M|      this->traversal_observer().OnNewVertexVisited(
   78|  4.54M|          next_vert, this->corner_table()->Next(corner_id));
   79|  4.54M|    }
   80|  4.54M|    if (!this->IsVertexVisited(prev_vert)) {
  ------------------
  |  Branch (80:9): [True: 4.54M, False: 1.97k]
  ------------------
   81|  4.54M|      this->MarkVertexVisited(prev_vert);
   82|  4.54M|      this->traversal_observer().OnNewVertexVisited(
   83|  4.54M|          prev_vert, this->corner_table()->Previous(corner_id));
   84|  4.54M|    }
   85|       |
   86|       |    // Start the actual traversal.
   87|  9.20M|    while (!corner_traversal_stack_.empty()) {
  ------------------
  |  Branch (87:12): [True: 4.65M, False: 4.54M]
  ------------------
   88|       |      // Currently processed corner.
   89|  4.65M|      corner_id = corner_traversal_stack_.back();
   90|  4.65M|      FaceIndex face_id(corner_id.value() / 3);
   91|       |      // Make sure the face hasn't been visited yet.
   92|  4.65M|      if (corner_id == kInvalidCornerIndex || this->IsFaceVisited(face_id)) {
  ------------------
  |  Branch (92:11): [True: 0, False: 4.65M]
  |  Branch (92:47): [True: 8.00k, False: 4.65M]
  ------------------
   93|       |        // This face has been already traversed.
   94|  8.00k|        corner_traversal_stack_.pop_back();
   95|  8.00k|        continue;
   96|  8.00k|      }
   97|  5.86M|      while (true) {
  ------------------
  |  Branch (97:14): [True: 5.86M, Folded]
  ------------------
   98|  5.86M|        this->MarkFaceVisited(face_id);
   99|  5.86M|        this->traversal_observer().OnNewFaceVisited(face_id);
  100|  5.86M|        const VertexIndex vert_id = this->corner_table()->Vertex(corner_id);
  101|  5.86M|        if (vert_id == kInvalidVertexIndex) {
  ------------------
  |  Branch (101:13): [True: 0, False: 5.86M]
  ------------------
  102|      0|          return false;
  103|      0|        }
  104|  5.86M|        if (!this->IsVertexVisited(vert_id)) {
  ------------------
  |  Branch (104:13): [True: 5.24M, False: 623k]
  ------------------
  105|  5.24M|          const bool on_boundary = this->corner_table()->IsOnBoundary(vert_id);
  106|  5.24M|          this->MarkVertexVisited(vert_id);
  107|  5.24M|          this->traversal_observer().OnNewVertexVisited(vert_id, corner_id);
  108|  5.24M|          if (!on_boundary) {
  ------------------
  |  Branch (108:15): [True: 602k, False: 4.63M]
  ------------------
  109|   602k|            corner_id = this->corner_table()->GetRightCorner(corner_id);
  110|   602k|            face_id = FaceIndex(corner_id.value() / 3);
  111|   602k|            continue;
  112|   602k|          }
  113|  5.24M|        }
  114|       |        // The current vertex has been already visited or it was on a boundary.
  115|       |        // We need to determine whether we can visit any of it's neighboring
  116|       |        // faces.
  117|  5.26M|        const CornerIndex right_corner_id =
  118|  5.26M|            this->corner_table()->GetRightCorner(corner_id);
  119|  5.26M|        const CornerIndex left_corner_id =
  120|  5.26M|            this->corner_table()->GetLeftCorner(corner_id);
  121|  5.26M|        const FaceIndex right_face_id(
  122|  5.26M|            (right_corner_id == kInvalidCornerIndex
  ------------------
  |  Branch (122:14): [True: 4.59M, False: 664k]
  ------------------
  123|  5.26M|                 ? kInvalidFaceIndex
  124|  5.26M|                 : FaceIndex(right_corner_id.value() / 3)));
  125|  5.26M|        const FaceIndex left_face_id(
  126|  5.26M|            (left_corner_id == kInvalidCornerIndex
  ------------------
  |  Branch (126:14): [True: 4.58M, False: 672k]
  ------------------
  127|  5.26M|                 ? kInvalidFaceIndex
  128|  5.26M|                 : FaceIndex(left_corner_id.value() / 3)));
  129|  5.26M|        if (this->IsFaceVisited(right_face_id)) {
  ------------------
  |  Branch (129:13): [True: 5.17M, False: 86.0k]
  ------------------
  130|       |          // Right face has been already visited.
  131|  5.17M|          if (this->IsFaceVisited(left_face_id)) {
  ------------------
  |  Branch (131:15): [True: 4.59M, False: 580k]
  ------------------
  132|       |            // Both neighboring faces are visited. End reached.
  133|  4.59M|            corner_traversal_stack_.pop_back();
  134|  4.59M|            break;  // Break from the while (true) loop.
  135|  4.59M|          } else {
  136|       |            // Go to the left face.
  137|   580k|            corner_id = left_corner_id;
  138|   580k|            face_id = left_face_id;
  139|   580k|          }
  140|  5.17M|        } else {
  141|       |          // Right face was not visited.
  142|  86.0k|          if (this->IsFaceVisited(left_face_id)) {
  ------------------
  |  Branch (142:15): [True: 31.0k, False: 54.9k]
  ------------------
  143|       |            // Left face visited, go to the right one.
  144|  31.0k|            corner_id = right_corner_id;
  145|  31.0k|            face_id = right_face_id;
  146|  54.9k|          } else {
  147|       |            // Both neighboring faces are unvisited, we need to visit both of
  148|       |            // them.
  149|       |
  150|       |            // Split the traversal.
  151|       |            // First make the top of the current corner stack point to the left
  152|       |            // face (this one will be processed second).
  153|  54.9k|            corner_traversal_stack_.back() = left_corner_id;
  154|       |            // Add a new corner to the top of the stack (right face needs to
  155|       |            // be traversed first).
  156|  54.9k|            corner_traversal_stack_.push_back(right_corner_id);
  157|       |            // Break from the while (true) loop.
  158|  54.9k|            break;
  159|  54.9k|          }
  160|  86.0k|        }
  161|  5.26M|      }
  162|  4.65M|    }
  163|  4.54M|    return true;
  164|  4.54M|  }
_ZN5draco19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE14OnTraversalEndEv:
   57|  2.07k|  void OnTraversalEnd() {}
_ZN5draco19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEEC2Ev:
   51|  4.28k|  DepthFirstTraverser() {}

_ZN5draco28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE16OnTraversalStartEv:
   58|    425|  void OnTraversalStart() {
   59|    425|    prediction_degree_.resize(this->corner_table()->num_vertices(), 0);
   60|    425|  }
_ZN5draco28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE18TraverseFromCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   65|  2.96M|  bool TraverseFromCorner(CornerIndex corner_id) {
   66|  2.96M|    if (prediction_degree_.size() == 0) {
  ------------------
  |  Branch (66:9): [True: 0, False: 2.96M]
  ------------------
   67|      0|      return true;
   68|      0|    }
   69|       |
   70|       |    // Traversal starts from the |corner_id|. It's going to follow either the
   71|       |    // right or the left neighboring faces to |corner_id| based on their
   72|       |    // prediction degree.
   73|  2.96M|    traversal_stacks_[0].push_back(corner_id);
   74|  2.96M|    best_priority_ = 0;
   75|       |    // For the first face, check the remaining corners as they may not be
   76|       |    // processed yet.
   77|  2.96M|    const VertexIndex next_vert =
   78|  2.96M|        this->corner_table()->Vertex(this->corner_table()->Next(corner_id));
   79|  2.96M|    const VertexIndex prev_vert =
   80|  2.96M|        this->corner_table()->Vertex(this->corner_table()->Previous(corner_id));
   81|  2.96M|    if (!this->IsVertexVisited(next_vert)) {
  ------------------
  |  Branch (81:9): [True: 1.24k, False: 2.96M]
  ------------------
   82|  1.24k|      this->MarkVertexVisited(next_vert);
   83|  1.24k|      this->traversal_observer().OnNewVertexVisited(
   84|  1.24k|          next_vert, this->corner_table()->Next(corner_id));
   85|  1.24k|    }
   86|  2.96M|    if (!this->IsVertexVisited(prev_vert)) {
  ------------------
  |  Branch (86:9): [True: 1.39k, False: 2.96M]
  ------------------
   87|  1.39k|      this->MarkVertexVisited(prev_vert);
   88|  1.39k|      this->traversal_observer().OnNewVertexVisited(
   89|  1.39k|          prev_vert, this->corner_table()->Previous(corner_id));
   90|  1.39k|    }
   91|  2.96M|    const VertexIndex tip_vertex = this->corner_table()->Vertex(corner_id);
   92|  2.96M|    if (!this->IsVertexVisited(tip_vertex)) {
  ------------------
  |  Branch (92:9): [True: 1.11k, False: 2.96M]
  ------------------
   93|  1.11k|      this->MarkVertexVisited(tip_vertex);
   94|  1.11k|      this->traversal_observer().OnNewVertexVisited(tip_vertex, corner_id);
   95|  1.11k|    }
   96|       |    // Start the actual traversal.
   97|  8.63M|    while ((corner_id = PopNextCornerToTraverse()) != kInvalidCornerIndex) {
  ------------------
  |  Branch (97:12): [True: 5.66M, False: 2.96M]
  ------------------
   98|  5.66M|      FaceIndex face_id(corner_id.value() / 3);
   99|       |      // Make sure the face hasn't been visited yet.
  100|  5.66M|      if (this->IsFaceVisited(face_id)) {
  ------------------
  |  Branch (100:11): [True: 4.43M, False: 1.23M]
  ------------------
  101|       |        // This face has been already traversed.
  102|  4.43M|        continue;
  103|  4.43M|      }
  104|       |
  105|  2.96M|      while (true) {
  ------------------
  |  Branch (105:14): [True: 2.96M, Folded]
  ------------------
  106|  2.96M|        face_id = FaceIndex(corner_id.value() / 3);
  107|  2.96M|        this->MarkFaceVisited(face_id);
  108|  2.96M|        this->traversal_observer().OnNewFaceVisited(face_id);
  109|       |
  110|       |        // If the newly reached vertex hasn't been visited, mark it and notify
  111|       |        // the observer.
  112|  2.96M|        const VertexIndex vert_id = this->corner_table()->Vertex(corner_id);
  113|  2.96M|        if (!this->IsVertexVisited(vert_id)) {
  ------------------
  |  Branch (113:13): [True: 1.50M, False: 1.46M]
  ------------------
  114|  1.50M|          this->MarkVertexVisited(vert_id);
  115|  1.50M|          this->traversal_observer().OnNewVertexVisited(vert_id, corner_id);
  116|  1.50M|        }
  117|       |
  118|       |        // Check whether we can traverse to the right and left neighboring
  119|       |        // faces.
  120|  2.96M|        const CornerIndex right_corner_id =
  121|  2.96M|            this->corner_table()->GetRightCorner(corner_id);
  122|  2.96M|        const CornerIndex left_corner_id =
  123|  2.96M|            this->corner_table()->GetLeftCorner(corner_id);
  124|  2.96M|        const FaceIndex right_face_id(
  125|  2.96M|            (right_corner_id == kInvalidCornerIndex
  ------------------
  |  Branch (125:14): [True: 18.0k, False: 2.94M]
  ------------------
  126|  2.96M|                 ? kInvalidFaceIndex
  127|  2.96M|                 : FaceIndex(right_corner_id.value() / 3)));
  128|  2.96M|        const FaceIndex left_face_id(
  129|  2.96M|            (left_corner_id == kInvalidCornerIndex
  ------------------
  |  Branch (129:14): [True: 21.5k, False: 2.94M]
  ------------------
  130|  2.96M|                 ? kInvalidFaceIndex
  131|  2.96M|                 : FaceIndex(left_corner_id.value() / 3)));
  132|  2.96M|        const bool is_right_face_visited = this->IsFaceVisited(right_face_id);
  133|  2.96M|        const bool is_left_face_visited = this->IsFaceVisited(left_face_id);
  134|       |
  135|  2.96M|        if (!is_left_face_visited) {
  ------------------
  |  Branch (135:13): [True: 2.33M, False: 635k]
  ------------------
  136|       |          // We can go to the left face.
  137|  2.33M|          const int priority = ComputePriority(left_corner_id);
  138|  2.33M|          if (is_right_face_visited && priority <= best_priority_) {
  ------------------
  |  Branch (138:15): [True: 863k, False: 1.46M]
  |  Branch (138:40): [True: 838k, False: 24.9k]
  ------------------
  139|       |            // Right face has been already visited and the priority is equal or
  140|       |            // better than the best priority. We are sure that the left face
  141|       |            // would be traversed next so there is no need to put it onto the
  142|       |            // stack.
  143|   838k|            corner_id = left_corner_id;
  144|   838k|            continue;
  145|  1.49M|          } else {
  146|  1.49M|            AddCornerToTraversalStack(left_corner_id, priority);
  147|  1.49M|          }
  148|  2.33M|        }
  149|  2.12M|        if (!is_right_face_visited) {
  ------------------
  |  Branch (149:13): [True: 2.09M, False: 30.7k]
  ------------------
  150|       |          // Go to the right face.
  151|  2.09M|          const int priority = ComputePriority(right_corner_id);
  152|  2.09M|          if (priority <= best_priority_) {
  ------------------
  |  Branch (152:15): [True: 895k, False: 1.20M]
  ------------------
  153|       |            // We are sure that the right face would be traversed next so there
  154|       |            // is no need to put it onto the stack.
  155|   895k|            corner_id = right_corner_id;
  156|   895k|            continue;
  157|  1.20M|          } else {
  158|  1.20M|            AddCornerToTraversalStack(right_corner_id, priority);
  159|  1.20M|          }
  160|  2.09M|        }
  161|       |
  162|       |        // Couldn't proceed directly to the next corner
  163|  1.23M|        break;
  164|  2.12M|      }
  165|  1.23M|    }
  166|  2.96M|    return true;
  167|  2.96M|  }
_ZN5draco28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE23PopNextCornerToTraverseEv:
  173|  8.63M|  CornerIndex PopNextCornerToTraverse() {
  174|  18.1M|    for (int i = best_priority_; i < kMaxPriority; ++i) {
  ------------------
  |  Branch (174:34): [True: 15.1M, False: 2.96M]
  ------------------
  175|  15.1M|      if (!traversal_stacks_[i].empty()) {
  ------------------
  |  Branch (175:11): [True: 5.66M, False: 9.51M]
  ------------------
  176|  5.66M|        const CornerIndex ret = traversal_stacks_[i].back();
  177|  5.66M|        traversal_stacks_[i].pop_back();
  178|  5.66M|        best_priority_ = i;
  179|  5.66M|        return ret;
  180|  5.66M|      }
  181|  15.1M|    }
  182|  2.96M|    return kInvalidCornerIndex;
  183|  8.63M|  }
_ZN5draco28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE15ComputePriorityENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  194|  4.43M|  inline int ComputePriority(CornerIndex corner_id) {
  195|  4.43M|    const VertexIndex v_tip = this->corner_table()->Vertex(corner_id);
  196|       |    // Priority 0 when traversing to already visited vertices.
  197|  4.43M|    int priority = 0;
  198|  4.43M|    if (!this->IsVertexVisited(v_tip)) {
  ------------------
  |  Branch (198:9): [True: 2.96M, False: 1.46M]
  ------------------
  199|  2.96M|      const int degree = ++prediction_degree_[v_tip];
  200|       |      // Priority 1 when prediction degree > 1, otherwise 2.
  201|  2.96M|      priority = (degree > 1 ? 1 : 2);
  ------------------
  |  Branch (201:19): [True: 1.46M, False: 1.50M]
  ------------------
  202|  2.96M|    }
  203|       |    // Clamp the priority to the maximum number of buckets.
  204|  4.43M|    if (priority >= kMaxPriority) {
  ------------------
  |  Branch (204:9): [True: 0, False: 4.43M]
  ------------------
  205|      0|      priority = kMaxPriority - 1;
  206|      0|    }
  207|  4.43M|    return priority;
  208|  4.43M|  }
_ZN5draco28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE25AddCornerToTraversalStackENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEi:
  185|  2.69M|  inline void AddCornerToTraversalStack(CornerIndex ci, int priority) {
  186|  2.69M|    traversal_stacks_[priority].push_back(ci);
  187|       |    // Make sure that the best available priority is up to date.
  188|  2.69M|    if (priority < best_priority_) {
  ------------------
  |  Branch (188:9): [True: 613k, False: 2.08M]
  ------------------
  189|   613k|      best_priority_ = priority;
  190|   613k|    }
  191|  2.69M|  }
_ZN5draco28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE14OnTraversalEndEv:
   63|    425|  void OnTraversalEnd() {}
_ZN5draco28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEEC2Ev:
   55|    920|  MaxPredictionDegreeTraverser() {}

_ZN5draco36MeshAttributeIndicesEncodingObserverINS_11CornerTableEE18OnNewVertexVisitedENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEENS3_IjNS_21CornerIndex_tag_type_EEE:
   50|  3.49M|  inline void OnNewVertexVisited(VertexIndex vertex, CornerIndex corner) {
   51|  3.49M|    const PointIndex point_id =
   52|  3.49M|        mesh_->face(FaceIndex(corner.value() / 3))[corner.value() % 3];
   53|       |    // Append the visited attribute to the encoding order.
   54|  3.49M|    sequencer_->AddPointId(point_id);
   55|       |
   56|       |    // Keep track of visited corners.
   57|  3.49M|    encoding_data_->encoded_attribute_value_index_to_corner_map.push_back(
   58|  3.49M|        corner);
   59|       |
   60|  3.49M|    encoding_data_
   61|  3.49M|        ->vertex_to_encoded_attribute_value_index_map[vertex.value()] =
   62|  3.49M|        encoding_data_->num_values;
   63|       |
   64|  3.49M|    encoding_data_->num_values++;
   65|  3.49M|  }
_ZN5draco36MeshAttributeIndicesEncodingObserverINS_11CornerTableEE16OnNewFaceVisitedENS_9IndexTypeIjNS_19FaceIndex_tag_type_EEE:
   48|  6.87M|  void OnNewFaceVisited(FaceIndex /* face */) {}
_ZN5draco36MeshAttributeIndicesEncodingObserverINS_11CornerTableEEC2EPKS1_PKNS_4MeshEPNS_15PointsSequencerEPNS_32MeshAttributeIndicesEncodingDataE:
   41|  2.24k|      : att_connectivity_(connectivity),
   42|  2.24k|        encoding_data_(encoding_data),
   43|  2.24k|        mesh_(mesh),
   44|  2.24k|        sequencer_(sequencer) {}
_ZN5draco36MeshAttributeIndicesEncodingObserverINS_11CornerTableEEC2Ev:
   33|  4.48k|      : att_connectivity_(nullptr),
   34|  4.48k|        encoding_data_(nullptr),
   35|  4.48k|        mesh_(nullptr),
   36|  4.48k|        sequencer_(nullptr) {}
_ZN5draco36MeshAttributeIndicesEncodingObserverINS_24MeshAttributeCornerTableEE18OnNewVertexVisitedENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEENS3_IjNS_21CornerIndex_tag_type_EEE:
   50|  14.3M|  inline void OnNewVertexVisited(VertexIndex vertex, CornerIndex corner) {
   51|  14.3M|    const PointIndex point_id =
   52|  14.3M|        mesh_->face(FaceIndex(corner.value() / 3))[corner.value() % 3];
   53|       |    // Append the visited attribute to the encoding order.
   54|  14.3M|    sequencer_->AddPointId(point_id);
   55|       |
   56|       |    // Keep track of visited corners.
   57|  14.3M|    encoding_data_->encoded_attribute_value_index_to_corner_map.push_back(
   58|  14.3M|        corner);
   59|       |
   60|  14.3M|    encoding_data_
   61|  14.3M|        ->vertex_to_encoded_attribute_value_index_map[vertex.value()] =
   62|  14.3M|        encoding_data_->num_values;
   63|       |
   64|  14.3M|    encoding_data_->num_values++;
   65|  14.3M|  }
_ZN5draco36MeshAttributeIndicesEncodingObserverINS_24MeshAttributeCornerTableEE16OnNewFaceVisitedENS_9IndexTypeIjNS_19FaceIndex_tag_type_EEE:
   48|  5.86M|  void OnNewFaceVisited(FaceIndex /* face */) {}
_ZN5draco36MeshAttributeIndicesEncodingObserverINS_24MeshAttributeCornerTableEEC2EPKS1_PKNS_4MeshEPNS_15PointsSequencerEPNS_32MeshAttributeIndicesEncodingDataE:
   41|  2.14k|      : att_connectivity_(connectivity),
   42|  2.14k|        encoding_data_(encoding_data),
   43|  2.14k|        mesh_(mesh),
   44|  2.14k|        sequencer_(sequencer) {}
_ZN5draco36MeshAttributeIndicesEncodingObserverINS_24MeshAttributeCornerTableEEC2Ev:
   33|  4.28k|      : att_connectivity_(nullptr),
   34|  4.28k|        encoding_data_(nullptr),
   35|  4.28k|        mesh_(nullptr),
   36|  4.28k|        sequencer_(nullptr) {}

_ZN5draco22MeshTraversalSequencerINS_28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEEC2EPKNS_4MeshEPKNS_32MeshAttributeIndicesEncodingDataE:
   34|    460|      : mesh_(mesh), encoding_data_(encoding_data), corner_order_(nullptr) {}
_ZN5draco22MeshTraversalSequencerINS_28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE34UpdatePointToAttributeIndexMappingEPNS_14PointAttributeE:
   48|    845|  bool UpdatePointToAttributeIndexMapping(PointAttribute* attribute) override {
   49|    845|    const auto* corner_table = traverser_.corner_table();
   50|    845|    attribute->SetExplicitMapping(mesh_->num_points());
   51|    845|    const size_t num_faces = mesh_->num_faces();
   52|    845|    const size_t num_points = mesh_->num_points();
   53|  4.08M|    for (FaceIndex f(0); f < static_cast<uint32_t>(num_faces); ++f) {
  ------------------
  |  Branch (53:26): [True: 4.08M, False: 845]
  ------------------
   54|  4.08M|      const auto& face = mesh_->face(f);
   55|  16.3M|      for (int p = 0; p < 3; ++p) {
  ------------------
  |  Branch (55:23): [True: 12.2M, False: 4.08M]
  ------------------
   56|  12.2M|        const PointIndex point_id = face[p];
   57|  12.2M|        const VertexIndex vert_id =
   58|  12.2M|            corner_table->Vertex(CornerIndex(3 * f.value() + p));
   59|  12.2M|        if (vert_id == kInvalidVertexIndex) {
  ------------------
  |  Branch (59:13): [True: 0, False: 12.2M]
  ------------------
   60|      0|          return false;
   61|      0|        }
   62|  12.2M|        const AttributeValueIndex att_entry_id(
   63|  12.2M|            encoding_data_
   64|  12.2M|                ->vertex_to_encoded_attribute_value_index_map[vert_id.value()]);
   65|  12.2M|        if (point_id >= num_points || att_entry_id.value() >= num_points) {
  ------------------
  |  Branch (65:13): [True: 0, False: 12.2M]
  |  Branch (65:13): [True: 0, False: 12.2M]
  |  Branch (65:39): [True: 0, False: 12.2M]
  ------------------
   66|       |          // There cannot be more attribute values than the number of points.
   67|      0|          return false;
   68|      0|        }
   69|  12.2M|        attribute->SetPointMapEntry(point_id, att_entry_id);
   70|  12.2M|      }
   71|  4.08M|    }
   72|    845|    return true;
   73|    845|  }
_ZN5draco22MeshTraversalSequencerINS_28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE24GenerateSequenceInternalEv:
   76|    425|  bool GenerateSequenceInternal() override {
   77|       |    // Preallocate memory for storing point indices. We expect the number of
   78|       |    // points to be the same as the number of corner table vertices.
   79|    425|    out_point_ids()->reserve(traverser_.corner_table()->num_vertices());
   80|       |
   81|    425|    traverser_.OnTraversalStart();
   82|    425|    if (corner_order_) {
  ------------------
  |  Branch (82:9): [True: 0, False: 425]
  ------------------
   83|      0|      for (uint32_t i = 0; i < corner_order_->size(); ++i) {
  ------------------
  |  Branch (83:28): [True: 0, False: 0]
  ------------------
   84|      0|        if (!ProcessCorner(corner_order_->at(i))) {
  ------------------
  |  Branch (84:13): [True: 0, False: 0]
  ------------------
   85|      0|          return false;
   86|      0|        }
   87|      0|      }
   88|    425|    } else {
   89|    425|      const int32_t num_faces = traverser_.corner_table()->num_faces();
   90|  2.96M|      for (int i = 0; i < num_faces; ++i) {
  ------------------
  |  Branch (90:23): [True: 2.96M, False: 425]
  ------------------
   91|  2.96M|        if (!ProcessCorner(CornerIndex(3 * i))) {
  ------------------
  |  Branch (91:13): [True: 0, False: 2.96M]
  ------------------
   92|      0|          return false;
   93|      0|        }
   94|  2.96M|      }
   95|    425|    }
   96|    425|    traverser_.OnTraversalEnd();
   97|    425|    return true;
   98|    425|  }
_ZN5draco22MeshTraversalSequencerINS_28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE13ProcessCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  101|  2.96M|  bool ProcessCorner(CornerIndex corner_id) {
  102|  2.96M|    return traverser_.TraverseFromCorner(corner_id);
  103|  2.96M|  }
_ZN5draco22MeshTraversalSequencerINS_28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE12SetTraverserERKS5_:
   35|    460|  void SetTraverser(const TraverserT& t) { traverser_ = t; }
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEEC2EPKNS_4MeshEPKNS_32MeshAttributeIndicesEncodingDataE:
   34|  1.78k|      : mesh_(mesh), encoding_data_(encoding_data), corner_order_(nullptr) {}
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE34UpdatePointToAttributeIndexMappingEPNS_14PointAttributeE:
   48|  7.79k|  bool UpdatePointToAttributeIndexMapping(PointAttribute* attribute) override {
   49|  7.79k|    const auto* corner_table = traverser_.corner_table();
   50|  7.79k|    attribute->SetExplicitMapping(mesh_->num_points());
   51|  7.79k|    const size_t num_faces = mesh_->num_faces();
   52|  7.79k|    const size_t num_points = mesh_->num_points();
   53|  6.18M|    for (FaceIndex f(0); f < static_cast<uint32_t>(num_faces); ++f) {
  ------------------
  |  Branch (53:26): [True: 6.17M, False: 7.79k]
  ------------------
   54|  6.17M|      const auto& face = mesh_->face(f);
   55|  24.6M|      for (int p = 0; p < 3; ++p) {
  ------------------
  |  Branch (55:23): [True: 18.5M, False: 6.17M]
  ------------------
   56|  18.5M|        const PointIndex point_id = face[p];
   57|  18.5M|        const VertexIndex vert_id =
   58|  18.5M|            corner_table->Vertex(CornerIndex(3 * f.value() + p));
   59|  18.5M|        if (vert_id == kInvalidVertexIndex) {
  ------------------
  |  Branch (59:13): [True: 0, False: 18.5M]
  ------------------
   60|      0|          return false;
   61|      0|        }
   62|  18.5M|        const AttributeValueIndex att_entry_id(
   63|  18.5M|            encoding_data_
   64|  18.5M|                ->vertex_to_encoded_attribute_value_index_map[vert_id.value()]);
   65|  18.5M|        if (point_id >= num_points || att_entry_id.value() >= num_points) {
  ------------------
  |  Branch (65:13): [True: 0, False: 18.5M]
  |  Branch (65:13): [True: 0, False: 18.5M]
  |  Branch (65:39): [True: 0, False: 18.5M]
  ------------------
   66|       |          // There cannot be more attribute values than the number of points.
   67|      0|          return false;
   68|      0|        }
   69|  18.5M|        attribute->SetPointMapEntry(point_id, att_entry_id);
   70|  18.5M|      }
   71|  6.17M|    }
   72|  7.79k|    return true;
   73|  7.79k|  }
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE24GenerateSequenceInternalEv:
   76|  1.70k|  bool GenerateSequenceInternal() override {
   77|       |    // Preallocate memory for storing point indices. We expect the number of
   78|       |    // points to be the same as the number of corner table vertices.
   79|  1.70k|    out_point_ids()->reserve(traverser_.corner_table()->num_vertices());
   80|       |
   81|  1.70k|    traverser_.OnTraversalStart();
   82|  1.70k|    if (corner_order_) {
  ------------------
  |  Branch (82:9): [True: 0, False: 1.70k]
  ------------------
   83|      0|      for (uint32_t i = 0; i < corner_order_->size(); ++i) {
  ------------------
  |  Branch (83:28): [True: 0, False: 0]
  ------------------
   84|      0|        if (!ProcessCorner(corner_order_->at(i))) {
  ------------------
  |  Branch (84:13): [True: 0, False: 0]
  ------------------
   85|      0|          return false;
   86|      0|        }
   87|      0|      }
   88|  1.70k|    } else {
   89|  1.70k|      const int32_t num_faces = traverser_.corner_table()->num_faces();
   90|  3.90M|      for (int i = 0; i < num_faces; ++i) {
  ------------------
  |  Branch (90:23): [True: 3.90M, False: 1.70k]
  ------------------
   91|  3.90M|        if (!ProcessCorner(CornerIndex(3 * i))) {
  ------------------
  |  Branch (91:13): [True: 0, False: 3.90M]
  ------------------
   92|      0|          return false;
   93|      0|        }
   94|  3.90M|      }
   95|  1.70k|    }
   96|  1.70k|    traverser_.OnTraversalEnd();
   97|  1.70k|    return true;
   98|  1.70k|  }
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE13ProcessCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  101|  3.90M|  bool ProcessCorner(CornerIndex corner_id) {
  102|  3.90M|    return traverser_.TraverseFromCorner(corner_id);
  103|  3.90M|  }
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE12SetTraverserERKS5_:
   35|  1.78k|  void SetTraverser(const TraverserT& t) { traverser_ = t; }
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEEC2EPKNS_4MeshEPKNS_32MeshAttributeIndicesEncodingDataE:
   34|  2.14k|      : mesh_(mesh), encoding_data_(encoding_data), corner_order_(nullptr) {}
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE34UpdatePointToAttributeIndexMappingEPNS_14PointAttributeE:
   48|  9.28k|  bool UpdatePointToAttributeIndexMapping(PointAttribute* attribute) override {
   49|  9.28k|    const auto* corner_table = traverser_.corner_table();
   50|  9.28k|    attribute->SetExplicitMapping(mesh_->num_points());
   51|  9.28k|    const size_t num_faces = mesh_->num_faces();
   52|  9.28k|    const size_t num_points = mesh_->num_points();
   53|  9.76M|    for (FaceIndex f(0); f < static_cast<uint32_t>(num_faces); ++f) {
  ------------------
  |  Branch (53:26): [True: 9.75M, False: 9.28k]
  ------------------
   54|  9.75M|      const auto& face = mesh_->face(f);
   55|  39.0M|      for (int p = 0; p < 3; ++p) {
  ------------------
  |  Branch (55:23): [True: 29.2M, False: 9.75M]
  ------------------
   56|  29.2M|        const PointIndex point_id = face[p];
   57|  29.2M|        const VertexIndex vert_id =
   58|  29.2M|            corner_table->Vertex(CornerIndex(3 * f.value() + p));
   59|  29.2M|        if (vert_id == kInvalidVertexIndex) {
  ------------------
  |  Branch (59:13): [True: 0, False: 29.2M]
  ------------------
   60|      0|          return false;
   61|      0|        }
   62|  29.2M|        const AttributeValueIndex att_entry_id(
   63|  29.2M|            encoding_data_
   64|  29.2M|                ->vertex_to_encoded_attribute_value_index_map[vert_id.value()]);
   65|  29.2M|        if (point_id >= num_points || att_entry_id.value() >= num_points) {
  ------------------
  |  Branch (65:13): [True: 0, False: 29.2M]
  |  Branch (65:13): [True: 1, False: 29.2M]
  |  Branch (65:39): [True: 1, False: 29.2M]
  ------------------
   66|       |          // There cannot be more attribute values than the number of points.
   67|      1|          return false;
   68|      1|        }
   69|  29.2M|        attribute->SetPointMapEntry(point_id, att_entry_id);
   70|  29.2M|      }
   71|  9.75M|    }
   72|  9.28k|    return true;
   73|  9.28k|  }
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE24GenerateSequenceInternalEv:
   76|  2.07k|  bool GenerateSequenceInternal() override {
   77|       |    // Preallocate memory for storing point indices. We expect the number of
   78|       |    // points to be the same as the number of corner table vertices.
   79|  2.07k|    out_point_ids()->reserve(traverser_.corner_table()->num_vertices());
   80|       |
   81|  2.07k|    traverser_.OnTraversalStart();
   82|  2.07k|    if (corner_order_) {
  ------------------
  |  Branch (82:9): [True: 0, False: 2.07k]
  ------------------
   83|      0|      for (uint32_t i = 0; i < corner_order_->size(); ++i) {
  ------------------
  |  Branch (83:28): [True: 0, False: 0]
  ------------------
   84|      0|        if (!ProcessCorner(corner_order_->at(i))) {
  ------------------
  |  Branch (84:13): [True: 0, False: 0]
  ------------------
   85|      0|          return false;
   86|      0|        }
   87|      0|      }
   88|  2.07k|    } else {
   89|  2.07k|      const int32_t num_faces = traverser_.corner_table()->num_faces();
   90|  5.86M|      for (int i = 0; i < num_faces; ++i) {
  ------------------
  |  Branch (90:23): [True: 5.86M, False: 2.07k]
  ------------------
   91|  5.86M|        if (!ProcessCorner(CornerIndex(3 * i))) {
  ------------------
  |  Branch (91:13): [True: 0, False: 5.86M]
  ------------------
   92|      0|          return false;
   93|      0|        }
   94|  5.86M|      }
   95|  2.07k|    }
   96|  2.07k|    traverser_.OnTraversalEnd();
   97|  2.07k|    return true;
   98|  2.07k|  }
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE13ProcessCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  101|  5.86M|  bool ProcessCorner(CornerIndex corner_id) {
  102|  5.86M|    return traverser_.TraverseFromCorner(corner_id);
  103|  5.86M|  }
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE12SetTraverserERKS5_:
   35|  2.14k|  void SetTraverser(const TraverserT& t) { traverser_ = t; }

_ZN5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEED2Ev:
   33|  4.28k|  virtual ~TraverserBase() = default;
_ZNK5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE12corner_tableEv:
   70|  39.9M|  inline const CornerTable* corner_table() const { return corner_table_; }
_ZNK5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE15IsVertexVisitedENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEE:
   63|  20.2M|  inline bool IsVertexVisited(VertexIndex vert_id) const {
   64|  20.2M|    return is_vertex_visited_[vert_id.value()];
   65|  20.2M|  }
_ZN5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE17MarkVertexVisitedENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEE:
   66|  3.49M|  inline void MarkVertexVisited(VertexIndex vert_id) {
   67|  3.49M|    is_vertex_visited_[vert_id.value()] = true;
   68|  3.49M|  }
_ZN5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE18traversal_observerEv:
   74|  10.3M|  inline TraversalObserverT& traversal_observer() {
   75|  10.3M|    return traversal_observer_;
   76|  10.3M|  }
_ZNK5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE13IsFaceVisitedENS_9IndexTypeIjNS_19FaceIndex_tag_type_EEE:
   45|  15.5M|  inline bool IsFaceVisited(FaceIndex face_id) const {
   46|  15.5M|    if (face_id == kInvalidFaceIndex) {
  ------------------
  |  Branch (46:9): [True: 94.6k, False: 15.4M]
  ------------------
   47|  94.6k|      return true;  // Invalid faces are always considered as visited.
   48|  94.6k|    }
   49|  15.4M|    return is_face_visited_[face_id.value()];
   50|  15.5M|  }
_ZN5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE15MarkFaceVisitedENS_9IndexTypeIjNS_19FaceIndex_tag_type_EEE:
   60|  6.87M|  inline void MarkFaceVisited(FaceIndex face_id) {
   61|  6.87M|    is_face_visited_[face_id.value()] = true;
   62|  6.87M|  }
_ZN5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEEC2Ev:
   32|  4.48k|  TraverserBase() : corner_table_(nullptr) {}
_ZN5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEED2Ev:
   33|  4.48k|  virtual ~TraverserBase() = default;
_ZN5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE4InitEPKS1_S3_:
   36|  2.24k|                    TraversalObserver traversal_observer) {
   37|  2.24k|    corner_table_ = corner_table;
   38|  2.24k|    is_face_visited_.assign(corner_table->num_faces(), false);
   39|  2.24k|    is_vertex_visited_.assign(corner_table_->num_vertices(), false);
   40|  2.24k|    traversal_observer_ = traversal_observer;
   41|  2.24k|  }
_ZNK5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE13IsFaceVisitedENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   53|  3.90M|  inline bool IsFaceVisited(CornerIndex corner_id) const {
   54|  3.90M|    if (corner_id == kInvalidCornerIndex) {
  ------------------
  |  Branch (54:9): [True: 0, False: 3.90M]
  ------------------
   55|      0|      return true;  // Invalid faces are always considered as visited.
   56|      0|    }
   57|  3.90M|    return is_face_visited_[corner_id.value() / 3];
   58|  3.90M|  }
_ZNK5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE12corner_tableEv:
   70|  49.5M|  inline const CornerTable* corner_table() const { return corner_table_; }
_ZNK5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE13IsFaceVisitedENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   53|  5.86M|  inline bool IsFaceVisited(CornerIndex corner_id) const {
   54|  5.86M|    if (corner_id == kInvalidCornerIndex) {
  ------------------
  |  Branch (54:9): [True: 0, False: 5.86M]
  ------------------
   55|      0|      return true;  // Invalid faces are always considered as visited.
   56|      0|    }
   57|  5.86M|    return is_face_visited_[corner_id.value() / 3];
   58|  5.86M|  }
_ZNK5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE15IsVertexVisitedENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEE:
   63|  14.9M|  inline bool IsVertexVisited(VertexIndex vert_id) const {
   64|  14.9M|    return is_vertex_visited_[vert_id.value()];
   65|  14.9M|  }
_ZN5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE17MarkVertexVisitedENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEE:
   66|  14.3M|  inline void MarkVertexVisited(VertexIndex vert_id) {
   67|  14.3M|    is_vertex_visited_[vert_id.value()] = true;
   68|  14.3M|  }
_ZN5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE18traversal_observerEv:
   74|  20.1M|  inline TraversalObserverT& traversal_observer() {
   75|  20.1M|    return traversal_observer_;
   76|  20.1M|  }
_ZNK5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE13IsFaceVisitedENS_9IndexTypeIjNS_19FaceIndex_tag_type_EEE:
   45|  15.1M|  inline bool IsFaceVisited(FaceIndex face_id) const {
   46|  15.1M|    if (face_id == kInvalidFaceIndex) {
  ------------------
  |  Branch (46:9): [True: 9.18M, False: 5.99M]
  ------------------
   47|  9.18M|      return true;  // Invalid faces are always considered as visited.
   48|  9.18M|    }
   49|  5.99M|    return is_face_visited_[face_id.value()];
   50|  15.1M|  }
_ZN5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE15MarkFaceVisitedENS_9IndexTypeIjNS_19FaceIndex_tag_type_EEE:
   60|  5.86M|  inline void MarkFaceVisited(FaceIndex face_id) {
   61|  5.86M|    is_face_visited_[face_id.value()] = true;
   62|  5.86M|  }
_ZN5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEEC2Ev:
   32|  4.28k|  TraverserBase() : corner_table_(nullptr) {}
_ZN5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE4InitEPKS1_S3_:
   36|  2.14k|                    TraversalObserver traversal_observer) {
   37|  2.14k|    corner_table_ = corner_table;
   38|  2.14k|    is_face_visited_.assign(corner_table->num_faces(), false);
   39|  2.14k|    is_vertex_visited_.assign(corner_table_->num_vertices(), false);
   40|  2.14k|    traversal_observer_ = traversal_observer;
   41|  2.14k|  }

_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi0EEC2Ej:
   86|    426|      : bit_length_(0),
   87|    426|        num_points_(0),
   88|    426|        num_decoded_points_(0),
   89|    426|        dimension_(dimension),
   90|    426|        p_(dimension, 0),
   91|    426|        axes_(dimension, 0) {}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi0EE12DecodePointsINS_34PointAttributeVectorOutputIteratorIjEEEEbPNS_13DecoderBufferERT_j:
  195|    270|    DecoderBuffer* buffer, OutputIteratorT& oit, uint32_t oit_max_points) {
  196|    270|  if (!buffer->Decode(&bit_length_)) {
  ------------------
  |  Branch (196:7): [True: 19, False: 251]
  ------------------
  197|     19|    return false;
  198|     19|  }
  199|    251|  if (bit_length_ > 32) {
  ------------------
  |  Branch (199:7): [True: 24, False: 227]
  ------------------
  200|     24|    return false;
  201|     24|  }
  202|    227|  if (!buffer->Decode(&num_points_)) {
  ------------------
  |  Branch (202:7): [True: 6, False: 221]
  ------------------
  203|      6|    return false;
  204|      6|  }
  205|    221|  if (num_points_ == 0) {
  ------------------
  |  Branch (205:7): [True: 73, False: 148]
  ------------------
  206|     73|    return true;
  207|     73|  }
  208|    148|  if (num_points_ > oit_max_points) {
  ------------------
  |  Branch (208:7): [True: 52, False: 96]
  ------------------
  209|     52|    return false;
  210|     52|  }
  211|     96|  num_decoded_points_ = 0;
  212|       |
  213|     96|  if (!numbers_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (213:7): [True: 7, False: 89]
  ------------------
  214|      7|    return false;
  215|      7|  }
  216|     89|  if (!remaining_bits_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (216:7): [True: 6, False: 83]
  ------------------
  217|      6|    return false;
  218|      6|  }
  219|     83|  if (!axis_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (219:7): [True: 1, False: 82]
  ------------------
  220|      1|    return false;
  221|      1|  }
  222|     82|  if (!half_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (222:7): [True: 2, False: 80]
  ------------------
  223|      2|    return false;
  224|      2|  }
  225|       |
  226|     80|  if (!DecodeInternal(num_points_, oit)) {
  ------------------
  |  Branch (226:7): [True: 52, False: 28]
  ------------------
  227|     52|    return false;
  228|     52|  }
  229|       |
  230|     28|  numbers_decoder_.EndDecoding();
  231|     28|  remaining_bits_decoder_.EndDecoding();
  232|     28|  axis_decoder_.EndDecoding();
  233|     28|  half_decoder_.EndDecoding();
  234|       |
  235|     28|  return true;
  236|     80|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi0EE14DecodeInternalINS_34PointAttributeVectorOutputIteratorIjEEEEbjRT_:
  263|     80|    uint32_t num_points, OutputIteratorT& oit) {
  264|     80|  typedef DecodingStatus Status;
  265|       |  // The tree can be 32 * dimension levels deep, so keeping a base and levels
  266|       |  // vector per level takes memory quadratic in the dimension. The walk keeps
  267|       |  // one of each instead. A split at depth d raises one level of the node at
  268|       |  // d, and the node at d + 1 has the same levels and one more base bit set.
  269|       |  // Each split is logged in |undo_|, and on reaching a node at depth t the
  270|       |  // walk undoes the splits deeper than t and the base bit of the last split
  271|       |  // at t.
  272|       |  //
  273|       |  // A split takes its node off the top of |status_stack|, where every node
  274|       |  // below is shallower, and pushes its halves at d and d + 1. So the depths
  275|       |  // on the stack strictly increase towards its top, and a node is reached
  276|       |  // only after everything deeper than it has been decoded.
  277|     80|  base_.assign(dimension_, 0);
  278|     80|  levels_.assign(dimension_, 0);
  279|     80|  undo_.clear();
  280|     80|  uint32_t depth = 0;
  281|     80|  DecodingStatus init_status(num_points, 0, 0);
  282|     80|  std::stack<Status> status_stack;
  283|     80|  status_stack.push(init_status);
  284|       |
  285|       |  // TODO(b/199760123): Use preallocated vector instead of stack.
  286|  9.49M|  while (!status_stack.empty()) {
  ------------------
  |  Branch (286:10): [True: 9.49M, False: 28]
  ------------------
  287|  9.49M|    const DecodingStatus status = status_stack.top();
  288|  9.49M|    status_stack.pop();
  289|       |
  290|  9.49M|    const uint32_t num_remaining_points = status.num_remaining_points;
  291|  9.49M|    const uint32_t last_axis = status.last_axis;
  292|       |    // A node at the current depth is the second half of the split just made,
  293|       |    // and nothing needs to be undone for it.
  294|  9.49M|    if (status.depth != depth) {
  ------------------
  |  Branch (294:9): [True: 4.74M, False: 4.74M]
  ------------------
  295|  4.74M|      if (status.depth > depth) {
  ------------------
  |  Branch (295:11): [True: 0, False: 4.74M]
  ------------------
  296|      0|        return false;
  297|      0|      }
  298|  9.49M|      while (!undo_.empty()) {
  ------------------
  |  Branch (298:14): [True: 9.49M, False: 0]
  ------------------
  299|  9.49M|        const SplitUndo& split = undo_.back();
  300|  9.49M|        if (split.depth < status.depth) {
  ------------------
  |  Branch (300:13): [True: 0, False: 9.49M]
  ------------------
  301|      0|          break;
  302|      0|        }
  303|  9.49M|        base_[split.axis] = split.old_base;
  304|  9.49M|        if (split.depth == status.depth) {
  ------------------
  |  Branch (304:13): [True: 4.74M, False: 4.74M]
  ------------------
  305|       |          // The node's own split, whose level stays raised.
  306|  4.74M|          break;
  307|  4.74M|        }
  308|  4.74M|        levels_[split.axis] = split.old_level;
  309|  4.74M|        undo_.pop_back();
  310|  4.74M|      }
  311|  4.74M|      depth = status.depth;
  312|  4.74M|    }
  313|  9.49M|    const VectorUint32& old_base = base_;
  314|  9.49M|    const VectorUint32& levels = levels_;
  315|       |
  316|  9.49M|    if (num_remaining_points > num_points) {
  ------------------
  |  Branch (316:9): [True: 0, False: 9.49M]
  ------------------
  317|      0|      return false;
  318|      0|    }
  319|       |
  320|  9.49M|    const uint32_t axis = GetAxis(num_remaining_points, levels, last_axis);
  321|  9.49M|    if (axis >= dimension_) {
  ------------------
  |  Branch (321:9): [True: 0, False: 9.49M]
  ------------------
  322|      0|      return false;
  323|      0|    }
  324|       |
  325|  9.49M|    const uint32_t level = levels[axis];
  326|       |
  327|       |    // All axes have been fully subdivided, just output points.
  328|  9.49M|    if ((bit_length_ - level) == 0) {
  ------------------
  |  Branch (328:9): [True: 4.74M, False: 4.74M]
  ------------------
  329|  45.9M|      for (uint32_t i = 0; i < num_remaining_points; i++) {
  ------------------
  |  Branch (329:28): [True: 41.1M, False: 4.74M]
  ------------------
  330|  41.1M|        *oit = old_base;
  331|  41.1M|        ++oit;
  332|  41.1M|        ++num_decoded_points_;
  333|  41.1M|      }
  334|  4.74M|      continue;
  335|  4.74M|    }
  336|       |
  337|  4.74M|    DRACO_DCHECK_EQ(true, num_remaining_points != 0);
  338|       |
  339|       |    // Fast decoding of remaining bits if number of points is 1 or 2.
  340|  4.74M|    if (num_remaining_points <= 2) {
  ------------------
  |  Branch (340:9): [True: 564, False: 4.74M]
  ------------------
  341|       |      // TODO(b/199760123): |axes_| not necessary, remove would change
  342|       |      // bitstream!
  343|    564|      axes_[0] = axis;
  344|  1.61k|      for (uint32_t i = 1; i < dimension_; i++) {
  ------------------
  |  Branch (344:28): [True: 1.05k, False: 564]
  ------------------
  345|  1.05k|        axes_[i] = DRACO_INCREMENT_MOD(axes_[i - 1], dimension_);
  ------------------
  |  |   24|  1.05k|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 160, False: 894]
  |  |  ------------------
  ------------------
  346|  1.05k|      }
  347|  1.48k|      for (uint32_t i = 0; i < num_remaining_points; ++i) {
  ------------------
  |  Branch (347:28): [True: 953, False: 536]
  ------------------
  348|  3.09k|        for (uint32_t j = 0; j < dimension_; j++) {
  ------------------
  |  Branch (348:30): [True: 2.17k, False: 925]
  ------------------
  349|  2.17k|          p_[axes_[j]] = 0;
  350|  2.17k|          const uint32_t num_remaining_bits = bit_length_ - levels[axes_[j]];
  351|  2.17k|          if (num_remaining_bits) {
  ------------------
  |  Branch (351:15): [True: 1.54k, False: 632]
  ------------------
  352|  1.54k|            if (!remaining_bits_decoder_.DecodeLeastSignificantBits32(
  ------------------
  |  Branch (352:17): [True: 28, False: 1.51k]
  ------------------
  353|  1.54k|                    num_remaining_bits, &p_[axes_[j]])) {
  354|     28|              return false;
  355|     28|            }
  356|  1.54k|          }
  357|  2.14k|          p_[axes_[j]] = old_base[axes_[j]] | p_[axes_[j]];
  358|  2.14k|        }
  359|    925|        *oit = p_;
  360|    925|        ++oit;
  361|    925|        ++num_decoded_points_;
  362|    925|      }
  363|    536|      continue;
  364|    564|    }
  365|       |
  366|  4.74M|    if (num_decoded_points_ > num_points_) {
  ------------------
  |  Branch (366:9): [True: 0, False: 4.74M]
  ------------------
  367|      0|      return false;
  368|      0|    }
  369|       |
  370|  4.74M|    const int num_remaining_bits = bit_length_ - level;
  371|  4.74M|    const uint32_t modifier = 1 << (num_remaining_bits - 1);
  372|       |
  373|  4.74M|    const int incoming_bits = MostSignificantBit(num_remaining_points);
  374|       |
  375|  4.74M|    uint32_t number = 0;
  376|  4.74M|    DecodeNumber(incoming_bits, &number);
  377|       |
  378|  4.74M|    uint32_t first_half = num_remaining_points / 2;
  379|  4.74M|    if (first_half < number) {
  ------------------
  |  Branch (379:9): [True: 24, False: 4.74M]
  ------------------
  380|       |      // Invalid |number|.
  381|     24|      return false;
  382|     24|    }
  383|  4.74M|    first_half -= number;
  384|  4.74M|    uint32_t second_half = num_remaining_points - first_half;
  385|       |
  386|  4.74M|    if (first_half != second_half) {
  ------------------
  |  Branch (386:9): [True: 2.74M, False: 2.00M]
  ------------------
  387|  2.74M|      if (!half_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (387:11): [True: 2.74M, False: 3.80k]
  ------------------
  388|  2.74M|        std::swap(first_half, second_half);
  389|  2.74M|      }
  390|  2.74M|    }
  391|       |
  392|  4.74M|    if (depth == std::numeric_limits<uint32_t>::max()) {
  ------------------
  |  Branch (392:9): [True: 0, False: 4.74M]
  ------------------
  393|      0|      return false;
  394|      0|    }
  395|       |    // Both halves see |axis| one level deeper. The first half stays at this
  396|       |    // depth and keeps the base, the second goes one deeper with the split bit
  397|       |    // set in its base.
  398|  4.74M|    undo_.push_back({depth, axis, levels_[axis], base_[axis]});
  399|  4.74M|    levels_[axis] += 1;
  400|  4.74M|    base_[axis] += modifier;
  401|  4.74M|    if (first_half) {
  ------------------
  |  Branch (401:9): [True: 4.74M, False: 23]
  ------------------
  402|  4.74M|      status_stack.push(DecodingStatus(first_half, axis, depth));
  403|  4.74M|    }
  404|  4.74M|    if (second_half) {
  ------------------
  |  Branch (404:9): [True: 4.74M, False: 62]
  ------------------
  405|  4.74M|      status_stack.push(DecodingStatus(second_half, axis, depth + 1));
  406|  4.74M|    }
  407|  4.74M|    ++depth;
  408|  4.74M|  }
  409|     28|  return true;
  410|     80|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi0EE14DecodingStatusC2Ejjj:
  130|  10.1M|        : num_remaining_points(num_remaining_points_),
  131|  10.1M|          last_axis(last_axis_),
  132|  10.1M|          depth(depth_) {}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi0EE12DecodeNumberEiPj:
  123|  5.07M|  void DecodeNumber(int nbits, uint32_t* value) {
  124|  5.07M|    numbers_decoder_.DecodeLeastSignificantBits32(nbits, value);
  125|  5.07M|  }
_ZNK5draco33DynamicIntegerPointsKdTreeDecoderILi0EE18num_decoded_pointsEv:
  114|    101|  uint32_t num_decoded_points() const { return num_decoded_points_; }
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi1EEC2Ej:
   86|    362|      : bit_length_(0),
   87|    362|        num_points_(0),
   88|    362|        num_decoded_points_(0),
   89|    362|        dimension_(dimension),
   90|    362|        p_(dimension, 0),
   91|    362|        axes_(dimension, 0) {}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi1EE12DecodePointsINS_34PointAttributeVectorOutputIteratorIjEEEEbPNS_13DecoderBufferERT_j:
  195|    249|    DecoderBuffer* buffer, OutputIteratorT& oit, uint32_t oit_max_points) {
  196|    249|  if (!buffer->Decode(&bit_length_)) {
  ------------------
  |  Branch (196:7): [True: 14, False: 235]
  ------------------
  197|     14|    return false;
  198|     14|  }
  199|    235|  if (bit_length_ > 32) {
  ------------------
  |  Branch (199:7): [True: 42, False: 193]
  ------------------
  200|     42|    return false;
  201|     42|  }
  202|    193|  if (!buffer->Decode(&num_points_)) {
  ------------------
  |  Branch (202:7): [True: 3, False: 190]
  ------------------
  203|      3|    return false;
  204|      3|  }
  205|    190|  if (num_points_ == 0) {
  ------------------
  |  Branch (205:7): [True: 51, False: 139]
  ------------------
  206|     51|    return true;
  207|     51|  }
  208|    139|  if (num_points_ > oit_max_points) {
  ------------------
  |  Branch (208:7): [True: 45, False: 94]
  ------------------
  209|     45|    return false;
  210|     45|  }
  211|     94|  num_decoded_points_ = 0;
  212|       |
  213|     94|  if (!numbers_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (213:7): [True: 7, False: 87]
  ------------------
  214|      7|    return false;
  215|      7|  }
  216|     87|  if (!remaining_bits_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (216:7): [True: 4, False: 83]
  ------------------
  217|      4|    return false;
  218|      4|  }
  219|     83|  if (!axis_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (219:7): [True: 1, False: 82]
  ------------------
  220|      1|    return false;
  221|      1|  }
  222|     82|  if (!half_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (222:7): [True: 3, False: 79]
  ------------------
  223|      3|    return false;
  224|      3|  }
  225|       |
  226|     79|  if (!DecodeInternal(num_points_, oit)) {
  ------------------
  |  Branch (226:7): [True: 61, False: 18]
  ------------------
  227|     61|    return false;
  228|     61|  }
  229|       |
  230|     18|  numbers_decoder_.EndDecoding();
  231|     18|  remaining_bits_decoder_.EndDecoding();
  232|     18|  axis_decoder_.EndDecoding();
  233|     18|  half_decoder_.EndDecoding();
  234|       |
  235|     18|  return true;
  236|     79|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi1EE14DecodeInternalINS_34PointAttributeVectorOutputIteratorIjEEEEbjRT_:
  263|     79|    uint32_t num_points, OutputIteratorT& oit) {
  264|     79|  typedef DecodingStatus Status;
  265|       |  // The tree can be 32 * dimension levels deep, so keeping a base and levels
  266|       |  // vector per level takes memory quadratic in the dimension. The walk keeps
  267|       |  // one of each instead. A split at depth d raises one level of the node at
  268|       |  // d, and the node at d + 1 has the same levels and one more base bit set.
  269|       |  // Each split is logged in |undo_|, and on reaching a node at depth t the
  270|       |  // walk undoes the splits deeper than t and the base bit of the last split
  271|       |  // at t.
  272|       |  //
  273|       |  // A split takes its node off the top of |status_stack|, where every node
  274|       |  // below is shallower, and pushes its halves at d and d + 1. So the depths
  275|       |  // on the stack strictly increase towards its top, and a node is reached
  276|       |  // only after everything deeper than it has been decoded.
  277|     79|  base_.assign(dimension_, 0);
  278|     79|  levels_.assign(dimension_, 0);
  279|     79|  undo_.clear();
  280|     79|  uint32_t depth = 0;
  281|     79|  DecodingStatus init_status(num_points, 0, 0);
  282|     79|  std::stack<Status> status_stack;
  283|     79|  status_stack.push(init_status);
  284|       |
  285|       |  // TODO(b/199760123): Use preallocated vector instead of stack.
  286|  7.39M|  while (!status_stack.empty()) {
  ------------------
  |  Branch (286:10): [True: 7.39M, False: 18]
  ------------------
  287|  7.39M|    const DecodingStatus status = status_stack.top();
  288|  7.39M|    status_stack.pop();
  289|       |
  290|  7.39M|    const uint32_t num_remaining_points = status.num_remaining_points;
  291|  7.39M|    const uint32_t last_axis = status.last_axis;
  292|       |    // A node at the current depth is the second half of the split just made,
  293|       |    // and nothing needs to be undone for it.
  294|  7.39M|    if (status.depth != depth) {
  ------------------
  |  Branch (294:9): [True: 3.69M, False: 3.70M]
  ------------------
  295|  3.69M|      if (status.depth > depth) {
  ------------------
  |  Branch (295:11): [True: 0, False: 3.69M]
  ------------------
  296|      0|        return false;
  297|      0|      }
  298|  7.39M|      while (!undo_.empty()) {
  ------------------
  |  Branch (298:14): [True: 7.39M, False: 0]
  ------------------
  299|  7.39M|        const SplitUndo& split = undo_.back();
  300|  7.39M|        if (split.depth < status.depth) {
  ------------------
  |  Branch (300:13): [True: 0, False: 7.39M]
  ------------------
  301|      0|          break;
  302|      0|        }
  303|  7.39M|        base_[split.axis] = split.old_base;
  304|  7.39M|        if (split.depth == status.depth) {
  ------------------
  |  Branch (304:13): [True: 3.69M, False: 3.69M]
  ------------------
  305|       |          // The node's own split, whose level stays raised.
  306|  3.69M|          break;
  307|  3.69M|        }
  308|  3.69M|        levels_[split.axis] = split.old_level;
  309|  3.69M|        undo_.pop_back();
  310|  3.69M|      }
  311|  3.69M|      depth = status.depth;
  312|  3.69M|    }
  313|  7.39M|    const VectorUint32& old_base = base_;
  314|  7.39M|    const VectorUint32& levels = levels_;
  315|       |
  316|  7.39M|    if (num_remaining_points > num_points) {
  ------------------
  |  Branch (316:9): [True: 0, False: 7.39M]
  ------------------
  317|      0|      return false;
  318|      0|    }
  319|       |
  320|  7.39M|    const uint32_t axis = GetAxis(num_remaining_points, levels, last_axis);
  321|  7.39M|    if (axis >= dimension_) {
  ------------------
  |  Branch (321:9): [True: 0, False: 7.39M]
  ------------------
  322|      0|      return false;
  323|      0|    }
  324|       |
  325|  7.39M|    const uint32_t level = levels[axis];
  326|       |
  327|       |    // All axes have been fully subdivided, just output points.
  328|  7.39M|    if ((bit_length_ - level) == 0) {
  ------------------
  |  Branch (328:9): [True: 3.69M, False: 3.70M]
  ------------------
  329|  14.3M|      for (uint32_t i = 0; i < num_remaining_points; i++) {
  ------------------
  |  Branch (329:28): [True: 10.6M, False: 3.69M]
  ------------------
  330|  10.6M|        *oit = old_base;
  331|  10.6M|        ++oit;
  332|  10.6M|        ++num_decoded_points_;
  333|  10.6M|      }
  334|  3.69M|      continue;
  335|  3.69M|    }
  336|       |
  337|  3.70M|    DRACO_DCHECK_EQ(true, num_remaining_points != 0);
  338|       |
  339|       |    // Fast decoding of remaining bits if number of points is 1 or 2.
  340|  3.70M|    if (num_remaining_points <= 2) {
  ------------------
  |  Branch (340:9): [True: 629, False: 3.70M]
  ------------------
  341|       |      // TODO(b/199760123): |axes_| not necessary, remove would change
  342|       |      // bitstream!
  343|    629|      axes_[0] = axis;
  344|  2.52k|      for (uint32_t i = 1; i < dimension_; i++) {
  ------------------
  |  Branch (344:28): [True: 1.89k, False: 629]
  ------------------
  345|  1.89k|        axes_[i] = DRACO_INCREMENT_MOD(axes_[i - 1], dimension_);
  ------------------
  |  |   24|  1.89k|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 176, False: 1.72k]
  |  |  ------------------
  ------------------
  346|  1.89k|      }
  347|  1.66k|      for (uint32_t i = 0; i < num_remaining_points; ++i) {
  ------------------
  |  Branch (347:28): [True: 1.06k, False: 595]
  ------------------
  348|  3.89k|        for (uint32_t j = 0; j < dimension_; j++) {
  ------------------
  |  Branch (348:30): [True: 2.85k, False: 1.03k]
  ------------------
  349|  2.85k|          p_[axes_[j]] = 0;
  350|  2.85k|          const uint32_t num_remaining_bits = bit_length_ - levels[axes_[j]];
  351|  2.85k|          if (num_remaining_bits) {
  ------------------
  |  Branch (351:15): [True: 1.83k, False: 1.02k]
  ------------------
  352|  1.83k|            if (!remaining_bits_decoder_.DecodeLeastSignificantBits32(
  ------------------
  |  Branch (352:17): [True: 34, False: 1.79k]
  ------------------
  353|  1.83k|                    num_remaining_bits, &p_[axes_[j]])) {
  354|     34|              return false;
  355|     34|            }
  356|  1.83k|          }
  357|  2.82k|          p_[axes_[j]] = old_base[axes_[j]] | p_[axes_[j]];
  358|  2.82k|        }
  359|  1.03k|        *oit = p_;
  360|  1.03k|        ++oit;
  361|  1.03k|        ++num_decoded_points_;
  362|  1.03k|      }
  363|    595|      continue;
  364|    629|    }
  365|       |
  366|  3.70M|    if (num_decoded_points_ > num_points_) {
  ------------------
  |  Branch (366:9): [True: 0, False: 3.70M]
  ------------------
  367|      0|      return false;
  368|      0|    }
  369|       |
  370|  3.70M|    const int num_remaining_bits = bit_length_ - level;
  371|  3.70M|    const uint32_t modifier = 1 << (num_remaining_bits - 1);
  372|       |
  373|  3.70M|    const int incoming_bits = MostSignificantBit(num_remaining_points);
  374|       |
  375|  3.70M|    uint32_t number = 0;
  376|  3.70M|    DecodeNumber(incoming_bits, &number);
  377|       |
  378|  3.70M|    uint32_t first_half = num_remaining_points / 2;
  379|  3.70M|    if (first_half < number) {
  ------------------
  |  Branch (379:9): [True: 27, False: 3.70M]
  ------------------
  380|       |      // Invalid |number|.
  381|     27|      return false;
  382|     27|    }
  383|  3.70M|    first_half -= number;
  384|  3.70M|    uint32_t second_half = num_remaining_points - first_half;
  385|       |
  386|  3.70M|    if (first_half != second_half) {
  ------------------
  |  Branch (386:9): [True: 2.15M, False: 1.54M]
  ------------------
  387|  2.15M|      if (!half_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (387:11): [True: 2.15M, False: 2.16k]
  ------------------
  388|  2.15M|        std::swap(first_half, second_half);
  389|  2.15M|      }
  390|  2.15M|    }
  391|       |
  392|  3.70M|    if (depth == std::numeric_limits<uint32_t>::max()) {
  ------------------
  |  Branch (392:9): [True: 0, False: 3.70M]
  ------------------
  393|      0|      return false;
  394|      0|    }
  395|       |    // Both halves see |axis| one level deeper. The first half stays at this
  396|       |    // depth and keeps the base, the second goes one deeper with the split bit
  397|       |    // set in its base.
  398|  3.70M|    undo_.push_back({depth, axis, levels_[axis], base_[axis]});
  399|  3.70M|    levels_[axis] += 1;
  400|  3.70M|    base_[axis] += modifier;
  401|  3.70M|    if (first_half) {
  ------------------
  |  Branch (401:9): [True: 3.70M, False: 27]
  ------------------
  402|  3.70M|      status_stack.push(DecodingStatus(first_half, axis, depth));
  403|  3.70M|    }
  404|  3.70M|    if (second_half) {
  ------------------
  |  Branch (404:9): [True: 3.70M, False: 50]
  ------------------
  405|  3.70M|      status_stack.push(DecodingStatus(second_half, axis, depth + 1));
  406|  3.70M|    }
  407|  3.70M|    ++depth;
  408|  3.70M|  }
  409|     18|  return true;
  410|     79|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi1EE14DecodingStatusC2Ejjj:
  130|  9.30M|        : num_remaining_points(num_remaining_points_),
  131|  9.30M|          last_axis(last_axis_),
  132|  9.30M|          depth(depth_) {}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi1EE7GetAxisEjRKNSt3__16vectorIjNS2_9allocatorIjEEEEj:
  241|  9.30M|    uint32_t last_axis) {
  242|  9.30M|  if (!Policy::select_axis) {
  ------------------
  |  Branch (242:7): [True: 9.30M, Folded]
  ------------------
  243|  9.30M|    return DRACO_INCREMENT_MOD(last_axis, dimension_);
  ------------------
  |  |   24|  9.30M|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 7.90M, False: 1.40M]
  |  |  ------------------
  ------------------
  244|  9.30M|  }
  245|       |
  246|      0|  uint32_t best_axis = 0;
  247|      0|  if (num_remaining_points < 64) {
  ------------------
  |  Branch (247:7): [True: 0, False: 0]
  ------------------
  248|      0|    for (uint32_t axis = 1; axis < dimension_; ++axis) {
  ------------------
  |  Branch (248:29): [True: 0, False: 0]
  ------------------
  249|      0|      if (levels[best_axis] > levels[axis]) {
  ------------------
  |  Branch (249:11): [True: 0, False: 0]
  ------------------
  250|      0|        best_axis = axis;
  251|      0|      }
  252|      0|    }
  253|      0|  } else {
  254|      0|    axis_decoder_.DecodeLeastSignificantBits32(4, &best_axis);
  255|      0|  }
  256|       |
  257|      0|  return best_axis;
  258|  9.30M|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi1EE12DecodeNumberEiPj:
  123|  4.65M|  void DecodeNumber(int nbits, uint32_t* value) {
  124|  4.65M|    numbers_decoder_.DecodeLeastSignificantBits32(nbits, value);
  125|  4.65M|  }
_ZNK5draco33DynamicIntegerPointsKdTreeDecoderILi1EE18num_decoded_pointsEv:
  114|     69|  uint32_t num_decoded_points() const { return num_decoded_points_; }
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi2EEC2Ej:
   86|    313|      : bit_length_(0),
   87|    313|        num_points_(0),
   88|    313|        num_decoded_points_(0),
   89|    313|        dimension_(dimension),
   90|    313|        p_(dimension, 0),
   91|    313|        axes_(dimension, 0) {}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi2EE12DecodePointsINS_34PointAttributeVectorOutputIteratorIjEEEEbPNS_13DecoderBufferERT_j:
  195|    171|    DecoderBuffer* buffer, OutputIteratorT& oit, uint32_t oit_max_points) {
  196|    171|  if (!buffer->Decode(&bit_length_)) {
  ------------------
  |  Branch (196:7): [True: 7, False: 164]
  ------------------
  197|      7|    return false;
  198|      7|  }
  199|    164|  if (bit_length_ > 32) {
  ------------------
  |  Branch (199:7): [True: 23, False: 141]
  ------------------
  200|     23|    return false;
  201|     23|  }
  202|    141|  if (!buffer->Decode(&num_points_)) {
  ------------------
  |  Branch (202:7): [True: 2, False: 139]
  ------------------
  203|      2|    return false;
  204|      2|  }
  205|    139|  if (num_points_ == 0) {
  ------------------
  |  Branch (205:7): [True: 25, False: 114]
  ------------------
  206|     25|    return true;
  207|     25|  }
  208|    114|  if (num_points_ > oit_max_points) {
  ------------------
  |  Branch (208:7): [True: 34, False: 80]
  ------------------
  209|     34|    return false;
  210|     34|  }
  211|     80|  num_decoded_points_ = 0;
  212|       |
  213|     80|  if (!numbers_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (213:7): [True: 1, False: 79]
  ------------------
  214|      1|    return false;
  215|      1|  }
  216|     79|  if (!remaining_bits_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (216:7): [True: 5, False: 74]
  ------------------
  217|      5|    return false;
  218|      5|  }
  219|     74|  if (!axis_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (219:7): [True: 2, False: 72]
  ------------------
  220|      2|    return false;
  221|      2|  }
  222|     72|  if (!half_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (222:7): [True: 1, False: 71]
  ------------------
  223|      1|    return false;
  224|      1|  }
  225|       |
  226|     71|  if (!DecodeInternal(num_points_, oit)) {
  ------------------
  |  Branch (226:7): [True: 60, False: 11]
  ------------------
  227|     60|    return false;
  228|     60|  }
  229|       |
  230|     11|  numbers_decoder_.EndDecoding();
  231|     11|  remaining_bits_decoder_.EndDecoding();
  232|     11|  axis_decoder_.EndDecoding();
  233|     11|  half_decoder_.EndDecoding();
  234|       |
  235|     11|  return true;
  236|     71|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi2EE14DecodeInternalINS_34PointAttributeVectorOutputIteratorIjEEEEbjRT_:
  263|     71|    uint32_t num_points, OutputIteratorT& oit) {
  264|     71|  typedef DecodingStatus Status;
  265|       |  // The tree can be 32 * dimension levels deep, so keeping a base and levels
  266|       |  // vector per level takes memory quadratic in the dimension. The walk keeps
  267|       |  // one of each instead. A split at depth d raises one level of the node at
  268|       |  // d, and the node at d + 1 has the same levels and one more base bit set.
  269|       |  // Each split is logged in |undo_|, and on reaching a node at depth t the
  270|       |  // walk undoes the splits deeper than t and the base bit of the last split
  271|       |  // at t.
  272|       |  //
  273|       |  // A split takes its node off the top of |status_stack|, where every node
  274|       |  // below is shallower, and pushes its halves at d and d + 1. So the depths
  275|       |  // on the stack strictly increase towards its top, and a node is reached
  276|       |  // only after everything deeper than it has been decoded.
  277|     71|  base_.assign(dimension_, 0);
  278|     71|  levels_.assign(dimension_, 0);
  279|     71|  undo_.clear();
  280|     71|  uint32_t depth = 0;
  281|     71|  DecodingStatus init_status(num_points, 0, 0);
  282|     71|  std::stack<Status> status_stack;
  283|     71|  status_stack.push(init_status);
  284|       |
  285|       |  // TODO(b/199760123): Use preallocated vector instead of stack.
  286|  64.3k|  while (!status_stack.empty()) {
  ------------------
  |  Branch (286:10): [True: 64.3k, False: 11]
  ------------------
  287|  64.3k|    const DecodingStatus status = status_stack.top();
  288|  64.3k|    status_stack.pop();
  289|       |
  290|  64.3k|    const uint32_t num_remaining_points = status.num_remaining_points;
  291|  64.3k|    const uint32_t last_axis = status.last_axis;
  292|       |    // A node at the current depth is the second half of the split just made,
  293|       |    // and nothing needs to be undone for it.
  294|  64.3k|    if (status.depth != depth) {
  ------------------
  |  Branch (294:9): [True: 57.3k, False: 6.95k]
  ------------------
  295|  57.3k|      if (status.depth > depth) {
  ------------------
  |  Branch (295:11): [True: 0, False: 57.3k]
  ------------------
  296|      0|        return false;
  297|      0|      }
  298|   120k|      while (!undo_.empty()) {
  ------------------
  |  Branch (298:14): [True: 120k, False: 0]
  ------------------
  299|   120k|        const SplitUndo& split = undo_.back();
  300|   120k|        if (split.depth < status.depth) {
  ------------------
  |  Branch (300:13): [True: 0, False: 120k]
  ------------------
  301|      0|          break;
  302|      0|        }
  303|   120k|        base_[split.axis] = split.old_base;
  304|   120k|        if (split.depth == status.depth) {
  ------------------
  |  Branch (304:13): [True: 57.3k, False: 63.1k]
  ------------------
  305|       |          // The node's own split, whose level stays raised.
  306|  57.3k|          break;
  307|  57.3k|        }
  308|  63.1k|        levels_[split.axis] = split.old_level;
  309|  63.1k|        undo_.pop_back();
  310|  63.1k|      }
  311|  57.3k|      depth = status.depth;
  312|  57.3k|    }
  313|  64.3k|    const VectorUint32& old_base = base_;
  314|  64.3k|    const VectorUint32& levels = levels_;
  315|       |
  316|  64.3k|    if (num_remaining_points > num_points) {
  ------------------
  |  Branch (316:9): [True: 0, False: 64.3k]
  ------------------
  317|      0|      return false;
  318|      0|    }
  319|       |
  320|  64.3k|    const uint32_t axis = GetAxis(num_remaining_points, levels, last_axis);
  321|  64.3k|    if (axis >= dimension_) {
  ------------------
  |  Branch (321:9): [True: 0, False: 64.3k]
  ------------------
  322|      0|      return false;
  323|      0|    }
  324|       |
  325|  64.3k|    const uint32_t level = levels[axis];
  326|       |
  327|       |    // All axes have been fully subdivided, just output points.
  328|  64.3k|    if ((bit_length_ - level) == 0) {
  ------------------
  |  Branch (328:9): [True: 358, False: 63.9k]
  ------------------
  329|   282k|      for (uint32_t i = 0; i < num_remaining_points; i++) {
  ------------------
  |  Branch (329:28): [True: 282k, False: 358]
  ------------------
  330|   282k|        *oit = old_base;
  331|   282k|        ++oit;
  332|   282k|        ++num_decoded_points_;
  333|   282k|      }
  334|    358|      continue;
  335|    358|    }
  336|       |
  337|  63.9k|    DRACO_DCHECK_EQ(true, num_remaining_points != 0);
  338|       |
  339|       |    // Fast decoding of remaining bits if number of points is 1 or 2.
  340|  63.9k|    if (num_remaining_points <= 2) {
  ------------------
  |  Branch (340:9): [True: 187, False: 63.7k]
  ------------------
  341|       |      // TODO(b/199760123): |axes_| not necessary, remove would change
  342|       |      // bitstream!
  343|    187|      axes_[0] = axis;
  344|    537|      for (uint32_t i = 1; i < dimension_; i++) {
  ------------------
  |  Branch (344:28): [True: 350, False: 187]
  ------------------
  345|    350|        axes_[i] = DRACO_INCREMENT_MOD(axes_[i - 1], dimension_);
  ------------------
  |  |   24|    350|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 26, False: 324]
  |  |  ------------------
  ------------------
  346|    350|      }
  347|    497|      for (uint32_t i = 0; i < num_remaining_points; ++i) {
  ------------------
  |  Branch (347:28): [True: 322, False: 175]
  ------------------
  348|    769|        for (uint32_t j = 0; j < dimension_; j++) {
  ------------------
  |  Branch (348:30): [True: 459, False: 310]
  ------------------
  349|    459|          p_[axes_[j]] = 0;
  350|    459|          const uint32_t num_remaining_bits = bit_length_ - levels[axes_[j]];
  351|    459|          if (num_remaining_bits) {
  ------------------
  |  Branch (351:15): [True: 459, False: 0]
  ------------------
  352|    459|            if (!remaining_bits_decoder_.DecodeLeastSignificantBits32(
  ------------------
  |  Branch (352:17): [True: 12, False: 447]
  ------------------
  353|    459|                    num_remaining_bits, &p_[axes_[j]])) {
  354|     12|              return false;
  355|     12|            }
  356|    459|          }
  357|    447|          p_[axes_[j]] = old_base[axes_[j]] | p_[axes_[j]];
  358|    447|        }
  359|    310|        *oit = p_;
  360|    310|        ++oit;
  361|    310|        ++num_decoded_points_;
  362|    310|      }
  363|    175|      continue;
  364|    187|    }
  365|       |
  366|  63.7k|    if (num_decoded_points_ > num_points_) {
  ------------------
  |  Branch (366:9): [True: 0, False: 63.7k]
  ------------------
  367|      0|      return false;
  368|      0|    }
  369|       |
  370|  63.7k|    const int num_remaining_bits = bit_length_ - level;
  371|  63.7k|    const uint32_t modifier = 1 << (num_remaining_bits - 1);
  372|       |
  373|  63.7k|    const int incoming_bits = MostSignificantBit(num_remaining_points);
  374|       |
  375|  63.7k|    uint32_t number = 0;
  376|  63.7k|    DecodeNumber(incoming_bits, &number);
  377|       |
  378|  63.7k|    uint32_t first_half = num_remaining_points / 2;
  379|  63.7k|    if (first_half < number) {
  ------------------
  |  Branch (379:9): [True: 48, False: 63.7k]
  ------------------
  380|       |      // Invalid |number|.
  381|     48|      return false;
  382|     48|    }
  383|  63.7k|    first_half -= number;
  384|  63.7k|    uint32_t second_half = num_remaining_points - first_half;
  385|       |
  386|  63.7k|    if (first_half != second_half) {
  ------------------
  |  Branch (386:9): [True: 63.3k, False: 342]
  ------------------
  387|  63.3k|      if (!half_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (387:11): [True: 57.2k, False: 6.11k]
  ------------------
  388|  57.2k|        std::swap(first_half, second_half);
  389|  57.2k|      }
  390|  63.3k|    }
  391|       |
  392|  63.7k|    if (depth == std::numeric_limits<uint32_t>::max()) {
  ------------------
  |  Branch (392:9): [True: 0, False: 63.7k]
  ------------------
  393|      0|      return false;
  394|      0|    }
  395|       |    // Both halves see |axis| one level deeper. The first half stays at this
  396|       |    // depth and keeps the base, the second goes one deeper with the split bit
  397|       |    // set in its base.
  398|  63.7k|    undo_.push_back({depth, axis, levels_[axis], base_[axis]});
  399|  63.7k|    levels_[axis] += 1;
  400|  63.7k|    base_[axis] += modifier;
  401|  63.7k|    if (first_half) {
  ------------------
  |  Branch (401:9): [True: 57.7k, False: 5.95k]
  ------------------
  402|  57.7k|      status_stack.push(DecodingStatus(first_half, axis, depth));
  403|  57.7k|    }
  404|  63.7k|    if (second_half) {
  ------------------
  |  Branch (404:9): [True: 6.88k, False: 56.8k]
  ------------------
  405|  6.88k|      status_stack.push(DecodingStatus(second_half, axis, depth + 1));
  406|  6.88k|    }
  407|  63.7k|    ++depth;
  408|  63.7k|  }
  409|     11|  return true;
  410|     71|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi2EE14DecodingStatusC2Ejjj:
  130|  4.27M|        : num_remaining_points(num_remaining_points_),
  131|  4.27M|          last_axis(last_axis_),
  132|  4.27M|          depth(depth_) {}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi2EE12DecodeNumberEiPj:
  123|  2.17M|  void DecodeNumber(int nbits, uint32_t* value) {
  124|  2.17M|    numbers_decoder_.DecodeLeastSignificantBits32(nbits, value);
  125|  2.17M|  }
_ZNK5draco33DynamicIntegerPointsKdTreeDecoderILi2EE18num_decoded_pointsEv:
  114|     36|  uint32_t num_decoded_points() const { return num_decoded_points_; }
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi3EEC2Ej:
   86|    337|      : bit_length_(0),
   87|    337|        num_points_(0),
   88|    337|        num_decoded_points_(0),
   89|    337|        dimension_(dimension),
   90|    337|        p_(dimension, 0),
   91|    337|        axes_(dimension, 0) {}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi3EE12DecodePointsINS_34PointAttributeVectorOutputIteratorIjEEEEbPNS_13DecoderBufferERT_j:
  195|    198|    DecoderBuffer* buffer, OutputIteratorT& oit, uint32_t oit_max_points) {
  196|    198|  if (!buffer->Decode(&bit_length_)) {
  ------------------
  |  Branch (196:7): [True: 3, False: 195]
  ------------------
  197|      3|    return false;
  198|      3|  }
  199|    195|  if (bit_length_ > 32) {
  ------------------
  |  Branch (199:7): [True: 22, False: 173]
  ------------------
  200|     22|    return false;
  201|     22|  }
  202|    173|  if (!buffer->Decode(&num_points_)) {
  ------------------
  |  Branch (202:7): [True: 1, False: 172]
  ------------------
  203|      1|    return false;
  204|      1|  }
  205|    172|  if (num_points_ == 0) {
  ------------------
  |  Branch (205:7): [True: 24, False: 148]
  ------------------
  206|     24|    return true;
  207|     24|  }
  208|    148|  if (num_points_ > oit_max_points) {
  ------------------
  |  Branch (208:7): [True: 35, False: 113]
  ------------------
  209|     35|    return false;
  210|     35|  }
  211|    113|  num_decoded_points_ = 0;
  212|       |
  213|    113|  if (!numbers_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (213:7): [True: 5, False: 108]
  ------------------
  214|      5|    return false;
  215|      5|  }
  216|    108|  if (!remaining_bits_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (216:7): [True: 7, False: 101]
  ------------------
  217|      7|    return false;
  218|      7|  }
  219|    101|  if (!axis_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (219:7): [True: 6, False: 95]
  ------------------
  220|      6|    return false;
  221|      6|  }
  222|     95|  if (!half_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (222:7): [True: 1, False: 94]
  ------------------
  223|      1|    return false;
  224|      1|  }
  225|       |
  226|     94|  if (!DecodeInternal(num_points_, oit)) {
  ------------------
  |  Branch (226:7): [True: 85, False: 9]
  ------------------
  227|     85|    return false;
  228|     85|  }
  229|       |
  230|      9|  numbers_decoder_.EndDecoding();
  231|      9|  remaining_bits_decoder_.EndDecoding();
  232|      9|  axis_decoder_.EndDecoding();
  233|      9|  half_decoder_.EndDecoding();
  234|       |
  235|      9|  return true;
  236|     94|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi3EE14DecodeInternalINS_34PointAttributeVectorOutputIteratorIjEEEEbjRT_:
  263|     94|    uint32_t num_points, OutputIteratorT& oit) {
  264|     94|  typedef DecodingStatus Status;
  265|       |  // The tree can be 32 * dimension levels deep, so keeping a base and levels
  266|       |  // vector per level takes memory quadratic in the dimension. The walk keeps
  267|       |  // one of each instead. A split at depth d raises one level of the node at
  268|       |  // d, and the node at d + 1 has the same levels and one more base bit set.
  269|       |  // Each split is logged in |undo_|, and on reaching a node at depth t the
  270|       |  // walk undoes the splits deeper than t and the base bit of the last split
  271|       |  // at t.
  272|       |  //
  273|       |  // A split takes its node off the top of |status_stack|, where every node
  274|       |  // below is shallower, and pushes its halves at d and d + 1. So the depths
  275|       |  // on the stack strictly increase towards its top, and a node is reached
  276|       |  // only after everything deeper than it has been decoded.
  277|     94|  base_.assign(dimension_, 0);
  278|     94|  levels_.assign(dimension_, 0);
  279|     94|  undo_.clear();
  280|     94|  uint32_t depth = 0;
  281|     94|  DecodingStatus init_status(num_points, 0, 0);
  282|     94|  std::stack<Status> status_stack;
  283|     94|  status_stack.push(init_status);
  284|       |
  285|       |  // TODO(b/199760123): Use preallocated vector instead of stack.
  286|  31.7k|  while (!status_stack.empty()) {
  ------------------
  |  Branch (286:10): [True: 31.7k, False: 9]
  ------------------
  287|  31.7k|    const DecodingStatus status = status_stack.top();
  288|  31.7k|    status_stack.pop();
  289|       |
  290|  31.7k|    const uint32_t num_remaining_points = status.num_remaining_points;
  291|  31.7k|    const uint32_t last_axis = status.last_axis;
  292|       |    // A node at the current depth is the second half of the split just made,
  293|       |    // and nothing needs to be undone for it.
  294|  31.7k|    if (status.depth != depth) {
  ------------------
  |  Branch (294:9): [True: 26.2k, False: 5.48k]
  ------------------
  295|  26.2k|      if (status.depth > depth) {
  ------------------
  |  Branch (295:11): [True: 0, False: 26.2k]
  ------------------
  296|      0|        return false;
  297|      0|      }
  298|  55.0k|      while (!undo_.empty()) {
  ------------------
  |  Branch (298:14): [True: 55.0k, False: 0]
  ------------------
  299|  55.0k|        const SplitUndo& split = undo_.back();
  300|  55.0k|        if (split.depth < status.depth) {
  ------------------
  |  Branch (300:13): [True: 0, False: 55.0k]
  ------------------
  301|      0|          break;
  302|      0|        }
  303|  55.0k|        base_[split.axis] = split.old_base;
  304|  55.0k|        if (split.depth == status.depth) {
  ------------------
  |  Branch (304:13): [True: 26.2k, False: 28.8k]
  ------------------
  305|       |          // The node's own split, whose level stays raised.
  306|  26.2k|          break;
  307|  26.2k|        }
  308|  28.8k|        levels_[split.axis] = split.old_level;
  309|  28.8k|        undo_.pop_back();
  310|  28.8k|      }
  311|  26.2k|      depth = status.depth;
  312|  26.2k|    }
  313|  31.7k|    const VectorUint32& old_base = base_;
  314|  31.7k|    const VectorUint32& levels = levels_;
  315|       |
  316|  31.7k|    if (num_remaining_points > num_points) {
  ------------------
  |  Branch (316:9): [True: 0, False: 31.7k]
  ------------------
  317|      0|      return false;
  318|      0|    }
  319|       |
  320|  31.7k|    const uint32_t axis = GetAxis(num_remaining_points, levels, last_axis);
  321|  31.7k|    if (axis >= dimension_) {
  ------------------
  |  Branch (321:9): [True: 0, False: 31.7k]
  ------------------
  322|      0|      return false;
  323|      0|    }
  324|       |
  325|  31.7k|    const uint32_t level = levels[axis];
  326|       |
  327|       |    // All axes have been fully subdivided, just output points.
  328|  31.7k|    if ((bit_length_ - level) == 0) {
  ------------------
  |  Branch (328:9): [True: 1.60k, False: 30.1k]
  ------------------
  329|  3.76M|      for (uint32_t i = 0; i < num_remaining_points; i++) {
  ------------------
  |  Branch (329:28): [True: 3.76M, False: 1.60k]
  ------------------
  330|  3.76M|        *oit = old_base;
  331|  3.76M|        ++oit;
  332|  3.76M|        ++num_decoded_points_;
  333|  3.76M|      }
  334|  1.60k|      continue;
  335|  1.60k|    }
  336|       |
  337|  30.1k|    DRACO_DCHECK_EQ(true, num_remaining_points != 0);
  338|       |
  339|       |    // Fast decoding of remaining bits if number of points is 1 or 2.
  340|  30.1k|    if (num_remaining_points <= 2) {
  ------------------
  |  Branch (340:9): [True: 538, False: 29.5k]
  ------------------
  341|       |      // TODO(b/199760123): |axes_| not necessary, remove would change
  342|       |      // bitstream!
  343|    538|      axes_[0] = axis;
  344|  2.33k|      for (uint32_t i = 1; i < dimension_; i++) {
  ------------------
  |  Branch (344:28): [True: 1.80k, False: 538]
  ------------------
  345|  1.80k|        axes_[i] = DRACO_INCREMENT_MOD(axes_[i - 1], dimension_);
  ------------------
  |  |   24|  1.80k|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 97, False: 1.70k]
  |  |  ------------------
  ------------------
  346|  1.80k|      }
  347|  1.44k|      for (uint32_t i = 0; i < num_remaining_points; ++i) {
  ------------------
  |  Branch (347:28): [True: 929, False: 517]
  ------------------
  348|  4.75k|        for (uint32_t j = 0; j < dimension_; j++) {
  ------------------
  |  Branch (348:30): [True: 3.84k, False: 908]
  ------------------
  349|  3.84k|          p_[axes_[j]] = 0;
  350|  3.84k|          const uint32_t num_remaining_bits = bit_length_ - levels[axes_[j]];
  351|  3.84k|          if (num_remaining_bits) {
  ------------------
  |  Branch (351:15): [True: 1.23k, False: 2.61k]
  ------------------
  352|  1.23k|            if (!remaining_bits_decoder_.DecodeLeastSignificantBits32(
  ------------------
  |  Branch (352:17): [True: 21, False: 1.21k]
  ------------------
  353|  1.23k|                    num_remaining_bits, &p_[axes_[j]])) {
  354|     21|              return false;
  355|     21|            }
  356|  1.23k|          }
  357|  3.82k|          p_[axes_[j]] = old_base[axes_[j]] | p_[axes_[j]];
  358|  3.82k|        }
  359|    908|        *oit = p_;
  360|    908|        ++oit;
  361|    908|        ++num_decoded_points_;
  362|    908|      }
  363|    517|      continue;
  364|    538|    }
  365|       |
  366|  29.5k|    if (num_decoded_points_ > num_points_) {
  ------------------
  |  Branch (366:9): [True: 0, False: 29.5k]
  ------------------
  367|      0|      return false;
  368|      0|    }
  369|       |
  370|  29.5k|    const int num_remaining_bits = bit_length_ - level;
  371|  29.5k|    const uint32_t modifier = 1 << (num_remaining_bits - 1);
  372|       |
  373|  29.5k|    const int incoming_bits = MostSignificantBit(num_remaining_points);
  374|       |
  375|  29.5k|    uint32_t number = 0;
  376|  29.5k|    DecodeNumber(incoming_bits, &number);
  377|       |
  378|  29.5k|    uint32_t first_half = num_remaining_points / 2;
  379|  29.5k|    if (first_half < number) {
  ------------------
  |  Branch (379:9): [True: 64, False: 29.4k]
  ------------------
  380|       |      // Invalid |number|.
  381|     64|      return false;
  382|     64|    }
  383|  29.4k|    first_half -= number;
  384|  29.4k|    uint32_t second_half = num_remaining_points - first_half;
  385|       |
  386|  29.4k|    if (first_half != second_half) {
  ------------------
  |  Branch (386:9): [True: 28.2k, False: 1.22k]
  ------------------
  387|  28.2k|      if (!half_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (387:11): [True: 24.8k, False: 3.40k]
  ------------------
  388|  24.8k|        std::swap(first_half, second_half);
  389|  24.8k|      }
  390|  28.2k|    }
  391|       |
  392|  29.4k|    if (depth == std::numeric_limits<uint32_t>::max()) {
  ------------------
  |  Branch (392:9): [True: 0, False: 29.4k]
  ------------------
  393|      0|      return false;
  394|      0|    }
  395|       |    // Both halves see |axis| one level deeper. The first half stays at this
  396|       |    // depth and keeps the base, the second goes one deeper with the split bit
  397|       |    // set in its base.
  398|  29.4k|    undo_.push_back({depth, axis, levels_[axis], base_[axis]});
  399|  29.4k|    levels_[axis] += 1;
  400|  29.4k|    base_[axis] += modifier;
  401|  29.4k|    if (first_half) {
  ------------------
  |  Branch (401:9): [True: 26.6k, False: 2.80k]
  ------------------
  402|  26.6k|      status_stack.push(DecodingStatus(first_half, axis, depth));
  403|  26.6k|    }
  404|  29.4k|    if (second_half) {
  ------------------
  |  Branch (404:9): [True: 5.39k, False: 24.1k]
  ------------------
  405|  5.39k|      status_stack.push(DecodingStatus(second_half, axis, depth + 1));
  406|  5.39k|    }
  407|  29.4k|    ++depth;
  408|  29.4k|  }
  409|      9|  return true;
  410|     94|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi3EE14DecodingStatusC2Ejjj:
  130|  4.24M|        : num_remaining_points(num_remaining_points_),
  131|  4.24M|          last_axis(last_axis_),
  132|  4.24M|          depth(depth_) {}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi3EE7GetAxisEjRKNSt3__16vectorIjNS2_9allocatorIjEEEEj:
  241|  4.24M|    uint32_t last_axis) {
  242|  4.24M|  if (!Policy::select_axis) {
  ------------------
  |  Branch (242:7): [True: 4.24M, Folded]
  ------------------
  243|  4.24M|    return DRACO_INCREMENT_MOD(last_axis, dimension_);
  ------------------
  |  |   24|  4.24M|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 1.20M, False: 3.03M]
  |  |  ------------------
  ------------------
  244|  4.24M|  }
  245|       |
  246|      0|  uint32_t best_axis = 0;
  247|      0|  if (num_remaining_points < 64) {
  ------------------
  |  Branch (247:7): [True: 0, False: 0]
  ------------------
  248|      0|    for (uint32_t axis = 1; axis < dimension_; ++axis) {
  ------------------
  |  Branch (248:29): [True: 0, False: 0]
  ------------------
  249|      0|      if (levels[best_axis] > levels[axis]) {
  ------------------
  |  Branch (249:11): [True: 0, False: 0]
  ------------------
  250|      0|        best_axis = axis;
  251|      0|      }
  252|      0|    }
  253|      0|  } else {
  254|      0|    axis_decoder_.DecodeLeastSignificantBits32(4, &best_axis);
  255|      0|  }
  256|       |
  257|      0|  return best_axis;
  258|  4.24M|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi3EE12DecodeNumberEiPj:
  123|  2.13M|  void DecodeNumber(int nbits, uint32_t* value) {
  124|  2.13M|    numbers_decoder_.DecodeLeastSignificantBits32(nbits, value);
  125|  2.13M|  }
_ZNK5draco33DynamicIntegerPointsKdTreeDecoderILi3EE18num_decoded_pointsEv:
  114|     33|  uint32_t num_decoded_points() const { return num_decoded_points_; }
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi4EEC2Ej:
   86|    322|      : bit_length_(0),
   87|    322|        num_points_(0),
   88|    322|        num_decoded_points_(0),
   89|    322|        dimension_(dimension),
   90|    322|        p_(dimension, 0),
   91|    322|        axes_(dimension, 0) {}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi4EE12DecodePointsINS_34PointAttributeVectorOutputIteratorIjEEEEbPNS_13DecoderBufferERT_j:
  195|    252|    DecoderBuffer* buffer, OutputIteratorT& oit, uint32_t oit_max_points) {
  196|    252|  if (!buffer->Decode(&bit_length_)) {
  ------------------
  |  Branch (196:7): [True: 6, False: 246]
  ------------------
  197|      6|    return false;
  198|      6|  }
  199|    246|  if (bit_length_ > 32) {
  ------------------
  |  Branch (199:7): [True: 26, False: 220]
  ------------------
  200|     26|    return false;
  201|     26|  }
  202|    220|  if (!buffer->Decode(&num_points_)) {
  ------------------
  |  Branch (202:7): [True: 4, False: 216]
  ------------------
  203|      4|    return false;
  204|      4|  }
  205|    216|  if (num_points_ == 0) {
  ------------------
  |  Branch (205:7): [True: 27, False: 189]
  ------------------
  206|     27|    return true;
  207|     27|  }
  208|    189|  if (num_points_ > oit_max_points) {
  ------------------
  |  Branch (208:7): [True: 36, False: 153]
  ------------------
  209|     36|    return false;
  210|     36|  }
  211|    153|  num_decoded_points_ = 0;
  212|       |
  213|    153|  if (!numbers_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (213:7): [True: 16, False: 137]
  ------------------
  214|     16|    return false;
  215|     16|  }
  216|    137|  if (!remaining_bits_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (216:7): [True: 1, False: 136]
  ------------------
  217|      1|    return false;
  218|      1|  }
  219|    136|  if (!axis_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (219:7): [True: 2, False: 134]
  ------------------
  220|      2|    return false;
  221|      2|  }
  222|    134|  if (!half_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (222:7): [True: 1, False: 133]
  ------------------
  223|      1|    return false;
  224|      1|  }
  225|       |
  226|    133|  if (!DecodeInternal(num_points_, oit)) {
  ------------------
  |  Branch (226:7): [True: 48, False: 85]
  ------------------
  227|     48|    return false;
  228|     48|  }
  229|       |
  230|     85|  numbers_decoder_.EndDecoding();
  231|     85|  remaining_bits_decoder_.EndDecoding();
  232|     85|  axis_decoder_.EndDecoding();
  233|     85|  half_decoder_.EndDecoding();
  234|       |
  235|     85|  return true;
  236|    133|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi4EE14DecodeInternalINS_34PointAttributeVectorOutputIteratorIjEEEEbjRT_:
  263|    133|    uint32_t num_points, OutputIteratorT& oit) {
  264|    133|  typedef DecodingStatus Status;
  265|       |  // The tree can be 32 * dimension levels deep, so keeping a base and levels
  266|       |  // vector per level takes memory quadratic in the dimension. The walk keeps
  267|       |  // one of each instead. A split at depth d raises one level of the node at
  268|       |  // d, and the node at d + 1 has the same levels and one more base bit set.
  269|       |  // Each split is logged in |undo_|, and on reaching a node at depth t the
  270|       |  // walk undoes the splits deeper than t and the base bit of the last split
  271|       |  // at t.
  272|       |  //
  273|       |  // A split takes its node off the top of |status_stack|, where every node
  274|       |  // below is shallower, and pushes its halves at d and d + 1. So the depths
  275|       |  // on the stack strictly increase towards its top, and a node is reached
  276|       |  // only after everything deeper than it has been decoded.
  277|    133|  base_.assign(dimension_, 0);
  278|    133|  levels_.assign(dimension_, 0);
  279|    133|  undo_.clear();
  280|    133|  uint32_t depth = 0;
  281|    133|  DecodingStatus init_status(num_points, 0, 0);
  282|    133|  std::stack<Status> status_stack;
  283|    133|  status_stack.push(init_status);
  284|       |
  285|       |  // TODO(b/199760123): Use preallocated vector instead of stack.
  286|  2.73M|  while (!status_stack.empty()) {
  ------------------
  |  Branch (286:10): [True: 2.73M, False: 85]
  ------------------
  287|  2.73M|    const DecodingStatus status = status_stack.top();
  288|  2.73M|    status_stack.pop();
  289|       |
  290|  2.73M|    const uint32_t num_remaining_points = status.num_remaining_points;
  291|  2.73M|    const uint32_t last_axis = status.last_axis;
  292|       |    // A node at the current depth is the second half of the split just made,
  293|       |    // and nothing needs to be undone for it.
  294|  2.73M|    if (status.depth != depth) {
  ------------------
  |  Branch (294:9): [True: 1.38M, False: 1.34M]
  ------------------
  295|  1.38M|      if (status.depth > depth) {
  ------------------
  |  Branch (295:11): [True: 0, False: 1.38M]
  ------------------
  296|      0|        return false;
  297|      0|      }
  298|  2.76M|      while (!undo_.empty()) {
  ------------------
  |  Branch (298:14): [True: 2.76M, False: 0]
  ------------------
  299|  2.76M|        const SplitUndo& split = undo_.back();
  300|  2.76M|        if (split.depth < status.depth) {
  ------------------
  |  Branch (300:13): [True: 0, False: 2.76M]
  ------------------
  301|      0|          break;
  302|      0|        }
  303|  2.76M|        base_[split.axis] = split.old_base;
  304|  2.76M|        if (split.depth == status.depth) {
  ------------------
  |  Branch (304:13): [True: 1.38M, False: 1.37M]
  ------------------
  305|       |          // The node's own split, whose level stays raised.
  306|  1.38M|          break;
  307|  1.38M|        }
  308|  1.37M|        levels_[split.axis] = split.old_level;
  309|  1.37M|        undo_.pop_back();
  310|  1.37M|      }
  311|  1.38M|      depth = status.depth;
  312|  1.38M|    }
  313|  2.73M|    const VectorUint32& old_base = base_;
  314|  2.73M|    const VectorUint32& levels = levels_;
  315|       |
  316|  2.73M|    if (num_remaining_points > num_points) {
  ------------------
  |  Branch (316:9): [True: 0, False: 2.73M]
  ------------------
  317|      0|      return false;
  318|      0|    }
  319|       |
  320|  2.73M|    const uint32_t axis = GetAxis(num_remaining_points, levels, last_axis);
  321|  2.73M|    if (axis >= dimension_) {
  ------------------
  |  Branch (321:9): [True: 0, False: 2.73M]
  ------------------
  322|      0|      return false;
  323|      0|    }
  324|       |
  325|  2.73M|    const uint32_t level = levels[axis];
  326|       |
  327|       |    // All axes have been fully subdivided, just output points.
  328|  2.73M|    if ((bit_length_ - level) == 0) {
  ------------------
  |  Branch (328:9): [True: 1.23M, False: 1.50M]
  ------------------
  329|   122M|      for (uint32_t i = 0; i < num_remaining_points; i++) {
  ------------------
  |  Branch (329:28): [True: 121M, False: 1.23M]
  ------------------
  330|   121M|        *oit = old_base;
  331|   121M|        ++oit;
  332|   121M|        ++num_decoded_points_;
  333|   121M|      }
  334|  1.23M|      continue;
  335|  1.23M|    }
  336|       |
  337|  1.50M|    DRACO_DCHECK_EQ(true, num_remaining_points != 0);
  338|       |
  339|       |    // Fast decoding of remaining bits if number of points is 1 or 2.
  340|  1.50M|    if (num_remaining_points <= 2) {
  ------------------
  |  Branch (340:9): [True: 96.4k, False: 1.40M]
  ------------------
  341|       |      // TODO(b/199760123): |axes_| not necessary, remove would change
  342|       |      // bitstream!
  343|  96.4k|      axes_[0] = axis;
  344|   149k|      for (uint32_t i = 1; i < dimension_; i++) {
  ------------------
  |  Branch (344:28): [True: 53.3k, False: 96.4k]
  ------------------
  345|  53.3k|        axes_[i] = DRACO_INCREMENT_MOD(axes_[i - 1], dimension_);
  ------------------
  |  |   24|  53.3k|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 15.0k, False: 38.2k]
  |  |  ------------------
  ------------------
  346|  53.3k|      }
  347|   248k|      for (uint32_t i = 0; i < num_remaining_points; ++i) {
  ------------------
  |  Branch (347:28): [True: 152k, False: 96.4k]
  ------------------
  348|   377k|        for (uint32_t j = 0; j < dimension_; j++) {
  ------------------
  |  Branch (348:30): [True: 225k, False: 152k]
  ------------------
  349|   225k|          p_[axes_[j]] = 0;
  350|   225k|          const uint32_t num_remaining_bits = bit_length_ - levels[axes_[j]];
  351|   225k|          if (num_remaining_bits) {
  ------------------
  |  Branch (351:15): [True: 194k, False: 30.8k]
  ------------------
  352|   194k|            if (!remaining_bits_decoder_.DecodeLeastSignificantBits32(
  ------------------
  |  Branch (352:17): [True: 43, False: 194k]
  ------------------
  353|   194k|                    num_remaining_bits, &p_[axes_[j]])) {
  354|     43|              return false;
  355|     43|            }
  356|   194k|          }
  357|   224k|          p_[axes_[j]] = old_base[axes_[j]] | p_[axes_[j]];
  358|   224k|        }
  359|   152k|        *oit = p_;
  360|   152k|        ++oit;
  361|   152k|        ++num_decoded_points_;
  362|   152k|      }
  363|  96.4k|      continue;
  364|  96.4k|    }
  365|       |
  366|  1.40M|    if (num_decoded_points_ > num_points_) {
  ------------------
  |  Branch (366:9): [True: 0, False: 1.40M]
  ------------------
  367|      0|      return false;
  368|      0|    }
  369|       |
  370|  1.40M|    const int num_remaining_bits = bit_length_ - level;
  371|  1.40M|    const uint32_t modifier = 1 << (num_remaining_bits - 1);
  372|       |
  373|  1.40M|    const int incoming_bits = MostSignificantBit(num_remaining_points);
  374|       |
  375|  1.40M|    uint32_t number = 0;
  376|  1.40M|    DecodeNumber(incoming_bits, &number);
  377|       |
  378|  1.40M|    uint32_t first_half = num_remaining_points / 2;
  379|  1.40M|    if (first_half < number) {
  ------------------
  |  Branch (379:9): [True: 5, False: 1.40M]
  ------------------
  380|       |      // Invalid |number|.
  381|      5|      return false;
  382|      5|    }
  383|  1.40M|    first_half -= number;
  384|  1.40M|    uint32_t second_half = num_remaining_points - first_half;
  385|       |
  386|  1.40M|    if (first_half != second_half) {
  ------------------
  |  Branch (386:9): [True: 1.33M, False: 75.4k]
  ------------------
  387|  1.33M|      if (!half_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (387:11): [True: 1.28M, False: 52.7k]
  ------------------
  388|  1.28M|        std::swap(first_half, second_half);
  389|  1.28M|      }
  390|  1.33M|    }
  391|       |
  392|  1.40M|    if (depth == std::numeric_limits<uint32_t>::max()) {
  ------------------
  |  Branch (392:9): [True: 0, False: 1.40M]
  ------------------
  393|      0|      return false;
  394|      0|    }
  395|       |    // Both halves see |axis| one level deeper. The first half stays at this
  396|       |    // depth and keeps the base, the second goes one deeper with the split bit
  397|       |    // set in its base.
  398|  1.40M|    undo_.push_back({depth, axis, levels_[axis], base_[axis]});
  399|  1.40M|    levels_[axis] += 1;
  400|  1.40M|    base_[axis] += modifier;
  401|  1.40M|    if (first_half) {
  ------------------
  |  Branch (401:9): [True: 1.38M, False: 18.8k]
  ------------------
  402|  1.38M|      status_stack.push(DecodingStatus(first_half, axis, depth));
  403|  1.38M|    }
  404|  1.40M|    if (second_half) {
  ------------------
  |  Branch (404:9): [True: 1.34M, False: 59.6k]
  ------------------
  405|  1.34M|      status_stack.push(DecodingStatus(second_half, axis, depth + 1));
  406|  1.34M|    }
  407|  1.40M|    ++depth;
  408|  1.40M|  }
  409|     85|  return true;
  410|    133|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi4EE14DecodingStatusC2Ejjj:
  130|  2.73M|        : num_remaining_points(num_remaining_points_),
  131|  2.73M|          last_axis(last_axis_),
  132|  2.73M|          depth(depth_) {}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi4EE12DecodeNumberEiPj:
  123|  1.40M|  void DecodeNumber(int nbits, uint32_t* value) {
  124|  1.40M|    numbers_decoder_.DecodeLeastSignificantBits32(nbits, value);
  125|  1.40M|  }
_ZNK5draco33DynamicIntegerPointsKdTreeDecoderILi4EE18num_decoded_pointsEv:
  114|    112|  uint32_t num_decoded_points() const { return num_decoded_points_; }
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi5EEC2Ej:
   86|    265|      : bit_length_(0),
   87|    265|        num_points_(0),
   88|    265|        num_decoded_points_(0),
   89|    265|        dimension_(dimension),
   90|    265|        p_(dimension, 0),
   91|    265|        axes_(dimension, 0) {}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi5EE12DecodePointsINS_34PointAttributeVectorOutputIteratorIjEEEEbPNS_13DecoderBufferERT_j:
  195|    227|    DecoderBuffer* buffer, OutputIteratorT& oit, uint32_t oit_max_points) {
  196|    227|  if (!buffer->Decode(&bit_length_)) {
  ------------------
  |  Branch (196:7): [True: 2, False: 225]
  ------------------
  197|      2|    return false;
  198|      2|  }
  199|    225|  if (bit_length_ > 32) {
  ------------------
  |  Branch (199:7): [True: 24, False: 201]
  ------------------
  200|     24|    return false;
  201|     24|  }
  202|    201|  if (!buffer->Decode(&num_points_)) {
  ------------------
  |  Branch (202:7): [True: 3, False: 198]
  ------------------
  203|      3|    return false;
  204|      3|  }
  205|    198|  if (num_points_ == 0) {
  ------------------
  |  Branch (205:7): [True: 7, False: 191]
  ------------------
  206|      7|    return true;
  207|      7|  }
  208|    191|  if (num_points_ > oit_max_points) {
  ------------------
  |  Branch (208:7): [True: 13, False: 178]
  ------------------
  209|     13|    return false;
  210|     13|  }
  211|    178|  num_decoded_points_ = 0;
  212|       |
  213|    178|  if (!numbers_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (213:7): [True: 23, False: 155]
  ------------------
  214|     23|    return false;
  215|     23|  }
  216|    155|  if (!remaining_bits_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (216:7): [True: 2, False: 153]
  ------------------
  217|      2|    return false;
  218|      2|  }
  219|    153|  if (!axis_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (219:7): [True: 4, False: 149]
  ------------------
  220|      4|    return false;
  221|      4|  }
  222|    149|  if (!half_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (222:7): [True: 1, False: 148]
  ------------------
  223|      1|    return false;
  224|      1|  }
  225|       |
  226|    148|  if (!DecodeInternal(num_points_, oit)) {
  ------------------
  |  Branch (226:7): [True: 98, False: 50]
  ------------------
  227|     98|    return false;
  228|     98|  }
  229|       |
  230|     50|  numbers_decoder_.EndDecoding();
  231|     50|  remaining_bits_decoder_.EndDecoding();
  232|     50|  axis_decoder_.EndDecoding();
  233|     50|  half_decoder_.EndDecoding();
  234|       |
  235|     50|  return true;
  236|    148|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi5EE14DecodeInternalINS_34PointAttributeVectorOutputIteratorIjEEEEbjRT_:
  263|    148|    uint32_t num_points, OutputIteratorT& oit) {
  264|    148|  typedef DecodingStatus Status;
  265|       |  // The tree can be 32 * dimension levels deep, so keeping a base and levels
  266|       |  // vector per level takes memory quadratic in the dimension. The walk keeps
  267|       |  // one of each instead. A split at depth d raises one level of the node at
  268|       |  // d, and the node at d + 1 has the same levels and one more base bit set.
  269|       |  // Each split is logged in |undo_|, and on reaching a node at depth t the
  270|       |  // walk undoes the splits deeper than t and the base bit of the last split
  271|       |  // at t.
  272|       |  //
  273|       |  // A split takes its node off the top of |status_stack|, where every node
  274|       |  // below is shallower, and pushes its halves at d and d + 1. So the depths
  275|       |  // on the stack strictly increase towards its top, and a node is reached
  276|       |  // only after everything deeper than it has been decoded.
  277|    148|  base_.assign(dimension_, 0);
  278|    148|  levels_.assign(dimension_, 0);
  279|    148|  undo_.clear();
  280|    148|  uint32_t depth = 0;
  281|    148|  DecodingStatus init_status(num_points, 0, 0);
  282|    148|  std::stack<Status> status_stack;
  283|    148|  status_stack.push(init_status);
  284|       |
  285|       |  // TODO(b/199760123): Use preallocated vector instead of stack.
  286|  3.16M|  while (!status_stack.empty()) {
  ------------------
  |  Branch (286:10): [True: 3.16M, False: 50]
  ------------------
  287|  3.16M|    const DecodingStatus status = status_stack.top();
  288|  3.16M|    status_stack.pop();
  289|       |
  290|  3.16M|    const uint32_t num_remaining_points = status.num_remaining_points;
  291|  3.16M|    const uint32_t last_axis = status.last_axis;
  292|       |    // A node at the current depth is the second half of the split just made,
  293|       |    // and nothing needs to be undone for it.
  294|  3.16M|    if (status.depth != depth) {
  ------------------
  |  Branch (294:9): [True: 1.63M, False: 1.53M]
  ------------------
  295|  1.63M|      if (status.depth > depth) {
  ------------------
  |  Branch (295:11): [True: 0, False: 1.63M]
  ------------------
  296|      0|        return false;
  297|      0|      }
  298|  3.23M|      while (!undo_.empty()) {
  ------------------
  |  Branch (298:14): [True: 3.23M, False: 0]
  ------------------
  299|  3.23M|        const SplitUndo& split = undo_.back();
  300|  3.23M|        if (split.depth < status.depth) {
  ------------------
  |  Branch (300:13): [True: 0, False: 3.23M]
  ------------------
  301|      0|          break;
  302|      0|        }
  303|  3.23M|        base_[split.axis] = split.old_base;
  304|  3.23M|        if (split.depth == status.depth) {
  ------------------
  |  Branch (304:13): [True: 1.63M, False: 1.60M]
  ------------------
  305|       |          // The node's own split, whose level stays raised.
  306|  1.63M|          break;
  307|  1.63M|        }
  308|  1.60M|        levels_[split.axis] = split.old_level;
  309|  1.60M|        undo_.pop_back();
  310|  1.60M|      }
  311|  1.63M|      depth = status.depth;
  312|  1.63M|    }
  313|  3.16M|    const VectorUint32& old_base = base_;
  314|  3.16M|    const VectorUint32& levels = levels_;
  315|       |
  316|  3.16M|    if (num_remaining_points > num_points) {
  ------------------
  |  Branch (316:9): [True: 0, False: 3.16M]
  ------------------
  317|      0|      return false;
  318|      0|    }
  319|       |
  320|  3.16M|    const uint32_t axis = GetAxis(num_remaining_points, levels, last_axis);
  321|  3.16M|    if (axis >= dimension_) {
  ------------------
  |  Branch (321:9): [True: 0, False: 3.16M]
  ------------------
  322|      0|      return false;
  323|      0|    }
  324|       |
  325|  3.16M|    const uint32_t level = levels[axis];
  326|       |
  327|       |    // All axes have been fully subdivided, just output points.
  328|  3.16M|    if ((bit_length_ - level) == 0) {
  ------------------
  |  Branch (328:9): [True: 1.36M, False: 1.79M]
  ------------------
  329|   200M|      for (uint32_t i = 0; i < num_remaining_points; i++) {
  ------------------
  |  Branch (329:28): [True: 198M, False: 1.36M]
  ------------------
  330|   198M|        *oit = old_base;
  331|   198M|        ++oit;
  332|   198M|        ++num_decoded_points_;
  333|   198M|      }
  334|  1.36M|      continue;
  335|  1.36M|    }
  336|       |
  337|  1.79M|    DRACO_DCHECK_EQ(true, num_remaining_points != 0);
  338|       |
  339|       |    // Fast decoding of remaining bits if number of points is 1 or 2.
  340|  1.79M|    if (num_remaining_points <= 2) {
  ------------------
  |  Branch (340:9): [True: 143k, False: 1.65M]
  ------------------
  341|       |      // TODO(b/199760123): |axes_| not necessary, remove would change
  342|       |      // bitstream!
  343|   143k|      axes_[0] = axis;
  344|   316k|      for (uint32_t i = 1; i < dimension_; i++) {
  ------------------
  |  Branch (344:28): [True: 172k, False: 143k]
  ------------------
  345|   172k|        axes_[i] = DRACO_INCREMENT_MOD(axes_[i - 1], dimension_);
  ------------------
  |  |   24|   172k|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 16.8k, False: 156k]
  |  |  ------------------
  ------------------
  346|   172k|      }
  347|   343k|      for (uint32_t i = 0; i < num_remaining_points; ++i) {
  ------------------
  |  Branch (347:28): [True: 200k, False: 143k]
  ------------------
  348|   683k|        for (uint32_t j = 0; j < dimension_; j++) {
  ------------------
  |  Branch (348:30): [True: 483k, False: 200k]
  ------------------
  349|   483k|          p_[axes_[j]] = 0;
  350|   483k|          const uint32_t num_remaining_bits = bit_length_ - levels[axes_[j]];
  351|   483k|          if (num_remaining_bits) {
  ------------------
  |  Branch (351:15): [True: 241k, False: 242k]
  ------------------
  352|   241k|            if (!remaining_bits_decoder_.DecodeLeastSignificantBits32(
  ------------------
  |  Branch (352:17): [True: 96, False: 241k]
  ------------------
  353|   241k|                    num_remaining_bits, &p_[axes_[j]])) {
  354|     96|              return false;
  355|     96|            }
  356|   241k|          }
  357|   483k|          p_[axes_[j]] = old_base[axes_[j]] | p_[axes_[j]];
  358|   483k|        }
  359|   200k|        *oit = p_;
  360|   200k|        ++oit;
  361|   200k|        ++num_decoded_points_;
  362|   200k|      }
  363|   143k|      continue;
  364|   143k|    }
  365|       |
  366|  1.65M|    if (num_decoded_points_ > num_points_) {
  ------------------
  |  Branch (366:9): [True: 0, False: 1.65M]
  ------------------
  367|      0|      return false;
  368|      0|    }
  369|       |
  370|  1.65M|    const int num_remaining_bits = bit_length_ - level;
  371|  1.65M|    const uint32_t modifier = 1 << (num_remaining_bits - 1);
  372|       |
  373|  1.65M|    const int incoming_bits = MostSignificantBit(num_remaining_points);
  374|       |
  375|  1.65M|    uint32_t number = 0;
  376|  1.65M|    DecodeNumber(incoming_bits, &number);
  377|       |
  378|  1.65M|    uint32_t first_half = num_remaining_points / 2;
  379|  1.65M|    if (first_half < number) {
  ------------------
  |  Branch (379:9): [True: 2, False: 1.65M]
  ------------------
  380|       |      // Invalid |number|.
  381|      2|      return false;
  382|      2|    }
  383|  1.65M|    first_half -= number;
  384|  1.65M|    uint32_t second_half = num_remaining_points - first_half;
  385|       |
  386|  1.65M|    if (first_half != second_half) {
  ------------------
  |  Branch (386:9): [True: 1.63M, False: 21.5k]
  ------------------
  387|  1.63M|      if (!half_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (387:11): [True: 1.56M, False: 73.0k]
  ------------------
  388|  1.56M|        std::swap(first_half, second_half);
  389|  1.56M|      }
  390|  1.63M|    }
  391|       |
  392|  1.65M|    if (depth == std::numeric_limits<uint32_t>::max()) {
  ------------------
  |  Branch (392:9): [True: 0, False: 1.65M]
  ------------------
  393|      0|      return false;
  394|      0|    }
  395|       |    // Both halves see |axis| one level deeper. The first half stays at this
  396|       |    // depth and keeps the base, the second goes one deeper with the split bit
  397|       |    // set in its base.
  398|  1.65M|    undo_.push_back({depth, axis, levels_[axis], base_[axis]});
  399|  1.65M|    levels_[axis] += 1;
  400|  1.65M|    base_[axis] += modifier;
  401|  1.65M|    if (first_half) {
  ------------------
  |  Branch (401:9): [True: 1.63M, False: 22.4k]
  ------------------
  402|  1.63M|      status_stack.push(DecodingStatus(first_half, axis, depth));
  403|  1.63M|    }
  404|  1.65M|    if (second_half) {
  ------------------
  |  Branch (404:9): [True: 1.53M, False: 122k]
  ------------------
  405|  1.53M|      status_stack.push(DecodingStatus(second_half, axis, depth + 1));
  406|  1.53M|    }
  407|  1.65M|    ++depth;
  408|  1.65M|  }
  409|     50|  return true;
  410|    148|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi5EE14DecodingStatusC2Ejjj:
  130|  3.16M|        : num_remaining_points(num_remaining_points_),
  131|  3.16M|          last_axis(last_axis_),
  132|  3.16M|          depth(depth_) {}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi5EE7GetAxisEjRKNSt3__16vectorIjNS2_9allocatorIjEEEEj:
  241|  3.16M|    uint32_t last_axis) {
  242|  3.16M|  if (!Policy::select_axis) {
  ------------------
  |  Branch (242:7): [True: 3.16M, Folded]
  ------------------
  243|  3.16M|    return DRACO_INCREMENT_MOD(last_axis, dimension_);
  ------------------
  |  |   24|  3.16M|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 1.53M, False: 1.62M]
  |  |  ------------------
  ------------------
  244|  3.16M|  }
  245|       |
  246|      0|  uint32_t best_axis = 0;
  247|      0|  if (num_remaining_points < 64) {
  ------------------
  |  Branch (247:7): [True: 0, False: 0]
  ------------------
  248|      0|    for (uint32_t axis = 1; axis < dimension_; ++axis) {
  ------------------
  |  Branch (248:29): [True: 0, False: 0]
  ------------------
  249|      0|      if (levels[best_axis] > levels[axis]) {
  ------------------
  |  Branch (249:11): [True: 0, False: 0]
  ------------------
  250|      0|        best_axis = axis;
  251|      0|      }
  252|      0|    }
  253|      0|  } else {
  254|      0|    axis_decoder_.DecodeLeastSignificantBits32(4, &best_axis);
  255|      0|  }
  256|       |
  257|      0|  return best_axis;
  258|  3.16M|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi5EE12DecodeNumberEiPj:
  123|  1.65M|  void DecodeNumber(int nbits, uint32_t* value) {
  124|  1.65M|    numbers_decoder_.DecodeLeastSignificantBits32(nbits, value);
  125|  1.65M|  }
_ZNK5draco33DynamicIntegerPointsKdTreeDecoderILi5EE18num_decoded_pointsEv:
  114|     57|  uint32_t num_decoded_points() const { return num_decoded_points_; }
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi6EEC2Ej:
   86|    284|      : bit_length_(0),
   87|    284|        num_points_(0),
   88|    284|        num_decoded_points_(0),
   89|    284|        dimension_(dimension),
   90|    284|        p_(dimension, 0),
   91|    284|        axes_(dimension, 0) {}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi6EE12DecodePointsINS_34PointAttributeVectorOutputIteratorIjEEEEbPNS_13DecoderBufferERT_j:
  195|    241|    DecoderBuffer* buffer, OutputIteratorT& oit, uint32_t oit_max_points) {
  196|    241|  if (!buffer->Decode(&bit_length_)) {
  ------------------
  |  Branch (196:7): [True: 4, False: 237]
  ------------------
  197|      4|    return false;
  198|      4|  }
  199|    237|  if (bit_length_ > 32) {
  ------------------
  |  Branch (199:7): [True: 18, False: 219]
  ------------------
  200|     18|    return false;
  201|     18|  }
  202|    219|  if (!buffer->Decode(&num_points_)) {
  ------------------
  |  Branch (202:7): [True: 1, False: 218]
  ------------------
  203|      1|    return false;
  204|      1|  }
  205|    218|  if (num_points_ == 0) {
  ------------------
  |  Branch (205:7): [True: 60, False: 158]
  ------------------
  206|     60|    return true;
  207|     60|  }
  208|    158|  if (num_points_ > oit_max_points) {
  ------------------
  |  Branch (208:7): [True: 39, False: 119]
  ------------------
  209|     39|    return false;
  210|     39|  }
  211|    119|  num_decoded_points_ = 0;
  212|       |
  213|    119|  if (!numbers_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (213:7): [True: 44, False: 75]
  ------------------
  214|     44|    return false;
  215|     44|  }
  216|     75|  if (!remaining_bits_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (216:7): [True: 2, False: 73]
  ------------------
  217|      2|    return false;
  218|      2|  }
  219|     73|  if (!axis_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (219:7): [True: 1, False: 72]
  ------------------
  220|      1|    return false;
  221|      1|  }
  222|     72|  if (!half_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (222:7): [True: 5, False: 67]
  ------------------
  223|      5|    return false;
  224|      5|  }
  225|       |
  226|     67|  if (!DecodeInternal(num_points_, oit)) {
  ------------------
  |  Branch (226:7): [True: 42, False: 25]
  ------------------
  227|     42|    return false;
  228|     42|  }
  229|       |
  230|     25|  numbers_decoder_.EndDecoding();
  231|     25|  remaining_bits_decoder_.EndDecoding();
  232|     25|  axis_decoder_.EndDecoding();
  233|     25|  half_decoder_.EndDecoding();
  234|       |
  235|     25|  return true;
  236|     67|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi6EE14DecodeInternalINS_34PointAttributeVectorOutputIteratorIjEEEEbjRT_:
  263|     67|    uint32_t num_points, OutputIteratorT& oit) {
  264|     67|  typedef DecodingStatus Status;
  265|       |  // The tree can be 32 * dimension levels deep, so keeping a base and levels
  266|       |  // vector per level takes memory quadratic in the dimension. The walk keeps
  267|       |  // one of each instead. A split at depth d raises one level of the node at
  268|       |  // d, and the node at d + 1 has the same levels and one more base bit set.
  269|       |  // Each split is logged in |undo_|, and on reaching a node at depth t the
  270|       |  // walk undoes the splits deeper than t and the base bit of the last split
  271|       |  // at t.
  272|       |  //
  273|       |  // A split takes its node off the top of |status_stack|, where every node
  274|       |  // below is shallower, and pushes its halves at d and d + 1. So the depths
  275|       |  // on the stack strictly increase towards its top, and a node is reached
  276|       |  // only after everything deeper than it has been decoded.
  277|     67|  base_.assign(dimension_, 0);
  278|     67|  levels_.assign(dimension_, 0);
  279|     67|  undo_.clear();
  280|     67|  uint32_t depth = 0;
  281|     67|  DecodingStatus init_status(num_points, 0, 0);
  282|     67|  std::stack<Status> status_stack;
  283|     67|  status_stack.push(init_status);
  284|       |
  285|       |  // TODO(b/199760123): Use preallocated vector instead of stack.
  286|   155k|  while (!status_stack.empty()) {
  ------------------
  |  Branch (286:10): [True: 155k, False: 25]
  ------------------
  287|   155k|    const DecodingStatus status = status_stack.top();
  288|   155k|    status_stack.pop();
  289|       |
  290|   155k|    const uint32_t num_remaining_points = status.num_remaining_points;
  291|   155k|    const uint32_t last_axis = status.last_axis;
  292|       |    // A node at the current depth is the second half of the split just made,
  293|       |    // and nothing needs to be undone for it.
  294|   155k|    if (status.depth != depth) {
  ------------------
  |  Branch (294:9): [True: 135k, False: 19.8k]
  ------------------
  295|   135k|      if (status.depth > depth) {
  ------------------
  |  Branch (295:11): [True: 0, False: 135k]
  ------------------
  296|      0|        return false;
  297|      0|      }
  298|   245k|      while (!undo_.empty()) {
  ------------------
  |  Branch (298:14): [True: 245k, False: 0]
  ------------------
  299|   245k|        const SplitUndo& split = undo_.back();
  300|   245k|        if (split.depth < status.depth) {
  ------------------
  |  Branch (300:13): [True: 0, False: 245k]
  ------------------
  301|      0|          break;
  302|      0|        }
  303|   245k|        base_[split.axis] = split.old_base;
  304|   245k|        if (split.depth == status.depth) {
  ------------------
  |  Branch (304:13): [True: 135k, False: 109k]
  ------------------
  305|       |          // The node's own split, whose level stays raised.
  306|   135k|          break;
  307|   135k|        }
  308|   109k|        levels_[split.axis] = split.old_level;
  309|   109k|        undo_.pop_back();
  310|   109k|      }
  311|   135k|      depth = status.depth;
  312|   135k|    }
  313|   155k|    const VectorUint32& old_base = base_;
  314|   155k|    const VectorUint32& levels = levels_;
  315|       |
  316|   155k|    if (num_remaining_points > num_points) {
  ------------------
  |  Branch (316:9): [True: 0, False: 155k]
  ------------------
  317|      0|      return false;
  318|      0|    }
  319|       |
  320|   155k|    const uint32_t axis = GetAxis(num_remaining_points, levels, last_axis);
  321|   155k|    if (axis >= dimension_) {
  ------------------
  |  Branch (321:9): [True: 9, False: 155k]
  ------------------
  322|      9|      return false;
  323|      9|    }
  324|       |
  325|   155k|    const uint32_t level = levels[axis];
  326|       |
  327|       |    // All axes have been fully subdivided, just output points.
  328|   155k|    if ((bit_length_ - level) == 0) {
  ------------------
  |  Branch (328:9): [True: 180, False: 155k]
  ------------------
  329|  8.09M|      for (uint32_t i = 0; i < num_remaining_points; i++) {
  ------------------
  |  Branch (329:28): [True: 8.09M, False: 180]
  ------------------
  330|  8.09M|        *oit = old_base;
  331|  8.09M|        ++oit;
  332|  8.09M|        ++num_decoded_points_;
  333|  8.09M|      }
  334|    180|      continue;
  335|    180|    }
  336|       |
  337|   155k|    DRACO_DCHECK_EQ(true, num_remaining_points != 0);
  338|       |
  339|       |    // Fast decoding of remaining bits if number of points is 1 or 2.
  340|   155k|    if (num_remaining_points <= 2) {
  ------------------
  |  Branch (340:9): [True: 235, False: 155k]
  ------------------
  341|       |      // TODO(b/199760123): |axes_| not necessary, remove would change
  342|       |      // bitstream!
  343|    235|      axes_[0] = axis;
  344|  14.7k|      for (uint32_t i = 1; i < dimension_; i++) {
  ------------------
  |  Branch (344:28): [True: 14.5k, False: 235]
  ------------------
  345|  14.5k|        axes_[i] = DRACO_INCREMENT_MOD(axes_[i - 1], dimension_);
  ------------------
  |  |   24|  14.5k|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 222, False: 14.3k]
  |  |  ------------------
  ------------------
  346|  14.5k|      }
  347|    534|      for (uint32_t i = 0; i < num_remaining_points; ++i) {
  ------------------
  |  Branch (347:28): [True: 320, False: 214]
  ------------------
  348|  17.6k|        for (uint32_t j = 0; j < dimension_; j++) {
  ------------------
  |  Branch (348:30): [True: 17.3k, False: 299]
  ------------------
  349|  17.3k|          p_[axes_[j]] = 0;
  350|  17.3k|          const uint32_t num_remaining_bits = bit_length_ - levels[axes_[j]];
  351|  17.3k|          if (num_remaining_bits) {
  ------------------
  |  Branch (351:15): [True: 16.9k, False: 396]
  ------------------
  352|  16.9k|            if (!remaining_bits_decoder_.DecodeLeastSignificantBits32(
  ------------------
  |  Branch (352:17): [True: 21, False: 16.8k]
  ------------------
  353|  16.9k|                    num_remaining_bits, &p_[axes_[j]])) {
  354|     21|              return false;
  355|     21|            }
  356|  16.9k|          }
  357|  17.2k|          p_[axes_[j]] = old_base[axes_[j]] | p_[axes_[j]];
  358|  17.2k|        }
  359|    299|        *oit = p_;
  360|    299|        ++oit;
  361|    299|        ++num_decoded_points_;
  362|    299|      }
  363|    214|      continue;
  364|    235|    }
  365|       |
  366|   155k|    if (num_decoded_points_ > num_points_) {
  ------------------
  |  Branch (366:9): [True: 0, False: 155k]
  ------------------
  367|      0|      return false;
  368|      0|    }
  369|       |
  370|   155k|    const int num_remaining_bits = bit_length_ - level;
  371|   155k|    const uint32_t modifier = 1 << (num_remaining_bits - 1);
  372|       |
  373|   155k|    const int incoming_bits = MostSignificantBit(num_remaining_points);
  374|       |
  375|   155k|    uint32_t number = 0;
  376|   155k|    DecodeNumber(incoming_bits, &number);
  377|       |
  378|   155k|    uint32_t first_half = num_remaining_points / 2;
  379|   155k|    if (first_half < number) {
  ------------------
  |  Branch (379:9): [True: 12, False: 155k]
  ------------------
  380|       |      // Invalid |number|.
  381|     12|      return false;
  382|     12|    }
  383|   155k|    first_half -= number;
  384|   155k|    uint32_t second_half = num_remaining_points - first_half;
  385|       |
  386|   155k|    if (first_half != second_half) {
  ------------------
  |  Branch (386:9): [True: 155k, False: 17]
  ------------------
  387|   155k|      if (!half_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (387:11): [True: 135k, False: 19.4k]
  ------------------
  388|   135k|        std::swap(first_half, second_half);
  389|   135k|      }
  390|   155k|    }
  391|       |
  392|   155k|    if (depth == std::numeric_limits<uint32_t>::max()) {
  ------------------
  |  Branch (392:9): [True: 0, False: 155k]
  ------------------
  393|      0|      return false;
  394|      0|    }
  395|       |    // Both halves see |axis| one level deeper. The first half stays at this
  396|       |    // depth and keeps the base, the second goes one deeper with the split bit
  397|       |    // set in its base.
  398|   155k|    undo_.push_back({depth, axis, levels_[axis], base_[axis]});
  399|   155k|    levels_[axis] += 1;
  400|   155k|    base_[axis] += modifier;
  401|   155k|    if (first_half) {
  ------------------
  |  Branch (401:9): [True: 136k, False: 19.2k]
  ------------------
  402|   136k|      status_stack.push(DecodingStatus(first_half, axis, depth));
  403|   136k|    }
  404|   155k|    if (second_half) {
  ------------------
  |  Branch (404:9): [True: 19.7k, False: 135k]
  ------------------
  405|  19.7k|      status_stack.push(DecodingStatus(second_half, axis, depth + 1));
  406|  19.7k|    }
  407|   155k|    ++depth;
  408|   155k|  }
  409|     25|  return true;
  410|     67|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi6EE14DecodingStatusC2Ejjj:
  130|   155k|        : num_remaining_points(num_remaining_points_),
  131|   155k|          last_axis(last_axis_),
  132|   155k|          depth(depth_) {}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi6EE12DecodeNumberEiPj:
  123|   155k|  void DecodeNumber(int nbits, uint32_t* value) {
  124|   155k|    numbers_decoder_.DecodeLeastSignificantBits32(nbits, value);
  125|   155k|  }
_ZNK5draco33DynamicIntegerPointsKdTreeDecoderILi6EE18num_decoded_pointsEv:
  114|     85|  uint32_t num_decoded_points() const { return num_decoded_points_; }
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi0EE7GetAxisEjRKNSt3__16vectorIjNS2_9allocatorIjEEEEj:
  241|  10.1M|    uint32_t last_axis) {
  242|  10.1M|  if (!Policy::select_axis) {
  ------------------
  |  Branch (242:7): [True: 10.1M, Folded]
  ------------------
  243|  10.1M|    return DRACO_INCREMENT_MOD(last_axis, dimension_);
  ------------------
  |  |   24|  10.1M|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 9.64M, False: 511k]
  |  |  ------------------
  ------------------
  244|  10.1M|  }
  245|       |
  246|      0|  uint32_t best_axis = 0;
  247|      0|  if (num_remaining_points < 64) {
  ------------------
  |  Branch (247:7): [True: 0, False: 0]
  ------------------
  248|      0|    for (uint32_t axis = 1; axis < dimension_; ++axis) {
  ------------------
  |  Branch (248:29): [True: 0, False: 0]
  ------------------
  249|      0|      if (levels[best_axis] > levels[axis]) {
  ------------------
  |  Branch (249:11): [True: 0, False: 0]
  ------------------
  250|      0|        best_axis = axis;
  251|      0|      }
  252|      0|    }
  253|      0|  } else {
  254|      0|    axis_decoder_.DecodeLeastSignificantBits32(4, &best_axis);
  255|      0|  }
  256|       |
  257|      0|  return best_axis;
  258|  10.1M|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi2EE7GetAxisEjRKNSt3__16vectorIjNS2_9allocatorIjEEEEj:
  241|  4.27M|    uint32_t last_axis) {
  242|  4.27M|  if (!Policy::select_axis) {
  ------------------
  |  Branch (242:7): [True: 4.27M, Folded]
  ------------------
  243|  4.27M|    return DRACO_INCREMENT_MOD(last_axis, dimension_);
  ------------------
  |  |   24|  4.27M|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 1.20M, False: 3.07M]
  |  |  ------------------
  ------------------
  244|  4.27M|  }
  245|       |
  246|      0|  uint32_t best_axis = 0;
  247|      0|  if (num_remaining_points < 64) {
  ------------------
  |  Branch (247:7): [True: 0, False: 0]
  ------------------
  248|      0|    for (uint32_t axis = 1; axis < dimension_; ++axis) {
  ------------------
  |  Branch (248:29): [True: 0, False: 0]
  ------------------
  249|      0|      if (levels[best_axis] > levels[axis]) {
  ------------------
  |  Branch (249:11): [True: 0, False: 0]
  ------------------
  250|      0|        best_axis = axis;
  251|      0|      }
  252|      0|    }
  253|      0|  } else {
  254|      0|    axis_decoder_.DecodeLeastSignificantBits32(4, &best_axis);
  255|      0|  }
  256|       |
  257|      0|  return best_axis;
  258|  4.27M|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi4EE7GetAxisEjRKNSt3__16vectorIjNS2_9allocatorIjEEEEj:
  241|  2.73M|    uint32_t last_axis) {
  242|  2.73M|  if (!Policy::select_axis) {
  ------------------
  |  Branch (242:7): [True: 2.73M, Folded]
  ------------------
  243|  2.73M|    return DRACO_INCREMENT_MOD(last_axis, dimension_);
  ------------------
  |  |   24|  2.73M|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 2.49M, False: 246k]
  |  |  ------------------
  ------------------
  244|  2.73M|  }
  245|       |
  246|      0|  uint32_t best_axis = 0;
  247|      0|  if (num_remaining_points < 64) {
  ------------------
  |  Branch (247:7): [True: 0, False: 0]
  ------------------
  248|      0|    for (uint32_t axis = 1; axis < dimension_; ++axis) {
  ------------------
  |  Branch (248:29): [True: 0, False: 0]
  ------------------
  249|      0|      if (levels[best_axis] > levels[axis]) {
  ------------------
  |  Branch (249:11): [True: 0, False: 0]
  ------------------
  250|      0|        best_axis = axis;
  251|      0|      }
  252|      0|    }
  253|      0|  } else {
  254|      0|    axis_decoder_.DecodeLeastSignificantBits32(4, &best_axis);
  255|      0|  }
  256|       |
  257|      0|  return best_axis;
  258|  2.73M|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi6EE7GetAxisEjRKNSt3__16vectorIjNS2_9allocatorIjEEEEj:
  241|   155k|    uint32_t last_axis) {
  242|   155k|  if (!Policy::select_axis) {
  ------------------
  |  Branch (242:7): [Folded, False: 155k]
  ------------------
  243|      0|    return DRACO_INCREMENT_MOD(last_axis, dimension_);
  ------------------
  |  |   24|      0|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  244|      0|  }
  245|       |
  246|   155k|  uint32_t best_axis = 0;
  247|   155k|  if (num_remaining_points < 64) {
  ------------------
  |  Branch (247:7): [True: 155k, False: 256]
  ------------------
  248|  21.6M|    for (uint32_t axis = 1; axis < dimension_; ++axis) {
  ------------------
  |  Branch (248:29): [True: 21.4M, False: 155k]
  ------------------
  249|  21.4M|      if (levels[best_axis] > levels[axis]) {
  ------------------
  |  Branch (249:11): [True: 154k, False: 21.3M]
  ------------------
  250|   154k|        best_axis = axis;
  251|   154k|      }
  252|  21.4M|    }
  253|   155k|  } else {
  254|    256|    axis_decoder_.DecodeLeastSignificantBits32(4, &best_axis);
  255|    256|  }
  256|       |
  257|   155k|  return best_axis;
  258|   155k|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi0EE12DecodePointsINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbPNS_13DecoderBufferERT_:
  188|    156|    DecoderBuffer* buffer, OutputIteratorT& oit) {
  189|    156|  return DecodePoints(buffer, oit, std::numeric_limits<uint32_t>::max());
  190|    156|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi0EE12DecodePointsINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbPNS_13DecoderBufferERT_j:
  195|    156|    DecoderBuffer* buffer, OutputIteratorT& oit, uint32_t oit_max_points) {
  196|    156|  if (!buffer->Decode(&bit_length_)) {
  ------------------
  |  Branch (196:7): [True: 3, False: 153]
  ------------------
  197|      3|    return false;
  198|      3|  }
  199|    153|  if (bit_length_ > 32) {
  ------------------
  |  Branch (199:7): [True: 24, False: 129]
  ------------------
  200|     24|    return false;
  201|     24|  }
  202|    129|  if (!buffer->Decode(&num_points_)) {
  ------------------
  |  Branch (202:7): [True: 3, False: 126]
  ------------------
  203|      3|    return false;
  204|      3|  }
  205|    126|  if (num_points_ == 0) {
  ------------------
  |  Branch (205:7): [True: 1, False: 125]
  ------------------
  206|      1|    return true;
  207|      1|  }
  208|    125|  if (num_points_ > oit_max_points) {
  ------------------
  |  Branch (208:7): [True: 0, False: 125]
  ------------------
  209|      0|    return false;
  210|      0|  }
  211|    125|  num_decoded_points_ = 0;
  212|       |
  213|    125|  if (!numbers_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (213:7): [True: 40, False: 85]
  ------------------
  214|     40|    return false;
  215|     40|  }
  216|     85|  if (!remaining_bits_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (216:7): [True: 5, False: 80]
  ------------------
  217|      5|    return false;
  218|      5|  }
  219|     80|  if (!axis_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (219:7): [True: 3, False: 77]
  ------------------
  220|      3|    return false;
  221|      3|  }
  222|     77|  if (!half_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (222:7): [True: 1, False: 76]
  ------------------
  223|      1|    return false;
  224|      1|  }
  225|       |
  226|     76|  if (!DecodeInternal(num_points_, oit)) {
  ------------------
  |  Branch (226:7): [True: 54, False: 22]
  ------------------
  227|     54|    return false;
  228|     54|  }
  229|       |
  230|     22|  numbers_decoder_.EndDecoding();
  231|     22|  remaining_bits_decoder_.EndDecoding();
  232|     22|  axis_decoder_.EndDecoding();
  233|     22|  half_decoder_.EndDecoding();
  234|       |
  235|     22|  return true;
  236|     76|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi0EE14DecodeInternalINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbjRT_:
  263|     76|    uint32_t num_points, OutputIteratorT& oit) {
  264|     76|  typedef DecodingStatus Status;
  265|       |  // The tree can be 32 * dimension levels deep, so keeping a base and levels
  266|       |  // vector per level takes memory quadratic in the dimension. The walk keeps
  267|       |  // one of each instead. A split at depth d raises one level of the node at
  268|       |  // d, and the node at d + 1 has the same levels and one more base bit set.
  269|       |  // Each split is logged in |undo_|, and on reaching a node at depth t the
  270|       |  // walk undoes the splits deeper than t and the base bit of the last split
  271|       |  // at t.
  272|       |  //
  273|       |  // A split takes its node off the top of |status_stack|, where every node
  274|       |  // below is shallower, and pushes its halves at d and d + 1. So the depths
  275|       |  // on the stack strictly increase towards its top, and a node is reached
  276|       |  // only after everything deeper than it has been decoded.
  277|     76|  base_.assign(dimension_, 0);
  278|     76|  levels_.assign(dimension_, 0);
  279|     76|  undo_.clear();
  280|     76|  uint32_t depth = 0;
  281|     76|  DecodingStatus init_status(num_points, 0, 0);
  282|     76|  std::stack<Status> status_stack;
  283|     76|  status_stack.push(init_status);
  284|       |
  285|       |  // TODO(b/199760123): Use preallocated vector instead of stack.
  286|   666k|  while (!status_stack.empty()) {
  ------------------
  |  Branch (286:10): [True: 666k, False: 22]
  ------------------
  287|   666k|    const DecodingStatus status = status_stack.top();
  288|   666k|    status_stack.pop();
  289|       |
  290|   666k|    const uint32_t num_remaining_points = status.num_remaining_points;
  291|   666k|    const uint32_t last_axis = status.last_axis;
  292|       |    // A node at the current depth is the second half of the split just made,
  293|       |    // and nothing needs to be undone for it.
  294|   666k|    if (status.depth != depth) {
  ------------------
  |  Branch (294:9): [True: 333k, False: 333k]
  ------------------
  295|   333k|      if (status.depth > depth) {
  ------------------
  |  Branch (295:11): [True: 0, False: 333k]
  ------------------
  296|      0|        return false;
  297|      0|      }
  298|   665k|      while (!undo_.empty()) {
  ------------------
  |  Branch (298:14): [True: 665k, False: 0]
  ------------------
  299|   665k|        const SplitUndo& split = undo_.back();
  300|   665k|        if (split.depth < status.depth) {
  ------------------
  |  Branch (300:13): [True: 0, False: 665k]
  ------------------
  301|      0|          break;
  302|      0|        }
  303|   665k|        base_[split.axis] = split.old_base;
  304|   665k|        if (split.depth == status.depth) {
  ------------------
  |  Branch (304:13): [True: 333k, False: 332k]
  ------------------
  305|       |          // The node's own split, whose level stays raised.
  306|   333k|          break;
  307|   333k|        }
  308|   332k|        levels_[split.axis] = split.old_level;
  309|   332k|        undo_.pop_back();
  310|   332k|      }
  311|   333k|      depth = status.depth;
  312|   333k|    }
  313|   666k|    const VectorUint32& old_base = base_;
  314|   666k|    const VectorUint32& levels = levels_;
  315|       |
  316|   666k|    if (num_remaining_points > num_points) {
  ------------------
  |  Branch (316:9): [True: 0, False: 666k]
  ------------------
  317|      0|      return false;
  318|      0|    }
  319|       |
  320|   666k|    const uint32_t axis = GetAxis(num_remaining_points, levels, last_axis);
  321|   666k|    if (axis >= dimension_) {
  ------------------
  |  Branch (321:9): [True: 0, False: 666k]
  ------------------
  322|      0|      return false;
  323|      0|    }
  324|       |
  325|   666k|    const uint32_t level = levels[axis];
  326|       |
  327|       |    // All axes have been fully subdivided, just output points.
  328|   666k|    if ((bit_length_ - level) == 0) {
  ------------------
  |  Branch (328:9): [True: 332k, False: 334k]
  ------------------
  329|   148M|      for (uint32_t i = 0; i < num_remaining_points; i++) {
  ------------------
  |  Branch (329:28): [True: 147M, False: 332k]
  ------------------
  330|   147M|        *oit = old_base;
  331|   147M|        ++oit;
  332|   147M|        ++num_decoded_points_;
  333|   147M|      }
  334|   332k|      continue;
  335|   332k|    }
  336|       |
  337|   334k|    DRACO_DCHECK_EQ(true, num_remaining_points != 0);
  338|       |
  339|       |    // Fast decoding of remaining bits if number of points is 1 or 2.
  340|   334k|    if (num_remaining_points <= 2) {
  ------------------
  |  Branch (340:9): [True: 711, False: 333k]
  ------------------
  341|       |      // TODO(b/199760123): |axes_| not necessary, remove would change
  342|       |      // bitstream!
  343|    711|      axes_[0] = axis;
  344|  2.13k|      for (uint32_t i = 1; i < dimension_; i++) {
  ------------------
  |  Branch (344:28): [True: 1.42k, False: 711]
  ------------------
  345|  1.42k|        axes_[i] = DRACO_INCREMENT_MOD(axes_[i - 1], dimension_);
  ------------------
  |  |   24|  1.42k|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 291, False: 1.13k]
  |  |  ------------------
  ------------------
  346|  1.42k|      }
  347|  1.86k|      for (uint32_t i = 0; i < num_remaining_points; ++i) {
  ------------------
  |  Branch (347:28): [True: 1.18k, False: 679]
  ------------------
  348|  4.67k|        for (uint32_t j = 0; j < dimension_; j++) {
  ------------------
  |  Branch (348:30): [True: 3.51k, False: 1.15k]
  ------------------
  349|  3.51k|          p_[axes_[j]] = 0;
  350|  3.51k|          const uint32_t num_remaining_bits = bit_length_ - levels[axes_[j]];
  351|  3.51k|          if (num_remaining_bits) {
  ------------------
  |  Branch (351:15): [True: 2.02k, False: 1.49k]
  ------------------
  352|  2.02k|            if (!remaining_bits_decoder_.DecodeLeastSignificantBits32(
  ------------------
  |  Branch (352:17): [True: 32, False: 1.98k]
  ------------------
  353|  2.02k|                    num_remaining_bits, &p_[axes_[j]])) {
  354|     32|              return false;
  355|     32|            }
  356|  2.02k|          }
  357|  3.48k|          p_[axes_[j]] = old_base[axes_[j]] | p_[axes_[j]];
  358|  3.48k|        }
  359|  1.15k|        *oit = p_;
  360|  1.15k|        ++oit;
  361|  1.15k|        ++num_decoded_points_;
  362|  1.15k|      }
  363|    679|      continue;
  364|    711|    }
  365|       |
  366|   333k|    if (num_decoded_points_ > num_points_) {
  ------------------
  |  Branch (366:9): [True: 0, False: 333k]
  ------------------
  367|      0|      return false;
  368|      0|    }
  369|       |
  370|   333k|    const int num_remaining_bits = bit_length_ - level;
  371|   333k|    const uint32_t modifier = 1 << (num_remaining_bits - 1);
  372|       |
  373|   333k|    const int incoming_bits = MostSignificantBit(num_remaining_points);
  374|       |
  375|   333k|    uint32_t number = 0;
  376|   333k|    DecodeNumber(incoming_bits, &number);
  377|       |
  378|   333k|    uint32_t first_half = num_remaining_points / 2;
  379|   333k|    if (first_half < number) {
  ------------------
  |  Branch (379:9): [True: 22, False: 333k]
  ------------------
  380|       |      // Invalid |number|.
  381|     22|      return false;
  382|     22|    }
  383|   333k|    first_half -= number;
  384|   333k|    uint32_t second_half = num_remaining_points - first_half;
  385|       |
  386|   333k|    if (first_half != second_half) {
  ------------------
  |  Branch (386:9): [True: 152k, False: 181k]
  ------------------
  387|   152k|      if (!half_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (387:11): [True: 151k, False: 841]
  ------------------
  388|   151k|        std::swap(first_half, second_half);
  389|   151k|      }
  390|   152k|    }
  391|       |
  392|   333k|    if (depth == std::numeric_limits<uint32_t>::max()) {
  ------------------
  |  Branch (392:9): [True: 0, False: 333k]
  ------------------
  393|      0|      return false;
  394|      0|    }
  395|       |    // Both halves see |axis| one level deeper. The first half stays at this
  396|       |    // depth and keeps the base, the second goes one deeper with the split bit
  397|       |    // set in its base.
  398|   333k|    undo_.push_back({depth, axis, levels_[axis], base_[axis]});
  399|   333k|    levels_[axis] += 1;
  400|   333k|    base_[axis] += modifier;
  401|   333k|    if (first_half) {
  ------------------
  |  Branch (401:9): [True: 333k, False: 49]
  ------------------
  402|   333k|      status_stack.push(DecodingStatus(first_half, axis, depth));
  403|   333k|    }
  404|   333k|    if (second_half) {
  ------------------
  |  Branch (404:9): [True: 333k, False: 125]
  ------------------
  405|   333k|      status_stack.push(DecodingStatus(second_half, axis, depth + 1));
  406|   333k|    }
  407|   333k|    ++depth;
  408|   333k|  }
  409|     22|  return true;
  410|     76|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi1EE12DecodePointsINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbPNS_13DecoderBufferERT_:
  188|    113|    DecoderBuffer* buffer, OutputIteratorT& oit) {
  189|    113|  return DecodePoints(buffer, oit, std::numeric_limits<uint32_t>::max());
  190|    113|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi1EE12DecodePointsINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbPNS_13DecoderBufferERT_j:
  195|    113|    DecoderBuffer* buffer, OutputIteratorT& oit, uint32_t oit_max_points) {
  196|    113|  if (!buffer->Decode(&bit_length_)) {
  ------------------
  |  Branch (196:7): [True: 2, False: 111]
  ------------------
  197|      2|    return false;
  198|      2|  }
  199|    111|  if (bit_length_ > 32) {
  ------------------
  |  Branch (199:7): [True: 10, False: 101]
  ------------------
  200|     10|    return false;
  201|     10|  }
  202|    101|  if (!buffer->Decode(&num_points_)) {
  ------------------
  |  Branch (202:7): [True: 1, False: 100]
  ------------------
  203|      1|    return false;
  204|      1|  }
  205|    100|  if (num_points_ == 0) {
  ------------------
  |  Branch (205:7): [True: 1, False: 99]
  ------------------
  206|      1|    return true;
  207|      1|  }
  208|     99|  if (num_points_ > oit_max_points) {
  ------------------
  |  Branch (208:7): [True: 0, False: 99]
  ------------------
  209|      0|    return false;
  210|      0|  }
  211|     99|  num_decoded_points_ = 0;
  212|       |
  213|     99|  if (!numbers_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (213:7): [True: 19, False: 80]
  ------------------
  214|     19|    return false;
  215|     19|  }
  216|     80|  if (!remaining_bits_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (216:7): [True: 7, False: 73]
  ------------------
  217|      7|    return false;
  218|      7|  }
  219|     73|  if (!axis_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (219:7): [True: 1, False: 72]
  ------------------
  220|      1|    return false;
  221|      1|  }
  222|     72|  if (!half_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (222:7): [True: 3, False: 69]
  ------------------
  223|      3|    return false;
  224|      3|  }
  225|       |
  226|     69|  if (!DecodeInternal(num_points_, oit)) {
  ------------------
  |  Branch (226:7): [True: 52, False: 17]
  ------------------
  227|     52|    return false;
  228|     52|  }
  229|       |
  230|     17|  numbers_decoder_.EndDecoding();
  231|     17|  remaining_bits_decoder_.EndDecoding();
  232|     17|  axis_decoder_.EndDecoding();
  233|     17|  half_decoder_.EndDecoding();
  234|       |
  235|     17|  return true;
  236|     69|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi1EE14DecodeInternalINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbjRT_:
  263|     69|    uint32_t num_points, OutputIteratorT& oit) {
  264|     69|  typedef DecodingStatus Status;
  265|       |  // The tree can be 32 * dimension levels deep, so keeping a base and levels
  266|       |  // vector per level takes memory quadratic in the dimension. The walk keeps
  267|       |  // one of each instead. A split at depth d raises one level of the node at
  268|       |  // d, and the node at d + 1 has the same levels and one more base bit set.
  269|       |  // Each split is logged in |undo_|, and on reaching a node at depth t the
  270|       |  // walk undoes the splits deeper than t and the base bit of the last split
  271|       |  // at t.
  272|       |  //
  273|       |  // A split takes its node off the top of |status_stack|, where every node
  274|       |  // below is shallower, and pushes its halves at d and d + 1. So the depths
  275|       |  // on the stack strictly increase towards its top, and a node is reached
  276|       |  // only after everything deeper than it has been decoded.
  277|     69|  base_.assign(dimension_, 0);
  278|     69|  levels_.assign(dimension_, 0);
  279|     69|  undo_.clear();
  280|     69|  uint32_t depth = 0;
  281|     69|  DecodingStatus init_status(num_points, 0, 0);
  282|     69|  std::stack<Status> status_stack;
  283|     69|  status_stack.push(init_status);
  284|       |
  285|       |  // TODO(b/199760123): Use preallocated vector instead of stack.
  286|  1.90M|  while (!status_stack.empty()) {
  ------------------
  |  Branch (286:10): [True: 1.90M, False: 17]
  ------------------
  287|  1.90M|    const DecodingStatus status = status_stack.top();
  288|  1.90M|    status_stack.pop();
  289|       |
  290|  1.90M|    const uint32_t num_remaining_points = status.num_remaining_points;
  291|  1.90M|    const uint32_t last_axis = status.last_axis;
  292|       |    // A node at the current depth is the second half of the split just made,
  293|       |    // and nothing needs to be undone for it.
  294|  1.90M|    if (status.depth != depth) {
  ------------------
  |  Branch (294:9): [True: 951k, False: 952k]
  ------------------
  295|   951k|      if (status.depth > depth) {
  ------------------
  |  Branch (295:11): [True: 0, False: 951k]
  ------------------
  296|      0|        return false;
  297|      0|      }
  298|  1.90M|      while (!undo_.empty()) {
  ------------------
  |  Branch (298:14): [True: 1.90M, False: 0]
  ------------------
  299|  1.90M|        const SplitUndo& split = undo_.back();
  300|  1.90M|        if (split.depth < status.depth) {
  ------------------
  |  Branch (300:13): [True: 0, False: 1.90M]
  ------------------
  301|      0|          break;
  302|      0|        }
  303|  1.90M|        base_[split.axis] = split.old_base;
  304|  1.90M|        if (split.depth == status.depth) {
  ------------------
  |  Branch (304:13): [True: 951k, False: 951k]
  ------------------
  305|       |          // The node's own split, whose level stays raised.
  306|   951k|          break;
  307|   951k|        }
  308|   951k|        levels_[split.axis] = split.old_level;
  309|   951k|        undo_.pop_back();
  310|   951k|      }
  311|   951k|      depth = status.depth;
  312|   951k|    }
  313|  1.90M|    const VectorUint32& old_base = base_;
  314|  1.90M|    const VectorUint32& levels = levels_;
  315|       |
  316|  1.90M|    if (num_remaining_points > num_points) {
  ------------------
  |  Branch (316:9): [True: 0, False: 1.90M]
  ------------------
  317|      0|      return false;
  318|      0|    }
  319|       |
  320|  1.90M|    const uint32_t axis = GetAxis(num_remaining_points, levels, last_axis);
  321|  1.90M|    if (axis >= dimension_) {
  ------------------
  |  Branch (321:9): [True: 0, False: 1.90M]
  ------------------
  322|      0|      return false;
  323|      0|    }
  324|       |
  325|  1.90M|    const uint32_t level = levels[axis];
  326|       |
  327|       |    // All axes have been fully subdivided, just output points.
  328|  1.90M|    if ((bit_length_ - level) == 0) {
  ------------------
  |  Branch (328:9): [True: 950k, False: 953k]
  ------------------
  329|  54.1M|      for (uint32_t i = 0; i < num_remaining_points; i++) {
  ------------------
  |  Branch (329:28): [True: 53.1M, False: 950k]
  ------------------
  330|  53.1M|        *oit = old_base;
  331|  53.1M|        ++oit;
  332|  53.1M|        ++num_decoded_points_;
  333|  53.1M|      }
  334|   950k|      continue;
  335|   950k|    }
  336|       |
  337|   953k|    DRACO_DCHECK_EQ(true, num_remaining_points != 0);
  338|       |
  339|       |    // Fast decoding of remaining bits if number of points is 1 or 2.
  340|   953k|    if (num_remaining_points <= 2) {
  ------------------
  |  Branch (340:9): [True: 1.12k, False: 952k]
  ------------------
  341|       |      // TODO(b/199760123): |axes_| not necessary, remove would change
  342|       |      // bitstream!
  343|  1.12k|      axes_[0] = axis;
  344|  3.37k|      for (uint32_t i = 1; i < dimension_; i++) {
  ------------------
  |  Branch (344:28): [True: 2.25k, False: 1.12k]
  ------------------
  345|  2.25k|        axes_[i] = DRACO_INCREMENT_MOD(axes_[i - 1], dimension_);
  ------------------
  |  |   24|  2.25k|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 383, False: 1.86k]
  |  |  ------------------
  ------------------
  346|  2.25k|      }
  347|  2.94k|      for (uint32_t i = 0; i < num_remaining_points; ++i) {
  ------------------
  |  Branch (347:28): [True: 1.85k, False: 1.08k]
  ------------------
  348|  7.31k|        for (uint32_t j = 0; j < dimension_; j++) {
  ------------------
  |  Branch (348:30): [True: 5.50k, False: 1.81k]
  ------------------
  349|  5.50k|          p_[axes_[j]] = 0;
  350|  5.50k|          const uint32_t num_remaining_bits = bit_length_ - levels[axes_[j]];
  351|  5.50k|          if (num_remaining_bits) {
  ------------------
  |  Branch (351:15): [True: 2.96k, False: 2.54k]
  ------------------
  352|  2.96k|            if (!remaining_bits_decoder_.DecodeLeastSignificantBits32(
  ------------------
  |  Branch (352:17): [True: 36, False: 2.92k]
  ------------------
  353|  2.96k|                    num_remaining_bits, &p_[axes_[j]])) {
  354|     36|              return false;
  355|     36|            }
  356|  2.96k|          }
  357|  5.46k|          p_[axes_[j]] = old_base[axes_[j]] | p_[axes_[j]];
  358|  5.46k|        }
  359|  1.81k|        *oit = p_;
  360|  1.81k|        ++oit;
  361|  1.81k|        ++num_decoded_points_;
  362|  1.81k|      }
  363|  1.08k|      continue;
  364|  1.12k|    }
  365|       |
  366|   952k|    if (num_decoded_points_ > num_points_) {
  ------------------
  |  Branch (366:9): [True: 0, False: 952k]
  ------------------
  367|      0|      return false;
  368|      0|    }
  369|       |
  370|   952k|    const int num_remaining_bits = bit_length_ - level;
  371|   952k|    const uint32_t modifier = 1 << (num_remaining_bits - 1);
  372|       |
  373|   952k|    const int incoming_bits = MostSignificantBit(num_remaining_points);
  374|       |
  375|   952k|    uint32_t number = 0;
  376|   952k|    DecodeNumber(incoming_bits, &number);
  377|       |
  378|   952k|    uint32_t first_half = num_remaining_points / 2;
  379|   952k|    if (first_half < number) {
  ------------------
  |  Branch (379:9): [True: 16, False: 952k]
  ------------------
  380|       |      // Invalid |number|.
  381|     16|      return false;
  382|     16|    }
  383|   952k|    first_half -= number;
  384|   952k|    uint32_t second_half = num_remaining_points - first_half;
  385|       |
  386|   952k|    if (first_half != second_half) {
  ------------------
  |  Branch (386:9): [True: 517k, False: 435k]
  ------------------
  387|   517k|      if (!half_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (387:11): [True: 515k, False: 1.14k]
  ------------------
  388|   515k|        std::swap(first_half, second_half);
  389|   515k|      }
  390|   517k|    }
  391|       |
  392|   952k|    if (depth == std::numeric_limits<uint32_t>::max()) {
  ------------------
  |  Branch (392:9): [True: 0, False: 952k]
  ------------------
  393|      0|      return false;
  394|      0|    }
  395|       |    // Both halves see |axis| one level deeper. The first half stays at this
  396|       |    // depth and keeps the base, the second goes one deeper with the split bit
  397|       |    // set in its base.
  398|   952k|    undo_.push_back({depth, axis, levels_[axis], base_[axis]});
  399|   952k|    levels_[axis] += 1;
  400|   952k|    base_[axis] += modifier;
  401|   952k|    if (first_half) {
  ------------------
  |  Branch (401:9): [True: 952k, False: 21]
  ------------------
  402|   952k|      status_stack.push(DecodingStatus(first_half, axis, depth));
  403|   952k|    }
  404|   952k|    if (second_half) {
  ------------------
  |  Branch (404:9): [True: 952k, False: 59]
  ------------------
  405|   952k|      status_stack.push(DecodingStatus(second_half, axis, depth + 1));
  406|   952k|    }
  407|   952k|    ++depth;
  408|   952k|  }
  409|     17|  return true;
  410|     69|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi2EE12DecodePointsINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbPNS_13DecoderBufferERT_:
  188|    142|    DecoderBuffer* buffer, OutputIteratorT& oit) {
  189|    142|  return DecodePoints(buffer, oit, std::numeric_limits<uint32_t>::max());
  190|    142|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi2EE12DecodePointsINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbPNS_13DecoderBufferERT_j:
  195|    142|    DecoderBuffer* buffer, OutputIteratorT& oit, uint32_t oit_max_points) {
  196|    142|  if (!buffer->Decode(&bit_length_)) {
  ------------------
  |  Branch (196:7): [True: 3, False: 139]
  ------------------
  197|      3|    return false;
  198|      3|  }
  199|    139|  if (bit_length_ > 32) {
  ------------------
  |  Branch (199:7): [True: 18, False: 121]
  ------------------
  200|     18|    return false;
  201|     18|  }
  202|    121|  if (!buffer->Decode(&num_points_)) {
  ------------------
  |  Branch (202:7): [True: 1, False: 120]
  ------------------
  203|      1|    return false;
  204|      1|  }
  205|    120|  if (num_points_ == 0) {
  ------------------
  |  Branch (205:7): [True: 1, False: 119]
  ------------------
  206|      1|    return true;
  207|      1|  }
  208|    119|  if (num_points_ > oit_max_points) {
  ------------------
  |  Branch (208:7): [True: 0, False: 119]
  ------------------
  209|      0|    return false;
  210|      0|  }
  211|    119|  num_decoded_points_ = 0;
  212|       |
  213|    119|  if (!numbers_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (213:7): [True: 40, False: 79]
  ------------------
  214|     40|    return false;
  215|     40|  }
  216|     79|  if (!remaining_bits_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (216:7): [True: 7, False: 72]
  ------------------
  217|      7|    return false;
  218|      7|  }
  219|     72|  if (!axis_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (219:7): [True: 3, False: 69]
  ------------------
  220|      3|    return false;
  221|      3|  }
  222|     69|  if (!half_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (222:7): [True: 1, False: 68]
  ------------------
  223|      1|    return false;
  224|      1|  }
  225|       |
  226|     68|  if (!DecodeInternal(num_points_, oit)) {
  ------------------
  |  Branch (226:7): [True: 63, False: 5]
  ------------------
  227|     63|    return false;
  228|     63|  }
  229|       |
  230|      5|  numbers_decoder_.EndDecoding();
  231|      5|  remaining_bits_decoder_.EndDecoding();
  232|      5|  axis_decoder_.EndDecoding();
  233|      5|  half_decoder_.EndDecoding();
  234|       |
  235|      5|  return true;
  236|     68|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi2EE14DecodeInternalINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbjRT_:
  263|     68|    uint32_t num_points, OutputIteratorT& oit) {
  264|     68|  typedef DecodingStatus Status;
  265|       |  // The tree can be 32 * dimension levels deep, so keeping a base and levels
  266|       |  // vector per level takes memory quadratic in the dimension. The walk keeps
  267|       |  // one of each instead. A split at depth d raises one level of the node at
  268|       |  // d, and the node at d + 1 has the same levels and one more base bit set.
  269|       |  // Each split is logged in |undo_|, and on reaching a node at depth t the
  270|       |  // walk undoes the splits deeper than t and the base bit of the last split
  271|       |  // at t.
  272|       |  //
  273|       |  // A split takes its node off the top of |status_stack|, where every node
  274|       |  // below is shallower, and pushes its halves at d and d + 1. So the depths
  275|       |  // on the stack strictly increase towards its top, and a node is reached
  276|       |  // only after everything deeper than it has been decoded.
  277|     68|  base_.assign(dimension_, 0);
  278|     68|  levels_.assign(dimension_, 0);
  279|     68|  undo_.clear();
  280|     68|  uint32_t depth = 0;
  281|     68|  DecodingStatus init_status(num_points, 0, 0);
  282|     68|  std::stack<Status> status_stack;
  283|     68|  status_stack.push(init_status);
  284|       |
  285|       |  // TODO(b/199760123): Use preallocated vector instead of stack.
  286|  4.21M|  while (!status_stack.empty()) {
  ------------------
  |  Branch (286:10): [True: 4.21M, False: 5]
  ------------------
  287|  4.21M|    const DecodingStatus status = status_stack.top();
  288|  4.21M|    status_stack.pop();
  289|       |
  290|  4.21M|    const uint32_t num_remaining_points = status.num_remaining_points;
  291|  4.21M|    const uint32_t last_axis = status.last_axis;
  292|       |    // A node at the current depth is the second half of the split just made,
  293|       |    // and nothing needs to be undone for it.
  294|  4.21M|    if (status.depth != depth) {
  ------------------
  |  Branch (294:9): [True: 2.10M, False: 2.10M]
  ------------------
  295|  2.10M|      if (status.depth > depth) {
  ------------------
  |  Branch (295:11): [True: 0, False: 2.10M]
  ------------------
  296|      0|        return false;
  297|      0|      }
  298|  4.21M|      while (!undo_.empty()) {
  ------------------
  |  Branch (298:14): [True: 4.21M, False: 0]
  ------------------
  299|  4.21M|        const SplitUndo& split = undo_.back();
  300|  4.21M|        if (split.depth < status.depth) {
  ------------------
  |  Branch (300:13): [True: 0, False: 4.21M]
  ------------------
  301|      0|          break;
  302|      0|        }
  303|  4.21M|        base_[split.axis] = split.old_base;
  304|  4.21M|        if (split.depth == status.depth) {
  ------------------
  |  Branch (304:13): [True: 2.10M, False: 2.10M]
  ------------------
  305|       |          // The node's own split, whose level stays raised.
  306|  2.10M|          break;
  307|  2.10M|        }
  308|  2.10M|        levels_[split.axis] = split.old_level;
  309|  2.10M|        undo_.pop_back();
  310|  2.10M|      }
  311|  2.10M|      depth = status.depth;
  312|  2.10M|    }
  313|  4.21M|    const VectorUint32& old_base = base_;
  314|  4.21M|    const VectorUint32& levels = levels_;
  315|       |
  316|  4.21M|    if (num_remaining_points > num_points) {
  ------------------
  |  Branch (316:9): [True: 0, False: 4.21M]
  ------------------
  317|      0|      return false;
  318|      0|    }
  319|       |
  320|  4.21M|    const uint32_t axis = GetAxis(num_remaining_points, levels, last_axis);
  321|  4.21M|    if (axis >= dimension_) {
  ------------------
  |  Branch (321:9): [True: 0, False: 4.21M]
  ------------------
  322|      0|      return false;
  323|      0|    }
  324|       |
  325|  4.21M|    const uint32_t level = levels[axis];
  326|       |
  327|       |    // All axes have been fully subdivided, just output points.
  328|  4.21M|    if ((bit_length_ - level) == 0) {
  ------------------
  |  Branch (328:9): [True: 2.10M, False: 2.10M]
  ------------------
  329|  30.6M|      for (uint32_t i = 0; i < num_remaining_points; i++) {
  ------------------
  |  Branch (329:28): [True: 28.5M, False: 2.10M]
  ------------------
  330|  28.5M|        *oit = old_base;
  331|  28.5M|        ++oit;
  332|  28.5M|        ++num_decoded_points_;
  333|  28.5M|      }
  334|  2.10M|      continue;
  335|  2.10M|    }
  336|       |
  337|  2.10M|    DRACO_DCHECK_EQ(true, num_remaining_points != 0);
  338|       |
  339|       |    // Fast decoding of remaining bits if number of points is 1 or 2.
  340|  2.10M|    if (num_remaining_points <= 2) {
  ------------------
  |  Branch (340:9): [True: 470, False: 2.10M]
  ------------------
  341|       |      // TODO(b/199760123): |axes_| not necessary, remove would change
  342|       |      // bitstream!
  343|    470|      axes_[0] = axis;
  344|  1.41k|      for (uint32_t i = 1; i < dimension_; i++) {
  ------------------
  |  Branch (344:28): [True: 940, False: 470]
  ------------------
  345|    940|        axes_[i] = DRACO_INCREMENT_MOD(axes_[i - 1], dimension_);
  ------------------
  |  |   24|    940|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 203, False: 737]
  |  |  ------------------
  ------------------
  346|    940|      }
  347|  1.24k|      for (uint32_t i = 0; i < num_remaining_points; ++i) {
  ------------------
  |  Branch (347:28): [True: 788, False: 453]
  ------------------
  348|  3.10k|        for (uint32_t j = 0; j < dimension_; j++) {
  ------------------
  |  Branch (348:30): [True: 2.33k, False: 771]
  ------------------
  349|  2.33k|          p_[axes_[j]] = 0;
  350|  2.33k|          const uint32_t num_remaining_bits = bit_length_ - levels[axes_[j]];
  351|  2.33k|          if (num_remaining_bits) {
  ------------------
  |  Branch (351:15): [True: 1.40k, False: 931]
  ------------------
  352|  1.40k|            if (!remaining_bits_decoder_.DecodeLeastSignificantBits32(
  ------------------
  |  Branch (352:17): [True: 17, False: 1.38k]
  ------------------
  353|  1.40k|                    num_remaining_bits, &p_[axes_[j]])) {
  354|     17|              return false;
  355|     17|            }
  356|  1.40k|          }
  357|  2.32k|          p_[axes_[j]] = old_base[axes_[j]] | p_[axes_[j]];
  358|  2.32k|        }
  359|    771|        *oit = p_;
  360|    771|        ++oit;
  361|    771|        ++num_decoded_points_;
  362|    771|      }
  363|    453|      continue;
  364|    470|    }
  365|       |
  366|  2.10M|    if (num_decoded_points_ > num_points_) {
  ------------------
  |  Branch (366:9): [True: 0, False: 2.10M]
  ------------------
  367|      0|      return false;
  368|      0|    }
  369|       |
  370|  2.10M|    const int num_remaining_bits = bit_length_ - level;
  371|  2.10M|    const uint32_t modifier = 1 << (num_remaining_bits - 1);
  372|       |
  373|  2.10M|    const int incoming_bits = MostSignificantBit(num_remaining_points);
  374|       |
  375|  2.10M|    uint32_t number = 0;
  376|  2.10M|    DecodeNumber(incoming_bits, &number);
  377|       |
  378|  2.10M|    uint32_t first_half = num_remaining_points / 2;
  379|  2.10M|    if (first_half < number) {
  ------------------
  |  Branch (379:9): [True: 46, False: 2.10M]
  ------------------
  380|       |      // Invalid |number|.
  381|     46|      return false;
  382|     46|    }
  383|  2.10M|    first_half -= number;
  384|  2.10M|    uint32_t second_half = num_remaining_points - first_half;
  385|       |
  386|  2.10M|    if (first_half != second_half) {
  ------------------
  |  Branch (386:9): [True: 1.31M, False: 789k]
  ------------------
  387|  1.31M|      if (!half_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (387:11): [True: 1.31M, False: 1.37k]
  ------------------
  388|  1.31M|        std::swap(first_half, second_half);
  389|  1.31M|      }
  390|  1.31M|    }
  391|       |
  392|  2.10M|    if (depth == std::numeric_limits<uint32_t>::max()) {
  ------------------
  |  Branch (392:9): [True: 0, False: 2.10M]
  ------------------
  393|      0|      return false;
  394|      0|    }
  395|       |    // Both halves see |axis| one level deeper. The first half stays at this
  396|       |    // depth and keeps the base, the second goes one deeper with the split bit
  397|       |    // set in its base.
  398|  2.10M|    undo_.push_back({depth, axis, levels_[axis], base_[axis]});
  399|  2.10M|    levels_[axis] += 1;
  400|  2.10M|    base_[axis] += modifier;
  401|  2.10M|    if (first_half) {
  ------------------
  |  Branch (401:9): [True: 2.10M, False: 107]
  ------------------
  402|  2.10M|      status_stack.push(DecodingStatus(first_half, axis, depth));
  403|  2.10M|    }
  404|  2.10M|    if (second_half) {
  ------------------
  |  Branch (404:9): [True: 2.10M, False: 140]
  ------------------
  405|  2.10M|      status_stack.push(DecodingStatus(second_half, axis, depth + 1));
  406|  2.10M|    }
  407|  2.10M|    ++depth;
  408|  2.10M|  }
  409|      5|  return true;
  410|     68|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi3EE12DecodePointsINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbPNS_13DecoderBufferERT_:
  188|    139|    DecoderBuffer* buffer, OutputIteratorT& oit) {
  189|    139|  return DecodePoints(buffer, oit, std::numeric_limits<uint32_t>::max());
  190|    139|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi3EE12DecodePointsINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbPNS_13DecoderBufferERT_j:
  195|    139|    DecoderBuffer* buffer, OutputIteratorT& oit, uint32_t oit_max_points) {
  196|    139|  if (!buffer->Decode(&bit_length_)) {
  ------------------
  |  Branch (196:7): [True: 1, False: 138]
  ------------------
  197|      1|    return false;
  198|      1|  }
  199|    138|  if (bit_length_ > 32) {
  ------------------
  |  Branch (199:7): [True: 6, False: 132]
  ------------------
  200|      6|    return false;
  201|      6|  }
  202|    132|  if (!buffer->Decode(&num_points_)) {
  ------------------
  |  Branch (202:7): [True: 3, False: 129]
  ------------------
  203|      3|    return false;
  204|      3|  }
  205|    129|  if (num_points_ == 0) {
  ------------------
  |  Branch (205:7): [True: 1, False: 128]
  ------------------
  206|      1|    return true;
  207|      1|  }
  208|    128|  if (num_points_ > oit_max_points) {
  ------------------
  |  Branch (208:7): [True: 0, False: 128]
  ------------------
  209|      0|    return false;
  210|      0|  }
  211|    128|  num_decoded_points_ = 0;
  212|       |
  213|    128|  if (!numbers_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (213:7): [True: 40, False: 88]
  ------------------
  214|     40|    return false;
  215|     40|  }
  216|     88|  if (!remaining_bits_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (216:7): [True: 3, False: 85]
  ------------------
  217|      3|    return false;
  218|      3|  }
  219|     85|  if (!axis_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (219:7): [True: 9, False: 76]
  ------------------
  220|      9|    return false;
  221|      9|  }
  222|     76|  if (!half_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (222:7): [True: 3, False: 73]
  ------------------
  223|      3|    return false;
  224|      3|  }
  225|       |
  226|     73|  if (!DecodeInternal(num_points_, oit)) {
  ------------------
  |  Branch (226:7): [True: 68, False: 5]
  ------------------
  227|     68|    return false;
  228|     68|  }
  229|       |
  230|      5|  numbers_decoder_.EndDecoding();
  231|      5|  remaining_bits_decoder_.EndDecoding();
  232|      5|  axis_decoder_.EndDecoding();
  233|      5|  half_decoder_.EndDecoding();
  234|       |
  235|      5|  return true;
  236|     73|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi3EE14DecodeInternalINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbjRT_:
  263|     73|    uint32_t num_points, OutputIteratorT& oit) {
  264|     73|  typedef DecodingStatus Status;
  265|       |  // The tree can be 32 * dimension levels deep, so keeping a base and levels
  266|       |  // vector per level takes memory quadratic in the dimension. The walk keeps
  267|       |  // one of each instead. A split at depth d raises one level of the node at
  268|       |  // d, and the node at d + 1 has the same levels and one more base bit set.
  269|       |  // Each split is logged in |undo_|, and on reaching a node at depth t the
  270|       |  // walk undoes the splits deeper than t and the base bit of the last split
  271|       |  // at t.
  272|       |  //
  273|       |  // A split takes its node off the top of |status_stack|, where every node
  274|       |  // below is shallower, and pushes its halves at d and d + 1. So the depths
  275|       |  // on the stack strictly increase towards its top, and a node is reached
  276|       |  // only after everything deeper than it has been decoded.
  277|     73|  base_.assign(dimension_, 0);
  278|     73|  levels_.assign(dimension_, 0);
  279|     73|  undo_.clear();
  280|     73|  uint32_t depth = 0;
  281|     73|  DecodingStatus init_status(num_points, 0, 0);
  282|     73|  std::stack<Status> status_stack;
  283|     73|  status_stack.push(init_status);
  284|       |
  285|       |  // TODO(b/199760123): Use preallocated vector instead of stack.
  286|  4.21M|  while (!status_stack.empty()) {
  ------------------
  |  Branch (286:10): [True: 4.21M, False: 5]
  ------------------
  287|  4.21M|    const DecodingStatus status = status_stack.top();
  288|  4.21M|    status_stack.pop();
  289|       |
  290|  4.21M|    const uint32_t num_remaining_points = status.num_remaining_points;
  291|  4.21M|    const uint32_t last_axis = status.last_axis;
  292|       |    // A node at the current depth is the second half of the split just made,
  293|       |    // and nothing needs to be undone for it.
  294|  4.21M|    if (status.depth != depth) {
  ------------------
  |  Branch (294:9): [True: 2.10M, False: 2.10M]
  ------------------
  295|  2.10M|      if (status.depth > depth) {
  ------------------
  |  Branch (295:11): [True: 0, False: 2.10M]
  ------------------
  296|      0|        return false;
  297|      0|      }
  298|  4.21M|      while (!undo_.empty()) {
  ------------------
  |  Branch (298:14): [True: 4.21M, False: 0]
  ------------------
  299|  4.21M|        const SplitUndo& split = undo_.back();
  300|  4.21M|        if (split.depth < status.depth) {
  ------------------
  |  Branch (300:13): [True: 0, False: 4.21M]
  ------------------
  301|      0|          break;
  302|      0|        }
  303|  4.21M|        base_[split.axis] = split.old_base;
  304|  4.21M|        if (split.depth == status.depth) {
  ------------------
  |  Branch (304:13): [True: 2.10M, False: 2.10M]
  ------------------
  305|       |          // The node's own split, whose level stays raised.
  306|  2.10M|          break;
  307|  2.10M|        }
  308|  2.10M|        levels_[split.axis] = split.old_level;
  309|  2.10M|        undo_.pop_back();
  310|  2.10M|      }
  311|  2.10M|      depth = status.depth;
  312|  2.10M|    }
  313|  4.21M|    const VectorUint32& old_base = base_;
  314|  4.21M|    const VectorUint32& levels = levels_;
  315|       |
  316|  4.21M|    if (num_remaining_points > num_points) {
  ------------------
  |  Branch (316:9): [True: 0, False: 4.21M]
  ------------------
  317|      0|      return false;
  318|      0|    }
  319|       |
  320|  4.21M|    const uint32_t axis = GetAxis(num_remaining_points, levels, last_axis);
  321|  4.21M|    if (axis >= dimension_) {
  ------------------
  |  Branch (321:9): [True: 0, False: 4.21M]
  ------------------
  322|      0|      return false;
  323|      0|    }
  324|       |
  325|  4.21M|    const uint32_t level = levels[axis];
  326|       |
  327|       |    // All axes have been fully subdivided, just output points.
  328|  4.21M|    if ((bit_length_ - level) == 0) {
  ------------------
  |  Branch (328:9): [True: 2.10M, False: 2.10M]
  ------------------
  329|  14.5M|      for (uint32_t i = 0; i < num_remaining_points; i++) {
  ------------------
  |  Branch (329:28): [True: 12.4M, False: 2.10M]
  ------------------
  330|  12.4M|        *oit = old_base;
  331|  12.4M|        ++oit;
  332|  12.4M|        ++num_decoded_points_;
  333|  12.4M|      }
  334|  2.10M|      continue;
  335|  2.10M|    }
  336|       |
  337|  2.10M|    DRACO_DCHECK_EQ(true, num_remaining_points != 0);
  338|       |
  339|       |    // Fast decoding of remaining bits if number of points is 1 or 2.
  340|  2.10M|    if (num_remaining_points <= 2) {
  ------------------
  |  Branch (340:9): [True: 1.21k, False: 2.10M]
  ------------------
  341|       |      // TODO(b/199760123): |axes_| not necessary, remove would change
  342|       |      // bitstream!
  343|  1.21k|      axes_[0] = axis;
  344|  3.65k|      for (uint32_t i = 1; i < dimension_; i++) {
  ------------------
  |  Branch (344:28): [True: 2.43k, False: 1.21k]
  ------------------
  345|  2.43k|        axes_[i] = DRACO_INCREMENT_MOD(axes_[i - 1], dimension_);
  ------------------
  |  |   24|  2.43k|#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M) - 1)) ? 0 : ((I) + 1))
  |  |  ------------------
  |  |  |  Branch (24:36): [True: 639, False: 1.79k]
  |  |  ------------------
  ------------------
  346|  2.43k|      }
  347|  3.28k|      for (uint32_t i = 0; i < num_remaining_points; ++i) {
  ------------------
  |  Branch (347:28): [True: 2.09k, False: 1.19k]
  ------------------
  348|  8.30k|        for (uint32_t j = 0; j < dimension_; j++) {
  ------------------
  |  Branch (348:30): [True: 6.23k, False: 2.06k]
  ------------------
  349|  6.23k|          p_[axes_[j]] = 0;
  350|  6.23k|          const uint32_t num_remaining_bits = bit_length_ - levels[axes_[j]];
  351|  6.23k|          if (num_remaining_bits) {
  ------------------
  |  Branch (351:15): [True: 4.55k, False: 1.68k]
  ------------------
  352|  4.55k|            if (!remaining_bits_decoder_.DecodeLeastSignificantBits32(
  ------------------
  |  Branch (352:17): [True: 24, False: 4.52k]
  ------------------
  353|  4.55k|                    num_remaining_bits, &p_[axes_[j]])) {
  354|     24|              return false;
  355|     24|            }
  356|  4.55k|          }
  357|  6.21k|          p_[axes_[j]] = old_base[axes_[j]] | p_[axes_[j]];
  358|  6.21k|        }
  359|  2.06k|        *oit = p_;
  360|  2.06k|        ++oit;
  361|  2.06k|        ++num_decoded_points_;
  362|  2.06k|      }
  363|  1.19k|      continue;
  364|  1.21k|    }
  365|       |
  366|  2.10M|    if (num_decoded_points_ > num_points_) {
  ------------------
  |  Branch (366:9): [True: 0, False: 2.10M]
  ------------------
  367|      0|      return false;
  368|      0|    }
  369|       |
  370|  2.10M|    const int num_remaining_bits = bit_length_ - level;
  371|  2.10M|    const uint32_t modifier = 1 << (num_remaining_bits - 1);
  372|       |
  373|  2.10M|    const int incoming_bits = MostSignificantBit(num_remaining_points);
  374|       |
  375|  2.10M|    uint32_t number = 0;
  376|  2.10M|    DecodeNumber(incoming_bits, &number);
  377|       |
  378|  2.10M|    uint32_t first_half = num_remaining_points / 2;
  379|  2.10M|    if (first_half < number) {
  ------------------
  |  Branch (379:9): [True: 44, False: 2.10M]
  ------------------
  380|       |      // Invalid |number|.
  381|     44|      return false;
  382|     44|    }
  383|  2.10M|    first_half -= number;
  384|  2.10M|    uint32_t second_half = num_remaining_points - first_half;
  385|       |
  386|  2.10M|    if (first_half != second_half) {
  ------------------
  |  Branch (386:9): [True: 726k, False: 1.38M]
  ------------------
  387|   726k|      if (!half_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (387:11): [True: 725k, False: 1.08k]
  ------------------
  388|   725k|        std::swap(first_half, second_half);
  389|   725k|      }
  390|   726k|    }
  391|       |
  392|  2.10M|    if (depth == std::numeric_limits<uint32_t>::max()) {
  ------------------
  |  Branch (392:9): [True: 0, False: 2.10M]
  ------------------
  393|      0|      return false;
  394|      0|    }
  395|       |    // Both halves see |axis| one level deeper. The first half stays at this
  396|       |    // depth and keeps the base, the second goes one deeper with the split bit
  397|       |    // set in its base.
  398|  2.10M|    undo_.push_back({depth, axis, levels_[axis], base_[axis]});
  399|  2.10M|    levels_[axis] += 1;
  400|  2.10M|    base_[axis] += modifier;
  401|  2.10M|    if (first_half) {
  ------------------
  |  Branch (401:9): [True: 2.10M, False: 43]
  ------------------
  402|  2.10M|      status_stack.push(DecodingStatus(first_half, axis, depth));
  403|  2.10M|    }
  404|  2.10M|    if (second_half) {
  ------------------
  |  Branch (404:9): [True: 2.10M, False: 129]
  ------------------
  405|  2.10M|      status_stack.push(DecodingStatus(second_half, axis, depth + 1));
  406|  2.10M|    }
  407|  2.10M|    ++depth;
  408|  2.10M|  }
  409|      5|  return true;
  410|     73|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi4EE12DecodePointsINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbPNS_13DecoderBufferERT_:
  188|     70|    DecoderBuffer* buffer, OutputIteratorT& oit) {
  189|     70|  return DecodePoints(buffer, oit, std::numeric_limits<uint32_t>::max());
  190|     70|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi4EE12DecodePointsINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbPNS_13DecoderBufferERT_j:
  195|     70|    DecoderBuffer* buffer, OutputIteratorT& oit, uint32_t oit_max_points) {
  196|     70|  if (!buffer->Decode(&bit_length_)) {
  ------------------
  |  Branch (196:7): [True: 2, False: 68]
  ------------------
  197|      2|    return false;
  198|      2|  }
  199|     68|  if (bit_length_ > 32) {
  ------------------
  |  Branch (199:7): [True: 11, False: 57]
  ------------------
  200|     11|    return false;
  201|     11|  }
  202|     57|  if (!buffer->Decode(&num_points_)) {
  ------------------
  |  Branch (202:7): [True: 1, False: 56]
  ------------------
  203|      1|    return false;
  204|      1|  }
  205|     56|  if (num_points_ == 0) {
  ------------------
  |  Branch (205:7): [True: 4, False: 52]
  ------------------
  206|      4|    return true;
  207|      4|  }
  208|     52|  if (num_points_ > oit_max_points) {
  ------------------
  |  Branch (208:7): [True: 0, False: 52]
  ------------------
  209|      0|    return false;
  210|      0|  }
  211|     52|  num_decoded_points_ = 0;
  212|       |
  213|     52|  if (!numbers_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (213:7): [True: 52, False: 0]
  ------------------
  214|     52|    return false;
  215|     52|  }
  216|      0|  if (!remaining_bits_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (216:7): [True: 0, False: 0]
  ------------------
  217|      0|    return false;
  218|      0|  }
  219|      0|  if (!axis_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (219:7): [True: 0, False: 0]
  ------------------
  220|      0|    return false;
  221|      0|  }
  222|      0|  if (!half_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (222:7): [True: 0, False: 0]
  ------------------
  223|      0|    return false;
  224|      0|  }
  225|       |
  226|      0|  if (!DecodeInternal(num_points_, oit)) {
  ------------------
  |  Branch (226:7): [True: 0, False: 0]
  ------------------
  227|      0|    return false;
  228|      0|  }
  229|       |
  230|      0|  numbers_decoder_.EndDecoding();
  231|      0|  remaining_bits_decoder_.EndDecoding();
  232|      0|  axis_decoder_.EndDecoding();
  233|      0|  half_decoder_.EndDecoding();
  234|       |
  235|      0|  return true;
  236|      0|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi5EE12DecodePointsINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbPNS_13DecoderBufferERT_:
  188|     38|    DecoderBuffer* buffer, OutputIteratorT& oit) {
  189|     38|  return DecodePoints(buffer, oit, std::numeric_limits<uint32_t>::max());
  190|     38|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi5EE12DecodePointsINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbPNS_13DecoderBufferERT_j:
  195|     38|    DecoderBuffer* buffer, OutputIteratorT& oit, uint32_t oit_max_points) {
  196|     38|  if (!buffer->Decode(&bit_length_)) {
  ------------------
  |  Branch (196:7): [True: 1, False: 37]
  ------------------
  197|      1|    return false;
  198|      1|  }
  199|     37|  if (bit_length_ > 32) {
  ------------------
  |  Branch (199:7): [True: 7, False: 30]
  ------------------
  200|      7|    return false;
  201|      7|  }
  202|     30|  if (!buffer->Decode(&num_points_)) {
  ------------------
  |  Branch (202:7): [True: 1, False: 29]
  ------------------
  203|      1|    return false;
  204|      1|  }
  205|     29|  if (num_points_ == 0) {
  ------------------
  |  Branch (205:7): [True: 1, False: 28]
  ------------------
  206|      1|    return true;
  207|      1|  }
  208|     28|  if (num_points_ > oit_max_points) {
  ------------------
  |  Branch (208:7): [True: 0, False: 28]
  ------------------
  209|      0|    return false;
  210|      0|  }
  211|     28|  num_decoded_points_ = 0;
  212|       |
  213|     28|  if (!numbers_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (213:7): [True: 28, False: 0]
  ------------------
  214|     28|    return false;
  215|     28|  }
  216|      0|  if (!remaining_bits_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (216:7): [True: 0, False: 0]
  ------------------
  217|      0|    return false;
  218|      0|  }
  219|      0|  if (!axis_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (219:7): [True: 0, False: 0]
  ------------------
  220|      0|    return false;
  221|      0|  }
  222|      0|  if (!half_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (222:7): [True: 0, False: 0]
  ------------------
  223|      0|    return false;
  224|      0|  }
  225|       |
  226|      0|  if (!DecodeInternal(num_points_, oit)) {
  ------------------
  |  Branch (226:7): [True: 0, False: 0]
  ------------------
  227|      0|    return false;
  228|      0|  }
  229|       |
  230|      0|  numbers_decoder_.EndDecoding();
  231|      0|  remaining_bits_decoder_.EndDecoding();
  232|      0|  axis_decoder_.EndDecoding();
  233|      0|  half_decoder_.EndDecoding();
  234|       |
  235|      0|  return true;
  236|      0|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi6EE12DecodePointsINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbPNS_13DecoderBufferERT_:
  188|     43|    DecoderBuffer* buffer, OutputIteratorT& oit) {
  189|     43|  return DecodePoints(buffer, oit, std::numeric_limits<uint32_t>::max());
  190|     43|}
_ZN5draco33DynamicIntegerPointsKdTreeDecoderILi6EE12DecodePointsINS_24ConversionOutputIteratorINSt3__120back_insert_iteratorINS4_6vectorINS_7VectorDIjLi3EEENS4_9allocatorIS8_EEEEEENS_9ConverterEEEEEbPNS_13DecoderBufferERT_j:
  195|     43|    DecoderBuffer* buffer, OutputIteratorT& oit, uint32_t oit_max_points) {
  196|     43|  if (!buffer->Decode(&bit_length_)) {
  ------------------
  |  Branch (196:7): [True: 4, False: 39]
  ------------------
  197|      4|    return false;
  198|      4|  }
  199|     39|  if (bit_length_ > 32) {
  ------------------
  |  Branch (199:7): [True: 7, False: 32]
  ------------------
  200|      7|    return false;
  201|      7|  }
  202|     32|  if (!buffer->Decode(&num_points_)) {
  ------------------
  |  Branch (202:7): [True: 1, False: 31]
  ------------------
  203|      1|    return false;
  204|      1|  }
  205|     31|  if (num_points_ == 0) {
  ------------------
  |  Branch (205:7): [True: 2, False: 29]
  ------------------
  206|      2|    return true;
  207|      2|  }
  208|     29|  if (num_points_ > oit_max_points) {
  ------------------
  |  Branch (208:7): [True: 0, False: 29]
  ------------------
  209|      0|    return false;
  210|      0|  }
  211|     29|  num_decoded_points_ = 0;
  212|       |
  213|     29|  if (!numbers_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (213:7): [True: 29, False: 0]
  ------------------
  214|     29|    return false;
  215|     29|  }
  216|      0|  if (!remaining_bits_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (216:7): [True: 0, False: 0]
  ------------------
  217|      0|    return false;
  218|      0|  }
  219|      0|  if (!axis_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (219:7): [True: 0, False: 0]
  ------------------
  220|      0|    return false;
  221|      0|  }
  222|      0|  if (!half_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (222:7): [True: 0, False: 0]
  ------------------
  223|      0|    return false;
  224|      0|  }
  225|       |
  226|      0|  if (!DecodeInternal(num_points_, oit)) {
  ------------------
  |  Branch (226:7): [True: 0, False: 0]
  ------------------
  227|      0|    return false;
  228|      0|  }
  229|       |
  230|      0|  numbers_decoder_.EndDecoding();
  231|      0|  remaining_bits_decoder_.EndDecoding();
  232|      0|  axis_decoder_.EndDecoding();
  233|      0|  half_decoder_.EndDecoding();
  234|       |
  235|      0|  return true;
  236|      0|}

_ZN5draco22FloatPointsTreeDecoderC2Ev:
   65|    844|    : num_points_(0), compression_level_(0), num_points_from_header_(0) {
   66|    844|  qinfo_.quantization_bits = 0;
   67|    844|  qinfo_.range = 0;
   68|    844|}
_ZN5draco22FloatPointsTreeDecoder30DecodePointCloudKdTreeInternalEPNS_13DecoderBufferEPNSt3__16vectorINS_7VectorDIjLi3EEENS3_9allocatorIS6_EEEE:
   71|    806|    DecoderBuffer* buffer, std::vector<Point3ui>* qpoints) {
   72|    806|  if (!buffer->Decode(&qinfo_.quantization_bits)) {
  ------------------
  |  Branch (72:7): [True: 1, False: 805]
  ------------------
   73|      1|    return false;
   74|      1|  }
   75|    805|  if (qinfo_.quantization_bits > 31) {
  ------------------
  |  Branch (75:7): [True: 23, False: 782]
  ------------------
   76|     23|    return false;
   77|     23|  }
   78|    782|  if (!buffer->Decode(&qinfo_.range)) {
  ------------------
  |  Branch (78:7): [True: 2, False: 780]
  ------------------
   79|      2|    return false;
   80|      2|  }
   81|    780|  if (!buffer->Decode(&num_points_)) {
  ------------------
  |  Branch (81:7): [True: 1, False: 779]
  ------------------
   82|      1|    return false;
   83|      1|  }
   84|    779|  if (num_points_from_header_ > 0 && num_points_ != num_points_from_header_) {
  ------------------
  |  Branch (84:7): [True: 50, False: 729]
  |  Branch (84:38): [True: 33, False: 17]
  ------------------
   85|     33|    return false;
   86|     33|  }
   87|    746|  if (!buffer->Decode(&compression_level_)) {
  ------------------
  |  Branch (87:7): [True: 2, False: 744]
  ------------------
   88|      2|    return false;
   89|      2|  }
   90|       |
   91|       |  // Only allow compression level in [0..6].
   92|    744|  if (6 < compression_level_) {
  ------------------
  |  Branch (92:7): [True: 39, False: 705]
  ------------------
   93|     39|    DRACO_LOGE("FloatPointsTreeDecoder: compression level %i not supported.\n",
  ------------------
  |  |   31|     39|#define DRACO_LOGE printf
  ------------------
   94|     39|               compression_level_);
   95|     39|    return false;
   96|     39|  }
   97|       |
   98|    705|  std::back_insert_iterator<std::vector<Point3ui>> oit_qpoints =
   99|    705|      std::back_inserter(*qpoints);
  100|    705|  ConversionOutputIterator<std::back_insert_iterator<std::vector<Point3ui>>,
  101|    705|                           Converter>
  102|    705|      oit(oit_qpoints);
  103|    705|  if (num_points_ > 0) {
  ------------------
  |  Branch (103:7): [True: 701, False: 4]
  ------------------
  104|    701|    qpoints->reserve(num_points_);
  105|    701|    switch (compression_level_) {
  106|    156|      case 0: {
  ------------------
  |  Branch (106:7): [True: 156, False: 545]
  ------------------
  107|    156|        DynamicIntegerPointsKdTreeDecoder<0> qpoints_decoder(3);
  108|    156|        qpoints_decoder.DecodePoints(buffer, oit);
  109|    156|        break;
  110|      0|      }
  111|    113|      case 1: {
  ------------------
  |  Branch (111:7): [True: 113, False: 588]
  ------------------
  112|    113|        DynamicIntegerPointsKdTreeDecoder<1> qpoints_decoder(3);
  113|    113|        qpoints_decoder.DecodePoints(buffer, oit);
  114|    113|        break;
  115|      0|      }
  116|    142|      case 2: {
  ------------------
  |  Branch (116:7): [True: 142, False: 559]
  ------------------
  117|    142|        DynamicIntegerPointsKdTreeDecoder<2> qpoints_decoder(3);
  118|    142|        qpoints_decoder.DecodePoints(buffer, oit);
  119|    142|        break;
  120|      0|      }
  121|    139|      case 3: {
  ------------------
  |  Branch (121:7): [True: 139, False: 562]
  ------------------
  122|    139|        DynamicIntegerPointsKdTreeDecoder<3> qpoints_decoder(3);
  123|    139|        qpoints_decoder.DecodePoints(buffer, oit);
  124|    139|        break;
  125|      0|      }
  126|     70|      case 4: {
  ------------------
  |  Branch (126:7): [True: 70, False: 631]
  ------------------
  127|     70|        DynamicIntegerPointsKdTreeDecoder<4> qpoints_decoder(3);
  128|     70|        qpoints_decoder.DecodePoints(buffer, oit);
  129|     70|        break;
  130|      0|      }
  131|     38|      case 5: {
  ------------------
  |  Branch (131:7): [True: 38, False: 663]
  ------------------
  132|     38|        DynamicIntegerPointsKdTreeDecoder<5> qpoints_decoder(3);
  133|     38|        qpoints_decoder.DecodePoints(buffer, oit);
  134|     38|        break;
  135|      0|      }
  136|     43|      case 6: {
  ------------------
  |  Branch (136:7): [True: 43, False: 658]
  ------------------
  137|     43|        DynamicIntegerPointsKdTreeDecoder<6> qpoints_decoder(3);
  138|     43|        qpoints_decoder.DecodePoints(buffer, oit);
  139|     43|        break;
  140|      0|      }
  141|      0|      default:
  ------------------
  |  Branch (141:7): [True: 0, False: 701]
  ------------------
  142|      0|        return false;
  143|    701|    }
  144|    701|  }
  145|       |
  146|    705|  if (qpoints->size() != num_points_) {
  ------------------
  |  Branch (146:7): [True: 688, False: 17]
  ------------------
  147|    688|    return false;
  148|    688|  }
  149|     17|  return true;
  150|    705|}
_ZN5draco24ConversionOutputIteratorINSt3__120back_insert_iteratorINS1_6vectorINS_7VectorDIjLi3EEENS1_9allocatorIS5_EEEEEENS_9ConverterEEC2ES9_:
   43|    705|  explicit ConversionOutputIterator(OutputIterator oit) : oit_(oit) {}
_ZN5draco24ConversionOutputIteratorINSt3__120back_insert_iteratorINS1_6vectorINS_7VectorDIjLi3EEENS1_9allocatorIS5_EEEEEENS_9ConverterEEdeEv:
   54|   242M|  Self& operator*() { return *this; }
_ZN5draco24ConversionOutputIteratorINSt3__120back_insert_iteratorINS1_6vectorINS_7VectorDIjLi3EEENS1_9allocatorIS5_EEEEEENS_9ConverterEEaSERKNS3_IjNS6_IjEEEE:
   55|   242M|  const Self& operator=(const SourceType& source) {
   56|   242M|    *oit_ = Converter()(source);
   57|   242M|    return *this;
   58|   242M|  }
_ZN5draco9ConverterclERKNSt3__16vectorIjNS1_9allocatorIjEEEE:
   29|   242M|  Point3ui operator()(const std::vector<uint32_t>& v) {
   30|   242M|    return Point3ui(v[0], v[1], v[2]);
   31|   242M|  }
_ZN5draco24ConversionOutputIteratorINSt3__120back_insert_iteratorINS1_6vectorINS_7VectorDIjLi3EEENS1_9allocatorIS5_EEEEEENS_9ConverterEEppEv:
   45|   242M|  const Self& operator++() {
   46|   242M|    ++oit_;
   47|   242M|    return *this;
   48|   242M|  }

_ZN5draco22FloatPointsTreeDecoder26set_num_points_from_headerEj:
   69|    844|  void set_num_points_from_header(uint32_t num_points) {
   70|    844|    num_points_from_header_ = num_points;
   71|    844|  }
_ZN5draco22FloatPointsTreeDecoder16DecodePointCloudINS_34PointAttributeVectorOutputIteratorIfEEEEbPNS_13DecoderBufferERT_:
  102|    844|                                              OutputIteratorT& out) {
  103|    844|  std::vector<Point3ui> qpoints;
  104|       |
  105|    844|  uint32_t decoded_version;
  106|    844|  if (!buffer->Decode(&decoded_version)) {
  ------------------
  |  Branch (106:7): [True: 5, False: 839]
  ------------------
  107|      5|    return false;
  108|      5|  }
  109|       |
  110|    839|  if (decoded_version == 3) {
  ------------------
  |  Branch (110:7): [True: 3, False: 836]
  ------------------
  111|      3|    int8_t method_number;
  112|      3|    if (!buffer->Decode(&method_number)) {
  ------------------
  |  Branch (112:9): [True: 1, False: 2]
  ------------------
  113|      1|      return false;
  114|      1|    }
  115|       |
  116|      2|    method_ = method_number;
  117|       |
  118|      2|    if (method_ == KDTREE) {
  ------------------
  |  Branch (118:9): [True: 1, False: 1]
  ------------------
  119|      1|      if (!DecodePointCloudKdTreeInternal(buffer, &qpoints)) {
  ------------------
  |  Branch (119:11): [True: 1, False: 0]
  ------------------
  120|      1|        return false;
  121|      1|      }
  122|      1|    } else {  // Unsupported method.
  123|      1|      fprintf(stderr, "Method not supported. \n");
  124|      1|      return false;
  125|      1|    }
  126|    836|  } else if (decoded_version == 2) {  // Version 2 only uses KDTREE method.
  ------------------
  |  Branch (126:14): [True: 805, False: 31]
  ------------------
  127|    805|    if (!DecodePointCloudKdTreeInternal(buffer, &qpoints)) {
  ------------------
  |  Branch (127:9): [True: 788, False: 17]
  ------------------
  128|    788|      return false;
  129|    788|    }
  130|    805|  } else {  // Unsupported version.
  131|     31|    fprintf(stderr, "Version not supported. \n");
  132|     31|    return false;
  133|     31|  }
  134|       |
  135|     17|  DequantizePoints3(qpoints.begin(), qpoints.end(), qinfo_, out);
  136|     17|  return true;
  137|    839|}

_ZN5draco17DequantizePoints3INSt3__111__wrap_iterIPNS_7VectorDIjLi3EEEEENS_34PointAttributeVectorOutputIteratorIfEEEEvRKT_SB_RKNS_16QuantizationInfoERT0_:
   63|     17|                       const QuantizationInfo& info, OutputIterator& oit) {
   64|     17|  DRACO_DCHECK_GE(info.quantization_bits, 0);
   65|     17|  DRACO_DCHECK_GE(info.range, 0);
   66|       |
   67|     17|  const uint32_t quantization_bits = info.quantization_bits;
   68|     17|  const float range = info.range;
   69|     17|  const uint32_t max_quantized_value((1u << quantization_bits) - 1);
   70|     17|  Dequantizer dequantize;
   71|     17|  dequantize.Init(range, max_quantized_value);
   72|       |
   73|     90|  for (auto it = begin; it != end; ++it) {
  ------------------
  |  Branch (73:25): [True: 73, False: 17]
  ------------------
   74|     73|    const float x = dequantize((*it)[0] - max_quantized_value);
   75|     73|    const float y = dequantize((*it)[1] - max_quantized_value);
   76|     73|    const float z = dequantize((*it)[2] - max_quantized_value);
   77|     73|    *oit = Point3f(x, y, z);
   78|     73|    ++oit;
   79|     73|  }
   80|     17|}

_ZN5draco17PointCloudDecoderC2Ev:
   22|  19.4k|    : point_cloud_(nullptr),
   23|  19.4k|      buffer_(nullptr),
   24|  19.4k|      version_major_(0),
   25|  19.4k|      version_minor_(0),
   26|  19.4k|      options_(nullptr) {}
_ZN5draco17PointCloudDecoder12DecodeHeaderEPNS_13DecoderBufferEPNS_11DracoHeaderE:
   29|  58.3k|                                       DracoHeader* out_header) {
   30|  58.3k|  constexpr char kIoErrorMsg[] = "Failed to parse Draco header.";
   31|  58.3k|  if (!buffer->Decode(out_header->draco_string, 5)) {
  ------------------
  |  Branch (31:7): [True: 3, False: 58.3k]
  ------------------
   32|      3|    return Status(Status::IO_ERROR, kIoErrorMsg);
   33|      3|  }
   34|  58.3k|  if (memcmp(out_header->draco_string, "DRACO", 5) != 0) {
  ------------------
  |  Branch (34:7): [True: 45, False: 58.3k]
  ------------------
   35|     45|    return Status(Status::DRACO_ERROR, "Not a Draco file.");
   36|     45|  }
   37|  58.3k|  if (!buffer->Decode(&(out_header->version_major))) {
  ------------------
  |  Branch (37:7): [True: 1, False: 58.3k]
  ------------------
   38|      1|    return Status(Status::IO_ERROR, kIoErrorMsg);
   39|      1|  }
   40|  58.3k|  if (!buffer->Decode(&(out_header->version_minor))) {
  ------------------
  |  Branch (40:7): [True: 1, False: 58.3k]
  ------------------
   41|      1|    return Status(Status::IO_ERROR, kIoErrorMsg);
   42|      1|  }
   43|  58.3k|  if (!buffer->Decode(&(out_header->encoder_type))) {
  ------------------
  |  Branch (43:7): [True: 1, False: 58.3k]
  ------------------
   44|      1|    return Status(Status::IO_ERROR, kIoErrorMsg);
   45|      1|  }
   46|  58.3k|  if (!buffer->Decode(&(out_header->encoder_method))) {
  ------------------
  |  Branch (46:7): [True: 1, False: 58.3k]
  ------------------
   47|      1|    return Status(Status::IO_ERROR, kIoErrorMsg);
   48|      1|  }
   49|  58.3k|  if (!buffer->Decode(&(out_header->flags))) {
  ------------------
  |  Branch (49:7): [True: 2, False: 58.3k]
  ------------------
   50|      2|    return Status(Status::IO_ERROR, kIoErrorMsg);
   51|      2|  }
   52|  58.3k|  return OkStatus();
   53|  58.3k|}
_ZN5draco17PointCloudDecoder14DecodeMetadataEv:
   55|  1.16k|Status PointCloudDecoder::DecodeMetadata() {
   56|  1.16k|  std::unique_ptr<GeometryMetadata> metadata =
   57|  1.16k|      std::unique_ptr<GeometryMetadata>(new GeometryMetadata());
   58|  1.16k|  MetadataDecoder metadata_decoder;
   59|  1.16k|  if (!metadata_decoder.DecodeGeometryMetadata(buffer_, metadata.get())) {
  ------------------
  |  Branch (59:7): [True: 1.14k, False: 23]
  ------------------
   60|  1.14k|    return Status(Status::DRACO_ERROR, "Failed to decode metadata.");
   61|  1.14k|  }
   62|     23|  point_cloud_->AddMetadata(std::move(metadata));
   63|     23|  return OkStatus();
   64|  1.16k|}
_ZN5draco17PointCloudDecoder6DecodeERKNS_12DracoOptionsINS_17GeometryAttribute4TypeEEEPNS_13DecoderBufferEPNS_10PointCloudE:
   68|  19.4k|                                 PointCloud* out_point_cloud) {
   69|  19.4k|  options_ = &options;
   70|  19.4k|  buffer_ = in_buffer;
   71|  19.4k|  point_cloud_ = out_point_cloud;
   72|  19.4k|  DracoHeader header;
   73|  19.4k|  DRACO_RETURN_IF_ERROR(DecodeHeader(buffer_, &header))
  ------------------
  |  |   74|  19.4k|  {                                                   \
  |  |   75|  19.4k|    const draco::Status _local_status = (expression); \
  |  |   76|  19.4k|    if (!_local_status.ok()) {                        \
  |  |  ------------------
  |  |  |  Branch (76:9): [True: 0, False: 19.4k]
  |  |  ------------------
  |  |   77|      0|      return _local_status;                           \
  |  |   78|      0|    }                                                 \
  |  |   79|  19.4k|  }
  ------------------
   74|       |  // Sanity check that we are really using the right decoder (mostly for cases
   75|       |  // where the Decode method was called manually outside of our main API.
   76|  19.4k|  if (header.encoder_type != GetGeometryType()) {
  ------------------
  |  Branch (76:7): [True: 0, False: 19.4k]
  ------------------
   77|      0|    return Status(Status::DRACO_ERROR,
   78|      0|                  "Using incompatible decoder for the input geometry.");
   79|      0|  }
   80|       |  // TODO(ostava): We should check the method as well, but currently decoders
   81|       |  // don't expose the decoding method id.
   82|  19.4k|  version_major_ = header.version_major;
   83|  19.4k|  version_minor_ = header.version_minor;
   84|       |
   85|  19.4k|  const uint8_t max_supported_major_version =
   86|  19.4k|      header.encoder_type == POINT_CLOUD ? kDracoPointCloudBitstreamVersionMajor
  ------------------
  |  Branch (86:7): [True: 3.09k, False: 16.3k]
  ------------------
   87|  19.4k|                                         : kDracoMeshBitstreamVersionMajor;
   88|  19.4k|  const uint8_t max_supported_minor_version =
   89|  19.4k|      header.encoder_type == POINT_CLOUD ? kDracoPointCloudBitstreamVersionMinor
  ------------------
  |  Branch (89:7): [True: 3.09k, False: 16.3k]
  ------------------
   90|  19.4k|                                         : kDracoMeshBitstreamVersionMinor;
   91|       |
   92|       |  // Check for version compatibility.
   93|  19.4k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   94|  19.4k|  if (version_major_ < 1 || version_major_ > max_supported_major_version) {
  ------------------
  |  Branch (94:7): [True: 1, False: 19.4k]
  |  Branch (94:29): [True: 9, False: 19.4k]
  ------------------
   95|     10|    return Status(Status::UNKNOWN_VERSION, "Unknown major version.");
   96|     10|  }
   97|  19.4k|  if (version_major_ == max_supported_major_version &&
  ------------------
  |  Branch (97:7): [True: 17.3k, False: 2.06k]
  ------------------
   98|  17.3k|      version_minor_ > max_supported_minor_version) {
  ------------------
  |  Branch (98:7): [True: 6, False: 17.3k]
  ------------------
   99|      6|    return Status(Status::UNKNOWN_VERSION, "Unknown minor version.");
  100|      6|  }
  101|       |#else
  102|       |  if (version_major_ != max_supported_major_version) {
  103|       |    return Status(Status::UNKNOWN_VERSION, "Unsupported major version.");
  104|       |  }
  105|       |  if (version_minor_ != max_supported_minor_version) {
  106|       |    return Status(Status::UNKNOWN_VERSION, "Unsupported minor version.");
  107|       |  }
  108|       |#endif
  109|  19.4k|  buffer_->set_bitstream_version(
  110|  19.4k|      DRACO_BITSTREAM_VERSION(version_major_, version_minor_));
  ------------------
  |  |  115|  19.4k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  111|       |
  112|  19.4k|  if (bitstream_version() >= DRACO_BITSTREAM_VERSION(1, 3) &&
  ------------------
  |  |  115|  38.8k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (112:7): [True: 18.6k, False: 783]
  ------------------
  113|  18.6k|      (header.flags & METADATA_FLAG_MASK)) {
  ------------------
  |  |  151|  18.6k|#define METADATA_FLAG_MASK 0x8000
  ------------------
  |  Branch (113:7): [True: 1.16k, False: 17.4k]
  ------------------
  114|  1.16k|    DRACO_RETURN_IF_ERROR(DecodeMetadata())
  ------------------
  |  |   74|  1.16k|  {                                                   \
  |  |   75|  1.16k|    const draco::Status _local_status = (expression); \
  |  |   76|  1.16k|    if (!_local_status.ok()) {                        \
  |  |  ------------------
  |  |  |  Branch (76:9): [True: 1.14k, False: 23]
  |  |  ------------------
  |  |   77|  1.14k|      return _local_status;                           \
  |  |   78|  1.14k|    }                                                 \
  |  |   79|  1.16k|  }
  ------------------
  115|  1.16k|  }
  116|  18.2k|  if (!InitializeDecoder()) {
  ------------------
  |  Branch (116:7): [True: 15, False: 18.2k]
  ------------------
  117|     15|    return Status(Status::DRACO_ERROR, "Failed to initialize the decoder.");
  118|     15|  }
  119|  18.2k|  if (!DecodeGeometryData()) {
  ------------------
  |  Branch (119:7): [True: 9.74k, False: 8.50k]
  ------------------
  120|  9.74k|    return Status(Status::DRACO_ERROR, "Failed to decode geometry data.");
  121|  9.74k|  }
  122|  8.50k|  if (!DecodePointAttributes()) {
  ------------------
  |  Branch (122:7): [True: 6.62k, False: 1.88k]
  ------------------
  123|  6.62k|    return Status(Status::DRACO_ERROR, "Failed to decode point attributes.");
  124|  6.62k|  }
  125|  1.88k|  return OkStatus();
  126|  8.50k|}
_ZN5draco17PointCloudDecoder21DecodePointAttributesEv:
  128|  8.50k|bool PointCloudDecoder::DecodePointAttributes() {
  129|  8.50k|  uint8_t num_attributes_decoders;
  130|  8.50k|  if (!buffer_->Decode(&num_attributes_decoders)) {
  ------------------
  |  Branch (130:7): [True: 230, False: 8.27k]
  ------------------
  131|    230|    return false;
  132|    230|  }
  133|       |  // Create all attribute decoders. This is implementation specific and the
  134|       |  // derived classes can use any data encoded in the
  135|       |  // PointCloudEncoder::EncodeAttributesEncoderIdentifier() call.
  136|  52.0k|  for (int i = 0; i < num_attributes_decoders; ++i) {
  ------------------
  |  Branch (136:19): [True: 44.3k, False: 7.75k]
  ------------------
  137|  44.3k|    if (!CreateAttributesDecoder(i)) {
  ------------------
  |  Branch (137:9): [True: 524, False: 43.7k]
  ------------------
  138|    524|      return false;
  139|    524|    }
  140|  44.3k|  }
  141|       |
  142|       |  // Initialize all attributes decoders. No data is decoded here.
  143|  43.6k|  for (auto& att_dec : attributes_decoders_) {
  ------------------
  |  Branch (143:22): [True: 43.6k, False: 7.75k]
  ------------------
  144|  43.6k|    if (!att_dec->Init(this, point_cloud_)) {
  ------------------
  |  Branch (144:9): [True: 0, False: 43.6k]
  ------------------
  145|      0|      return false;
  146|      0|    }
  147|  43.6k|  }
  148|       |
  149|       |  // Decode any data needed by the attribute decoders.
  150|  18.6k|  for (int i = 0; i < num_attributes_decoders; ++i) {
  ------------------
  |  Branch (150:19): [True: 11.3k, False: 7.31k]
  ------------------
  151|  11.3k|    if (!attributes_decoders_[i]->DecodeAttributesDecoderData(buffer_)) {
  ------------------
  |  Branch (151:9): [True: 434, False: 10.8k]
  ------------------
  152|    434|      return false;
  153|    434|    }
  154|  11.3k|  }
  155|       |
  156|       |  // Create map between attribute and decoder ids.
  157|  15.7k|  for (int i = 0; i < num_attributes_decoders; ++i) {
  ------------------
  |  Branch (157:19): [True: 8.46k, False: 7.31k]
  ------------------
  158|  8.46k|    const int32_t num_attributes = attributes_decoders_[i]->GetNumAttributes();
  159|  33.0k|    for (int j = 0; j < num_attributes; ++j) {
  ------------------
  |  Branch (159:21): [True: 24.6k, False: 8.46k]
  ------------------
  160|  24.6k|      int att_id = attributes_decoders_[i]->GetAttributeId(j);
  161|  24.6k|      if (att_id >= attribute_to_decoder_map_.size()) {
  ------------------
  |  Branch (161:11): [True: 24.6k, False: 0]
  ------------------
  162|  24.6k|        attribute_to_decoder_map_.resize(att_id + 1);
  163|  24.6k|      }
  164|  24.6k|      attribute_to_decoder_map_[att_id] = i;
  165|  24.6k|    }
  166|  8.46k|  }
  167|       |
  168|       |  // Decode the actual attributes using the created attribute decoders.
  169|  7.31k|  if (!DecodeAllAttributes()) {
  ------------------
  |  Branch (169:7): [True: 5.43k, False: 1.88k]
  ------------------
  170|  5.43k|    return false;
  171|  5.43k|  }
  172|       |
  173|  1.88k|  if (!OnAttributesDecoded()) {
  ------------------
  |  Branch (173:7): [True: 0, False: 1.88k]
  ------------------
  174|      0|    return false;
  175|      0|  }
  176|  1.88k|  return true;
  177|  1.88k|}
_ZN5draco17PointCloudDecoder19DecodeAllAttributesEv:
  179|  7.31k|bool PointCloudDecoder::DecodeAllAttributes() {
  180|  7.52k|  for (auto& att_dec : attributes_decoders_) {
  ------------------
  |  Branch (180:22): [True: 7.52k, False: 1.88k]
  ------------------
  181|  7.52k|    if (!att_dec->DecodeAttributes(buffer_)) {
  ------------------
  |  Branch (181:9): [True: 5.43k, False: 2.09k]
  ------------------
  182|  5.43k|      return false;
  183|  5.43k|    }
  184|  7.52k|  }
  185|  1.88k|  return true;
  186|  7.31k|}
_ZN5draco17PointCloudDecoder20GetPortableAttributeEi:
  189|  2.22k|    int32_t parent_att_id) {
  190|  2.22k|  if (parent_att_id < 0 || parent_att_id >= point_cloud_->num_attributes()) {
  ------------------
  |  Branch (190:7): [True: 0, False: 2.22k]
  |  Branch (190:28): [True: 0, False: 2.22k]
  ------------------
  191|      0|    return nullptr;
  192|      0|  }
  193|  2.22k|  const int32_t parent_att_decoder_id =
  194|  2.22k|      attribute_to_decoder_map_[parent_att_id];
  195|  2.22k|  return attributes_decoders_[parent_att_decoder_id]->GetPortableAttribute(
  196|  2.22k|      parent_att_id);
  197|  2.22k|}

_ZNK5draco17PointCloudDecoder15GetGeometryTypeEv:
   33|  3.18k|  virtual EncodedGeometryType GetGeometryType() const { return POINT_CLOUD; }
_ZN5draco17PointCloudDecoder20SetAttributesDecoderEiNSt3__110unique_ptrINS_26AttributesDecoderInterfaceENS1_14default_deleteIS3_EEEE:
   44|  43.7k|      int att_decoder_id, std::unique_ptr<AttributesDecoderInterface> decoder) {
   45|  43.7k|    if (att_decoder_id < 0) {
  ------------------
  |  Branch (45:9): [True: 0, False: 43.7k]
  ------------------
   46|      0|      return false;
   47|      0|    }
   48|  43.7k|    if (att_decoder_id >= static_cast<int>(attributes_decoders_.size())) {
  ------------------
  |  Branch (48:9): [True: 43.7k, False: 0]
  ------------------
   49|  43.7k|      attributes_decoders_.resize(att_decoder_id + 1);
   50|  43.7k|    }
   51|  43.7k|    attributes_decoders_[att_decoder_id] = std::move(decoder);
   52|  43.7k|    return true;
   53|  43.7k|  }
_ZNK5draco17PointCloudDecoder17bitstream_versionEv:
   63|   209k|  uint16_t bitstream_version() const {
   64|   209k|    return DRACO_BITSTREAM_VERSION(version_major_, version_minor_);
  ------------------
  |  |  115|   209k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
   65|   209k|  }
_ZN5draco17PointCloudDecoder18attributes_decoderEi:
   67|  7.61k|  const AttributesDecoderInterface* attributes_decoder(int dec_id) {
   68|  7.61k|    return attributes_decoders_[dec_id].get();
   69|  7.61k|  }
_ZNK5draco17PointCloudDecoder23num_attributes_decodersEv:
   70|  7.61k|  int32_t num_attributes_decoders() const {
   71|  7.61k|    return static_cast<int32_t>(attributes_decoders_.size());
   72|  7.61k|  }
_ZN5draco17PointCloudDecoder11point_cloudEv:
   76|  82.0k|  PointCloud* point_cloud() { return point_cloud_; }
_ZNK5draco17PointCloudDecoder11point_cloudEv:
   77|  12.2k|  const PointCloud* point_cloud() const { return point_cloud_; }
_ZN5draco17PointCloudDecoder6bufferEv:
   79|   164k|  DecoderBuffer* buffer() { return buffer_; }
_ZNK5draco17PointCloudDecoder7optionsEv:
   80|  7.84k|  const DecoderOptions* options() const { return options_; }
_ZN5draco17PointCloudDecoder17InitializeDecoderEv:
   85|  8.17k|  virtual bool InitializeDecoder() { return true; }
_ZN5draco17PointCloudDecoder18DecodeGeometryDataEv:
   89|  5.76k|  virtual bool DecodeGeometryData() { return true; }
_ZN5draco17PointCloudDecoder19OnAttributesDecodedEv:
   93|    362|  virtual bool OnAttributesDecoded() { return true; }
_ZN5draco17PointCloudDecoderD2Ev:
   31|  19.4k|  virtual ~PointCloudDecoder() = default;

_ZN5draco23PointCloudKdTreeDecoder18DecodeGeometryDataEv:
   21|  2.52k|bool PointCloudKdTreeDecoder::DecodeGeometryData() {
   22|  2.52k|  int32_t num_points;
   23|  2.52k|  if (!buffer()->Decode(&num_points)) {
  ------------------
  |  Branch (23:7): [True: 1, False: 2.52k]
  ------------------
   24|      1|    return false;
   25|      1|  }
   26|  2.52k|  if (num_points < 0) {
  ------------------
  |  Branch (26:7): [True: 36, False: 2.48k]
  ------------------
   27|     36|    return false;
   28|     36|  }
   29|  2.48k|  point_cloud()->set_num_points(num_points);
   30|  2.48k|  return true;
   31|  2.52k|}
_ZN5draco23PointCloudKdTreeDecoder23CreateAttributesDecoderEi:
   33|  16.2k|bool PointCloudKdTreeDecoder::CreateAttributesDecoder(int32_t att_decoder_id) {
   34|       |  // Always create the basic attribute decoder.
   35|  16.2k|  return SetAttributesDecoder(
   36|  16.2k|      att_decoder_id,
   37|  16.2k|      std::unique_ptr<AttributesDecoder>(new KdTreeAttributesDecoder()));
   38|  16.2k|}

_ZN5draco27PointCloudSequentialDecoder18DecodeGeometryDataEv:
   22|    301|bool PointCloudSequentialDecoder::DecodeGeometryData() {
   23|    301|  int32_t num_points;
   24|    301|  if (!buffer()->Decode(&num_points)) {
  ------------------
  |  Branch (24:7): [True: 4, False: 297]
  ------------------
   25|      4|    return false;
   26|      4|  }
   27|    297|  if (num_points < 0) {
  ------------------
  |  Branch (27:7): [True: 36, False: 261]
  ------------------
   28|     36|    return false;
   29|     36|  }
   30|    261|  point_cloud()->set_num_points(num_points);
   31|    261|  return true;
   32|    297|}
_ZN5draco27PointCloudSequentialDecoder23CreateAttributesDecoderEi:
   35|  5.79k|    int32_t att_decoder_id) {
   36|       |  // Always create the basic attribute decoder.
   37|  5.79k|  return SetAttributesDecoder(
   38|  5.79k|      att_decoder_id,
   39|  5.79k|      std::unique_ptr<AttributesDecoder>(
   40|  5.79k|          new SequentialAttributeDecodersController(
   41|  5.79k|              std::unique_ptr<PointsSequencer>(
   42|  5.79k|                  new LinearSequencer(point_cloud()->num_points())))));
   43|  5.79k|}

_ZN5draco26ConvertSymbolsToSignedIntsEPKjiPi:
   30|  8.21k|                                int32_t* out) {
   31|  1.76G|  for (int i = 0; i < in_values; ++i) {
  ------------------
  |  Branch (31:19): [True: 1.76G, False: 8.21k]
  ------------------
   32|  1.76G|    out[i] = ConvertSymbolToSignedInt(in[i]);
   33|  1.76G|  }
   34|  8.21k|}

_ZN5draco18MostSignificantBitEj:
   58|  17.2M|inline int MostSignificantBit(uint32_t n) {
   59|  17.2M|#if defined(__GNUC__)
   60|  17.2M|  return 31 ^ __builtin_clz(n);
   61|       |#elif defined(_MSC_VER)
   62|       |
   63|       |  unsigned long where;
   64|       |  _BitScanReverse(&where, n);
   65|       |  return (int)where;
   66|       |#else
   67|       |  uint32_t msb = 0;
   68|       |  if (n) {
   69|       |    if (0xFFFF0000 & n) {
   70|       |      n >>= (1 << 4);
   71|       |      msb |= (1 << 4);
   72|       |    }
   73|       |    if (0x0000FF00 & n) {
   74|       |      n >>= (1 << 3);
   75|       |      msb |= (1 << 3);
   76|       |    }
   77|       |    if (0x000000F0 & n) {
   78|       |      n >>= (1 << 2);
   79|       |      msb |= (1 << 2);
   80|       |    }
   81|       |    if (0x0000000C & n) {
   82|       |      n >>= (1 << 1);
   83|       |      msb |= (1 << 1);
   84|       |    }
   85|       |    if (0x00000002 & n) {
   86|       |      msb |= (1 << 0);
   87|       |    }
   88|       |  } else {
   89|       |    msb = -1;
   90|       |  }
   91|       |  return msb;
   92|       |#endif
   93|  17.2M|}
_ZN5draco24ConvertSymbolToSignedIntIjEENSt3__111make_signedIT_E4typeES3_:
  127|  1.76G|    IntTypeT val) {
  128|  1.76G|  static_assert(std::is_integral<IntTypeT>::value, "IntTypeT is not integral.");
  129|  1.76G|  typedef typename std::make_signed<IntTypeT>::type SignedType;
  130|  1.76G|  const bool is_positive = !static_cast<bool>(val & 1);
  131|  1.76G|  val >>= 1;
  132|  1.76G|  if (is_positive) {
  ------------------
  |  Branch (132:7): [True: 1.75G, False: 5.96M]
  ------------------
  133|  1.75G|    return static_cast<SignedType>(val);
  134|  1.75G|  }
  135|  5.96M|  SignedType ret = static_cast<SignedType>(val);
  136|  5.96M|  ret = -ret - 1;
  137|  5.96M|  return ret;
  138|  1.76G|}

_ZN5draco10DataBufferC2Ev:
   21|  25.6k|DataBuffer::DataBuffer() = default;
_ZN5draco10DataBuffer6UpdateEPKvl:
   23|  26.2k|bool DataBuffer::Update(const void* data, int64_t size) {
   24|  26.2k|  const int64_t offset = 0;
   25|  26.2k|  return this->Update(data, size, offset);
   26|  26.2k|}
_ZN5draco10DataBuffer6UpdateEPKvll:
   28|  26.2k|bool DataBuffer::Update(const void* data, int64_t size, int64_t offset) {
   29|  26.2k|  if (data == nullptr) {
  ------------------
  |  Branch (29:7): [True: 25.0k, False: 1.22k]
  ------------------
   30|  25.0k|    if (size + offset < 0) {
  ------------------
  |  Branch (30:9): [True: 0, False: 25.0k]
  ------------------
   31|      0|      return false;
   32|      0|    }
   33|       |    // If no data is provided, just resize the buffer.
   34|  25.0k|    data_.resize(size + offset);
   35|  25.0k|  } else {
   36|  1.22k|    if (size < 0) {
  ------------------
  |  Branch (36:9): [True: 0, False: 1.22k]
  ------------------
   37|      0|      return false;
   38|      0|    }
   39|  1.22k|    if (size + offset > static_cast<int64_t>(data_.size())) {
  ------------------
  |  Branch (39:9): [True: 846, False: 377]
  ------------------
   40|    846|      data_.resize(size + offset);
   41|    846|    }
   42|  1.22k|    const uint8_t* const byte_data = static_cast<const uint8_t*>(data);
   43|  1.22k|    std::copy(byte_data, byte_data + size, data_.data() + offset);
   44|  1.22k|  }
   45|  26.2k|  descriptor_.buffer_update_count++;
   46|  26.2k|  return true;
   47|  26.2k|}
_ZN5draco10DataBuffer6ResizeEl:
   49|  5.96k|void DataBuffer::Resize(int64_t size) {
   50|  5.96k|  data_.resize(size);
   51|  5.96k|  descriptor_.buffer_update_count++;
   52|  5.96k|}

_ZN5draco20DataBufferDescriptorC2Ev:
   28|  67.2k|  DataBufferDescriptor() : buffer_id(0), buffer_update_count(0) {}
_ZNK5draco10DataBuffer4ReadElPvm:
   47|  40.6M|  void Read(int64_t byte_pos, void* out_data, size_t data_size) const {
   48|  40.6M|    memcpy(out_data, data() + byte_pos, data_size);
   49|  40.6M|  }
_ZN5draco10DataBuffer5WriteElPKvm:
   53|   691M|  void Write(int64_t byte_pos, const void* in_data, size_t data_size) {
   54|   691M|    memcpy(const_cast<uint8_t*>(data()) + byte_pos, in_data, data_size);
   55|   691M|  }
_ZNK5draco10DataBuffer12update_countEv:
   67|  24.9k|  int64_t update_count() const { return descriptor_.buffer_update_count; }
_ZNK5draco10DataBuffer9data_sizeEv:
   68|  57.5M|  size_t data_size() const { return data_.size(); }
_ZNK5draco10DataBuffer4dataEv:
   69|  40.6M|  const uint8_t* data() const { return data_.data(); }
_ZN5draco10DataBuffer4dataEv:
   70|   768M|  uint8_t* data() { return data_.data(); }
_ZNK5draco10DataBuffer9buffer_idEv:
   71|  24.9k|  int64_t buffer_id() const { return descriptor_.buffer_id; }

_ZN5draco13DecoderBufferC2Ev:
   23|  59.1k|    : data_(nullptr),
   24|  59.1k|      data_size_(0),
   25|  59.1k|      pos_(0),
   26|  59.1k|      bit_mode_(false),
   27|  59.1k|      bitstream_version_(0) {}
_ZN5draco13DecoderBuffer4InitEPKcm:
   29|  19.5k|void DecoderBuffer::Init(const char* data, size_t data_size) {
   30|  19.5k|  Init(data, data_size, bitstream_version_);
   31|  19.5k|}
_ZN5draco13DecoderBuffer4InitEPKcmt:
   33|  33.9k|void DecoderBuffer::Init(const char* data, size_t data_size, uint16_t version) {
   34|  33.9k|  data_ = data;
   35|  33.9k|  data_size_ = data_size;
   36|  33.9k|  bitstream_version_ = version;
   37|  33.9k|  pos_ = 0;
   38|  33.9k|}
_ZN5draco13DecoderBuffer16StartBitDecodingEbPm:
   40|  9.42k|bool DecoderBuffer::StartBitDecoding(bool decode_size, uint64_t* out_size) {
   41|  9.42k|  if (decode_size) {
  ------------------
  |  Branch (41:7): [True: 6.61k, False: 2.80k]
  ------------------
   42|  6.61k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   43|  6.61k|    if (bitstream_version_ < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  6.61k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (43:9): [True: 1.36k, False: 5.25k]
  ------------------
   44|  1.36k|      if (!Decode(out_size)) {
  ------------------
  |  Branch (44:11): [True: 17, False: 1.34k]
  ------------------
   45|     17|        return false;
   46|     17|      }
   47|  1.36k|    } else
   48|  5.25k|#endif
   49|  5.25k|    {
   50|  5.25k|      if (!DecodeVarint(out_size, this)) {
  ------------------
  |  Branch (50:11): [True: 51, False: 5.20k]
  ------------------
   51|     51|        return false;
   52|     51|      }
   53|  5.25k|    }
   54|  6.61k|  }
   55|  9.35k|  bit_mode_ = true;
   56|  9.35k|  bit_decoder_.reset(data_head(), remaining_size());
   57|  9.35k|  return true;
   58|  9.42k|}
_ZN5draco13DecoderBuffer14EndBitDecodingEv:
   60|  7.90k|void DecoderBuffer::EndBitDecoding() {
   61|  7.90k|  bit_mode_ = false;
   62|  7.90k|  const uint64_t bits_decoded = bit_decoder_.BitsDecoded();
   63|  7.90k|  const uint64_t bytes_decoded = (bits_decoded + 7) / 8;
   64|  7.90k|  pos_ += bytes_decoded;
   65|  7.90k|}
_ZN5draco13DecoderBuffer10BitDecoderC2Ev:
   68|  59.1k|    : bit_buffer_(nullptr), bit_buffer_end_(nullptr), bit_offset_(0) {}
_ZN5draco13DecoderBuffer10BitDecoderD2Ev:
   70|  98.1k|DecoderBuffer::BitDecoder::~BitDecoder() = default;

_ZN5draco13DecoderBuffer28DecodeLeastSignificantBits32EjPj:
   57|  23.5M|  bool DecodeLeastSignificantBits32(uint32_t nbits, uint32_t* out_value) {
   58|  23.5M|    if (!bit_decoder_active()) {
  ------------------
  |  Branch (58:9): [True: 0, False: 23.5M]
  ------------------
   59|      0|      return false;
   60|      0|    }
   61|  23.5M|    return bit_decoder_.GetBits(nbits, out_value);
   62|  23.5M|  }
_ZN5draco13DecoderBuffer6DecodeEPvm:
   76|  2.19G|  bool Decode(void* out_data, size_t size_to_decode) {
   77|  2.19G|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (77:9): [True: 552, False: 2.19G]
  ------------------
   78|    552|      return false;  // Buffer overflow.
   79|    552|    }
   80|  2.19G|    memcpy(out_data, (data_ + pos_), size_to_decode);
   81|  2.19G|    pos_ += size_to_decode;
   82|  2.19G|    return true;
   83|  2.19G|  }
_ZN5draco13DecoderBuffer7AdvanceEl:
  105|  45.8k|  void Advance(int64_t bytes) { pos_ += bytes; }
_ZN5draco13DecoderBuffer21set_bitstream_versionEt:
  111|  19.4k|  void set_bitstream_version(uint16_t version) { bitstream_version_ = version; }
_ZNK5draco13DecoderBuffer9data_headEv:
  114|  63.3k|  const char* data_head() const { return data_ + pos_; }
_ZNK5draco13DecoderBuffer14remaining_sizeEv:
  115|   267k|  int64_t remaining_size() const { return data_size_ - pos_; }
_ZNK5draco13DecoderBuffer12decoded_sizeEv:
  116|  8.23k|  int64_t decoded_size() const { return pos_; }
_ZNK5draco13DecoderBuffer18bit_decoder_activeEv:
  117|  23.5M|  bool bit_decoder_active() const { return bit_mode_; }
_ZNK5draco13DecoderBuffer17bitstream_versionEv:
  120|  4.43M|  uint16_t bitstream_version() const { return bitstream_version_; }
_ZN5draco13DecoderBuffer10BitDecoder5resetEPKvm:
  130|  9.35k|    void reset(const void* b, size_t s) {
  131|  9.35k|      bit_offset_ = 0;
  132|  9.35k|      bit_buffer_ = static_cast<const uint8_t*>(b);
  133|  9.35k|      bit_buffer_end_ = bit_buffer_ + s;
  134|  9.35k|    }
_ZNK5draco13DecoderBuffer10BitDecoder11BitsDecodedEv:
  137|  7.90k|    uint64_t BitsDecoded() const { return static_cast<uint64_t>(bit_offset_); }
_ZN5draco13DecoderBuffer10BitDecoder7GetBitsEjPj:
  158|  23.5M|    bool GetBits(uint32_t nbits, uint32_t* x) {
  159|  23.5M|      if (nbits > 32) {
  ------------------
  |  Branch (159:11): [True: 3, False: 23.5M]
  ------------------
  160|      3|        return false;
  161|      3|      }
  162|  23.5M|      uint32_t value = 0;
  163|  49.2M|      for (uint32_t bit = 0; bit < nbits; ++bit) {
  ------------------
  |  Branch (163:30): [True: 25.7M, False: 23.5M]
  ------------------
  164|  25.7M|        value |= GetBit() << bit;
  165|  25.7M|      }
  166|  23.5M|      *x = value;
  167|  23.5M|      return true;
  168|  23.5M|    }
_ZN5draco13DecoderBuffer10BitDecoder6GetBitEv:
  173|  25.7M|    int GetBit() {
  174|  25.7M|      const size_t off = bit_offset_;
  175|  25.7M|      const size_t byte_offset = off >> 3;
  176|  25.7M|      const int bit_shift = static_cast<int>(off & 0x7);
  177|  25.7M|      if (bit_buffer_ + byte_offset < bit_buffer_end_) {
  ------------------
  |  Branch (177:11): [True: 21.9M, False: 3.77M]
  ------------------
  178|  21.9M|        const int bit = (bit_buffer_[byte_offset] >> bit_shift) & 1;
  179|  21.9M|        bit_offset_ = off + 1;
  180|  21.9M|        return bit;
  181|  21.9M|      }
  182|  3.77M|      return 0;
  183|  25.7M|    }
_ZN5draco13DecoderBuffer6DecodeIhEEbPT_:
   68|  8.36M|  bool Decode(T* out_val) {
   69|  8.36M|    if (!Peek(out_val)) {
  ------------------
  |  Branch (69:9): [True: 5.62k, False: 8.36M]
  ------------------
   70|  5.62k|      return false;
   71|  5.62k|    }
   72|  8.36M|    pos_ += sizeof(T);
   73|  8.36M|    return true;
   74|  8.36M|  }
_ZN5draco13DecoderBuffer4PeekIhEEbPT_:
   87|  8.36M|  bool Peek(T* out_val) {
   88|  8.36M|    const size_t size_to_decode = sizeof(T);
   89|  8.36M|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (89:9): [True: 5.62k, False: 8.36M]
  ------------------
   90|  5.62k|      return false;  // Buffer overflow.
   91|  5.62k|    }
   92|  8.36M|    memcpy(out_val, (data_ + pos_), size_to_decode);
   93|  8.36M|    return true;
   94|  8.36M|  }
_ZN5draco13DecoderBuffer6DecodeIiEEbPT_:
   68|  16.2k|  bool Decode(T* out_val) {
   69|  16.2k|    if (!Peek(out_val)) {
  ------------------
  |  Branch (69:9): [True: 138, False: 16.1k]
  ------------------
   70|    138|      return false;
   71|    138|    }
   72|  16.1k|    pos_ += sizeof(T);
   73|  16.1k|    return true;
   74|  16.2k|  }
_ZN5draco13DecoderBuffer4PeekIiEEbPT_:
   87|  16.2k|  bool Peek(T* out_val) {
   88|  16.2k|    const size_t size_to_decode = sizeof(T);
   89|  16.2k|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (89:9): [True: 138, False: 16.1k]
  ------------------
   90|    138|      return false;  // Buffer overflow.
   91|    138|    }
   92|  16.1k|    memcpy(out_val, (data_ + pos_), size_to_decode);
   93|  16.1k|    return true;
   94|  16.2k|  }
_ZN5draco13DecoderBuffer6DecodeIjEEbPT_:
   68|   597k|  bool Decode(T* out_val) {
   69|   597k|    if (!Peek(out_val)) {
  ------------------
  |  Branch (69:9): [True: 584, False: 596k]
  ------------------
   70|    584|      return false;
   71|    584|    }
   72|   596k|    pos_ += sizeof(T);
   73|   596k|    return true;
   74|   597k|  }
_ZN5draco13DecoderBuffer4PeekIjEEbPT_:
   87|   597k|  bool Peek(T* out_val) {
   88|   597k|    const size_t size_to_decode = sizeof(T);
   89|   597k|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (89:9): [True: 584, False: 596k]
  ------------------
   90|    584|      return false;  // Buffer overflow.
   91|    584|    }
   92|   596k|    memcpy(out_val, (data_ + pos_), size_to_decode);
   93|   596k|    return true;
   94|   597k|  }
_ZN5draco13DecoderBuffer6DecodeIaEEbPT_:
   68|  24.6k|  bool Decode(T* out_val) {
   69|  24.6k|    if (!Peek(out_val)) {
  ------------------
  |  Branch (69:9): [True: 188, False: 24.4k]
  ------------------
   70|    188|      return false;
   71|    188|    }
   72|  24.4k|    pos_ += sizeof(T);
   73|  24.4k|    return true;
   74|  24.6k|  }
_ZN5draco13DecoderBuffer4PeekIaEEbPT_:
   87|  24.6k|  bool Peek(T* out_val) {
   88|  24.6k|    const size_t size_to_decode = sizeof(T);
   89|  24.6k|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (89:9): [True: 188, False: 24.4k]
  ------------------
   90|    188|      return false;  // Buffer overflow.
   91|    188|    }
   92|  24.4k|    memcpy(out_val, (data_ + pos_), size_to_decode);
   93|  24.4k|    return true;
   94|  24.6k|  }
_ZN5draco13DecoderBuffer6DecodeINS_13HoleEventDataEEEbPT_:
   68|  1.73M|  bool Decode(T* out_val) {
   69|  1.73M|    if (!Peek(out_val)) {
  ------------------
  |  Branch (69:9): [True: 139, False: 1.73M]
  ------------------
   70|    139|      return false;
   71|    139|    }
   72|  1.73M|    pos_ += sizeof(T);
   73|  1.73M|    return true;
   74|  1.73M|  }
_ZN5draco13DecoderBuffer4PeekINS_13HoleEventDataEEEbPT_:
   87|  1.73M|  bool Peek(T* out_val) {
   88|  1.73M|    const size_t size_to_decode = sizeof(T);
   89|  1.73M|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (89:9): [True: 139, False: 1.73M]
  ------------------
   90|    139|      return false;  // Buffer overflow.
   91|    139|    }
   92|  1.73M|    memcpy(out_val, (data_ + pos_), size_to_decode);
   93|  1.73M|    return true;
   94|  1.73M|  }
_ZN5draco13DecoderBuffer6DecodeItEEbPT_:
   68|  59.5k|  bool Decode(T* out_val) {
   69|  59.5k|    if (!Peek(out_val)) {
  ------------------
  |  Branch (69:9): [True: 42, False: 59.5k]
  ------------------
   70|     42|      return false;
   71|     42|    }
   72|  59.5k|    pos_ += sizeof(T);
   73|  59.5k|    return true;
   74|  59.5k|  }
_ZN5draco13DecoderBuffer4PeekItEEbPT_:
   87|  59.5k|  bool Peek(T* out_val) {
   88|  59.5k|    const size_t size_to_decode = sizeof(T);
   89|  59.5k|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (89:9): [True: 42, False: 59.5k]
  ------------------
   90|     42|      return false;  // Buffer overflow.
   91|     42|    }
   92|  59.5k|    memcpy(out_val, (data_ + pos_), size_to_decode);
   93|  59.5k|    return true;
   94|  59.5k|  }
_ZN5draco13DecoderBuffer6DecodeImEEbPT_:
   68|  1.77k|  bool Decode(T* out_val) {
   69|  1.77k|    if (!Peek(out_val)) {
  ------------------
  |  Branch (69:9): [True: 60, False: 1.71k]
  ------------------
   70|     60|      return false;
   71|     60|    }
   72|  1.71k|    pos_ += sizeof(T);
   73|  1.71k|    return true;
   74|  1.77k|  }
_ZN5draco13DecoderBuffer4PeekImEEbPT_:
   87|  1.77k|  bool Peek(T* out_val) {
   88|  1.77k|    const size_t size_to_decode = sizeof(T);
   89|  1.77k|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (89:9): [True: 60, False: 1.71k]
  ------------------
   90|     60|      return false;  // Buffer overflow.
   91|     60|    }
   92|  1.71k|    memcpy(out_val, (data_ + pos_), size_to_decode);
   93|  1.71k|    return true;
   94|  1.77k|  }
_ZN5draco13DecoderBuffer6DecodeIfEEbPT_:
   68|  1.03k|  bool Decode(T* out_val) {
   69|  1.03k|    if (!Peek(out_val)) {
  ------------------
  |  Branch (69:9): [True: 12, False: 1.01k]
  ------------------
   70|     12|      return false;
   71|     12|    }
   72|  1.01k|    pos_ += sizeof(T);
   73|  1.01k|    return true;
   74|  1.03k|  }
_ZN5draco13DecoderBuffer4PeekIfEEbPT_:
   87|  1.03k|  bool Peek(T* out_val) {
   88|  1.03k|    const size_t size_to_decode = sizeof(T);
   89|  1.03k|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (89:9): [True: 12, False: 1.01k]
  ------------------
   90|     12|      return false;  // Buffer overflow.
   91|     12|    }
   92|  1.01k|    memcpy(out_val, (data_ + pos_), size_to_decode);
   93|  1.01k|    return true;
   94|  1.03k|  }

_ZNK5draco9IndexTypeIjNS_29AttributeValueIndex_tag_type_EE5valueEv:
   73|   598M|  constexpr ValueTypeT value() const { return value_; }
_ZNK5draco9IndexTypeIjNS_20PointIndex_tag_type_EE5valueEv:
   73|   536M|  constexpr ValueTypeT value() const { return value_; }
_ZNK5draco9IndexTypeIjNS_19FaceIndex_tag_type_EEgeERKj:
   98|  15.4M|  constexpr bool operator>=(const ValueTypeT& val) const {
   99|  15.4M|    return value_ >= val;
  100|  15.4M|  }
_ZNK5draco9IndexTypeIjNS_19FaceIndex_tag_type_EE5valueEv:
   73|   327M|  constexpr ValueTypeT value() const { return value_; }
_ZNK5draco9IndexTypeIjNS_21CornerIndex_tag_type_EE5valueEv:
   73|  3.90G|  constexpr ValueTypeT value() const { return value_; }
_ZNK5draco9IndexTypeIjNS_19FaceIndex_tag_type_EEltERKj:
   90|  35.5M|  constexpr bool operator<(const ValueTypeT& val) const { return value_ < val; }
_ZN5draco9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEaSERKS2_:
  151|   148M|  inline ThisIndexType& operator=(const ThisIndexType& i) {
  152|   148M|    value_ = i.value_;
  153|   148M|    return *this;
  154|   148M|  }
_ZN5draco9IndexTypeIjNS_20PointIndex_tag_type_EEaSERKS2_:
  151|  2.36G|  inline ThisIndexType& operator=(const ThisIndexType& i) {
  152|  2.36G|    value_ = i.value_;
  153|  2.36G|    return *this;
  154|  2.36G|  }
_ZN5draco9IndexTypeIjNS_19FaceIndex_tag_type_EEppEv:
  102|  35.4M|  inline ThisIndexType& operator++() {
  103|  35.4M|    ++value_;
  104|  35.4M|    return *this;
  105|  35.4M|  }
_ZNK5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEeqERKS2_:
   75|  2.91G|  constexpr bool operator==(const IndexType& i) const {
   76|  2.91G|    return value_ == i.value_;
   77|  2.91G|  }
_ZNK5draco9IndexTypeIjNS_21VertexIndex_tag_type_EE5valueEv:
   73|  1.09G|  constexpr ValueTypeT value() const { return value_; }
_ZNK5draco9IndexTypeIjNS_21VertexIndex_tag_type_EEltERKS2_:
   87|  3.85k|  constexpr bool operator<(const IndexType& i) const {
   88|  3.85k|    return value_ < i.value_;
   89|  3.85k|  }
_ZNK5draco9IndexTypeIjNS_21VertexIndex_tag_type_EEeqERKS2_:
   75|   158M|  constexpr bool operator==(const IndexType& i) const {
   76|   158M|    return value_ == i.value_;
   77|   158M|  }
_ZNK5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEmiERKj:
  131|   268M|  constexpr ThisIndexType operator-(const ValueTypeT& val) const {
  132|   268M|    return ThisIndexType(value_ - val);
  133|   268M|  }
_ZNK5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEplERKj:
  125|   814M|  constexpr ThisIndexType operator+(const ValueTypeT& val) const {
  126|   814M|    return ThisIndexType(value_ + val);
  127|   814M|  }
_ZNK5draco9IndexTypeIjNS_19FaceIndex_tag_type_EEeqERKS2_:
   75|  30.7M|  constexpr bool operator==(const IndexType& i) const {
   76|  30.7M|    return value_ == i.value_;
   77|  30.7M|  }
_ZNK5draco9IndexTypeIjNS_21VertexIndex_tag_type_EEneERKS2_:
   81|   273M|  constexpr bool operator!=(const IndexType& i) const {
   82|   273M|    return value_ != i.value_;
   83|   273M|  }
_ZNK5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEneERKS2_:
   81|   456M|  constexpr bool operator!=(const IndexType& i) const {
   82|   456M|    return value_ != i.value_;
   83|   456M|  }
_ZN5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEppEv:
  102|   618M|  inline ThisIndexType& operator++() {
  103|   618M|    ++value_;
  104|   618M|    return *this;
  105|   618M|  }
_ZN5draco9IndexTypeIjNS_21VertexIndex_tag_type_EEaSERKS2_:
  151|   472M|  inline ThisIndexType& operator=(const ThisIndexType& i) {
  152|   472M|    value_ = i.value_;
  153|   472M|    return *this;
  154|   472M|  }
_ZN5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEaSERKS2_:
  151|  1.18G|  inline ThisIndexType& operator=(const ThisIndexType& i) {
  152|  1.18G|    value_ = i.value_;
  153|  1.18G|    return *this;
  154|  1.18G|  }
_ZNK5draco9IndexTypeIjNS_20PointIndex_tag_type_EEgeERKj:
   98|  60.0M|  constexpr bool operator>=(const ValueTypeT& val) const {
   99|  60.0M|    return value_ >= val;
  100|  60.0M|  }
_ZNK5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEltERKj:
   90|  15.7M|  constexpr bool operator<(const ValueTypeT& val) const { return value_ < val; }
_ZN5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEC2Ej:
   71|  1.31G|  constexpr explicit IndexType(ValueTypeT value) : value_(value) {}
_ZN5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEC2ERKS2_:
   70|  23.0G|  constexpr IndexType(const IndexType& i) : value_(i.value_) {}
_ZN5draco9IndexTypeIjNS_19FaceIndex_tag_type_EEC2Ej:
   71|   241M|  constexpr explicit IndexType(ValueTypeT value) : value_(value) {}
_ZN5draco9IndexTypeIjNS_21VertexIndex_tag_type_EEC2ERKS2_:
   70|  17.0G|  constexpr IndexType(const IndexType& i) : value_(i.value_) {}
_ZN5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEC2Ev:
   69|   258M|  constexpr IndexType() : value_(ValueTypeT()) {}
_ZNK5draco9IndexTypeIjNS_21VertexIndex_tag_type_EEplERKj:
  125|  16.2M|  constexpr ThisIndexType operator+(const ValueTypeT& val) const {
  126|  16.2M|    return ThisIndexType(value_ + val);
  127|  16.2M|  }
_ZN5draco9IndexTypeIjNS_21VertexIndex_tag_type_EEC2Ej:
   71|   183M|  constexpr explicit IndexType(ValueTypeT value) : value_(value) {}
_ZNK5draco9IndexTypeIjNS_19FaceIndex_tag_type_EEltERKS2_:
   87|  46.6M|  constexpr bool operator<(const IndexType& i) const {
   88|  46.6M|    return value_ < i.value_;
   89|  46.6M|  }
_ZN5draco9IndexTypeIjNS_20PointIndex_tag_type_EEC2ERKS2_:
   70|   717M|  constexpr IndexType(const IndexType& i) : value_(i.value_) {}
_ZN5draco9IndexTypeIjNS_20PointIndex_tag_type_EEC2Ev:
   69|  2.36G|  constexpr IndexType() : value_(ValueTypeT()) {}
_ZN5draco9IndexTypeIjNS_19FaceIndex_tag_type_EEC2ERKS2_:
   70|   101M|  constexpr IndexType(const IndexType& i) : value_(i.value_) {}
_ZN5draco9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEC2Ej:
   71|   492M|  constexpr explicit IndexType(ValueTypeT value) : value_(value) {}
_ZN5draco9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEC2ERKS2_:
   70|   874M|  constexpr IndexType(const IndexType& i) : value_(i.value_) {}
_ZN5draco9IndexTypeIjNS_19FaceIndex_tag_type_EEaSERKS2_:
  151|  8.06M|  inline ThisIndexType& operator=(const ThisIndexType& i) {
  152|  8.06M|    value_ = i.value_;
  153|  8.06M|    return *this;
  154|  8.06M|  }
_ZN5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEpLERKj:
  139|  15.7M|  inline ThisIndexType operator+=(const ValueTypeT& val) {
  140|  15.7M|    value_ += val;
  141|  15.7M|    return *this;
  142|  15.7M|  }
_ZN5draco9IndexTypeIjNS_20PointIndex_tag_type_EEaSERKj:
  155|  46.4M|  inline ThisIndexType& operator=(const ValueTypeT& val) {
  156|  46.4M|    value_ = val;
  157|  46.4M|    return *this;
  158|  46.4M|  }
_ZN5draco9IndexTypeIjNS_20PointIndex_tag_type_EEC2Ej:
   71|  2.32G|  constexpr explicit IndexType(ValueTypeT value) : value_(value) {}
_ZNK5draco9IndexTypeIjNS_21VertexIndex_tag_type_EEltERKj:
   90|  9.47M|  constexpr bool operator<(const ValueTypeT& val) const { return value_ < val; }
_ZN5draco9IndexTypeIjNS_21VertexIndex_tag_type_EEppEv:
  102|  9.46M|  inline ThisIndexType& operator++() {
  103|  9.46M|    ++value_;
  104|  9.46M|    return *this;
  105|  9.46M|  }
_ZNK5draco9IndexTypeIjNS_20PointIndex_tag_type_EEltERKj:
   90|  36.6M|  constexpr bool operator<(const ValueTypeT& val) const { return value_ < val; }
_ZNK5draco9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEltERKj:
   90|  40.6M|  constexpr bool operator<(const ValueTypeT& val) const { return value_ < val; }
_ZN5draco9IndexTypeIjNS_20PointIndex_tag_type_EEppEv:
  102|   420M|  inline ThisIndexType& operator++() {
  103|   420M|    ++value_;
  104|   420M|    return *this;
  105|   420M|  }
_ZN5draco9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEppEv:
  102|  40.6M|  inline ThisIndexType& operator++() {
  103|  40.6M|    ++value_;
  104|  40.6M|    return *this;
  105|  40.6M|  }
_ZNK5draco9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEgeERKj:
   98|   384M|  constexpr bool operator>=(const ValueTypeT& val) const {
   99|   384M|    return value_ >= val;
  100|   384M|  }

_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_IjNS_29AttributeValueIndex_tag_type_EEEEixERKS3_:
   73|  55.7M|  inline const_reference operator[](const IndexTypeT& index) const {
   74|  55.7M|    return vector_[index.value()];
   75|  55.7M|  }
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_IjNS_29AttributeValueIndex_tag_type_EEEE4sizeEv:
   59|  36.6M|  size_t size() const { return vector_.size(); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_IjNS_29AttributeValueIndex_tag_type_EEEE5clearEv:
   48|  15.3k|  void clear() { vector_.clear(); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_IjNS_29AttributeValueIndex_tag_type_EEEE6resizeEmRKS5_:
   51|  22.5k|  void resize(size_t size, const ValueTypeT& val) { vector_.resize(size, val); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_IjNS_29AttributeValueIndex_tag_type_EEEEixERKS3_:
   70|  96.6M|  inline reference operator[](const IndexTypeT& index) {
   71|  96.6M|    return vector_[index.value()];
   72|  96.6M|  }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_19FaceIndex_tag_type_EEENSt3__15arrayINS1_IjNS_20PointIndex_tag_type_EEELm3EEEE9push_backERKS8_:
   62|  4.17k|  void push_back(const ValueTypeT& val) { vector_.push_back(val); }
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_19FaceIndex_tag_type_EEENSt3__15arrayINS1_IjNS_20PointIndex_tag_type_EEELm3EEEE4sizeEv:
   59|  30.9M|  size_t size() const { return vector_.size(); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_19FaceIndex_tag_type_EEENSt3__15arrayINS1_IjNS_20PointIndex_tag_type_EEELm3EEEE6resizeEmRKS8_:
   51|  5.02k|  void resize(size_t size, const ValueTypeT& val) { vector_.resize(size, val); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_19FaceIndex_tag_type_EEENSt3__15arrayINS1_IjNS_20PointIndex_tag_type_EEELm3EEEEixERKS3_:
   70|  15.4M|  inline reference operator[](const IndexTypeT& index) {
   71|  15.4M|    return vector_[index.value()];
   72|  15.4M|  }
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_19FaceIndex_tag_type_EEENSt3__15arrayINS1_IjNS_20PointIndex_tag_type_EEELm3EEEEixERKS3_:
   73|  37.8M|  inline const_reference operator[](const IndexTypeT& index) const {
   74|  37.8M|    return vector_[index.value()];
   75|  37.8M|  }
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEENS1_IjNS_21CornerIndex_tag_type_EEEE4sizeEv:
   59|   211M|  size_t size() const { return vector_.size(); }
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEENS1_IjNS_21VertexIndex_tag_type_EEEE4sizeEv:
   59|  20.0M|  size_t size() const { return vector_.size(); }
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEES3_EixERKS3_:
   73|   406M|  inline const_reference operator[](const IndexTypeT& index) const {
   74|   406M|    return vector_[index.value()];
   75|   406M|  }
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEENS1_IjNS_21VertexIndex_tag_type_EEEEixERKS3_:
   73|   933M|  inline const_reference operator[](const IndexTypeT& index) const {
   74|   933M|    return vector_[index.value()];
   75|   933M|  }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEENS1_IjNS_21VertexIndex_tag_type_EEEEixERKS3_:
   70|   418M|  inline reference operator[](const IndexTypeT& index) {
   71|   418M|    return vector_[index.value()];
   72|   418M|  }
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEENS1_IjNS_21CornerIndex_tag_type_EEEEixERKS3_:
   73|  69.3M|  inline const_reference operator[](const IndexTypeT& index) const {
   74|  69.3M|    return vector_[index.value()];
   75|  69.3M|  }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEES3_EixERKS3_:
   70|   351M|  inline reference operator[](const IndexTypeT& index) {
   71|   351M|    return vector_[index.value()];
   72|   351M|  }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEENS1_IjNS_21CornerIndex_tag_type_EEEE9push_backERKS5_:
   62|   104M|  void push_back(const ValueTypeT& val) { vector_.push_back(val); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEENS1_IjNS_21CornerIndex_tag_type_EEEEixERKS3_:
   70|   228M|  inline reference operator[](const IndexTypeT& index) {
   71|   228M|    return vector_[index.value()];
   72|   228M|  }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEiE6resizeEmRKi:
   51|  2.65k|  void resize(size_t size, const ValueTypeT& val) { vector_.resize(size, val); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEiEixERKS3_:
   70|   236M|  inline reference operator[](const IndexTypeT& index) {
   71|   236M|    return vector_[index.value()];
   72|   236M|  }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEiEC2Ev:
   39|  78.3k|  IndexTypeVector() {}
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEiE4sizeEv:
   59|  2.96M|  size_t size() const { return vector_.size(); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEaEC2Ev:
   39|  74.3k|  IndexTypeVector() {}
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEENS1_IjNS_21VertexIndex_tag_type_EEEEC2Ev:
   39|  9.21k|  IndexTypeVector() {}
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEES3_EC2Ev:
   39|  9.21k|  IndexTypeVector() {}
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEENS1_IjNS_21CornerIndex_tag_type_EEEEC2Ev:
   39|  9.21k|  IndexTypeVector() {}
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEES3_EC2Ev:
   39|  9.21k|  IndexTypeVector() {}
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEiE5clearEv:
   48|  18.5k|  void clear() { vector_.clear(); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEiE4swapERS4_:
   55|  18.5k|  void swap(IndexTypeVector<IndexTypeT, ValueTypeT>& arg) {
   56|  18.5k|    vector_.swap(arg.vector_);
   57|  18.5k|  }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEaE5clearEv:
   48|  18.5k|  void clear() { vector_.clear(); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEaE4swapERS4_:
   55|  18.5k|  void swap(IndexTypeVector<IndexTypeT, ValueTypeT>& arg) {
   56|  18.5k|    vector_.swap(arg.vector_);
   57|  18.5k|  }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEENS1_IjNS_21VertexIndex_tag_type_EEEE6assignEmRKS5_:
   52|  9.20k|  void assign(size_t size, const ValueTypeT& val) { vector_.assign(size, val); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEES3_E6assignEmRKS3_:
   52|  9.20k|  void assign(size_t size, const ValueTypeT& val) { vector_.assign(size, val); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEENS1_IjNS_21CornerIndex_tag_type_EEEE7reserveEm:
   49|  9.20k|  void reserve(size_t size) { vector_.reserve(size); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_19FaceIndex_tag_type_EEENSt3__15arrayINS1_IjNS_20PointIndex_tag_type_EEELm3EEEEC2Ev:
   39|  16.3k|  IndexTypeVector() {}
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_IjNS_29AttributeValueIndex_tag_type_EEEEC2Ev:
   39|  41.5k|  IndexTypeVector() {}

_ZN5draco14DataTypeLengthENS_8DataTypeE:
   19|  79.3k|int32_t DataTypeLength(DataType dt) {
   20|  79.3k|  switch (dt) {
   21|  27.6k|    case DT_INT8:
  ------------------
  |  Branch (21:5): [True: 27.6k, False: 51.7k]
  ------------------
   22|  33.7k|    case DT_UINT8:
  ------------------
  |  Branch (22:5): [True: 6.11k, False: 73.2k]
  ------------------
   23|  33.7k|      return 1;
   24|  4.01k|    case DT_INT16:
  ------------------
  |  Branch (24:5): [True: 4.01k, False: 75.3k]
  ------------------
   25|  6.65k|    case DT_UINT16:
  ------------------
  |  Branch (25:5): [True: 2.63k, False: 76.7k]
  ------------------
   26|  6.65k|      return 2;
   27|  31.4k|    case DT_INT32:
  ------------------
  |  Branch (27:5): [True: 31.4k, False: 47.9k]
  ------------------
   28|  33.3k|    case DT_UINT32:
  ------------------
  |  Branch (28:5): [True: 1.91k, False: 77.4k]
  ------------------
   29|  33.3k|      return 4;
   30|    223|    case DT_INT64:
  ------------------
  |  Branch (30:5): [True: 223, False: 79.1k]
  ------------------
   31|    747|    case DT_UINT64:
  ------------------
  |  Branch (31:5): [True: 524, False: 78.8k]
  ------------------
   32|    747|      return 8;
   33|  4.42k|    case DT_FLOAT32:
  ------------------
  |  Branch (33:5): [True: 4.42k, False: 74.9k]
  ------------------
   34|  4.42k|      return 4;
   35|    208|    case DT_FLOAT64:
  ------------------
  |  Branch (35:5): [True: 208, False: 79.1k]
  ------------------
   36|    208|      return 8;
   37|    240|    case DT_BOOL:
  ------------------
  |  Branch (37:5): [True: 240, False: 79.1k]
  ------------------
   38|    240|      return 1;
   39|      0|    default:
  ------------------
  |  Branch (39:5): [True: 0, False: 79.3k]
  ------------------
   40|      0|      return -1;
   41|  79.3k|  }
   42|  79.3k|}

_ZN5draco13AddAsUnsignedIiTnPNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std9is_signedIS3_EE5valueEvE4typeELPv0EEES3_S3_S3_:
   14|  77.2M|inline DataTypeT AddAsUnsigned(DataTypeT a, DataTypeT b) {
   15|  77.2M|  typedef typename std::make_unsigned<DataTypeT>::type DataTypeUT;
   16|  77.2M|  return static_cast<DataTypeT>(static_cast<DataTypeUT>(a) +
   17|  77.2M|                                static_cast<DataTypeUT>(b));
   18|  77.2M|}

_ZN5draco7IntSqrtEm:
   31|     83|inline uint64_t IntSqrt(uint64_t number) {
   32|     83|  if (number == 0) {
  ------------------
  |  Branch (32:7): [True: 0, False: 83]
  ------------------
   33|      0|    return 0;
   34|      0|  }
   35|       |  // First estimate good initial value of the square root as log2(number).
   36|     83|  uint64_t act_number = number;
   37|     83|  uint64_t square_root = 1;
   38|  1.01k|  while (act_number >= 2) {
  ------------------
  |  Branch (38:10): [True: 932, False: 83]
  ------------------
   39|       |    // Double the square root until |square_root * square_root > number|.
   40|    932|    square_root *= 2;
   41|    932|    act_number /= 4;
   42|    932|  }
   43|       |  // Perform Newton's (or Babylonian) method to find the true floor(sqrt()).
   44|    190|  do {
   45|       |    // New |square_root| estimate is computed as the average between
   46|       |    // |square_root| and |number / square_root|.
   47|    190|    square_root = (square_root + number / square_root) / 2;
   48|       |
   49|       |    // Note that after the first iteration, the estimate is always going to be
   50|       |    // larger or equal to the true square root value. Therefore to check
   51|       |    // convergence, we can simply detect condition when the square of the
   52|       |    // estimated square root is larger than the input.
   53|    190|  } while (square_root * square_root > number);
  ------------------
  |  Branch (53:12): [True: 107, False: 83]
  ------------------
   54|     83|  return square_root;
   55|     83|}

_ZN5draco7Options7SetBoolERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEb:
   38|  19.5k|void Options::SetBool(const std::string& name, bool val) {
   39|  19.5k|  options_[name] = std::to_string(val ? 1 : 0);
  ------------------
  |  Branch (39:35): [True: 19.5k, False: 0]
  ------------------
   40|  19.5k|}
_ZNK5draco7Options6GetIntERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEi:
   48|  3.73k|int Options::GetInt(const std::string& name, int default_val) const {
   49|  3.73k|  const auto it = options_.find(name);
   50|  3.73k|  if (it == options_.end()) {
  ------------------
  |  Branch (50:7): [True: 2.48k, False: 1.24k]
  ------------------
   51|  2.48k|    return default_val;
   52|  2.48k|  }
   53|  1.24k|  return std::atoi(it->second.c_str());
   54|  3.73k|}
_ZNK5draco7Options7GetBoolERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEb:
   72|  3.73k|bool Options::GetBool(const std::string& name, bool default_val) const {
   73|  3.73k|  const int ret = GetInt(name, -1);
   74|  3.73k|  if (ret == -1) {
  ------------------
  |  Branch (74:7): [True: 2.48k, False: 1.24k]
  ------------------
   75|  2.48k|    return default_val;
   76|  2.48k|  }
   77|  1.24k|  return static_cast<bool>(ret);
   78|  3.73k|}

_ZN5draco7OptionsC2Ev:
   32|  39.0k|  Options() = default;
_ZN5draco7OptionsD2Ev:
   33|  78.0k|  ~Options() = default;
_ZNK5draco7Options11IsOptionSetERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
   70|  1.24k|  bool IsOptionSet(const std::string& name) const {
   71|  1.24k|    return options_.count(name) > 0;
   72|  1.24k|  }

_ZN5draco11DequantizerC2Ev:
   27|    129|Dequantizer::Dequantizer() : delta_(1.f) {}
_ZN5draco11Dequantizer4InitEfi:
   29|    129|bool Dequantizer::Init(float range, int32_t max_quantized_value) {
   30|    129|  if (max_quantized_value <= 0) {
  ------------------
  |  Branch (30:7): [True: 17, False: 112]
  ------------------
   31|     17|    return false;
   32|     17|  }
   33|    112|  delta_ = range / static_cast<float>(max_quantized_value);
   34|    112|  return true;
   35|    129|}

_ZNK5draco11Dequantizer15DequantizeFloatEi:
   71|  38.3M|  inline float DequantizeFloat(int32_t val) const {
   72|  38.3M|    return static_cast<float>(val) * delta_;
   73|  38.3M|  }
_ZNK5draco11DequantizerclEi:
   74|    219|  inline float operator()(int32_t val) const { return DequantizeFloat(val); }

_ZN5draco6StatusC2ENS0_4CodeE:
   41|   102k|  explicit Status(Code code) : code_(code) {}
_ZN5draco6StatusC2ENS0_4CodeERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
   43|  17.6k|      : code_(code), error_msg_(error_msg) {}
_ZNK5draco6Status2okEv:
   52|   137k|  bool ok() const { return code_ == OK; }
_ZN5draco8OkStatusEv:
   66|   102k|inline Status OkStatus() { return Status(Status::OK); }
_ZN5draco6StatusC2ERKS0_:
   39|  17.7k|  Status(const Status& status) = default;

_ZN5draco8StatusOrINSt3__110unique_ptrINS_17PointCloudDecoderENS1_14default_deleteIS3_EEEEEC2EOS6_:
   39|  3.09k|  StatusOr(T&& value) : status_(OkStatus()), value_(std::move(value)) {}
_ZN5draco8StatusOrINSt3__110unique_ptrINS_17PointCloudDecoderENS1_14default_deleteIS3_EEEEEC2ERKNS_6StatusE:
   37|     10|  StatusOr(const Status& status) : status_(status) {}
_ZN5draco8StatusOrINSt3__110unique_ptrINS_11MeshDecoderENS1_14default_deleteIS3_EEEEEC2EOS6_:
   39|  16.3k|  StatusOr(T&& value) : status_(OkStatus()), value_(std::move(value)) {}
_ZN5draco8StatusOrINSt3__110unique_ptrINS_11MeshDecoderENS1_14default_deleteIS3_EEEEEC2ERKNS_6StatusE:
   37|      9|  StatusOr(const Status& status) : status_(status) {}
_ZN5draco8StatusOrINS_19EncodedGeometryTypeEEC2ERKNS_6StatusE:
   37|     61|  StatusOr(const Status& status) : status_(status) {}
_ZN5draco8StatusOrINS_19EncodedGeometryTypeEEC2EOS1_:
   39|  19.4k|  StatusOr(T&& value) : status_(OkStatus()), value_(std::move(value)) {}
_ZNK5draco8StatusOrINS_19EncodedGeometryTypeEE2okEv:
   53|  19.5k|  bool ok() const { return status_.ok(); }
_ZNK5draco8StatusOrINS_19EncodedGeometryTypeEE6statusEv:
   43|     61|  const Status& status() const { return status_; }
_ZN5draco8StatusOrINSt3__110unique_ptrINS_10PointCloudENS1_14default_deleteIS3_EEEEEC2ERKNS_6StatusE:
   37|  17.6k|  StatusOr(const Status& status) : status_(status) {}
_ZNO5draco8StatusOrINS_19EncodedGeometryTypeEE5valueEv:
   46|  19.4k|  T&& value() && { return std::move(value_); }
_ZN5draco8StatusOrINSt3__110unique_ptrINS_10PointCloudENS1_14default_deleteIS3_EEEEEC2EOS6_:
   39|  1.88k|  StatusOr(T&& value) : status_(OkStatus()), value_(std::move(value)) {}
_ZNK5draco8StatusOrINSt3__110unique_ptrINS_17PointCloudDecoderENS1_14default_deleteIS3_EEEEE2okEv:
   53|  3.10k|  bool ok() const { return status_.ok(); }
_ZNK5draco8StatusOrINSt3__110unique_ptrINS_17PointCloudDecoderENS1_14default_deleteIS3_EEEEE6statusEv:
   43|     10|  const Status& status() const { return status_; }
_ZNO5draco8StatusOrINSt3__110unique_ptrINS_17PointCloudDecoderENS1_14default_deleteIS3_EEEEE5valueEv:
   46|  3.09k|  T&& value() && { return std::move(value_); }
_ZNK5draco8StatusOrINSt3__110unique_ptrINS_11MeshDecoderENS1_14default_deleteIS3_EEEEE2okEv:
   53|  16.3k|  bool ok() const { return status_.ok(); }
_ZNK5draco8StatusOrINSt3__110unique_ptrINS_11MeshDecoderENS1_14default_deleteIS3_EEEEE6statusEv:
   43|      9|  const Status& status() const { return status_; }
_ZNO5draco8StatusOrINSt3__110unique_ptrINS_11MeshDecoderENS1_14default_deleteIS3_EEEEE5valueEv:
   46|  16.3k|  T&& value() && { return std::move(value_); }

_ZN5draco12DecodeVarintIjEEbPT_PNS_13DecoderBufferE:
   63|   515k|bool DecodeVarint(IntTypeT* out_val, DecoderBuffer* buffer) {
   64|   515k|  if (std::is_unsigned<IntTypeT>::value) {
  ------------------
  |  Branch (64:7): [True: 515k, Folded]
  ------------------
   65|   515k|    if (!DecodeVarintUnsigned<IntTypeT>(1, out_val, buffer)) {
  ------------------
  |  Branch (65:9): [True: 2.05k, False: 513k]
  ------------------
   66|  2.05k|      return false;
   67|  2.05k|    }
   68|   515k|  } else {
   69|       |    // IntTypeT is a signed value. Decode the symbol and convert to signed.
   70|      0|    typename std::make_unsigned<IntTypeT>::type symbol;
   71|      0|    if (!DecodeVarintUnsigned(1, &symbol, buffer)) {
  ------------------
  |  Branch (71:9): [True: 0, False: 0]
  ------------------
   72|      0|      return false;
   73|      0|    }
   74|      0|    *out_val = ConvertSymbolToSignedInt(symbol);
   75|      0|  }
   76|   513k|  return true;
   77|   515k|}
mesh_edgebreaker_decoder_impl.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedIjEEbiPT_PNS_13DecoderBufferE:
   30|   215k|bool DecodeVarintUnsigned(int depth, IntTypeT* out_val, DecoderBuffer* buffer) {
   31|   215k|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|   215k|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 77, False: 215k]
  ------------------
   33|     77|    return false;
   34|     77|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|   215k|  uint8_t in;
   39|   215k|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 1.22k, False: 214k]
  ------------------
   40|  1.22k|    return false;
   41|  1.22k|  }
   42|   214k|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 25.9k, False: 188k]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|  25.9k|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 594, False: 25.3k]
  ------------------
   45|    594|      return false;
   46|    594|    }
   47|       |    // Append decoded info from this byte.
   48|  25.3k|    *out_val <<= 7;
   49|  25.3k|    *out_val |= in & ((1 << 7) - 1);
   50|   188k|  } else {
   51|       |    // Last byte reached
   52|   188k|    *out_val = in;
   53|   188k|  }
   54|   213k|  return true;
   55|   214k|}
mesh_sequential_decoder.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedIjEEbiPT_PNS_13DecoderBufferE:
   30|  15.5k|bool DecodeVarintUnsigned(int depth, IntTypeT* out_val, DecoderBuffer* buffer) {
   31|  15.5k|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|  15.5k|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 4, False: 15.5k]
  ------------------
   33|      4|    return false;
   34|      4|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|  15.5k|  uint8_t in;
   39|  15.5k|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 54, False: 15.5k]
  ------------------
   40|     54|    return false;
   41|     54|  }
   42|  15.5k|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 1.54k, False: 13.9k]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|  1.54k|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 52, False: 1.49k]
  ------------------
   45|     52|      return false;
   46|     52|    }
   47|       |    // Append decoded info from this byte.
   48|  1.49k|    *out_val <<= 7;
   49|  1.49k|    *out_val |= in & ((1 << 7) - 1);
   50|  13.9k|  } else {
   51|       |    // Last byte reached
   52|  13.9k|    *out_val = in;
   53|  13.9k|  }
   54|  15.4k|  return true;
   55|  15.5k|}
_ZN5draco12DecodeVarintImEEbPT_PNS_13DecoderBufferE:
   63|  9.48k|bool DecodeVarint(IntTypeT* out_val, DecoderBuffer* buffer) {
   64|  9.48k|  if (std::is_unsigned<IntTypeT>::value) {
  ------------------
  |  Branch (64:7): [True: 9.48k, Folded]
  ------------------
   65|  9.48k|    if (!DecodeVarintUnsigned<IntTypeT>(1, out_val, buffer)) {
  ------------------
  |  Branch (65:9): [True: 185, False: 9.29k]
  ------------------
   66|    185|      return false;
   67|    185|    }
   68|  9.48k|  } else {
   69|       |    // IntTypeT is a signed value. Decode the symbol and convert to signed.
   70|      0|    typename std::make_unsigned<IntTypeT>::type symbol;
   71|      0|    if (!DecodeVarintUnsigned(1, &symbol, buffer)) {
  ------------------
  |  Branch (71:9): [True: 0, False: 0]
  ------------------
   72|      0|      return false;
   73|      0|    }
   74|      0|    *out_val = ConvertSymbolToSignedInt(symbol);
   75|      0|  }
   76|  9.29k|  return true;
   77|  9.48k|}
decoder_buffer.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedImEEbiPT_PNS_13DecoderBufferE:
   30|  5.69k|bool DecodeVarintUnsigned(int depth, IntTypeT* out_val, DecoderBuffer* buffer) {
   31|  5.69k|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|  5.69k|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 1, False: 5.69k]
  ------------------
   33|      1|    return false;
   34|      1|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|  5.69k|  uint8_t in;
   39|  5.69k|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 50, False: 5.64k]
  ------------------
   40|     50|    return false;
   41|     50|  }
   42|  5.64k|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 439, False: 5.20k]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|    439|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 39, False: 400]
  ------------------
   45|     39|      return false;
   46|     39|    }
   47|       |    // Append decoded info from this byte.
   48|    400|    *out_val <<= 7;
   49|    400|    *out_val |= in & ((1 << 7) - 1);
   50|  5.20k|  } else {
   51|       |    // Last byte reached
   52|  5.20k|    *out_val = in;
   53|  5.20k|  }
   54|  5.60k|  return true;
   55|  5.64k|}
metadata_decoder.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedIjEEbiPT_PNS_13DecoderBufferE:
   30|   221k|bool DecodeVarintUnsigned(int depth, IntTypeT* out_val, DecoderBuffer* buffer) {
   31|   221k|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|   221k|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 15, False: 221k]
  ------------------
   33|     15|    return false;
   34|     15|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|   221k|  uint8_t in;
   39|   221k|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 244, False: 221k]
  ------------------
   40|    244|    return false;
   41|    244|  }
   42|   221k|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 2.25k, False: 219k]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|  2.25k|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 102, False: 2.15k]
  ------------------
   45|    102|      return false;
   46|    102|    }
   47|       |    // Append decoded info from this byte.
   48|  2.15k|    *out_val <<= 7;
   49|  2.15k|    *out_val |= in & ((1 << 7) - 1);
   50|   219k|  } else {
   51|       |    // Last byte reached
   52|   219k|    *out_val = in;
   53|   219k|  }
   54|   221k|  return true;
   55|   221k|}
_ZN5draco12DecodeVarintIiEEbPT_PNS_13DecoderBufferE:
   63|  5.80k|bool DecodeVarint(IntTypeT* out_val, DecoderBuffer* buffer) {
   64|  5.80k|  if (std::is_unsigned<IntTypeT>::value) {
  ------------------
  |  Branch (64:7): [Folded, False: 5.80k]
  ------------------
   65|      0|    if (!DecodeVarintUnsigned<IntTypeT>(1, out_val, buffer)) {
  ------------------
  |  Branch (65:9): [True: 0, False: 0]
  ------------------
   66|      0|      return false;
   67|      0|    }
   68|  5.80k|  } else {
   69|       |    // IntTypeT is a signed value. Decode the symbol and convert to signed.
   70|  5.80k|    typename std::make_unsigned<IntTypeT>::type symbol;
   71|  5.80k|    if (!DecodeVarintUnsigned(1, &symbol, buffer)) {
  ------------------
  |  Branch (71:9): [True: 79, False: 5.72k]
  ------------------
   72|     79|      return false;
   73|     79|    }
   74|  5.72k|    *out_val = ConvertSymbolToSignedInt(symbol);
   75|  5.72k|  }
   76|  5.72k|  return true;
   77|  5.80k|}
kd_tree_attributes_decoder.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedIjEEbiPT_PNS_13DecoderBufferE:
   30|  6.30k|bool DecodeVarintUnsigned(int depth, IntTypeT* out_val, DecoderBuffer* buffer) {
   31|  6.30k|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|  6.30k|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 16, False: 6.29k]
  ------------------
   33|     16|    return false;
   34|     16|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|  6.29k|  uint8_t in;
   39|  6.29k|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 63, False: 6.22k]
  ------------------
   40|     63|    return false;
   41|     63|  }
   42|  6.22k|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 501, False: 5.72k]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|    501|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 97, False: 404]
  ------------------
   45|     97|      return false;
   46|     97|    }
   47|       |    // Append decoded info from this byte.
   48|    404|    *out_val <<= 7;
   49|    404|    *out_val |= in & ((1 << 7) - 1);
   50|  5.72k|  } else {
   51|       |    // Last byte reached
   52|  5.72k|    *out_val = in;
   53|  5.72k|  }
   54|  6.13k|  return true;
   55|  6.22k|}
sequential_integer_attribute_decoder.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedIjEEbiPT_PNS_13DecoderBufferE:
   30|  5.11k|bool DecodeVarintUnsigned(int depth, IntTypeT* out_val, DecoderBuffer* buffer) {
   31|  5.11k|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|  5.11k|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 2, False: 5.11k]
  ------------------
   33|      2|    return false;
   34|      2|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|  5.11k|  uint8_t in;
   39|  5.11k|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 30, False: 5.08k]
  ------------------
   40|     30|    return false;
   41|     30|  }
   42|  5.08k|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 856, False: 4.22k]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|    856|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 19, False: 837]
  ------------------
   45|     19|      return false;
   46|     19|    }
   47|       |    // Append decoded info from this byte.
   48|    837|    *out_val <<= 7;
   49|    837|    *out_val |= in & ((1 << 7) - 1);
   50|  4.22k|  } else {
   51|       |    // Last byte reached
   52|  4.22k|    *out_val = in;
   53|  4.22k|  }
   54|  5.06k|  return true;
   55|  5.08k|}
rans_bit_decoder.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedIjEEbiPT_PNS_13DecoderBufferE:
   30|  36.3k|bool DecodeVarintUnsigned(int depth, IntTypeT* out_val, DecoderBuffer* buffer) {
   31|  36.3k|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|  36.3k|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 7, False: 36.3k]
  ------------------
   33|      7|    return false;
   34|      7|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|  36.3k|  uint8_t in;
   39|  36.3k|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 42, False: 36.2k]
  ------------------
   40|     42|    return false;
   41|     42|  }
   42|  36.2k|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 662, False: 35.6k]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|    662|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 52, False: 610]
  ------------------
   45|     52|      return false;
   46|     52|    }
   47|       |    // Append decoded info from this byte.
   48|    610|    *out_val <<= 7;
   49|    610|    *out_val |= in & ((1 << 7) - 1);
   50|  35.6k|  } else {
   51|       |    // Last byte reached
   52|  35.6k|    *out_val = in;
   53|  35.6k|  }
   54|  36.2k|  return true;
   55|  36.2k|}
symbol_decoding.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedIjEEbiPT_PNS_13DecoderBufferE:
   30|  11.9k|bool DecodeVarintUnsigned(int depth, IntTypeT* out_val, DecoderBuffer* buffer) {
   31|  11.9k|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|  11.9k|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 94, False: 11.8k]
  ------------------
   33|     94|    return false;
   34|     94|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|  11.8k|  uint8_t in;
   39|  11.8k|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 150, False: 11.7k]
  ------------------
   40|    150|    return false;
   41|    150|  }
   42|  11.7k|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 2.88k, False: 8.85k]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|  2.88k|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 543, False: 2.33k]
  ------------------
   45|    543|      return false;
   46|    543|    }
   47|       |    // Append decoded info from this byte.
   48|  2.33k|    *out_val <<= 7;
   49|  2.33k|    *out_val |= in & ((1 << 7) - 1);
   50|  8.85k|  } else {
   51|       |    // Last byte reached
   52|  8.85k|    *out_val = in;
   53|  8.85k|  }
   54|  11.1k|  return true;
   55|  11.7k|}
symbol_decoding.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedImEEbiPT_PNS_13DecoderBufferE:
   30|  9.08k|bool DecodeVarintUnsigned(int depth, IntTypeT* out_val, DecoderBuffer* buffer) {
   31|  9.08k|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|  9.08k|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 53, False: 9.03k]
  ------------------
   33|     53|    return false;
   34|     53|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|  9.03k|  uint8_t in;
   39|  9.03k|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 81, False: 8.95k]
  ------------------
   40|     81|    return false;
   41|     81|  }
   42|  8.95k|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 4.86k, False: 4.08k]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|  4.86k|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 630, False: 4.23k]
  ------------------
   45|    630|      return false;
   46|    630|    }
   47|       |    // Append decoded info from this byte.
   48|  4.23k|    *out_val <<= 7;
   49|  4.23k|    *out_val |= in & ((1 << 7) - 1);
   50|  4.23k|  } else {
   51|       |    // Last byte reached
   52|  4.08k|    *out_val = in;
   53|  4.08k|  }
   54|  8.32k|  return true;
   55|  8.95k|}
attributes_decoder.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedIjEEbiPT_PNS_13DecoderBufferE:
   30|  46.3k|bool DecodeVarintUnsigned(int depth, IntTypeT* out_val, DecoderBuffer* buffer) {
   31|  46.3k|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|  46.3k|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 7, False: 46.3k]
  ------------------
   33|      7|    return false;
   34|      7|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|  46.3k|  uint8_t in;
   39|  46.3k|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 97, False: 46.2k]
  ------------------
   40|     97|    return false;
   41|     97|  }
   42|  46.2k|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 3.56k, False: 42.6k]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|  3.56k|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 65, False: 3.50k]
  ------------------
   45|     65|      return false;
   46|     65|    }
   47|       |    // Append decoded info from this byte.
   48|  3.50k|    *out_val <<= 7;
   49|  3.50k|    *out_val |= in & ((1 << 7) - 1);
   50|  42.6k|  } else {
   51|       |    // Last byte reached
   52|  42.6k|    *out_val = in;
   53|  42.6k|  }
   54|  46.1k|  return true;
   55|  46.2k|}

_ZN5draco7VectorDIfLi3EEC2Ev:
   42|  31.8k|  VectorD() {
   43|   127k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (43:21): [True: 95.5k, False: 31.8k]
  ------------------
   44|  95.5k|      (*this)[i] = Scalar(0);
   45|  95.5k|    }
   46|  31.8k|  }
_ZN5draco7VectorDIfLi3EEixEi:
  114|   154k|  Scalar& operator[](int i) { return v_[i]; }
_ZNK5draco7VectorDIfLi3EEixEi:
  115|   125k|  const Scalar& operator[](int i) const { return v_[i]; }
_ZN5draco7VectorDIjLi3EEixEi:
  114|  1.74G|  Scalar& operator[](int i) { return v_[i]; }
_ZN5draco7VectorDIfLi3EEC2ERKfS3_S3_:
   61|     73|      : v_({{c0, c1, c2}}) {
   62|     73|    DRACO_DCHECK_EQ(dimension, 3);
   63|     73|  }
_ZNK5draco7VectorDIlLi3EEixEi:
  115|   137M|  const Scalar& operator[](int i) const { return v_[i]; }
_ZNK5draco7VectorDIlLi3EEmiERKS1_:
  139|  15.1M|  Self operator-(const Self& o) const {
  140|  15.1M|    Self ret;
  141|  60.6M|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (141:21): [True: 45.5M, False: 15.1M]
  ------------------
  142|  45.5M|      ret[i] = (*this)[i] - o[i];
  143|  45.5M|    }
  144|  15.1M|    return ret;
  145|  15.1M|  }
_ZN5draco12CrossProductIlTnPNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std9is_signedIS3_EE5valueEvE4typeELPv0EEENS_7VectorDIS3_Li3EEERKS9_SB_:
  325|  7.55M|                                 const VectorD<ScalarT, 3>& v) {
  326|       |  // Preventing accidental use with uint32_t and the like.
  327|  7.55M|  static_assert(std::is_signed<ScalarT>::value,
  328|  7.55M|                "ScalarT must be a signed type. ");
  329|  7.55M|  VectorD<ScalarT, 3> r;
  330|  7.55M|  typedef typename std::make_unsigned<ScalarT>::type ScalarUT;
  331|  7.55M|  const ScalarUT u0 = static_cast<ScalarUT>(u[0]);
  332|  7.55M|  const ScalarUT u1 = static_cast<ScalarUT>(u[1]);
  333|  7.55M|  const ScalarUT u2 = static_cast<ScalarUT>(u[2]);
  334|  7.55M|  const ScalarUT v0 = static_cast<ScalarUT>(v[0]);
  335|  7.55M|  const ScalarUT v1 = static_cast<ScalarUT>(v[1]);
  336|  7.55M|  const ScalarUT v2 = static_cast<ScalarUT>(v[2]);
  337|  7.55M|  r[0] = static_cast<ScalarT>((u1 * v2) - (u2 * v1));
  338|  7.55M|  r[1] = static_cast<ScalarT>((u2 * v0) - (u0 * v2));
  339|  7.55M|  r[2] = static_cast<ScalarT>((u0 * v1) - (u1 * v0));
  340|  7.55M|  return r;
  341|  7.55M|}
_ZN5draco7VectorDIlLi3EE4dataEv:
  284|  7.55M|  Scalar* data() { return &(v_[0]); }
_ZNK5draco7VectorDIlLi3EE4dataEv:
  285|  7.55M|  const Scalar* data() const { return &(v_[0]); }
_ZNK5draco7VectorDIlLi3EE6AbsSumEv:
  239|  3.87M|  Scalar AbsSum() const {
  240|  3.87M|    Scalar result(0);
  241|  15.4M|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (241:21): [True: 11.6M, False: 3.85M]
  ------------------
  242|  11.6M|      Scalar next_value = std::abs(v_[i]);
  243|  11.6M|      if (result > std::numeric_limits<Scalar>::max() - next_value) {
  ------------------
  |  Branch (243:11): [True: 14.2k, False: 11.5M]
  ------------------
  244|       |        // Return the max if adding would have caused an overflow.
  245|  14.2k|        return std::numeric_limits<Scalar>::max();
  246|  14.2k|      }
  247|  11.5M|      result += next_value;
  248|  11.5M|    }
  249|  3.85M|    return result;
  250|  3.87M|  }
_ZNK5draco7VectorDIlLi3EEdvERKl:
  184|   243k|  Self operator/(const Scalar& o) const {
  185|   243k|    Self ret;
  186|   973k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (186:21): [True: 729k, False: 243k]
  ------------------
  187|   729k|      ret[i] = (*this)[i] / o;
  188|   729k|    }
  189|   243k|    return ret;
  190|   243k|  }
_ZN5draco7VectorDIlLi3EEixEi:
  114|   237M|  Scalar& operator[](int i) { return v_[i]; }
_ZN5draco7VectorDIiLi3EEixEi:
  114|  19.6M|  Scalar& operator[](int i) { return v_[i]; }
_ZN5draco7VectorDIiLi3EE4dataEv:
  284|  11.6M|  Scalar* data() { return &(v_[0]); }
_ZNK5draco7VectorDIiLi3EEngEv:
  122|  3.26M|  Self operator-() const {
  123|  3.26M|    Self ret;
  124|  13.0M|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (124:21): [True: 9.80M, False: 3.26M]
  ------------------
  125|  9.80M|      ret[i] = -(*this)[i];
  126|  9.80M|    }
  127|  3.26M|    return ret;
  128|  3.26M|  }
_ZNK5draco7VectorDIiLi3EEixEi:
  115|  9.80M|  const Scalar& operator[](int i) const { return v_[i]; }
_ZNK5draco7VectorDIjLi2EEmiERKS1_:
  139|  2.20M|  Self operator-(const Self& o) const {
  140|  2.20M|    Self ret;
  141|  6.62M|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (141:21): [True: 4.41M, False: 2.20M]
  ------------------
  142|  4.41M|      ret[i] = (*this)[i] - o[i];
  143|  4.41M|    }
  144|  2.20M|    return ret;
  145|  2.20M|  }
_ZN5draco7VectorDIjLi2EEixEi:
  114|  26.5M|  Scalar& operator[](int i) { return v_[i]; }
_ZNK5draco7VectorDIjLi2EEixEi:
  115|  39.7M|  const Scalar& operator[](int i) const { return v_[i]; }
_ZN5draco7VectorDIiLi2EEixEi:
  114|  52.3M|  Scalar& operator[](int i) { return v_[i]; }
_ZNK5draco7VectorDIjLi2EEplERKS1_:
  131|  4.41M|  Self operator+(const Self& o) const {
  132|  4.41M|    Self ret;
  133|  13.2M|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (133:21): [True: 8.83M, False: 4.41M]
  ------------------
  134|  8.83M|      ret[i] = (*this)[i] + o[i];
  135|  8.83M|    }
  136|  4.41M|    return ret;
  137|  4.41M|  }
_ZNK5draco7VectorDIiLi2EEixEi:
  115|  54.2M|  const Scalar& operator[](int i) const { return v_[i]; }
_ZNK5draco7VectorDIiLi2EEmiERKS1_:
  139|   971k|  Self operator-(const Self& o) const {
  140|   971k|    Self ret;
  141|  2.91M|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (141:21): [True: 1.94M, False: 971k]
  ------------------
  142|  1.94M|      ret[i] = (*this)[i] - o[i];
  143|  1.94M|    }
  144|   971k|    return ret;
  145|   971k|  }
_ZNK5draco7VectorDIiLi2EEplERKS1_:
  131|   971k|  Self operator+(const Self& o) const {
  132|   971k|    Self ret;
  133|  2.91M|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (133:21): [True: 1.94M, False: 971k]
  ------------------
  134|  1.94M|      ret[i] = (*this)[i] + o[i];
  135|  1.94M|    }
  136|   971k|    return ret;
  137|   971k|  }
_ZNK5draco7VectorDIfLi2EEeqERKS1_:
  208|   775k|  bool operator==(const Self& o) const {
  209|  2.31M|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (209:21): [True: 1.54M, False: 769k]
  ------------------
  210|  1.54M|      if ((*this)[i] != o[i]) {
  ------------------
  |  Branch (210:11): [True: 6.06k, False: 1.53M]
  ------------------
  211|  6.06k|        return false;
  212|  6.06k|      }
  213|  1.54M|    }
  214|   769k|    return true;
  215|   775k|  }
_ZNK5draco7VectorDIfLi2EEixEi:
  115|  9.30M|  const Scalar& operator[](int i) const { return v_[i]; }
_ZNK5draco7VectorDIfLi3EEmiERKS1_:
  139|  12.8k|  Self operator-(const Self& o) const {
  140|  12.8k|    Self ret;
  141|  51.5k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (141:21): [True: 38.6k, False: 12.8k]
  ------------------
  142|  38.6k|      ret[i] = (*this)[i] - o[i];
  143|  38.6k|    }
  144|  12.8k|    return ret;
  145|  12.8k|  }
_ZNK5draco7VectorDIfLi3EE11SquaredNormEv:
  236|  6.82k|  Scalar SquaredNorm() const { return this->Dot(*this); }
_ZNK5draco7VectorDIfLi3EE3DotERKS1_:
  252|  7.57k|  Scalar Dot(const Self& o) const {
  253|  7.57k|    Scalar ret(0);
  254|  30.3k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (254:21): [True: 22.7k, False: 7.57k]
  ------------------
  255|  22.7k|      ret += (*this)[i] * o[i];
  256|  22.7k|    }
  257|  7.57k|    return ret;
  258|  7.57k|  }
_ZNK5draco7VectorDIfLi3EEmlERKf:
  176|    756|  Self operator*(const Scalar& o) const {
  177|    756|    Self ret;
  178|  3.02k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (178:21): [True: 2.26k, False: 756]
  ------------------
  179|  2.26k|      ret[i] = (*this)[i] * o;
  180|  2.26k|    }
  181|    756|    return ret;
  182|    756|  }
_ZNK5draco7VectorDIfLi2EEmiERKS1_:
  139|  6.06k|  Self operator-(const Self& o) const {
  140|  6.06k|    Self ret;
  141|  18.1k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (141:21): [True: 12.1k, False: 6.06k]
  ------------------
  142|  12.1k|      ret[i] = (*this)[i] - o[i];
  143|  12.1k|    }
  144|  6.06k|    return ret;
  145|  6.06k|  }
_ZN5draco7VectorDIfLi2EEC2Ev:
   42|  12.1k|  VectorD() {
   43|  36.3k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (43:21): [True: 24.2k, False: 12.1k]
  ------------------
   44|  24.2k|      (*this)[i] = Scalar(0);
   45|  24.2k|    }
   46|  12.1k|  }
_ZN5draco7VectorDIfLi2EEC2ERKfS3_:
   54|  1.55M|  VectorD(const Scalar& c0, const Scalar& c1) : v_({{c0, c1}}) {
   55|  1.55M|    DRACO_DCHECK_EQ(dimension, 2);
   56|  1.55M|    v_[0] = c0;
   57|  1.55M|    v_[1] = c1;
   58|  1.55M|  }
_ZN5draco7VectorDIfLi2EEixEi:
  114|  48.4k|  Scalar& operator[](int i) { return v_[i]; }
_ZNK5draco7VectorDIlLi2EEeqERKS1_:
  208|   551k|  bool operator==(const Self& o) const {
  209|  1.53M|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (209:21): [True: 1.04M, False: 492k]
  ------------------
  210|  1.04M|      if ((*this)[i] != o[i]) {
  ------------------
  |  Branch (210:11): [True: 58.8k, False: 985k]
  ------------------
  211|  58.8k|        return false;
  212|  58.8k|      }
  213|  1.04M|    }
  214|   492k|    return true;
  215|   551k|  }
_ZNK5draco7VectorDIlLi2EEixEi:
  115|  3.07M|  const Scalar& operator[](int i) const { return v_[i]; }
_ZN5draco7VectorDIlLi3EEC2Ev:
   42|  45.9M|  VectorD() {
   43|   183M|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (43:21): [True: 137M, False: 45.9M]
  ------------------
   44|   137M|      (*this)[i] = Scalar(0);
   45|   137M|    }
   46|  45.9M|  }
_ZNK5draco7VectorDIlLi3EE11SquaredNormEv:
  236|  58.9k|  Scalar SquaredNorm() const { return this->Dot(*this); }
_ZNK5draco7VectorDIlLi3EE3DotERKS1_:
  252|  59.0k|  Scalar Dot(const Self& o) const {
  253|  59.0k|    Scalar ret(0);
  254|   236k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (254:21): [True: 177k, False: 59.0k]
  ------------------
  255|   177k|      ret += (*this)[i] * o[i];
  256|   177k|    }
  257|  59.0k|    return ret;
  258|  59.0k|  }
_ZNK5draco7VectorDIlLi2EEmiERKS1_:
  139|     84|  Self operator-(const Self& o) const {
  140|     84|    Self ret;
  141|    252|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (141:21): [True: 168, False: 84]
  ------------------
  142|    168|      ret[i] = (*this)[i] - o[i];
  143|    168|    }
  144|     84|    return ret;
  145|     84|  }
_ZN5draco7VectorDImLi2EEC2IlLi2EEERKNS0_IT_XT0_EEE:
  104|    270|  explicit VectorD(const VectorD<OtherScalarT, other_dimension_t>& src_vector) {
  105|    810|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (105:21): [True: 540, False: 270]
  ------------------
  106|    540|      if (i < other_dimension_t) {
  ------------------
  |  Branch (106:11): [True: 540, False: 0]
  ------------------
  107|    540|        v_[i] = Scalar(src_vector[i]);
  108|    540|      } else {
  109|      0|        v_[i] = Scalar(0);
  110|      0|      }
  111|    540|    }
  112|    270|  }
_ZNK5draco7VectorDImLi2EEmlERKm:
  176|    166|  Self operator*(const Scalar& o) const {
  177|    166|    Self ret;
  178|    498|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (178:21): [True: 332, False: 166]
  ------------------
  179|    332|      ret[i] = (*this)[i] * o;
  180|    332|    }
  181|    166|    return ret;
  182|    166|  }
_ZN5draco7VectorDImLi2EEC2Ev:
   42|    301|  VectorD() {
   43|    903|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (43:21): [True: 602, False: 301]
  ------------------
   44|    602|      (*this)[i] = Scalar(0);
   45|    602|    }
   46|    301|  }
_ZNK5draco7VectorDImLi2EEixEi:
  115|  1.14k|  const Scalar& operator[](int i) const { return v_[i]; }
_ZN5draco7VectorDImLi2EEixEi:
  114|  1.20k|  Scalar& operator[](int i) { return v_[i]; }
_ZNK5draco7VectorDImLi2EEplERKS1_:
  131|    123|  Self operator+(const Self& o) const {
  132|    123|    Self ret;
  133|    369|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (133:21): [True: 246, False: 123]
  ------------------
  134|    246|      ret[i] = (*this)[i] + o[i];
  135|    246|    }
  136|    123|    return ret;
  137|    123|  }
_ZN5draco7VectorDIlLi2EEC2ImLi2EEERKNS0_IT_XT0_EEE:
  104|    135|  explicit VectorD(const VectorD<OtherScalarT, other_dimension_t>& src_vector) {
  105|    405|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (105:21): [True: 270, False: 135]
  ------------------
  106|    270|      if (i < other_dimension_t) {
  ------------------
  |  Branch (106:11): [True: 270, False: 0]
  ------------------
  107|    270|        v_[i] = Scalar(src_vector[i]);
  108|    270|      } else {
  109|      0|        v_[i] = Scalar(0);
  110|      0|      }
  111|    270|    }
  112|    135|  }
_ZNK5draco7VectorDIlLi3EEplERKS1_:
  131|     83|  Self operator+(const Self& o) const {
  132|     83|    Self ret;
  133|    332|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (133:21): [True: 249, False: 83]
  ------------------
  134|    249|      ret[i] = (*this)[i] + o[i];
  135|    249|    }
  136|     83|    return ret;
  137|     83|  }
_ZN5dracomlIlLi3EEENS_7VectorDIT_XT0_EEERKS2_RKS3_:
  294|     83|    const ScalarT& o, const VectorD<ScalarT, dimension_t>& v) {
  295|     83|  return v * o;
  296|     83|}
_ZNK5draco7VectorDIlLi3EEmlERKl:
  176|     83|  Self operator*(const Scalar& o) const {
  177|     83|    Self ret;
  178|    332|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (178:21): [True: 249, False: 83]
  ------------------
  179|    249|      ret[i] = (*this)[i] * o;
  180|    249|    }
  181|     83|    return ret;
  182|     83|  }
_ZN5draco7VectorDIlLi2EEC2ERKlS3_:
   54|  1.10M|  VectorD(const Scalar& c0, const Scalar& c1) : v_({{c0, c1}}) {
   55|  1.10M|    DRACO_DCHECK_EQ(dimension, 2);
   56|  1.10M|    v_[0] = c0;
   57|  1.10M|    v_[1] = c1;
   58|  1.10M|  }
_ZNK5draco7VectorDIlLi2EEmlERKl:
  176|     83|  Self operator*(const Scalar& o) const {
  177|     83|    Self ret;
  178|    249|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (178:21): [True: 166, False: 83]
  ------------------
  179|    166|      ret[i] = (*this)[i] * o;
  180|    166|    }
  181|     83|    return ret;
  182|     83|  }
_ZN5draco7VectorDIlLi2EEC2Ev:
   42|    302|  VectorD() {
   43|    906|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (43:21): [True: 604, False: 302]
  ------------------
   44|    604|      (*this)[i] = Scalar(0);
   45|    604|    }
   46|    302|  }
_ZNK5draco7VectorDIlLi2EEdvERKl:
  184|     52|  Self operator/(const Scalar& o) const {
  185|     52|    Self ret;
  186|    156|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (186:21): [True: 104, False: 52]
  ------------------
  187|    104|      ret[i] = (*this)[i] / o;
  188|    104|    }
  189|     52|    return ret;
  190|     52|  }
_ZNK5draco7VectorDImLi2EEmiERKS1_:
  139|     12|  Self operator-(const Self& o) const {
  140|     12|    Self ret;
  141|     36|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (141:21): [True: 24, False: 12]
  ------------------
  142|     24|      ret[i] = (*this)[i] - o[i];
  143|     24|    }
  144|     12|    return ret;
  145|     12|  }
_ZN5draco7VectorDIlLi2EEixEi:
  114|  1.14k|  Scalar& operator[](int i) { return v_[i]; }
_ZN5draco7VectorDIiLi3EEC2Ev:
   42|  3.26M|  VectorD() {
   43|  13.0M|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (43:21): [True: 9.80M, False: 3.26M]
  ------------------
   44|  9.80M|      (*this)[i] = Scalar(0);
   45|  9.80M|    }
   46|  3.26M|  }
_ZN5draco7VectorDIiLi2EEC2ERKiS3_:
   54|  11.1M|  VectorD(const Scalar& c0, const Scalar& c1) : v_({{c0, c1}}) {
   55|  11.1M|    DRACO_DCHECK_EQ(dimension, 2);
   56|  11.1M|    v_[0] = c0;
   57|  11.1M|    v_[1] = c1;
   58|  11.1M|  }
_ZN5draco7VectorDIjLi2EEC2IiLi2EEERKNS0_IT_XT0_EEE:
  104|  13.2M|  explicit VectorD(const VectorD<OtherScalarT, other_dimension_t>& src_vector) {
  105|  39.7M|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (105:21): [True: 26.5M, False: 13.2M]
  ------------------
  106|  26.5M|      if (i < other_dimension_t) {
  ------------------
  |  Branch (106:11): [True: 26.5M, False: 0]
  ------------------
  107|  26.5M|        v_[i] = Scalar(src_vector[i]);
  108|  26.5M|      } else {
  109|      0|        v_[i] = Scalar(0);
  110|      0|      }
  111|  26.5M|    }
  112|  13.2M|  }
_ZN5draco7VectorDIjLi2EEC2Ev:
   42|  6.62M|  VectorD() {
   43|  19.8M|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (43:21): [True: 13.2M, False: 6.62M]
  ------------------
   44|  13.2M|      (*this)[i] = Scalar(0);
   45|  13.2M|    }
   46|  6.62M|  }
_ZN5draco7VectorDIiLi2EEC2IjLi2EEERKNS0_IT_XT0_EEE:
  104|  6.62M|  explicit VectorD(const VectorD<OtherScalarT, other_dimension_t>& src_vector) {
  105|  19.8M|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (105:21): [True: 13.2M, False: 6.62M]
  ------------------
  106|  13.2M|      if (i < other_dimension_t) {
  ------------------
  |  Branch (106:11): [True: 13.2M, False: 0]
  ------------------
  107|  13.2M|        v_[i] = Scalar(src_vector[i]);
  108|  13.2M|      } else {
  109|      0|        v_[i] = Scalar(0);
  110|      0|      }
  111|  13.2M|    }
  112|  6.62M|  }
_ZN5draco7VectorDIiLi2EEC2ERKS1_:
   90|  5.74M|  VectorD(const Self& o) {
   91|  17.2M|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (91:21): [True: 11.4M, False: 5.74M]
  ------------------
   92|  11.4M|      (*this)[i] = o[i];
   93|  11.4M|    }
   94|  5.74M|  }
_ZN5draco7VectorDIiLi2EEC2Ev:
   42|  1.94M|  VectorD() {
   43|  5.82M|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (43:21): [True: 3.88M, False: 1.94M]
  ------------------
   44|  3.88M|      (*this)[i] = Scalar(0);
   45|  3.88M|    }
   46|  1.94M|  }
_ZN5draco7VectorDIjLi3EEC2ERKS1_:
   90|   583M|  VectorD(const Self& o) {
   91|  2.33G|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (91:21): [True: 1.74G, False: 583M]
  ------------------
   92|  1.74G|      (*this)[i] = o[i];
   93|  1.74G|    }
   94|   583M|  }
_ZNK5draco7VectorDIjLi3EEixEi:
  115|  1.74G|  const Scalar& operator[](int i) const { return v_[i]; }
_ZN5draco7VectorDIjLi3EEC2ERKjS3_S3_:
   61|   242M|      : v_({{c0, c1, c2}}) {
   62|   242M|    DRACO_DCHECK_EQ(dimension, 3);
   63|   242M|  }

_ZN5draco11CornerTableC2Ev:
   26|  9.21k|    : num_original_vertices_(0),
   27|  9.21k|      num_degenerated_faces_(0),
   28|  9.21k|      num_isolated_vertices_(0),
   29|  9.21k|      valence_cache_(*this) {}
_ZN5draco11CornerTable5ResetEii:
   66|  9.21k|bool CornerTable::Reset(int num_faces, int num_vertices) {
   67|  9.21k|  if (num_faces < 0 || num_vertices < 0) {
  ------------------
  |  Branch (67:7): [True: 0, False: 9.21k]
  |  Branch (67:24): [True: 1, False: 9.20k]
  ------------------
   68|      1|    return false;
   69|      1|  }
   70|  9.20k|  const unsigned int num_faces_unsigned = num_faces;
   71|  9.20k|  if (num_faces_unsigned >
  ------------------
  |  Branch (71:7): [True: 0, False: 9.20k]
  ------------------
   72|  9.20k|      std::numeric_limits<CornerIndex::ValueType>::max() / 3) {
   73|      0|    return false;
   74|      0|  }
   75|  9.20k|  corner_to_vertex_map_.assign(num_faces_unsigned * 3, kInvalidVertexIndex);
   76|  9.20k|  opposite_corners_.assign(num_faces_unsigned * 3, kInvalidCornerIndex);
   77|  9.20k|  vertex_corners_.reserve(num_vertices);
   78|  9.20k|  valence_cache_.ClearValenceCache();
   79|  9.20k|  valence_cache_.ClearValenceCacheInaccurate();
   80|  9.20k|  return true;
   81|  9.20k|}

_ZNK5draco11CornerTable12num_verticesEv:
   73|   106M|  inline int num_vertices() const {
   74|   106M|    return static_cast<int>(vertex_corners_.size());
   75|   106M|  }
_ZNK5draco11CornerTable11num_cornersEv:
   76|  15.7M|  inline int num_corners() const {
   77|  15.7M|    return static_cast<int>(corner_to_vertex_map_.size());
   78|  15.7M|  }
_ZNK5draco11CornerTable9num_facesEv:
   79|  4.33M|  inline int num_faces() const {
   80|  4.33M|    return static_cast<int>(corner_to_vertex_map_.size() / 3);
   81|  4.33M|  }
_ZNK5draco11CornerTable8OppositeENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   83|   406M|  inline CornerIndex Opposite(CornerIndex corner) const {
   84|   406M|    if (corner == kInvalidCornerIndex) {
  ------------------
  |  Branch (84:9): [True: 0, False: 406M]
  ------------------
   85|      0|      return corner;
   86|      0|    }
   87|   406M|    return opposite_corners_[corner];
   88|   406M|  }
_ZNK5draco11CornerTable4NextENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   89|   636M|  inline CornerIndex Next(CornerIndex corner) const {
   90|   636M|    if (corner == kInvalidCornerIndex) {
  ------------------
  |  Branch (90:9): [True: 18.4M, False: 618M]
  ------------------
   91|  18.4M|      return corner;
   92|  18.4M|    }
   93|   618M|    return LocalIndex(++corner) ? corner : corner - 3;
  ------------------
  |  Branch (93:12): [True: 543M, False: 75.1M]
  ------------------
   94|   636M|  }
_ZNK5draco11CornerTable8PreviousENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   95|   585M|  inline CornerIndex Previous(CornerIndex corner) const {
   96|   585M|    if (corner == kInvalidCornerIndex) {
  ------------------
  |  Branch (96:9): [True: 7.62M, False: 578M]
  ------------------
   97|  7.62M|      return corner;
   98|  7.62M|    }
   99|   578M|    return LocalIndex(corner) ? corner - 1 : corner + 2;
  ------------------
  |  Branch (99:12): [True: 193M, False: 384M]
  ------------------
  100|   585M|  }
_ZNK5draco11CornerTable6VertexENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  101|   933M|  inline VertexIndex Vertex(CornerIndex corner) const {
  102|   933M|    if (corner == kInvalidCornerIndex) {
  ------------------
  |  Branch (102:9): [True: 0, False: 933M]
  ------------------
  103|      0|      return kInvalidVertexIndex;
  104|      0|    }
  105|   933M|    return ConfidentVertex(corner);
  106|   933M|  }
_ZNK5draco11CornerTable15ConfidentVertexENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  107|   933M|  inline VertexIndex ConfidentVertex(CornerIndex corner) const {
  108|   933M|    DRACO_DCHECK_GE(corner.value(), 0);
  109|   933M|    DRACO_DCHECK_LT(corner.value(), num_corners());
  110|   933M|    return corner_to_vertex_map_[corner];
  111|   933M|  }
_ZNK5draco11CornerTable4FaceENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  112|  62.3M|  inline FaceIndex Face(CornerIndex corner) const {
  113|  62.3M|    if (corner == kInvalidCornerIndex) {
  ------------------
  |  Branch (113:9): [True: 0, False: 62.3M]
  ------------------
  114|      0|      return kInvalidFaceIndex;
  115|      0|    }
  116|  62.3M|    return FaceIndex(corner.value() / 3);
  117|  62.3M|  }
_ZNK5draco11CornerTable10LocalIndexENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  128|  1.19G|  inline int LocalIndex(CornerIndex corner) const { return corner.value() % 3; }
_ZNK5draco11CornerTable14LeftMostCornerENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEE:
  150|  69.3M|  inline CornerIndex LeftMostCorner(VertexIndex v) const {
  151|  69.3M|    return vertex_corners_[v];
  152|  69.3M|  }
_ZNK5draco11CornerTable12IsOnBoundaryENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEE:
  185|  1.97M|  inline bool IsOnBoundary(VertexIndex vert) const {
  186|  1.97M|    const CornerIndex corner = LeftMostCorner(vert);
  187|  1.97M|    if (SwingLeft(corner) == kInvalidCornerIndex) {
  ------------------
  |  Branch (187:9): [True: 51.3k, False: 1.92M]
  ------------------
  188|  51.3k|      return true;
  189|  51.3k|    }
  190|  1.92M|    return false;
  191|  1.97M|  }
_ZNK5draco11CornerTable10SwingRightENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  200|   113M|  inline CornerIndex SwingRight(CornerIndex corner) const {
  201|   113M|    return Previous(Opposite(Previous(corner)));
  202|   113M|  }
_ZNK5draco11CornerTable9SwingLeftENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  205|  22.9M|  inline CornerIndex SwingLeft(CornerIndex corner) const {
  206|  22.9M|    return Next(Opposite(Next(corner)));
  207|  22.9M|  }
_ZNK5draco11CornerTable13GetLeftCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  217|  4.94M|  inline CornerIndex GetLeftCorner(CornerIndex corner_id) const {
  218|  4.94M|    if (corner_id == kInvalidCornerIndex) {
  ------------------
  |  Branch (218:9): [True: 0, False: 4.94M]
  ------------------
  219|      0|      return kInvalidCornerIndex;
  220|      0|    }
  221|  4.94M|    return Opposite(Previous(corner_id));
  222|  4.94M|  }
_ZNK5draco11CornerTable14GetRightCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  223|  6.87M|  inline CornerIndex GetRightCorner(CornerIndex corner_id) const {
  224|  6.87M|    if (corner_id == kInvalidCornerIndex) {
  ------------------
  |  Branch (224:9): [True: 0, False: 6.87M]
  ------------------
  225|      0|      return kInvalidCornerIndex;
  226|      0|    }
  227|  6.87M|    return Opposite(Next(corner_id));
  228|  6.87M|  }
_ZN5draco11CornerTable17SetOppositeCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEES3_:
  248|   351M|                                CornerIndex opp_corner_id) {
  249|   351M|    DRACO_DCHECK(GetValenceCache().IsCacheEmpty());
  250|   351M|    opposite_corners_[corner_id] = opp_corner_id;
  251|   351M|  }
_ZN5draco11CornerTable17MapCornerToVertexENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEENS1_IjNS_21VertexIndex_tag_type_EEE:
  265|   418M|  inline void MapCornerToVertex(CornerIndex corner_id, VertexIndex vert_id) {
  266|   418M|    DRACO_DCHECK(GetValenceCache().IsCacheEmpty());
  267|   418M|    corner_to_vertex_map_[corner_id] = vert_id;
  268|   418M|  }
_ZN5draco11CornerTable12AddNewVertexEv:
  270|   104M|  VertexIndex AddNewVertex() {
  271|   104M|    DRACO_DCHECK(GetValenceCache().IsCacheEmpty());
  272|       |    // Add a new invalid vertex.
  273|   104M|    vertex_corners_.push_back(kInvalidCornerIndex);
  274|   104M|    return VertexIndex(static_cast<uint32_t>(vertex_corners_.size() - 1));
  275|   104M|  }
_ZN5draco11CornerTable17SetLeftMostCornerENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEENS1_IjNS_21CornerIndex_tag_type_EEE:
  292|   227M|  void SetLeftMostCorner(VertexIndex vert, CornerIndex corner) {
  293|   227M|    DRACO_DCHECK(GetValenceCache().IsCacheEmpty());
  294|   227M|    if (vert != kInvalidVertexIndex) {
  ------------------
  |  Branch (294:9): [True: 227M, False: 0]
  ------------------
  295|   227M|      vertex_corners_[vert] = corner;
  296|   227M|    }
  297|   227M|  }
_ZN5draco11CornerTable18MakeVertexIsolatedENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEE:
  328|  1.17M|  void MakeVertexIsolated(VertexIndex vert) {
  329|  1.17M|    DRACO_DCHECK(GetValenceCache().IsCacheEmpty());
  330|  1.17M|    vertex_corners_[vert] = kInvalidCornerIndex;
  331|  1.17M|  }

_ZN5draco21VertexCornersIteratorINS_11CornerTableEEC2EPKS1_NS_9IndexTypeIjNS_21VertexIndex_tag_type_EEE:
  228|  3.08k|      : corner_table_(table),
  229|  3.08k|        start_corner_(table->LeftMostCorner(vert_id)),
  230|  3.08k|        corner_(start_corner_),
  231|  3.08k|        left_traversal_(true) {}
_ZNK5draco21VertexCornersIteratorINS_11CornerTableEE3EndEv:
  244|  4.19M|  bool End() const { return corner_ == kInvalidCornerIndex; }
_ZN5draco21VertexCornersIteratorINS_11CornerTableEEppEv:
  267|  11.0k|  VertexCornersIterator& operator++() {
  268|  11.0k|    Next();
  269|  11.0k|    return *this;
  270|  11.0k|  }
_ZN5draco21VertexCornersIteratorINS_11CornerTableEE4NextEv:
  247|  3.58M|  void Next() {
  248|  3.58M|    if (left_traversal_) {
  ------------------
  |  Branch (248:9): [True: 3.56M, False: 24.4k]
  ------------------
  249|  3.56M|      corner_ = corner_table_->SwingLeft(corner_);
  250|  3.56M|      if (corner_ == kInvalidCornerIndex) {
  ------------------
  |  Branch (250:11): [True: 21.1k, False: 3.53M]
  ------------------
  251|       |        // Open boundary reached.
  252|  21.1k|        corner_ = corner_table_->SwingRight(start_corner_);
  253|  21.1k|        left_traversal_ = false;
  254|  3.53M|      } else if (corner_ == start_corner_) {
  ------------------
  |  Branch (254:18): [True: 589k, False: 2.94M]
  ------------------
  255|       |        // End reached.
  256|   589k|        corner_ = kInvalidCornerIndex;
  257|   589k|      }
  258|  3.56M|    } else {
  259|       |      // Go to the right until we reach a boundary there (no explicit check
  260|       |      // is needed in this case).
  261|  24.4k|      corner_ = corner_table_->SwingRight(corner_);
  262|  24.4k|    }
  263|  3.58M|  }
_ZNK5draco21VertexCornersIteratorINS_11CornerTableEE6CornerEv:
  241|  7.15M|  CornerIndex Corner() const { return corner_; }
_ZNK5draco21VertexCornersIteratorINS_24MeshAttributeCornerTableEE3EndEv:
  244|  7.24M|  bool End() const { return corner_ == kInvalidCornerIndex; }
_ZNK5draco21VertexCornersIteratorINS_24MeshAttributeCornerTableEE6CornerEv:
  241|  7.95M|  CornerIndex Corner() const { return corner_; }
_ZN5draco21VertexCornersIteratorINS_24MeshAttributeCornerTableEE4NextEv:
  247|  3.98M|  void Next() {
  248|  3.98M|    if (left_traversal_) {
  ------------------
  |  Branch (248:9): [True: 3.94M, False: 34.4k]
  ------------------
  249|  3.94M|      corner_ = corner_table_->SwingLeft(corner_);
  250|  3.94M|      if (corner_ == kInvalidCornerIndex) {
  ------------------
  |  Branch (250:11): [True: 3.13M, False: 814k]
  ------------------
  251|       |        // Open boundary reached.
  252|  3.13M|        corner_ = corner_table_->SwingRight(start_corner_);
  253|  3.13M|        left_traversal_ = false;
  254|  3.13M|      } else if (corner_ == start_corner_) {
  ------------------
  |  Branch (254:18): [True: 132k, False: 681k]
  ------------------
  255|       |        // End reached.
  256|   132k|        corner_ = kInvalidCornerIndex;
  257|   132k|      }
  258|  3.94M|    } else {
  259|       |      // Go to the right until we reach a boundary there (no explicit check
  260|       |      // is needed in this case).
  261|  34.4k|      corner_ = corner_table_->SwingRight(corner_);
  262|  34.4k|    }
  263|  3.98M|  }
_ZN5draco21VertexCornersIteratorINS_24MeshAttributeCornerTableEEC2EPKS1_NS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  235|  3.26M|      : corner_table_(table),
  236|  3.26M|        start_corner_(corner_id),
  237|  3.26M|        corner_(start_corner_),
  238|  3.26M|        left_traversal_(true) {}
_ZN5draco21VertexCornersIteratorINS_11CornerTableEEC2EPKS1_NS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  235|   607k|      : corner_table_(table),
  236|   607k|        start_corner_(corner_id),
  237|   607k|        corner_(start_corner_),
  238|   607k|        left_traversal_(true) {}

_ZN5draco4MeshC2Ev:
   33|  16.3k|Mesh::Mesh() {}

_ZN5draco4Mesh7AddFaceERKNSt3__15arrayINS_9IndexTypeIjNS_20PointIndex_tag_type_EEELm3EEE:
   74|  4.17k|  void AddFace(const Face& face) { faces_.push_back(face); }
_ZN5draco4Mesh7SetFaceENS_9IndexTypeIjNS_19FaceIndex_tag_type_EEERKNSt3__15arrayINS1_IjNS_20PointIndex_tag_type_EEELm3EEE:
   76|  15.4M|  void SetFace(FaceIndex face_id, const Face& face) {
   77|  15.4M|    if (face_id >= static_cast<uint32_t>(faces_.size())) {
  ------------------
  |  Branch (77:9): [True: 0, False: 15.4M]
  ------------------
   78|      0|      faces_.resize(face_id.value() + 1, Face());
   79|      0|    }
   80|  15.4M|    faces_[face_id] = face;
   81|  15.4M|  }
_ZN5draco4Mesh11SetNumFacesEm:
   85|  5.02k|  void SetNumFaces(size_t num_faces) { faces_.resize(num_faces, Face()); }
_ZNK5draco4Mesh9num_facesEv:
   87|  15.4M|  FaceIndex::ValueType num_faces() const {
   88|  15.4M|    return static_cast<uint32_t>(faces_.size());
   89|  15.4M|  }
_ZNK5draco4Mesh4faceENS_9IndexTypeIjNS_19FaceIndex_tag_type_EEE:
   90|  37.8M|  const Face& face(FaceIndex face_id) const {
   91|  37.8M|    DRACO_DCHECK_LE(0, face_id.value());
   92|  37.8M|    DRACO_DCHECK_LT(face_id.value(), static_cast<int>(faces_.size()));
   93|  37.8M|    return faces_[face_id];
   94|  37.8M|  }
_ZN5draco4Mesh12SetAttributeEiNSt3__110unique_ptrINS_14PointAttributeENS1_14default_deleteIS3_EEEE:
   96|  21.0k|  void SetAttribute(int att_id, std::unique_ptr<PointAttribute> pa) override {
   97|  21.0k|    PointCloud::SetAttribute(att_id, std::move(pa));
   98|  21.0k|    if (static_cast<int>(attribute_data_.size()) <= att_id) {
  ------------------
  |  Branch (98:9): [True: 21.0k, False: 0]
  ------------------
   99|  21.0k|      attribute_data_.resize(att_id + 1);
  100|  21.0k|    }
  101|  21.0k|  }
_ZN5draco4Mesh13AttributeDataC2Ev:
  170|  21.0k|    AttributeData() : element_type(MESH_CORNER_ATTRIBUTE) {}

_ZN5draco24MeshAttributeCornerTableC2Ev:
   23|  46.6k|    : no_interior_seams_(true), corner_table_(nullptr), valence_cache_(*this) {}
_ZN5draco24MeshAttributeCornerTable9InitEmptyEPKNS_11CornerTableE:
   25|  9.30k|bool MeshAttributeCornerTable::InitEmpty(const CornerTable* table) {
   26|  9.30k|  if (table == nullptr) {
  ------------------
  |  Branch (26:7): [True: 0, False: 9.30k]
  ------------------
   27|      0|    return false;
   28|      0|  }
   29|  9.30k|  valence_cache_.ClearValenceCache();
   30|  9.30k|  valence_cache_.ClearValenceCacheInaccurate();
   31|  9.30k|  is_edge_on_seam_.assign(table->num_corners(), false);
   32|  9.30k|  is_vertex_on_seam_.assign(table->num_vertices(), false);
   33|  9.30k|  corner_to_vertex_map_.assign(table->num_corners(), kInvalidVertexIndex);
   34|  9.30k|  vertex_to_attribute_entry_id_map_.reserve(table->num_vertices());
   35|  9.30k|  vertex_to_left_most_corner_map_.reserve(table->num_vertices());
   36|  9.30k|  corner_table_ = table;
   37|  9.30k|  no_interior_seams_ = true;
   38|  9.30k|  return true;
   39|  9.30k|}
_ZN5draco24MeshAttributeCornerTable11AddSeamEdgeENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  108|  23.5M|void MeshAttributeCornerTable::AddSeamEdge(CornerIndex c) {
  109|  23.5M|  DRACO_DCHECK(GetValenceCache().IsCacheEmpty());
  110|  23.5M|  is_edge_on_seam_[c.value()] = true;
  111|       |  // Mark seam vertices.
  112|  23.5M|  is_vertex_on_seam_[corner_table_->Vertex(corner_table_->Next(c)).value()] =
  113|  23.5M|      true;
  114|  23.5M|  is_vertex_on_seam_[corner_table_->Vertex(corner_table_->Previous(c))
  115|  23.5M|                         .value()] = true;
  116|       |
  117|  23.5M|  const CornerIndex opp_corner = corner_table_->Opposite(c);
  118|  23.5M|  if (opp_corner != kInvalidCornerIndex) {
  ------------------
  |  Branch (118:7): [True: 22.9M, False: 617k]
  ------------------
  119|  22.9M|    no_interior_seams_ = false;
  120|  22.9M|    is_edge_on_seam_[opp_corner.value()] = true;
  121|  22.9M|    is_vertex_on_seam_[corner_table_->Vertex(corner_table_->Next(opp_corner))
  122|  22.9M|                           .value()] = true;
  123|  22.9M|    is_vertex_on_seam_
  124|  22.9M|        [corner_table_->Vertex(corner_table_->Previous(opp_corner)).value()] =
  125|  22.9M|            true;
  126|  22.9M|  }
  127|  23.5M|}
_ZN5draco24MeshAttributeCornerTable17RecomputeVerticesEPKNS_4MeshEPKNS_14PointAttributeE:
  130|  9.30k|                                                 const PointAttribute* att) {
  131|  9.30k|  DRACO_DCHECK(GetValenceCache().IsCacheEmpty());
  132|  9.30k|  if (mesh != nullptr && att != nullptr) {
  ------------------
  |  Branch (132:7): [True: 0, False: 9.30k]
  |  Branch (132:26): [True: 0, False: 0]
  ------------------
  133|      0|    return RecomputeVerticesInternal<true>(mesh, att);
  134|  9.30k|  } else {
  135|  9.30k|    return RecomputeVerticesInternal<false>(nullptr, nullptr);
  136|  9.30k|  }
  137|  9.30k|}
_ZN5draco24MeshAttributeCornerTable25RecomputeVerticesInternalILb0EEEbPKNS_4MeshEPKNS_14PointAttributeE:
  141|  9.30k|    const Mesh* mesh, const PointAttribute* att) {
  142|  9.30k|  DRACO_DCHECK(GetValenceCache().IsCacheEmpty());
  143|  9.30k|  vertex_to_attribute_entry_id_map_.clear();
  144|  9.30k|  vertex_to_left_most_corner_map_.clear();
  145|  9.30k|  int num_new_vertices = 0;
  146|  9.47M|  for (VertexIndex v(0); v < corner_table_->num_vertices(); ++v) {
  ------------------
  |  Branch (146:26): [True: 9.46M, False: 9.30k]
  ------------------
  147|  9.46M|    const CornerIndex c = corner_table_->LeftMostCorner(v);
  148|  9.46M|    if (c == kInvalidCornerIndex) {
  ------------------
  |  Branch (148:9): [True: 75.8k, False: 9.38M]
  ------------------
  149|  75.8k|      continue;  // Isolated vertex?
  150|  75.8k|    }
  151|  9.38M|    AttributeValueIndex first_vert_id(num_new_vertices++);
  152|  9.38M|    if (init_vertex_to_attribute_entry_map) {
  ------------------
  |  Branch (152:9): [Folded, False: 9.38M]
  ------------------
  153|      0|      const PointIndex point_id = mesh->CornerToPointId(c.value());
  154|      0|      vertex_to_attribute_entry_id_map_.push_back(att->mapped_index(point_id));
  155|  9.38M|    } else {
  156|       |      // Identity mapping
  157|  9.38M|      vertex_to_attribute_entry_id_map_.push_back(first_vert_id);
  158|  9.38M|    }
  159|  9.38M|    CornerIndex first_c = c;
  160|  9.38M|    CornerIndex act_c;
  161|       |    // Check if the vertex is on a seam edge, if it is we need to find the first
  162|       |    // attribute entry on the seam edge when traversing in the CCW direction.
  163|  9.38M|    if (is_vertex_on_seam_[v.value()]) {
  ------------------
  |  Branch (163:9): [True: 8.39M, False: 994k]
  ------------------
  164|       |      // Try to swing left on the modified corner table. We need to get the
  165|       |      // first corner that defines an attribute seam.
  166|  8.39M|      act_c = SwingLeft(first_c);
  167|  8.58M|      while (act_c != kInvalidCornerIndex) {
  ------------------
  |  Branch (167:14): [True: 189k, False: 8.39M]
  ------------------
  168|   189k|        first_c = act_c;
  169|   189k|        act_c = SwingLeft(act_c);
  170|   189k|        if (act_c == c) {
  ------------------
  |  Branch (170:13): [True: 0, False: 189k]
  ------------------
  171|       |          // We reached the initial corner which shouldn't happen when we swing
  172|       |          // left from |c|.
  173|      0|          return false;
  174|      0|        }
  175|   189k|      }
  176|  8.39M|    }
  177|  9.38M|    corner_to_vertex_map_[first_c.value()] = VertexIndex(first_vert_id.value());
  178|  9.38M|    vertex_to_left_most_corner_map_.push_back(first_c);
  179|  9.38M|    act_c = corner_table_->SwingRight(first_c);
  180|  53.8M|    while (act_c != kInvalidCornerIndex && act_c != first_c) {
  ------------------
  |  Branch (180:12): [True: 53.1M, False: 622k]
  |  Branch (180:44): [True: 44.4M, False: 8.76M]
  ------------------
  181|  44.4M|      if (IsCornerOppositeToSeamEdge(corner_table_->Next(act_c))) {
  ------------------
  |  Branch (181:11): [True: 38.4M, False: 6.01M]
  ------------------
  182|  38.4M|        first_vert_id = AttributeValueIndex(num_new_vertices++);
  183|  38.4M|        if (init_vertex_to_attribute_entry_map) {
  ------------------
  |  Branch (183:13): [Folded, False: 38.4M]
  ------------------
  184|      0|          const PointIndex point_id = mesh->CornerToPointId(act_c.value());
  185|      0|          vertex_to_attribute_entry_id_map_.push_back(
  186|      0|              att->mapped_index(point_id));
  187|  38.4M|        } else {
  188|       |          // Identity mapping.
  189|  38.4M|          vertex_to_attribute_entry_id_map_.push_back(first_vert_id);
  190|  38.4M|        }
  191|  38.4M|        vertex_to_left_most_corner_map_.push_back(act_c);
  192|  38.4M|      }
  193|  44.4M|      corner_to_vertex_map_[act_c.value()] = VertexIndex(first_vert_id.value());
  194|  44.4M|      act_c = corner_table_->SwingRight(act_c);
  195|  44.4M|    }
  196|  9.38M|  }
  197|  9.30k|  return true;
  198|  9.30k|}

_ZNK5draco24MeshAttributeCornerTable26IsCornerOppositeToSeamEdgeENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   45|  87.8M|  inline bool IsCornerOppositeToSeamEdge(CornerIndex corner) const {
   46|  87.8M|    return is_edge_on_seam_[corner.value()];
   47|  87.8M|  }
_ZNK5draco24MeshAttributeCornerTable8OppositeENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   49|  43.4M|  inline CornerIndex Opposite(CornerIndex corner) const {
   50|  43.4M|    if (corner == kInvalidCornerIndex || IsCornerOppositeToSeamEdge(corner)) {
  ------------------
  |  Branch (50:9): [True: 0, False: 43.4M]
  |  Branch (50:42): [True: 37.6M, False: 5.80M]
  ------------------
   51|  37.6M|      return kInvalidCornerIndex;
   52|  37.6M|    }
   53|  5.80M|    return corner_table_->Opposite(corner);
   54|  43.4M|  }
_ZNK5draco24MeshAttributeCornerTable4NextENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   56|  60.6M|  inline CornerIndex Next(CornerIndex corner) const {
   57|  60.6M|    return corner_table_->Next(corner);
   58|  60.6M|  }
_ZNK5draco24MeshAttributeCornerTable8PreviousENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   60|  36.7M|  inline CornerIndex Previous(CornerIndex corner) const {
   61|  36.7M|    return corner_table_->Previous(corner);
   62|  36.7M|  }
_ZNK5draco24MeshAttributeCornerTable14IsCornerOnSeamENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   65|  7.63M|  inline bool IsCornerOnSeam(CornerIndex corner) const {
   66|  7.63M|    return is_vertex_on_seam_[corner_table_->Vertex(corner).value()];
   67|  7.63M|  }
_ZNK5draco24MeshAttributeCornerTable13GetLeftCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   71|  5.26M|  inline CornerIndex GetLeftCorner(CornerIndex corner) const {
   72|  5.26M|    return Opposite(Previous(corner));
   73|  5.26M|  }
_ZNK5draco24MeshAttributeCornerTable14GetRightCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   74|  5.86M|  inline CornerIndex GetRightCorner(CornerIndex corner) const {
   75|  5.86M|    return Opposite(Next(corner));
   76|  5.86M|  }
_ZNK5draco24MeshAttributeCornerTable10SwingRightENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   79|  7.39M|  inline CornerIndex SwingRight(CornerIndex corner) const {
   80|  7.39M|    return Previous(Opposite(Previous(corner)));
   81|  7.39M|  }
_ZNK5draco24MeshAttributeCornerTable9SwingLeftENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   84|  19.0M|  inline CornerIndex SwingLeft(CornerIndex corner) const {
   85|  19.0M|    return Next(Opposite(Next(corner)));
   86|  19.0M|  }
_ZNK5draco24MeshAttributeCornerTable12num_verticesEv:
   88|  13.5k|  int num_vertices() const {
   89|  13.5k|    return static_cast<int>(vertex_to_attribute_entry_id_map_.size());
   90|  13.5k|  }
_ZNK5draco24MeshAttributeCornerTable9num_facesEv:
   91|  4.21k|  int num_faces() const { return static_cast<int>(corner_table_->num_faces()); }
_ZNK5draco24MeshAttributeCornerTable11num_cornersEv:
   92|  1.96k|  int num_corners() const { return corner_table_->num_corners(); }
_ZNK5draco24MeshAttributeCornerTable6VertexENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   94|   155M|  VertexIndex Vertex(CornerIndex corner) const {
   95|   155M|    DRACO_DCHECK_LT(corner.value(), corner_to_vertex_map_.size());
   96|   155M|    return ConfidentVertex(corner);
   97|   155M|  }
_ZNK5draco24MeshAttributeCornerTable15ConfidentVertexENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   98|   155M|  VertexIndex ConfidentVertex(CornerIndex corner) const {
   99|   155M|    return corner_to_vertex_map_[corner.value()];
  100|   155M|  }
_ZNK5draco24MeshAttributeCornerTable14LeftMostCornerENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEE:
  106|  5.24M|  inline CornerIndex LeftMostCorner(VertexIndex v) const {
  107|  5.24M|    return vertex_to_left_most_corner_map_[v.value()];
  108|  5.24M|  }
_ZNK5draco24MeshAttributeCornerTable12IsOnBoundaryENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEE:
  122|  5.24M|  inline bool IsOnBoundary(VertexIndex vert) const {
  123|  5.24M|    const CornerIndex corner = LeftMostCorner(vert);
  124|  5.24M|    if (corner == kInvalidCornerIndex) {
  ------------------
  |  Branch (124:9): [True: 0, False: 5.24M]
  ------------------
  125|      0|      return true;
  126|      0|    }
  127|  5.24M|    if (SwingLeft(corner) == kInvalidCornerIndex) {
  ------------------
  |  Branch (127:9): [True: 4.63M, False: 602k]
  ------------------
  128|  4.63M|      return true;
  129|  4.63M|    }
  130|   602k|    return false;
  131|  5.24M|  }

_ZN5draco12ValenceCacheINS_11CornerTableEEC2ERKS1_:
   35|  9.21k|  explicit ValenceCache(const CornerTableT& table) : table_(table) {}
_ZNK5draco12ValenceCacheINS_11CornerTableEE17ClearValenceCacheEv:
  123|  9.20k|  void ClearValenceCache() const {
  124|  9.20k|    vertex_valence_cache_32_bit_.clear();
  125|       |    // Force erasure.
  126|  9.20k|    IndexTypeVector<VertexIndex, int32_t>().swap(vertex_valence_cache_32_bit_);
  127|  9.20k|  }
_ZNK5draco12ValenceCacheINS_11CornerTableEE27ClearValenceCacheInaccurateEv:
  118|  9.20k|  void ClearValenceCacheInaccurate() const {
  119|  9.20k|    vertex_valence_cache_8_bit_.clear();
  120|       |    // Force erasure.
  121|  9.20k|    IndexTypeVector<VertexIndex, int8_t>().swap(vertex_valence_cache_8_bit_);
  122|  9.20k|  }
_ZN5draco12ValenceCacheINS_24MeshAttributeCornerTableEEC2ERKS1_:
   35|  46.6k|  explicit ValenceCache(const CornerTableT& table) : table_(table) {}
_ZNK5draco12ValenceCacheINS_24MeshAttributeCornerTableEE17ClearValenceCacheEv:
  123|  9.30k|  void ClearValenceCache() const {
  124|  9.30k|    vertex_valence_cache_32_bit_.clear();
  125|       |    // Force erasure.
  126|  9.30k|    IndexTypeVector<VertexIndex, int32_t>().swap(vertex_valence_cache_32_bit_);
  127|  9.30k|  }
_ZNK5draco12ValenceCacheINS_24MeshAttributeCornerTableEE27ClearValenceCacheInaccurateEv:
  118|  9.30k|  void ClearValenceCacheInaccurate() const {
  119|  9.30k|    vertex_valence_cache_8_bit_.clear();
  120|       |    // Force erasure.
  121|  9.30k|    IndexTypeVector<VertexIndex, int8_t>().swap(vertex_valence_cache_8_bit_);
  122|  9.30k|  }

_ZN5draco16GeometryMetadata20AddAttributeMetadataENSt3__110unique_ptrINS_17AttributeMetadataENS1_14default_deleteIS3_EEEE:
   50|  1.15k|    std::unique_ptr<AttributeMetadata> att_metadata) {
   51|  1.15k|  if (!att_metadata) {
  ------------------
  |  Branch (51:7): [True: 0, False: 1.15k]
  ------------------
   52|      0|    return false;
   53|      0|  }
   54|  1.15k|  att_metadatas_.push_back(std::move(att_metadata));
   55|  1.15k|  return true;
   56|  1.15k|}

_ZN5draco17AttributeMetadataC2Ev:
   27|  1.81k|  AttributeMetadata() : att_unique_id_(0) {}
_ZN5draco17AttributeMetadata17set_att_unique_idEj:
   32|  1.81k|  void set_att_unique_id(uint32_t att_unique_id) {
   33|  1.81k|    att_unique_id_ = att_unique_id;
   34|  1.81k|  }
_ZN5draco16GeometryMetadataC2Ev:
   60|  1.16k|  GeometryMetadata() {}

_ZN5draco10EntryValueC2ERKS0_:
   21|   197k|EntryValue::EntryValue(const EntryValue& value) {
   22|   197k|  data_.resize(value.data_.size());
   23|   197k|  memcpy(&data_[0], &value.data_[0], value.data_.size());
   24|   197k|}
_ZN5draco8Metadata14AddEntryBinaryERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEERKNS1_6vectorIhNS5_IhEEEE:
   97|  98.5k|                              const std::vector<uint8_t>& value) {
   98|  98.5k|  AddEntry(name, value);
   99|  98.5k|}
_ZN5draco8Metadata14AddSubMetadataERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS1_10unique_ptrIS0_NS1_14default_deleteIS0_EEEE:
  107|  57.0k|                              std::unique_ptr<Metadata> sub_metadata) {
  108|  57.0k|  auto sub_ptr = sub_metadatas_.find(name);
  109|       |  // Avoid accidentally writing over a sub-metadata with the same name.
  110|  57.0k|  if (sub_ptr != sub_metadatas_.end()) {
  ------------------
  |  Branch (110:7): [True: 26, False: 56.9k]
  ------------------
  111|     26|    return false;
  112|     26|  }
  113|  56.9k|  sub_metadatas_[name] = std::move(sub_metadata);
  114|  56.9k|  return true;
  115|  57.0k|}

_ZN5draco8MetadataC2Ev:
   98|  60.0k|  Metadata() {}
_ZN5draco8Metadata8AddEntryINSt3__16vectorIhNS2_9allocatorIhEEEEEEvRKNS2_12basic_stringIcNS2_11char_traitsIcEENS4_IcEEEERKT_:
  164|  98.5k|  void AddEntry(const std::string& entry_name, const DataTypeT& entry_value) {
  165|  98.5k|    const auto itr = entries_.find(entry_name);
  166|  98.5k|    if (itr != entries_.end()) {
  ------------------
  |  Branch (166:9): [True: 79.9k, False: 18.5k]
  ------------------
  167|  79.9k|      entries_.erase(itr);
  168|  79.9k|    }
  169|  98.5k|    entries_.insert(std::make_pair(entry_name, EntryValue(entry_value)));
  170|  98.5k|  }
_ZN5draco10EntryValueC2IhEERKNSt3__16vectorIT_NS2_9allocatorIS4_EEEE:
   41|  98.5k|  explicit EntryValue(const std::vector<DataTypeT>& data) {
   42|  98.5k|    const size_t total_size = sizeof(DataTypeT) * data.size();
   43|  98.5k|    data_.resize(total_size);
   44|  98.5k|    memcpy(&data_[0], &data[0], total_size);
   45|  98.5k|  }

_ZN5draco15MetadataDecoderC2Ev:
   23|  1.16k|MetadataDecoder::MetadataDecoder() : buffer_(nullptr) {}
_ZN5draco15MetadataDecoder22DecodeGeometryMetadataEPNS_13DecoderBufferEPNS_16GeometryMetadataE:
   35|  1.16k|                                             GeometryMetadata* metadata) {
   36|  1.16k|  if (!metadata) {
  ------------------
  |  Branch (36:7): [True: 0, False: 1.16k]
  ------------------
   37|      0|    return false;
   38|      0|  }
   39|  1.16k|  buffer_ = in_buffer;
   40|  1.16k|  uint32_t num_att_metadata = 0;
   41|  1.16k|  if (!DecodeVarint(&num_att_metadata, buffer_)) {
  ------------------
  |  Branch (41:7): [True: 24, False: 1.14k]
  ------------------
   42|     24|    return false;
   43|     24|  }
   44|       |  // Decode attribute metadata.
   45|  2.30k|  for (uint32_t i = 0; i < num_att_metadata; ++i) {
  ------------------
  |  Branch (45:24): [True: 1.85k, False: 443]
  ------------------
   46|  1.85k|    uint32_t att_unique_id;
   47|  1.85k|    if (!DecodeVarint(&att_unique_id, buffer_)) {
  ------------------
  |  Branch (47:9): [True: 42, False: 1.81k]
  ------------------
   48|     42|      return false;
   49|     42|    }
   50|  1.81k|    std::unique_ptr<AttributeMetadata> att_metadata =
   51|  1.81k|        std::unique_ptr<AttributeMetadata>(new AttributeMetadata());
   52|  1.81k|    att_metadata->set_att_unique_id(att_unique_id);
   53|  1.81k|    if (!DecodeMetadata(static_cast<Metadata*>(att_metadata.get()))) {
  ------------------
  |  Branch (53:9): [True: 660, False: 1.15k]
  ------------------
   54|    660|      return false;
   55|    660|    }
   56|  1.15k|    metadata->AddAttributeMetadata(std::move(att_metadata));
   57|  1.15k|  }
   58|    443|  return DecodeMetadata(static_cast<Metadata*>(metadata));
   59|  1.14k|}
_ZN5draco15MetadataDecoder14DecodeMetadataEPNS_8MetadataE:
   61|  2.26k|bool MetadataDecoder::DecodeMetadata(Metadata* metadata) {
   62|       |  // Limit metadata nesting depth to avoid stack overflow in destructor.
   63|  2.26k|  constexpr int kMaxSubmetadataLevel = 1000;
   64|       |
   65|  2.26k|  struct MetadataTuple {
   66|  2.26k|    Metadata* parent_metadata;
   67|  2.26k|    Metadata* decoded_metadata;
   68|  2.26k|    int level;
   69|  2.26k|  };
   70|  2.26k|  std::vector<MetadataTuple> metadata_stack;
   71|  2.26k|  metadata_stack.push_back({nullptr, metadata, 0});
   72|  60.5k|  while (!metadata_stack.empty()) {
  ------------------
  |  Branch (72:10): [True: 59.3k, False: 1.18k]
  ------------------
   73|  59.3k|    const MetadataTuple mp = metadata_stack.back();
   74|  59.3k|    metadata_stack.pop_back();
   75|  59.3k|    metadata = mp.decoded_metadata;
   76|       |
   77|  59.3k|    if (mp.parent_metadata != nullptr) {
  ------------------
  |  Branch (77:9): [True: 57.0k, False: 2.26k]
  ------------------
   78|  57.0k|      if (mp.level > kMaxSubmetadataLevel) {
  ------------------
  |  Branch (78:11): [True: 3, False: 57.0k]
  ------------------
   79|      3|        return false;
   80|      3|      }
   81|  57.0k|      std::string sub_metadata_name;
   82|  57.0k|      if (!DecodeName(&sub_metadata_name)) {
  ------------------
  |  Branch (82:11): [True: 73, False: 57.0k]
  ------------------
   83|     73|        return false;
   84|     73|      }
   85|  57.0k|      std::unique_ptr<Metadata> sub_metadata =
   86|  57.0k|          std::unique_ptr<Metadata>(new Metadata());
   87|  57.0k|      metadata = sub_metadata.get();
   88|  57.0k|      if (!mp.parent_metadata->AddSubMetadata(sub_metadata_name,
  ------------------
  |  Branch (88:11): [True: 26, False: 56.9k]
  ------------------
   89|  57.0k|                                              std::move(sub_metadata))) {
   90|     26|        return false;
   91|     26|      }
   92|  57.0k|    }
   93|  59.2k|    if (metadata == nullptr) {
  ------------------
  |  Branch (93:9): [True: 0, False: 59.2k]
  ------------------
   94|      0|      return false;
   95|      0|    }
   96|       |
   97|  59.2k|    uint32_t num_entries = 0;
   98|  59.2k|    if (!DecodeVarint(&num_entries, buffer_)) {
  ------------------
  |  Branch (98:9): [True: 64, False: 59.1k]
  ------------------
   99|     64|      return false;
  100|     64|    }
  101|   157k|    for (uint32_t i = 0; i < num_entries; ++i) {
  ------------------
  |  Branch (101:26): [True: 99.3k, False: 58.4k]
  ------------------
  102|  99.3k|      if (!DecodeEntry(metadata)) {
  ------------------
  |  Branch (102:11): [True: 771, False: 98.5k]
  ------------------
  103|    771|        return false;
  104|    771|      }
  105|  99.3k|    }
  106|  58.4k|    uint32_t num_sub_metadata = 0;
  107|  58.4k|    if (!DecodeVarint(&num_sub_metadata, buffer_)) {
  ------------------
  |  Branch (107:9): [True: 36, False: 58.3k]
  ------------------
  108|     36|      return false;
  109|     36|    }
  110|  58.3k|    if (num_sub_metadata > buffer_->remaining_size()) {
  ------------------
  |  Branch (110:9): [True: 107, False: 58.2k]
  ------------------
  111|       |      // The decoded number of metadata items is unreasonably high.
  112|    107|      return false;
  113|    107|    }
  114|   333k|    for (uint32_t i = 0; i < num_sub_metadata; ++i) {
  ------------------
  |  Branch (114:26): [True: 274k, False: 58.2k]
  ------------------
  115|   274k|      metadata_stack.push_back(
  116|   274k|          {metadata, nullptr, mp.parent_metadata ? mp.level + 1 : mp.level});
  ------------------
  |  Branch (116:31): [True: 265k, False: 9.07k]
  ------------------
  117|   274k|    }
  118|  58.2k|  }
  119|  1.18k|  return true;
  120|  2.26k|}
_ZN5draco15MetadataDecoder11DecodeEntryEPNS_8MetadataE:
  122|  99.3k|bool MetadataDecoder::DecodeEntry(Metadata* metadata) {
  123|  99.3k|  std::string entry_name;
  124|  99.3k|  if (!DecodeName(&entry_name)) {
  ------------------
  |  Branch (124:7): [True: 392, False: 98.9k]
  ------------------
  125|    392|    return false;
  126|    392|  }
  127|  98.9k|  uint32_t data_size = 0;
  128|  98.9k|  if (!DecodeVarint(&data_size, buffer_)) {
  ------------------
  |  Branch (128:7): [True: 93, False: 98.8k]
  ------------------
  129|     93|    return false;
  130|     93|  }
  131|  98.8k|  if (data_size == 0) {
  ------------------
  |  Branch (131:7): [True: 94, False: 98.7k]
  ------------------
  132|     94|    return false;
  133|     94|  }
  134|  98.7k|  if (data_size > buffer_->remaining_size()) {
  ------------------
  |  Branch (134:7): [True: 192, False: 98.5k]
  ------------------
  135|    192|    return false;
  136|    192|  }
  137|  98.5k|  std::vector<uint8_t> entry_value(data_size);
  138|  98.5k|  if (!buffer_->Decode(&entry_value[0], data_size)) {
  ------------------
  |  Branch (138:7): [True: 0, False: 98.5k]
  ------------------
  139|      0|    return false;
  140|      0|  }
  141|  98.5k|  metadata->AddEntryBinary(entry_name, entry_value);
  142|  98.5k|  return true;
  143|  98.5k|}
_ZN5draco15MetadataDecoder10DecodeNameEPNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  145|   156k|bool MetadataDecoder::DecodeName(std::string* name) {
  146|   156k|  uint8_t name_len = 0;
  147|   156k|  if (!buffer_->Decode(&name_len)) {
  ------------------
  |  Branch (147:7): [True: 133, False: 156k]
  ------------------
  148|    133|    return false;
  149|    133|  }
  150|   156k|  name->resize(name_len);
  151|   156k|  if (name_len == 0) {
  ------------------
  |  Branch (151:7): [True: 28.9k, False: 127k]
  ------------------
  152|  28.9k|    return true;
  153|  28.9k|  }
  154|   127k|  if (!buffer_->Decode(&name->at(0), name_len)) {
  ------------------
  |  Branch (154:7): [True: 332, False: 126k]
  ------------------
  155|    332|    return false;
  156|    332|  }
  157|   126k|  return true;
  158|   127k|}

_ZN5draco10PointCloudC2Ev:
   27|  19.4k|PointCloud::PointCloud() : num_points_(0) {}
_ZNK5draco10PointCloud18NumNamedAttributesENS_17GeometryAttribute4TypeE:
   62|  2.23k|int32_t PointCloud::NumNamedAttributes(GeometryAttribute::Type type) const {
   63|  2.23k|  if (type == GeometryAttribute::INVALID ||
  ------------------
  |  Branch (63:7): [True: 0, False: 2.23k]
  ------------------
   64|  2.23k|      type >= GeometryAttribute::NAMED_ATTRIBUTES_COUNT) {
  ------------------
  |  Branch (64:7): [True: 0, False: 2.23k]
  ------------------
   65|      0|    return 0;
   66|      0|  }
   67|  2.23k|  return static_cast<int32_t>(named_attribute_index_[type].size());
   68|  2.23k|}
_ZNK5draco10PointCloud19GetNamedAttributeIdENS_17GeometryAttribute4TypeE:
   70|  2.23k|int32_t PointCloud::GetNamedAttributeId(GeometryAttribute::Type type) const {
   71|  2.23k|  return GetNamedAttributeId(type, 0);
   72|  2.23k|}
_ZNK5draco10PointCloud19GetNamedAttributeIdENS_17GeometryAttribute4TypeEi:
   75|  2.23k|                                        int i) const {
   76|  2.23k|  if (NumNamedAttributes(type) <= i) {
  ------------------
  |  Branch (76:7): [True: 5, False: 2.22k]
  ------------------
   77|      5|    return -1;
   78|      5|  }
   79|  2.22k|  return named_attribute_index_[type][i];
   80|  2.23k|}
_ZN5draco10PointCloud12AddAttributeENSt3__110unique_ptrINS_14PointAttributeENS1_14default_deleteIS3_EEEE:
  140|  31.7k|int PointCloud::AddAttribute(std::unique_ptr<PointAttribute> pa) {
  141|  31.7k|  SetAttribute(static_cast<int>(attributes_.size()), std::move(pa));
  142|  31.7k|  return static_cast<int>(attributes_.size() - 1);
  143|  31.7k|}
_ZN5draco10PointCloud12SetAttributeEiNSt3__110unique_ptrINS_14PointAttributeENS1_14default_deleteIS3_EEEE:
  178|  31.7k|void PointCloud::SetAttribute(int att_id, std::unique_ptr<PointAttribute> pa) {
  179|  31.7k|  DRACO_DCHECK(att_id >= 0);
  180|  31.7k|  if (static_cast<int>(attributes_.size()) <= att_id) {
  ------------------
  |  Branch (180:7): [True: 31.7k, False: 0]
  ------------------
  181|  31.7k|    attributes_.resize(att_id + 1);
  182|  31.7k|  }
  183|  31.7k|  if (pa->attribute_type() < GeometryAttribute::NAMED_ATTRIBUTES_COUNT) {
  ------------------
  |  Branch (183:7): [True: 31.7k, False: 0]
  ------------------
  184|  31.7k|    named_attribute_index_[pa->attribute_type()].push_back(att_id);
  185|  31.7k|  }
  186|  31.7k|  pa->set_unique_id(att_id);
  187|  31.7k|  attributes_[att_id] = std::move(pa);
  188|  31.7k|}

_ZNK5draco10PointCloud14num_attributesEv:
   78|  2.22k|  int32_t num_attributes() const {
   79|  2.22k|    return static_cast<int32_t>(attributes_.size());
   80|  2.22k|  }
_ZNK5draco10PointCloud9attributeEi:
   81|  12.2k|  const PointAttribute* attribute(int32_t att_id) const {
   82|  12.2k|    DRACO_DCHECK_LE(0, att_id);
   83|  12.2k|    DRACO_DCHECK_LT(att_id, static_cast<int32_t>(attributes_.size()));
   84|  12.2k|    return attributes_[att_id].get();
   85|  12.2k|  }
_ZN5draco10PointCloud9attributeEi:
   89|  78.7k|  PointAttribute* attribute(int32_t att_id) {
   90|  78.7k|    DRACO_DCHECK_LE(0, att_id);
   91|  78.7k|    DRACO_DCHECK_LT(att_id, static_cast<int32_t>(attributes_.size()));
   92|  78.7k|    return attributes_[att_id].get();
   93|  78.7k|  }
_ZN5draco10PointCloud11AddMetadataENSt3__110unique_ptrINS_16GeometryMetadataENS1_14default_deleteIS3_EEEE:
  144|     23|  void AddMetadata(std::unique_ptr<GeometryMetadata> metadata) {
  145|     23|    metadata_ = std::move(metadata);
  146|     23|  }
_ZNK5draco10PointCloud10num_pointsEv:
  198|  60.1k|  PointIndex::ValueType num_points() const { return num_points_; }
_ZN5draco10PointCloud14set_num_pointsEj:
  203|  8.50k|  void set_num_points(PointIndex::ValueType num) { num_points_ = num; }
_ZN5draco10PointCloudD2Ev:
   39|  19.4k|  virtual ~PointCloud() = default;

LLVMFuzzerTestOneInput:
   21|  19.5k|extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   22|  19.5k|  draco::DecoderBuffer buffer;
   23|  19.5k|  buffer.Init(reinterpret_cast<const char*>(data), size);
   24|       |
   25|  19.5k|  draco::Decoder decoder;
   26|  19.5k|  decoder.SetSkipAttributeTransform(draco::GeometryAttribute::POSITION);
   27|  19.5k|  decoder.DecodePointCloudFromBuffer(&buffer);
   28|       |
   29|  19.5k|  return 0;
   30|  19.5k|}

