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

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

_ZNK5draco30AttributeQuantizationTransform28CopyToAttributeTransformDataEPNS_22AttributeTransformDataE:
   49|     25|    AttributeTransformData *out_data) const {
   50|     25|  out_data->set_transform_type(ATTRIBUTE_QUANTIZATION_TRANSFORM);
   51|     25|  out_data->AppendParameterValue(quantization_bits_);
   52|    798|  for (int i = 0; i < min_values_.size(); ++i) {
  ------------------
  |  Branch (52:19): [True: 773, False: 25]
  ------------------
   53|    773|    out_data->AppendParameterValue(min_values_[i]);
   54|    773|  }
   55|     25|  out_data->AppendParameterValue(range_);
   56|     25|}
_ZN5draco30AttributeQuantizationTransform25InverseTransformAttributeERKNS_14PointAttributeEPS1_:
   72|     21|    const PointAttribute &attribute, PointAttribute *target_attribute) {
   73|     21|  if (target_attribute->data_type() != DT_FLOAT32) {
  ------------------
  |  Branch (73:7): [True: 0, False: 21]
  ------------------
   74|      0|    return false;
   75|      0|  }
   76|       |
   77|       |  // Convert all quantized values back to floats.
   78|     21|  const int32_t max_quantized_value =
   79|     21|      (1u << static_cast<uint32_t>(quantization_bits_)) - 1;
   80|     21|  const int num_components = target_attribute->num_components();
   81|     21|  const int entry_size = sizeof(float) * num_components;
   82|     21|  const std::unique_ptr<float[]> att_val(new float[num_components]);
   83|     21|  int quant_val_id = 0;
   84|     21|  int out_byte_pos = 0;
   85|     21|  Dequantizer dequantizer;
   86|     21|  if (!dequantizer.Init(range_, max_quantized_value)) {
  ------------------
  |  Branch (86:7): [True: 0, False: 21]
  ------------------
   87|      0|    return false;
   88|      0|  }
   89|     21|  const int32_t *const source_attribute_data =
   90|     21|      reinterpret_cast<const int32_t *>(
   91|     21|          attribute.GetAddress(AttributeValueIndex(0)));
   92|       |
   93|     21|  const int num_values = target_attribute->size();
   94|       |
   95|   108k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (95:24): [True: 108k, False: 21]
  ------------------
   96|  3.55M|    for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (96:21): [True: 3.44M, False: 108k]
  ------------------
   97|  3.44M|      float value =
   98|  3.44M|          dequantizer.DequantizeFloat(source_attribute_data[quant_val_id++]);
   99|  3.44M|      value = value + min_values_[c];
  100|  3.44M|      att_val[c] = value;
  101|  3.44M|    }
  102|       |    // Store the floating point value into the attribute buffer.
  103|   108k|    target_attribute->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
  104|   108k|    out_byte_pos += entry_size;
  105|   108k|  }
  106|     21|  return true;
  107|     21|}
_ZN5draco30AttributeQuantizationTransform19IsQuantizationValidEi:
  110|     44|    int quantization_bits) {
  111|       |  // Currently we allow only up to 30 bit quantization.
  112|     44|  return quantization_bits >= 1 && quantization_bits <= 30;
  ------------------
  |  Branch (112:10): [True: 38, False: 6]
  |  Branch (112:36): [True: 26, False: 12]
  ------------------
  113|     44|}
_ZN5draco30AttributeQuantizationTransform16DecodeParametersERKNS_14PointAttributeEPNS_13DecoderBufferE:
  196|     48|    const PointAttribute &attribute, DecoderBuffer *decoder_buffer) {
  197|     48|  min_values_.resize(attribute.num_components());
  198|     48|  if (!decoder_buffer->Decode(&min_values_[0],
  ------------------
  |  Branch (198:7): [True: 3, False: 45]
  ------------------
  199|     48|                              sizeof(float) * min_values_.size())) {
  200|      3|    return false;
  201|      3|  }
  202|     45|  if (!decoder_buffer->Decode(&range_)) {
  ------------------
  |  Branch (202:7): [True: 0, False: 45]
  ------------------
  203|      0|    return false;
  204|      0|  }
  205|     45|  uint8_t quantization_bits;
  206|     45|  if (!decoder_buffer->Decode(&quantization_bits)) {
  ------------------
  |  Branch (206:7): [True: 1, False: 44]
  ------------------
  207|      1|    return false;
  208|      1|  }
  209|     44|  if (!IsQuantizationValid(quantization_bits)) {
  ------------------
  |  Branch (209:7): [True: 18, False: 26]
  ------------------
  210|     18|    return false;
  211|     18|  }
  212|     26|  quantization_bits_ = quantization_bits;
  213|     26|  return true;
  214|     44|}

_ZN5draco30AttributeQuantizationTransformC2Ev:
   29|     60|  AttributeQuantizationTransform() : quantization_bits_(-1), range_(0.f) {}

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

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

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

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

_ZNK5draco17GeometryAttribute10GetBytePosENS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEE:
  118|   117k|  inline int64_t GetBytePos(AttributeValueIndex att_index) const {
  119|   117k|    return byte_offset_ + byte_stride_ * att_index.value();
  120|   117k|  }
_ZNK5draco17GeometryAttribute10GetAddressENS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEE:
  122|   114k|  inline const uint8_t *GetAddress(AttributeValueIndex att_index) const {
  123|   114k|    const int64_t byte_pos = GetBytePos(att_index);
  124|   114k|    return buffer_->data() + byte_pos;
  125|   114k|  }
_ZN5draco17GeometryAttribute10GetAddressENS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEE:
  126|  2.53k|  inline uint8_t *GetAddress(AttributeValueIndex att_index) {
  127|  2.53k|    const int64_t byte_pos = GetBytePos(att_index);
  128|  2.53k|    return buffer_->data() + byte_pos;
  129|  2.53k|  }
_ZNK5draco17GeometryAttribute14IsAddressValidEPKh:
  130|   343k|  inline bool IsAddressValid(const uint8_t *address) const {
  131|   343k|    return ((buffer_->data() + buffer_->data_size()) > address);
  132|   343k|  }
_ZNK5draco17GeometryAttribute14attribute_typeEv:
  266|   132k|  Type attribute_type() const { return attribute_type_; }
_ZNK5draco17GeometryAttribute9data_typeEv:
  269|  5.09k|  DataType data_type() const { return data_type_; }
_ZNK5draco17GeometryAttribute14num_componentsEv:
  273|  9.37k|  uint8_t num_components() const { return num_components_; }
_ZNK5draco17GeometryAttribute11byte_strideEv:
  282|    200|  int64_t byte_stride() const { return byte_stride_; }
_ZNK5draco17GeometryAttribute9unique_idEv:
  287|  1.89k|  uint32_t unique_id() const { return unique_id_; }
_ZN5draco17GeometryAttribute13set_unique_idEj:
  288|   196k|  void set_unique_id(uint32_t id) { unique_id_ = id; }
_ZNK5draco17GeometryAttribute12ConvertValueIlEEbNS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEEPT_:
  229|  52.2k|  bool ConvertValue(AttributeValueIndex att_index, OutT *out_value) const {
  230|  52.2k|    return ConvertValue<OutT>(att_index, num_components_, out_value);
  231|  52.2k|  }
_ZNK5draco17GeometryAttribute12ConvertValueIlEEbNS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEEaPT_:
  179|  52.2k|                    OutT *out_val) const {
  180|  52.2k|    if (out_val == nullptr) {
  ------------------
  |  Branch (180:9): [True: 0, False: 52.2k]
  ------------------
  181|      0|      return false;
  182|      0|    }
  183|  52.2k|    switch (data_type_) {
  184|      0|      case DT_INT8:
  ------------------
  |  Branch (184:7): [True: 0, False: 52.2k]
  ------------------
  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: 52.2k]
  ------------------
  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: 52.2k]
  ------------------
  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: 52.2k]
  ------------------
  194|      0|        return ConvertTypedValue<uint16_t, OutT>(att_id, out_num_components,
  195|      0|                                                 out_val);
  196|  52.2k|      case DT_INT32:
  ------------------
  |  Branch (196:7): [True: 52.2k, False: 0]
  ------------------
  197|  52.2k|        return ConvertTypedValue<int32_t, OutT>(att_id, out_num_components,
  198|  52.2k|                                                out_val);
  199|      0|      case DT_UINT32:
  ------------------
  |  Branch (199:7): [True: 0, False: 52.2k]
  ------------------
  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: 52.2k]
  ------------------
  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: 52.2k]
  ------------------
  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: 52.2k]
  ------------------
  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: 52.2k]
  ------------------
  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: 52.2k]
  ------------------
  215|      0|        return ConvertTypedValue<bool, OutT>(att_id, out_num_components,
  216|      0|                                             out_val);
  217|      0|      default:
  ------------------
  |  Branch (217:7): [True: 0, False: 52.2k]
  ------------------
  218|       |        // Wrong attribute type.
  219|      0|        return false;
  220|  52.2k|    }
  221|  52.2k|  }
_ZNK5draco17GeometryAttribute17ConvertTypedValueIilEEbNS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEEhPT0_:
  306|  52.2k|                         OutT *out_value) const {
  307|  52.2k|    const uint8_t *src_address = GetAddress(att_id);
  308|       |
  309|       |    // Convert all components available in both the original and output formats.
  310|   209k|    for (int i = 0; i < std::min(num_components_, out_num_components); ++i) {
  ------------------
  |  Branch (310:21): [True: 156k, False: 52.2k]
  ------------------
  311|   156k|      if (!IsAddressValid(src_address)) {
  ------------------
  |  Branch (311:11): [True: 0, False: 156k]
  ------------------
  312|      0|        return false;
  313|      0|      }
  314|   156k|      const T in_value = *reinterpret_cast<const T *>(src_address);
  315|   156k|      if (!ConvertComponentValue<T, OutT>(in_value, normalized_,
  ------------------
  |  Branch (315:11): [True: 0, False: 156k]
  ------------------
  316|   156k|                                          out_value + i)) {
  317|      0|        return false;
  318|      0|      }
  319|   156k|      src_address += sizeof(T);
  320|   156k|    }
  321|       |    // Fill empty data for unused output components if needed.
  322|  52.2k|    for (int i = num_components_; i < out_num_components; ++i) {
  ------------------
  |  Branch (322:35): [True: 0, False: 52.2k]
  ------------------
  323|      0|      out_value[i] = static_cast<OutT>(0);
  324|      0|    }
  325|  52.2k|    return true;
  326|  52.2k|  }
_ZN5draco17GeometryAttribute21ConvertComponentValueIilEEbRKT_bPT0_:
  364|   156k|                                    OutT *out_value) {
  365|       |    // Make sure the |in_value| can be represented as an integral type OutT.
  366|   156k|    if (std::is_integral<OutT>::value) {
  ------------------
  |  Branch (366:9): [Folded - Ignored]
  ------------------
  367|       |      // Make sure the |in_value| fits within the range of values that OutT
  368|       |      // is able to represent. Perform the check only for integral types.
  369|   156k|      if (!std::is_same<T, bool>::value && std::is_integral<T>::value) {
  ------------------
  |  Branch (369:11): [Folded - Ignored]
  |  Branch (369:44): [Folded - Ignored]
  ------------------
  370|   156k|        static constexpr OutT kOutMin =
  371|   156k|            std::is_signed<T>::value ? std::numeric_limits<OutT>::min() : 0;
  ------------------
  |  Branch (371:13): [Folded - Ignored]
  ------------------
  372|   156k|        if (in_value < kOutMin || in_value > std::numeric_limits<OutT>::max()) {
  ------------------
  |  Branch (372:13): [True: 0, False: 156k]
  |  Branch (372:35): [True: 0, False: 156k]
  ------------------
  373|      0|          return false;
  374|      0|        }
  375|   156k|      }
  376|       |
  377|       |      // Check conversion of floating point |in_value| to integral value OutT.
  378|   156k|      if (std::is_floating_point<T>::value) {
  ------------------
  |  Branch (378:11): [Folded - Ignored]
  ------------------
  379|       |        // Make sure the floating point |in_value| is not NaN and not Inf as
  380|       |        // integral type OutT is unable to represent these values.
  381|      0|        if (sizeof(in_value) > sizeof(double)) {
  ------------------
  |  Branch (381:13): [Folded - Ignored]
  ------------------
  382|      0|          if (std::isnan(static_cast<long double>(in_value)) ||
  ------------------
  |  Branch (382:15): [True: 0, False: 0]
  ------------------
  383|      0|              std::isinf(static_cast<long double>(in_value))) {
  ------------------
  |  Branch (383:15): [True: 0, False: 0]
  ------------------
  384|      0|            return false;
  385|      0|          }
  386|      0|        } else if (sizeof(in_value) > sizeof(float)) {
  ------------------
  |  Branch (386:20): [Folded - Ignored]
  ------------------
  387|      0|          if (std::isnan(static_cast<double>(in_value)) ||
  ------------------
  |  Branch (387:15): [True: 0, False: 0]
  ------------------
  388|      0|              std::isinf(static_cast<double>(in_value))) {
  ------------------
  |  Branch (388:15): [True: 0, False: 0]
  ------------------
  389|      0|            return false;
  390|      0|          }
  391|      0|        } else {
  392|      0|          if (std::isnan(static_cast<float>(in_value)) ||
  ------------------
  |  Branch (392:15): [True: 0, False: 0]
  ------------------
  393|      0|              std::isinf(static_cast<float>(in_value))) {
  ------------------
  |  Branch (393:15): [True: 0, False: 0]
  ------------------
  394|      0|            return false;
  395|      0|          }
  396|      0|        }
  397|       |
  398|       |        // Make sure the floating point |in_value| fits within the range of
  399|       |        // values that integral type OutT is able to represent.
  400|      0|        if (in_value < std::numeric_limits<OutT>::min() ||
  ------------------
  |  Branch (400:13): [True: 0, False: 0]
  ------------------
  401|      0|            in_value >= std::numeric_limits<OutT>::max()) {
  ------------------
  |  Branch (401:13): [True: 0, False: 0]
  ------------------
  402|      0|          return false;
  403|      0|        }
  404|      0|      }
  405|   156k|    }
  406|       |
  407|   156k|    if (std::is_integral<T>::value && std::is_floating_point<OutT>::value &&
  ------------------
  |  Branch (407:9): [Folded - Ignored]
  |  Branch (407:39): [Folded - Ignored]
  ------------------
  408|   156k|        normalized) {
  ------------------
  |  Branch (408:9): [True: 0, False: 0]
  ------------------
  409|       |      // When converting integer to floating point, normalize the value if
  410|       |      // necessary.
  411|      0|      *out_value = static_cast<OutT>(in_value);
  412|      0|      *out_value /= static_cast<OutT>(std::numeric_limits<T>::max());
  413|   156k|    } else if (std::is_floating_point<T>::value &&
  ------------------
  |  Branch (413:16): [Folded - Ignored]
  ------------------
  414|   156k|               std::is_integral<OutT>::value && normalized) {
  ------------------
  |  Branch (414:16): [Folded - Ignored]
  |  Branch (414:49): [True: 0, False: 0]
  ------------------
  415|       |      // Converting from floating point to a normalized integer.
  416|      0|      if (in_value > 1 || in_value < 0) {
  ------------------
  |  Branch (416:11): [True: 0, False: 0]
  |  Branch (416:27): [True: 0, False: 0]
  ------------------
  417|       |        // Normalized float values need to be between 0 and 1.
  418|      0|        return false;
  419|      0|      }
  420|       |      // TODO(ostava): Consider allowing float to normalized integer conversion
  421|       |      // for 64-bit integer types. Currently it doesn't work because we don't
  422|       |      // have a floating point type that could store all 64 bit integers.
  423|      0|      if (sizeof(OutT) > 4) {
  ------------------
  |  Branch (423:11): [Folded - Ignored]
  ------------------
  424|      0|        return false;
  425|      0|      }
  426|       |      // Expand the float to the range of the output integer and round it to the
  427|       |      // nearest representable value. Use doubles for the math to ensure the
  428|       |      // integer values are represented properly during the conversion process.
  429|      0|      *out_value = static_cast<OutT>(std::floor(
  430|      0|          in_value * static_cast<double>(std::numeric_limits<OutT>::max()) +
  431|      0|          0.5));
  432|   156k|    } else {
  433|   156k|      *out_value = static_cast<OutT>(in_value);
  434|   156k|    }
  435|       |
  436|       |    // TODO(ostava): Add handling of normalized attributes when converting
  437|       |    // between different integer representations. If the attribute is
  438|       |    // normalized, integer values should be converted as if they represent 0-1
  439|       |    // range. E.g. when we convert uint16 to uint8, the range <0, 2^16 - 1>
  440|       |    // should be converted to range <0, 2^8 - 1>.
  441|   156k|    return true;
  442|   156k|  }
_ZNK5draco17GeometryAttribute12ConvertValueIfEEbNS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEEPT_:
  229|  62.1k|  bool ConvertValue(AttributeValueIndex att_index, OutT *out_value) const {
  230|  62.1k|    return ConvertValue<OutT>(att_index, num_components_, out_value);
  231|  62.1k|  }
_ZNK5draco17GeometryAttribute12ConvertValueIfEEbNS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEEaPT_:
  179|  62.1k|                    OutT *out_val) const {
  180|  62.1k|    if (out_val == nullptr) {
  ------------------
  |  Branch (180:9): [True: 0, False: 62.1k]
  ------------------
  181|      0|      return false;
  182|      0|    }
  183|  62.1k|    switch (data_type_) {
  184|      0|      case DT_INT8:
  ------------------
  |  Branch (184:7): [True: 0, False: 62.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: 62.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: 62.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: 62.1k]
  ------------------
  194|      0|        return ConvertTypedValue<uint16_t, OutT>(att_id, out_num_components,
  195|      0|                                                 out_val);
  196|  62.1k|      case DT_INT32:
  ------------------
  |  Branch (196:7): [True: 62.1k, False: 0]
  ------------------
  197|  62.1k|        return ConvertTypedValue<int32_t, OutT>(att_id, out_num_components,
  198|  62.1k|                                                out_val);
  199|      0|      case DT_UINT32:
  ------------------
  |  Branch (199:7): [True: 0, False: 62.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: 62.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: 62.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: 62.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: 62.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: 62.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: 62.1k]
  ------------------
  218|       |        // Wrong attribute type.
  219|      0|        return false;
  220|  62.1k|    }
  221|  62.1k|  }
_ZNK5draco17GeometryAttribute17ConvertTypedValueIifEEbNS_9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEEhPT0_:
  306|  62.1k|                         OutT *out_value) const {
  307|  62.1k|    const uint8_t *src_address = GetAddress(att_id);
  308|       |
  309|       |    // Convert all components available in both the original and output formats.
  310|   248k|    for (int i = 0; i < std::min(num_components_, out_num_components); ++i) {
  ------------------
  |  Branch (310:21): [True: 186k, False: 62.1k]
  ------------------
  311|   186k|      if (!IsAddressValid(src_address)) {
  ------------------
  |  Branch (311:11): [True: 0, False: 186k]
  ------------------
  312|      0|        return false;
  313|      0|      }
  314|   186k|      const T in_value = *reinterpret_cast<const T *>(src_address);
  315|   186k|      if (!ConvertComponentValue<T, OutT>(in_value, normalized_,
  ------------------
  |  Branch (315:11): [True: 0, False: 186k]
  ------------------
  316|   186k|                                          out_value + i)) {
  317|      0|        return false;
  318|      0|      }
  319|   186k|      src_address += sizeof(T);
  320|   186k|    }
  321|       |    // Fill empty data for unused output components if needed.
  322|  62.1k|    for (int i = num_components_; i < out_num_components; ++i) {
  ------------------
  |  Branch (322:35): [True: 0, False: 62.1k]
  ------------------
  323|      0|      out_value[i] = static_cast<OutT>(0);
  324|      0|    }
  325|  62.1k|    return true;
  326|  62.1k|  }
_ZN5draco17GeometryAttribute21ConvertComponentValueIifEEbRKT_bPT0_:
  364|   186k|                                    OutT *out_value) {
  365|       |    // Make sure the |in_value| can be represented as an integral type OutT.
  366|   186k|    if (std::is_integral<OutT>::value) {
  ------------------
  |  Branch (366:9): [Folded - Ignored]
  ------------------
  367|       |      // Make sure the |in_value| fits within the range of values that OutT
  368|       |      // is able to represent. Perform the check only for integral types.
  369|      0|      if (!std::is_same<T, bool>::value && std::is_integral<T>::value) {
  ------------------
  |  Branch (369:11): [Folded - Ignored]
  |  Branch (369:44): [Folded - Ignored]
  ------------------
  370|      0|        static constexpr OutT kOutMin =
  371|      0|            std::is_signed<T>::value ? std::numeric_limits<OutT>::min() : 0;
  ------------------
  |  Branch (371:13): [Folded - Ignored]
  ------------------
  372|      0|        if (in_value < kOutMin || in_value > std::numeric_limits<OutT>::max()) {
  ------------------
  |  Branch (372:13): [True: 0, False: 0]
  |  Branch (372:35): [True: 0, False: 0]
  ------------------
  373|      0|          return false;
  374|      0|        }
  375|      0|      }
  376|       |
  377|       |      // Check conversion of floating point |in_value| to integral value OutT.
  378|      0|      if (std::is_floating_point<T>::value) {
  ------------------
  |  Branch (378:11): [Folded - Ignored]
  ------------------
  379|       |        // Make sure the floating point |in_value| is not NaN and not Inf as
  380|       |        // integral type OutT is unable to represent these values.
  381|      0|        if (sizeof(in_value) > sizeof(double)) {
  ------------------
  |  Branch (381:13): [Folded - Ignored]
  ------------------
  382|      0|          if (std::isnan(static_cast<long double>(in_value)) ||
  ------------------
  |  Branch (382:15): [True: 0, False: 0]
  ------------------
  383|      0|              std::isinf(static_cast<long double>(in_value))) {
  ------------------
  |  Branch (383:15): [True: 0, False: 0]
  ------------------
  384|      0|            return false;
  385|      0|          }
  386|      0|        } else if (sizeof(in_value) > sizeof(float)) {
  ------------------
  |  Branch (386:20): [Folded - Ignored]
  ------------------
  387|      0|          if (std::isnan(static_cast<double>(in_value)) ||
  ------------------
  |  Branch (387:15): [True: 0, False: 0]
  ------------------
  388|      0|              std::isinf(static_cast<double>(in_value))) {
  ------------------
  |  Branch (388:15): [True: 0, False: 0]
  ------------------
  389|      0|            return false;
  390|      0|          }
  391|      0|        } else {
  392|      0|          if (std::isnan(static_cast<float>(in_value)) ||
  ------------------
  |  Branch (392:15): [True: 0, False: 0]
  ------------------
  393|      0|              std::isinf(static_cast<float>(in_value))) {
  ------------------
  |  Branch (393:15): [True: 0, False: 0]
  ------------------
  394|      0|            return false;
  395|      0|          }
  396|      0|        }
  397|       |
  398|       |        // Make sure the floating point |in_value| fits within the range of
  399|       |        // values that integral type OutT is able to represent.
  400|      0|        if (in_value < std::numeric_limits<OutT>::min() ||
  ------------------
  |  Branch (400:13): [True: 0, False: 0]
  ------------------
  401|      0|            in_value >= std::numeric_limits<OutT>::max()) {
  ------------------
  |  Branch (401:13): [True: 0, False: 0]
  ------------------
  402|      0|          return false;
  403|      0|        }
  404|      0|      }
  405|      0|    }
  406|       |
  407|   186k|    if (std::is_integral<T>::value && std::is_floating_point<OutT>::value &&
  ------------------
  |  Branch (407:9): [Folded - Ignored]
  |  Branch (407:39): [Folded - Ignored]
  ------------------
  408|   186k|        normalized) {
  ------------------
  |  Branch (408:9): [True: 0, False: 186k]
  ------------------
  409|       |      // When converting integer to floating point, normalize the value if
  410|       |      // necessary.
  411|      0|      *out_value = static_cast<OutT>(in_value);
  412|      0|      *out_value /= static_cast<OutT>(std::numeric_limits<T>::max());
  413|   186k|    } else if (std::is_floating_point<T>::value &&
  ------------------
  |  Branch (413:16): [Folded - Ignored]
  ------------------
  414|   186k|               std::is_integral<OutT>::value && normalized) {
  ------------------
  |  Branch (414:16): [Folded - Ignored]
  |  Branch (414:49): [True: 0, False: 0]
  ------------------
  415|       |      // Converting from floating point to a normalized integer.
  416|      0|      if (in_value > 1 || in_value < 0) {
  ------------------
  |  Branch (416:11): [True: 0, False: 0]
  |  Branch (416:27): [True: 0, False: 0]
  ------------------
  417|       |        // Normalized float values need to be between 0 and 1.
  418|      0|        return false;
  419|      0|      }
  420|       |      // TODO(ostava): Consider allowing float to normalized integer conversion
  421|       |      // for 64-bit integer types. Currently it doesn't work because we don't
  422|       |      // have a floating point type that could store all 64 bit integers.
  423|      0|      if (sizeof(OutT) > 4) {
  ------------------
  |  Branch (423:11): [Folded - Ignored]
  ------------------
  424|      0|        return false;
  425|      0|      }
  426|       |      // Expand the float to the range of the output integer and round it to the
  427|       |      // nearest representable value. Use doubles for the math to ensure the
  428|       |      // integer values are represented properly during the conversion process.
  429|      0|      *out_value = static_cast<OutT>(std::floor(
  430|      0|          in_value * static_cast<double>(std::numeric_limits<OutT>::max()) +
  431|      0|          0.5));
  432|   186k|    } else {
  433|   186k|      *out_value = static_cast<OutT>(in_value);
  434|   186k|    }
  435|       |
  436|       |    // TODO(ostava): Add handling of normalized attributes when converting
  437|       |    // between different integer representations. If the attribute is
  438|       |    // normalized, integer values should be converted as if they represent 0-1
  439|       |    // range. E.g. when we convert uint16 to uint8, the range <0, 2^16 - 1>
  440|       |    // should be converted to range <0, 2^8 - 1>.
  441|   186k|    return true;
  442|   186k|  }

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

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

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

_ZNK5draco17AttributesDecoder14GetAttributeIdEi:
   44|  54.7k|  int32_t GetAttributeId(int i) const override {
   45|  54.7k|    return point_attribute_ids_[i];
   46|  54.7k|  }
_ZNK5draco17AttributesDecoder16GetNumAttributesEv:
   47|  10.9k|  int32_t GetNumAttributes() const override {
   48|  10.9k|    return static_cast<int32_t>(point_attribute_ids_.size());
   49|  10.9k|  }
_ZNK5draco17AttributesDecoder10GetDecoderEv:
   50|  31.8k|  PointCloudDecoder *GetDecoder() const override {
   51|  31.8k|    return point_cloud_decoder_;
   52|  31.8k|  }
_ZN5draco17AttributesDecoder16DecodeAttributesEPNS_13DecoderBufferE:
   55|    717|  bool DecodeAttributes(DecoderBuffer *in_buffer) override {
   56|    717|    if (!DecodePortableAttributes(in_buffer)) {
  ------------------
  |  Branch (56:9): [True: 310, False: 407]
  ------------------
   57|    310|      return false;
   58|    310|    }
   59|    407|    if (!DecodeDataNeededByPortableTransforms(in_buffer)) {
  ------------------
  |  Branch (59:9): [True: 22, False: 385]
  ------------------
   60|     22|      return false;
   61|     22|    }
   62|    385|    if (!TransformAttributesToOriginalFormat()) {
  ------------------
  |  Branch (62:9): [True: 30, False: 355]
  ------------------
   63|     30|      return false;
   64|     30|    }
   65|    355|    return true;
   66|    385|  }
_ZNK5draco17AttributesDecoder27GetLocalIdForPointAttributeEi:
   69|    237|  int32_t GetLocalIdForPointAttribute(int32_t point_attribute_id) const {
   70|    237|    const int id_map_size =
   71|    237|        static_cast<int>(point_attribute_to_local_id_map_.size());
   72|    237|    if (point_attribute_id >= id_map_size) {
  ------------------
  |  Branch (72:9): [True: 0, False: 237]
  ------------------
   73|      0|      return -1;
   74|      0|    }
   75|    237|    return point_attribute_to_local_id_map_[point_attribute_id];
   76|    237|  }
_ZN5draco17AttributesDecoderD2Ev:
   35|  13.8k|  virtual ~AttributesDecoder() = default;

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

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

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

_ZN5draco17OctahedronToolBoxC2Ev:
   57|    192|        center_value_(-1) {}
_ZN5draco17OctahedronToolBox19SetQuantizationBitsEi:
   59|    163|  bool SetQuantizationBits(int32_t q) {
   60|    163|    if (q < 2 || q > 30) {
  ------------------
  |  Branch (60:9): [True: 129, False: 34]
  |  Branch (60:18): [True: 9, False: 25]
  ------------------
   61|    138|      return false;
   62|    138|    }
   63|     25|    quantization_bits_ = q;
   64|     25|    max_quantized_value_ = (1u << quantization_bits_) - 1;
   65|     25|    max_value_ = max_quantized_value_ - 1;
   66|     25|    dequantization_scale_ = 2.f / max_value_;
   67|     25|    center_value_ = max_value_ / 2;
   68|     25|    return true;
   69|    163|  }
_ZNK5draco17OctahedronToolBox28CanonicalizeOctahedralCoordsEiiPiS1_:
   76|  5.72k|                                           int32_t *out_t) const {
   77|  5.72k|    if ((s == 0 && t == 0) || (s == 0 && t == max_value_) ||
  ------------------
  |  Branch (77:10): [True: 95, False: 5.63k]
  |  Branch (77:20): [True: 0, False: 95]
  |  Branch (77:32): [True: 95, False: 5.63k]
  |  Branch (77:42): [True: 0, False: 95]
  ------------------
   78|  5.72k|        (s == max_value_ && t == 0)) {
  ------------------
  |  Branch (78:10): [True: 5.38k, False: 337]
  |  Branch (78:29): [True: 2.14k, False: 3.24k]
  ------------------
   79|  2.14k|      s = max_value_;
   80|  2.14k|      t = max_value_;
   81|  3.58k|    } else if (s == 0 && t > center_value_) {
  ------------------
  |  Branch (81:16): [True: 95, False: 3.49k]
  |  Branch (81:26): [True: 63, False: 32]
  ------------------
   82|     63|      t = center_value_ - (t - center_value_);
   83|  3.52k|    } else if (s == max_value_ && t < center_value_) {
  ------------------
  |  Branch (83:16): [True: 3.24k, False: 274]
  |  Branch (83:35): [True: 2.00k, False: 1.24k]
  ------------------
   84|  2.00k|      t = center_value_ + (center_value_ - t);
   85|  2.00k|    } else if (t == max_value_ && s < center_value_) {
  ------------------
  |  Branch (85:16): [True: 1.28k, False: 239]
  |  Branch (85:35): [True: 106, False: 1.17k]
  ------------------
   86|    106|      s = center_value_ + (center_value_ - s);
   87|  1.41k|    } else if (t == 0 && s > center_value_) {
  ------------------
  |  Branch (87:16): [True: 27, False: 1.38k]
  |  Branch (87:26): [True: 0, False: 27]
  ------------------
   88|      0|      s = center_value_ - (s - center_value_);
   89|      0|    }
   90|       |
   91|  5.72k|    *out_s = s;
   92|  5.72k|    *out_t = t;
   93|  5.72k|  }
_ZNK5draco17OctahedronToolBox40IntegerVectorToQuantizedOctahedralCoordsEPKiPiS3_:
   99|  5.72k|                                                       int32_t *out_t) const {
  100|  5.72k|    DRACO_DCHECK_EQ(
  101|  5.72k|        std::abs(int_vec[0]) + std::abs(int_vec[1]) + std::abs(int_vec[2]),
  102|  5.72k|        center_value_);
  103|  5.72k|    int32_t s, t;
  104|  5.72k|    if (int_vec[0] >= 0) {
  ------------------
  |  Branch (104:9): [True: 5.25k, False: 474]
  ------------------
  105|       |      // Right hemisphere.
  106|  5.25k|      s = (int_vec[1] + center_value_);
  107|  5.25k|      t = (int_vec[2] + center_value_);
  108|  5.25k|    } else {
  109|       |      // Left hemisphere.
  110|    474|      if (int_vec[1] < 0) {
  ------------------
  |  Branch (110:11): [True: 7, False: 467]
  ------------------
  111|      7|        s = std::abs(int_vec[2]);
  112|    467|      } else {
  113|    467|        s = (max_value_ - std::abs(int_vec[2]));
  114|    467|      }
  115|    474|      if (int_vec[2] < 0) {
  ------------------
  |  Branch (115:11): [True: 29, False: 445]
  ------------------
  116|     29|        t = std::abs(int_vec[1]);
  117|    445|      } else {
  118|    445|        t = (max_value_ - std::abs(int_vec[1]));
  119|    445|      }
  120|    474|    }
  121|  5.72k|    CanonicalizeOctahedralCoords(s, t, out_s, out_t);
  122|  5.72k|  }
_ZNK5draco17OctahedronToolBox37QuantizedOctahedralCoordsToUnitVectorEiiPf:
  198|  16.6k|                                                    float *out_vector) const {
  199|  16.6k|    OctahedralCoordsToUnitVector(in_s * dequantization_scale_ - 1.f,
  200|  16.6k|                                 in_t * dequantization_scale_ - 1.f,
  201|  16.6k|                                 out_vector);
  202|  16.6k|  }
_ZNK5draco17OctahedronToolBox11IsInDiamondERKiS2_:
  205|  14.8k|  inline bool IsInDiamond(const int32_t &s, const int32_t &t) const {
  206|       |    // Expect center already at origin.
  207|  14.8k|    DRACO_DCHECK_LE(s, center_value_);
  208|  14.8k|    DRACO_DCHECK_LE(t, center_value_);
  209|  14.8k|    DRACO_DCHECK_GE(s, -center_value_);
  210|  14.8k|    DRACO_DCHECK_GE(t, -center_value_);
  211|  14.8k|    const uint32_t st =
  212|  14.8k|        static_cast<uint32_t>(std::abs(s)) + static_cast<uint32_t>(std::abs(t));
  213|  14.8k|    return st <= center_value_;
  214|  14.8k|  }
_ZNK5draco17OctahedronToolBox13InvertDiamondEPiS1_:
  216|  29.5k|  void InvertDiamond(int32_t *s, int32_t *t) const {
  217|       |    // Expect center already at origin.
  218|  29.5k|    DRACO_DCHECK_LE(*s, center_value_);
  219|  29.5k|    DRACO_DCHECK_LE(*t, center_value_);
  220|  29.5k|    DRACO_DCHECK_GE(*s, -center_value_);
  221|  29.5k|    DRACO_DCHECK_GE(*t, -center_value_);
  222|  29.5k|    int32_t sign_s = 0;
  223|  29.5k|    int32_t sign_t = 0;
  224|  29.5k|    if (*s >= 0 && *t >= 0) {
  ------------------
  |  Branch (224:9): [True: 25.5k, False: 3.98k]
  |  Branch (224:20): [True: 23.8k, False: 1.65k]
  ------------------
  225|  23.8k|      sign_s = 1;
  226|  23.8k|      sign_t = 1;
  227|  23.8k|    } else if (*s <= 0 && *t <= 0) {
  ------------------
  |  Branch (227:16): [True: 4.00k, False: 1.63k]
  |  Branch (227:27): [True: 1.67k, False: 2.32k]
  ------------------
  228|  1.67k|      sign_s = -1;
  229|  1.67k|      sign_t = -1;
  230|  3.95k|    } else {
  231|  3.95k|      sign_s = (*s > 0) ? 1 : -1;
  ------------------
  |  Branch (231:16): [True: 1.63k, False: 2.32k]
  ------------------
  232|  3.95k|      sign_t = (*t > 0) ? 1 : -1;
  ------------------
  |  Branch (232:16): [True: 2.32k, False: 1.63k]
  ------------------
  233|  3.95k|    }
  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|  29.5k|    const uint32_t corner_point_s = sign_s * center_value_;
  239|  29.5k|    const uint32_t corner_point_t = sign_t * center_value_;
  240|  29.5k|    uint32_t us = *s;
  241|  29.5k|    uint32_t ut = *t;
  242|  29.5k|    us = us + us - corner_point_s;
  243|  29.5k|    ut = ut + ut - corner_point_t;
  244|  29.5k|    if (sign_s * sign_t >= 0) {
  ------------------
  |  Branch (244:9): [True: 25.5k, False: 3.95k]
  ------------------
  245|  25.5k|      uint32_t temp = us;
  246|  25.5k|      us = -ut;
  247|  25.5k|      ut = -temp;
  248|  25.5k|    } else {
  249|  3.95k|      std::swap(us, ut);
  250|  3.95k|    }
  251|  29.5k|    us = us + corner_point_s;
  252|  29.5k|    ut = ut + corner_point_t;
  253|       |
  254|  29.5k|    *s = us;
  255|  29.5k|    *t = ut;
  256|  29.5k|    *s /= 2;
  257|  29.5k|    *t /= 2;
  258|  29.5k|  }
_ZNK5draco17OctahedronToolBox6ModMaxEi:
  272|  29.6k|  int32_t ModMax(int32_t x) const {
  273|  29.6k|    if (x > this->center_value()) {
  ------------------
  |  Branch (273:9): [True: 190, False: 29.4k]
  ------------------
  274|    190|      return x - this->max_quantized_value();
  275|    190|    }
  276|  29.4k|    if (x < -this->center_value()) {
  ------------------
  |  Branch (276:9): [True: 121, False: 29.3k]
  ------------------
  277|    121|      return x + this->max_quantized_value();
  278|    121|    }
  279|  29.3k|    return x;
  280|  29.4k|  }
_ZNK5draco17OctahedronToolBox17quantization_bitsEv:
  291|     26|  int32_t quantization_bits() const { return quantization_bits_; }
_ZNK5draco17OctahedronToolBox19max_quantized_valueEv:
  292|    311|  int32_t max_quantized_value() const { return max_quantized_value_; }
_ZNK5draco17OctahedronToolBox12center_valueEv:
  294|  88.8k|  int32_t center_value() const { return center_value_; }
_ZNK5draco17OctahedronToolBox28OctahedralCoordsToUnitVectorEffPf:
  298|  16.6k|                                           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|  16.6k|    float y = in_s_scaled;
  329|  16.6k|    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|  16.6k|    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|  16.6k|    float x_offset = -x;
  342|  16.6k|    x_offset = x_offset < 0 ? 0 : x_offset;
  ------------------
  |  Branch (342:16): [True: 0, False: 16.6k]
  ------------------
  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|  16.6k|    y += y < 0 ? x_offset : -x_offset;
  ------------------
  |  Branch (347:10): [True: 16.3k, False: 220]
  ------------------
  348|  16.6k|    z += z < 0 ? x_offset : -x_offset;
  ------------------
  |  Branch (348:10): [True: 16.3k, False: 223]
  ------------------
  349|       |
  350|       |    // Normalize the computed vector.
  351|  16.6k|    const float norm_squared = x * x + y * y + z * z;
  352|  16.6k|    if (norm_squared < 1e-6) {
  ------------------
  |  Branch (352:9): [True: 0, False: 16.6k]
  ------------------
  353|      0|      out_vector[0] = 0;
  354|      0|      out_vector[1] = 0;
  355|      0|      out_vector[2] = 0;
  356|  16.6k|    } else {
  357|  16.6k|      const float d = 1.0f / std::sqrt(norm_squared);
  358|  16.6k|      out_vector[0] = x * d;
  359|  16.6k|      out_vector[1] = y * d;
  360|  16.6k|      out_vector[2] = z * d;
  361|  16.6k|    }
  362|  16.6k|  }
_ZNK5draco17OctahedronToolBox25CanonicalizeIntegerVectorIiEEvPT_:
  173|  5.72k|  void CanonicalizeIntegerVector(T *vec) const {
  174|  5.72k|    static_assert(std::is_integral<T>::value, "T must be an integral type.");
  175|  5.72k|    static_assert(std::is_signed<T>::value, "T must be a signed type.");
  176|  5.72k|    const int64_t abs_sum = static_cast<int64_t>(std::abs(vec[0])) +
  177|  5.72k|                            static_cast<int64_t>(std::abs(vec[1])) +
  178|  5.72k|                            static_cast<int64_t>(std::abs(vec[2]));
  179|       |
  180|  5.72k|    if (abs_sum == 0) {
  ------------------
  |  Branch (180:9): [True: 1.17k, False: 4.54k]
  ------------------
  181|  1.17k|      vec[0] = center_value_;  // vec[1] == v[2] == 0
  182|  4.54k|    } else {
  183|  4.54k|      vec[0] =
  184|  4.54k|          (static_cast<int64_t>(vec[0]) * static_cast<int64_t>(center_value_)) /
  185|  4.54k|          abs_sum;
  186|  4.54k|      vec[1] =
  187|  4.54k|          (static_cast<int64_t>(vec[1]) * static_cast<int64_t>(center_value_)) /
  188|  4.54k|          abs_sum;
  189|  4.54k|      if (vec[2] >= 0) {
  ------------------
  |  Branch (189:11): [True: 2.57k, False: 1.97k]
  ------------------
  190|  2.57k|        vec[2] = center_value_ - std::abs(vec[0]) - std::abs(vec[1]);
  191|  2.57k|      } else {
  192|  1.97k|        vec[2] = -(center_value_ - std::abs(vec[0]) - std::abs(vec[1]));
  193|  1.97k|      }
  194|  4.54k|    }
  195|  5.72k|  }

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

_ZN5draco56MeshPredictionSchemeConstrainedMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   52|     52|        selected_mode_(Mode::OPTIMAL_MULTI_PARALLELOGRAM) {}
_ZN5draco56MeshPredictionSchemeConstrainedMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  193|     52|                                                                *buffer) {
  194|     52|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  195|     52|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|     52|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (195:7): [True: 9, False: 43]
  ------------------
  196|       |    // Decode prediction mode.
  197|      9|    uint8_t mode;
  198|      9|    if (!buffer->Decode(&mode)) {
  ------------------
  |  Branch (198:9): [True: 0, False: 9]
  ------------------
  199|      0|      return false;
  200|      0|    }
  201|       |
  202|      9|    if (mode != Mode::OPTIMAL_MULTI_PARALLELOGRAM) {
  ------------------
  |  Branch (202:9): [True: 4, False: 5]
  ------------------
  203|       |      // Unsupported mode.
  204|      4|      return false;
  205|      4|    }
  206|      9|  }
  207|     48|#endif
  208|       |
  209|       |  // Encode selected edges using separate rans bit coder for each context.
  210|    209|  for (int i = 0; i < kMaxNumParallelograms; ++i) {
  ------------------
  |  Branch (210:19): [True: 174, False: 35]
  ------------------
  211|    174|    uint32_t num_flags;
  212|    174|    if (!DecodeVarint<uint32_t>(&num_flags, buffer)) {
  ------------------
  |  Branch (212:9): [True: 0, False: 174]
  ------------------
  213|      0|      return false;
  214|      0|    }
  215|    174|    if (num_flags > this->mesh_data().corner_table()->num_corners()) {
  ------------------
  |  Branch (215:9): [True: 8, False: 166]
  ------------------
  216|      8|      return false;
  217|      8|    }
  218|    166|    if (num_flags > 0) {
  ------------------
  |  Branch (218:9): [True: 106, False: 60]
  ------------------
  219|    106|      is_crease_edge_[i].resize(num_flags);
  220|    106|      RAnsBitDecoder decoder;
  221|    106|      if (!decoder.StartDecoding(buffer)) {
  ------------------
  |  Branch (221:11): [True: 5, False: 101]
  ------------------
  222|      5|        return false;
  223|      5|      }
  224|  17.3k|      for (uint32_t j = 0; j < num_flags; ++j) {
  ------------------
  |  Branch (224:28): [True: 17.2k, False: 101]
  ------------------
  225|  17.2k|        is_crease_edge_[i][j] = decoder.DecodeNextBit();
  226|  17.2k|      }
  227|    101|      decoder.EndDecoding();
  228|    101|    }
  229|    166|  }
  230|     35|  return MeshPredictionSchemeDecoder<DataTypeT, TransformT,
  231|     35|                                     MeshDataT>::DecodePredictionData(buffer);
  232|     48|}
_ZN5draco56MeshPredictionSchemeConstrainedMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   86|     29|                          const PointIndex * /* entry_to_point_id_map */) {
   87|     29|  this->transform().Init(num_components);
   88|       |
   89|       |  // Predicted values for all simple parallelograms encountered at any given
   90|       |  // vertex.
   91|     29|  std::vector<DataTypeT> pred_vals[kMaxNumParallelograms];
   92|    145|  for (int i = 0; i < kMaxNumParallelograms; ++i) {
  ------------------
  |  Branch (92:19): [True: 116, False: 29]
  ------------------
   93|    116|    pred_vals[i].resize(num_components, 0);
   94|    116|  }
   95|     29|  this->transform().ComputeOriginalValue(pred_vals[0].data(), in_corr,
   96|     29|                                         out_data);
   97|       |
   98|     29|  const CornerTable *const table = this->mesh_data().corner_table();
   99|     29|  const std::vector<int32_t> *const vertex_to_data_map =
  100|     29|      this->mesh_data().vertex_to_data_map();
  101|       |
  102|       |  // Current position in the |is_crease_edge_| array for each context.
  103|     29|  std::vector<int> is_crease_edge_pos(kMaxNumParallelograms, 0);
  104|       |
  105|       |  // Used to store predicted value for multi-parallelogram prediction.
  106|     29|  std::vector<DataTypeT> multi_pred_vals(num_components);
  107|       |
  108|     29|  const int corner_map_size =
  109|     29|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  110|  1.87k|  for (int p = 1; p < corner_map_size; ++p) {
  ------------------
  |  Branch (110:19): [True: 1.86k, False: 13]
  ------------------
  111|  1.86k|    const CornerIndex start_corner_id =
  112|  1.86k|        this->mesh_data().data_to_corner_map()->at(p);
  113|       |
  114|  1.86k|    CornerIndex corner_id(start_corner_id);
  115|  1.86k|    int num_parallelograms = 0;
  116|  1.86k|    bool first_pass = true;
  117|  24.0k|    while (corner_id != kInvalidCornerIndex) {
  ------------------
  |  Branch (117:12): [True: 22.3k, False: 1.65k]
  ------------------
  118|  22.3k|      if (ComputeParallelogramPrediction(
  ------------------
  |  Branch (118:11): [True: 693, False: 21.6k]
  ------------------
  119|  22.3k|              p, corner_id, table, *vertex_to_data_map, out_data,
  120|  22.3k|              num_components, &(pred_vals[num_parallelograms][0]))) {
  121|       |        // Parallelogram prediction applied and stored in
  122|       |        // |pred_vals[num_parallelograms]|
  123|    693|        ++num_parallelograms;
  124|       |        // Stop processing when we reach the maximum number of allowed
  125|       |        // parallelograms.
  126|    693|        if (num_parallelograms == kMaxNumParallelograms) {
  ------------------
  |  Branch (126:13): [True: 2, False: 691]
  ------------------
  127|      2|          break;
  128|      2|        }
  129|    693|      }
  130|       |
  131|       |      // Proceed to the next corner attached to the vertex. First swing left
  132|       |      // and if we reach a boundary, swing right from the start corner.
  133|  22.3k|      if (first_pass) {
  ------------------
  |  Branch (133:11): [True: 21.5k, False: 774]
  ------------------
  134|  21.5k|        corner_id = table->SwingLeft(corner_id);
  135|  21.5k|      } else {
  136|    774|        corner_id = table->SwingRight(corner_id);
  137|    774|      }
  138|  22.3k|      if (corner_id == start_corner_id) {
  ------------------
  |  Branch (138:11): [True: 212, False: 22.1k]
  ------------------
  139|    212|        break;
  140|    212|      }
  141|  22.1k|      if (corner_id == kInvalidCornerIndex && first_pass) {
  ------------------
  |  Branch (141:11): [True: 1.94k, False: 20.2k]
  |  Branch (141:47): [True: 1.65k, False: 293]
  ------------------
  142|  1.65k|        first_pass = false;
  143|  1.65k|        corner_id = table->SwingRight(start_corner_id);
  144|  1.65k|      }
  145|  22.1k|    }
  146|       |
  147|       |    // Check which of the available parallelograms are actually used and compute
  148|       |    // the final predicted value.
  149|  1.86k|    int num_used_parallelograms = 0;
  150|  1.86k|    if (num_parallelograms > 0) {
  ------------------
  |  Branch (150:9): [True: 535, False: 1.32k]
  ------------------
  151|  34.3k|      for (int i = 0; i < num_components; ++i) {
  ------------------
  |  Branch (151:23): [True: 33.7k, False: 535]
  ------------------
  152|  33.7k|        multi_pred_vals[i] = 0;
  153|  33.7k|      }
  154|       |      // Check which parallelograms are actually used.
  155|  1.21k|      for (int i = 0; i < num_parallelograms; ++i) {
  ------------------
  |  Branch (155:23): [True: 692, False: 519]
  ------------------
  156|    692|        const int context = num_parallelograms - 1;
  157|    692|        const int pos = is_crease_edge_pos[context]++;
  158|    692|        if (is_crease_edge_[context].size() <= pos) {
  ------------------
  |  Branch (158:13): [True: 16, False: 676]
  ------------------
  159|     16|          return false;
  160|     16|        }
  161|    676|        const bool is_crease = is_crease_edge_[context][pos];
  162|    676|        if (!is_crease) {
  ------------------
  |  Branch (162:13): [True: 411, False: 265]
  ------------------
  163|    411|          ++num_used_parallelograms;
  164|  33.1k|          for (int j = 0; j < num_components; ++j) {
  ------------------
  |  Branch (164:27): [True: 32.7k, False: 411]
  ------------------
  165|  32.7k|            multi_pred_vals[j] =
  166|  32.7k|                AddAsUnsigned(multi_pred_vals[j], pred_vals[i][j]);
  167|  32.7k|          }
  168|    411|        }
  169|    676|      }
  170|    535|    }
  171|  1.84k|    const int dst_offset = p * num_components;
  172|  1.84k|    if (num_used_parallelograms == 0) {
  ------------------
  |  Branch (172:9): [True: 1.47k, False: 378]
  ------------------
  173|       |      // No parallelogram was valid.
  174|       |      // We use the last decoded point as a reference.
  175|  1.47k|      const int src_offset = (p - 1) * num_components;
  176|  1.47k|      this->transform().ComputeOriginalValue(
  177|  1.47k|          out_data + src_offset, in_corr + dst_offset, out_data + dst_offset);
  178|  1.47k|    } else {
  179|       |      // Compute the correction from the predicted value.
  180|  27.8k|      for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (180:23): [True: 27.4k, False: 378]
  ------------------
  181|  27.4k|        multi_pred_vals[c] /= num_used_parallelograms;
  182|  27.4k|      }
  183|    378|      this->transform().ComputeOriginalValue(
  184|    378|          multi_pred_vals.data(), in_corr + dst_offset, out_data + dst_offset);
  185|    378|    }
  186|  1.84k|  }
  187|     13|  return true;
  188|     29|}
_ZN5draco56MeshPredictionSchemeConstrainedMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   52|     47|        selected_mode_(Mode::OPTIMAL_MULTI_PARALLELOGRAM) {}
_ZN5draco56MeshPredictionSchemeConstrainedMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  193|     47|                                                                *buffer) {
  194|     47|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  195|     47|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|     47|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (195:7): [True: 0, False: 47]
  ------------------
  196|       |    // Decode prediction mode.
  197|      0|    uint8_t mode;
  198|      0|    if (!buffer->Decode(&mode)) {
  ------------------
  |  Branch (198:9): [True: 0, False: 0]
  ------------------
  199|      0|      return false;
  200|      0|    }
  201|       |
  202|      0|    if (mode != Mode::OPTIMAL_MULTI_PARALLELOGRAM) {
  ------------------
  |  Branch (202:9): [True: 0, False: 0]
  ------------------
  203|       |      // Unsupported mode.
  204|      0|      return false;
  205|      0|    }
  206|      0|  }
  207|     47|#endif
  208|       |
  209|       |  // Encode selected edges using separate rans bit coder for each context.
  210|    171|  for (int i = 0; i < kMaxNumParallelograms; ++i) {
  ------------------
  |  Branch (210:19): [True: 148, False: 23]
  ------------------
  211|    148|    uint32_t num_flags;
  212|    148|    if (!DecodeVarint<uint32_t>(&num_flags, buffer)) {
  ------------------
  |  Branch (212:9): [True: 0, False: 148]
  ------------------
  213|      0|      return false;
  214|      0|    }
  215|    148|    if (num_flags > this->mesh_data().corner_table()->num_corners()) {
  ------------------
  |  Branch (215:9): [True: 22, False: 126]
  ------------------
  216|     22|      return false;
  217|     22|    }
  218|    126|    if (num_flags > 0) {
  ------------------
  |  Branch (218:9): [True: 67, False: 59]
  ------------------
  219|     67|      is_crease_edge_[i].resize(num_flags);
  220|     67|      RAnsBitDecoder decoder;
  221|     67|      if (!decoder.StartDecoding(buffer)) {
  ------------------
  |  Branch (221:11): [True: 2, False: 65]
  ------------------
  222|      2|        return false;
  223|      2|      }
  224|  25.2k|      for (uint32_t j = 0; j < num_flags; ++j) {
  ------------------
  |  Branch (224:28): [True: 25.1k, False: 65]
  ------------------
  225|  25.1k|        is_crease_edge_[i][j] = decoder.DecodeNextBit();
  226|  25.1k|      }
  227|     65|      decoder.EndDecoding();
  228|     65|    }
  229|    126|  }
  230|     23|  return MeshPredictionSchemeDecoder<DataTypeT, TransformT,
  231|     23|                                     MeshDataT>::DecodePredictionData(buffer);
  232|     47|}
_ZN5draco56MeshPredictionSchemeConstrainedMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   86|     21|                          const PointIndex * /* entry_to_point_id_map */) {
   87|     21|  this->transform().Init(num_components);
   88|       |
   89|       |  // Predicted values for all simple parallelograms encountered at any given
   90|       |  // vertex.
   91|     21|  std::vector<DataTypeT> pred_vals[kMaxNumParallelograms];
   92|    105|  for (int i = 0; i < kMaxNumParallelograms; ++i) {
  ------------------
  |  Branch (92:19): [True: 84, False: 21]
  ------------------
   93|     84|    pred_vals[i].resize(num_components, 0);
   94|     84|  }
   95|     21|  this->transform().ComputeOriginalValue(pred_vals[0].data(), in_corr,
   96|     21|                                         out_data);
   97|       |
   98|     21|  const CornerTable *const table = this->mesh_data().corner_table();
   99|     21|  const std::vector<int32_t> *const vertex_to_data_map =
  100|     21|      this->mesh_data().vertex_to_data_map();
  101|       |
  102|       |  // Current position in the |is_crease_edge_| array for each context.
  103|     21|  std::vector<int> is_crease_edge_pos(kMaxNumParallelograms, 0);
  104|       |
  105|       |  // Used to store predicted value for multi-parallelogram prediction.
  106|     21|  std::vector<DataTypeT> multi_pred_vals(num_components);
  107|       |
  108|     21|  const int corner_map_size =
  109|     21|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  110|    542|  for (int p = 1; p < corner_map_size; ++p) {
  ------------------
  |  Branch (110:19): [True: 533, False: 9]
  ------------------
  111|    533|    const CornerIndex start_corner_id =
  112|    533|        this->mesh_data().data_to_corner_map()->at(p);
  113|       |
  114|    533|    CornerIndex corner_id(start_corner_id);
  115|    533|    int num_parallelograms = 0;
  116|    533|    bool first_pass = true;
  117|  2.67k|    while (corner_id != kInvalidCornerIndex) {
  ------------------
  |  Branch (117:12): [True: 2.50k, False: 178]
  ------------------
  118|  2.50k|      if (ComputeParallelogramPrediction(
  ------------------
  |  Branch (118:11): [True: 641, False: 1.85k]
  ------------------
  119|  2.50k|              p, corner_id, table, *vertex_to_data_map, out_data,
  120|  2.50k|              num_components, &(pred_vals[num_parallelograms][0]))) {
  121|       |        // Parallelogram prediction applied and stored in
  122|       |        // |pred_vals[num_parallelograms]|
  123|    641|        ++num_parallelograms;
  124|       |        // Stop processing when we reach the maximum number of allowed
  125|       |        // parallelograms.
  126|    641|        if (num_parallelograms == kMaxNumParallelograms) {
  ------------------
  |  Branch (126:13): [True: 5, False: 636]
  ------------------
  127|      5|          break;
  128|      5|        }
  129|    641|      }
  130|       |
  131|       |      // Proceed to the next corner attached to the vertex. First swing left
  132|       |      // and if we reach a boundary, swing right from the start corner.
  133|  2.49k|      if (first_pass) {
  ------------------
  |  Branch (133:11): [True: 2.25k, False: 244]
  ------------------
  134|  2.25k|        corner_id = table->SwingLeft(corner_id);
  135|  2.25k|      } else {
  136|    244|        corner_id = table->SwingRight(corner_id);
  137|    244|      }
  138|  2.49k|      if (corner_id == start_corner_id) {
  ------------------
  |  Branch (138:11): [True: 350, False: 2.14k]
  ------------------
  139|    350|        break;
  140|    350|      }
  141|  2.14k|      if (corner_id == kInvalidCornerIndex && first_pass) {
  ------------------
  |  Branch (141:11): [True: 263, False: 1.88k]
  |  Branch (141:47): [True: 182, False: 81]
  ------------------
  142|    182|        first_pass = false;
  143|    182|        corner_id = table->SwingRight(start_corner_id);
  144|    182|      }
  145|  2.14k|    }
  146|       |
  147|       |    // Check which of the available parallelograms are actually used and compute
  148|       |    // the final predicted value.
  149|    533|    int num_used_parallelograms = 0;
  150|    533|    if (num_parallelograms > 0) {
  ------------------
  |  Branch (150:9): [True: 385, False: 148]
  ------------------
  151|  23.6k|      for (int i = 0; i < num_components; ++i) {
  ------------------
  |  Branch (151:23): [True: 23.2k, False: 385]
  ------------------
  152|  23.2k|        multi_pred_vals[i] = 0;
  153|  23.2k|      }
  154|       |      // Check which parallelograms are actually used.
  155|  1.01k|      for (int i = 0; i < num_parallelograms; ++i) {
  ------------------
  |  Branch (155:23): [True: 637, False: 373]
  ------------------
  156|    637|        const int context = num_parallelograms - 1;
  157|    637|        const int pos = is_crease_edge_pos[context]++;
  158|    637|        if (is_crease_edge_[context].size() <= pos) {
  ------------------
  |  Branch (158:13): [True: 12, False: 625]
  ------------------
  159|     12|          return false;
  160|     12|        }
  161|    625|        const bool is_crease = is_crease_edge_[context][pos];
  162|    625|        if (!is_crease) {
  ------------------
  |  Branch (162:13): [True: 251, False: 374]
  ------------------
  163|    251|          ++num_used_parallelograms;
  164|  16.8k|          for (int j = 0; j < num_components; ++j) {
  ------------------
  |  Branch (164:27): [True: 16.6k, False: 251]
  ------------------
  165|  16.6k|            multi_pred_vals[j] =
  166|  16.6k|                AddAsUnsigned(multi_pred_vals[j], pred_vals[i][j]);
  167|  16.6k|          }
  168|    251|        }
  169|    625|      }
  170|    385|    }
  171|    521|    const int dst_offset = p * num_components;
  172|    521|    if (num_used_parallelograms == 0) {
  ------------------
  |  Branch (172:9): [True: 352, False: 169]
  ------------------
  173|       |      // No parallelogram was valid.
  174|       |      // We use the last decoded point as a reference.
  175|    352|      const int src_offset = (p - 1) * num_components;
  176|    352|      this->transform().ComputeOriginalValue(
  177|    352|          out_data + src_offset, in_corr + dst_offset, out_data + dst_offset);
  178|    352|    } else {
  179|       |      // Compute the correction from the predicted value.
  180|  11.5k|      for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (180:23): [True: 11.3k, False: 169]
  ------------------
  181|  11.3k|        multi_pred_vals[c] /= num_used_parallelograms;
  182|  11.3k|      }
  183|    169|      this->transform().ComputeOriginalValue(
  184|    169|          multi_pred_vals.data(), in_corr + dst_offset, out_data + dst_offset);
  185|    169|    }
  186|    521|  }
  187|      9|  return true;
  188|     21|}

_ZN5draco24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEE3SetEPKNS_4MeshEPKS1_PKNSt3__16vectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEENS8_9allocatorISC_EEEEPKNS9_IiNSD_IiEEEE:
   37|    201|           const std::vector<int32_t> *vertex_to_data_map) {
   38|    201|    mesh_ = mesh;
   39|    201|    corner_table_ = table;
   40|    201|    data_to_corner_map_ = data_to_corner_map;
   41|    201|    vertex_to_data_map_ = vertex_to_data_map;
   42|    201|  }
_ZNK5draco24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEE12corner_tableEv:
   45|  30.7k|  const CornerTable *corner_table() const { return corner_table_; }
_ZNK5draco24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEE18vertex_to_data_mapEv:
   46|  24.8k|  const std::vector<int32_t> *vertex_to_data_map() const {
   47|  24.8k|    return vertex_to_data_map_;
   48|  24.8k|  }
_ZNK5draco24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEE18data_to_corner_mapEv:
   49|   109k|  const std::vector<CornerIndex> *data_to_corner_map() const {
   50|   109k|    return data_to_corner_map_;
   51|   109k|  }
_ZN5draco24MeshPredictionSchemeDataINS_11CornerTableEE3SetEPKNS_4MeshEPKS1_PKNSt3__16vectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEENS8_9allocatorISC_EEEEPKNS9_IiNSD_IiEEEE:
   37|    316|           const std::vector<int32_t> *vertex_to_data_map) {
   38|    316|    mesh_ = mesh;
   39|    316|    corner_table_ = table;
   40|    316|    data_to_corner_map_ = data_to_corner_map;
   41|    316|    vertex_to_data_map_ = vertex_to_data_map;
   42|    316|  }
_ZNK5draco24MeshPredictionSchemeDataINS_11CornerTableEE12corner_tableEv:
   45|   321k|  const CornerTable *corner_table() const { return corner_table_; }
_ZNK5draco24MeshPredictionSchemeDataINS_11CornerTableEE18vertex_to_data_mapEv:
   46|   173k|  const std::vector<int32_t> *vertex_to_data_map() const {
   47|   173k|    return vertex_to_data_map_;
   48|   173k|  }
_ZNK5draco24MeshPredictionSchemeDataINS_11CornerTableEE18data_to_corner_mapEv:
   49|   148k|  const std::vector<CornerIndex> *data_to_corner_map() const {
   50|   148k|    return data_to_corner_map_;
   51|   148k|  }
_ZN5draco24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEC2Ev:
   33|    201|        data_to_corner_map_(nullptr) {}
_ZN5draco24MeshPredictionSchemeDataINS_11CornerTableEEC2Ev:
   33|    316|        data_to_corner_map_(nullptr) {}

_ZN5draco27MeshPredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   35|    200|        mesh_data_(mesh_data) {}
_ZNK5draco27MeshPredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE9mesh_dataEv:
   38|   113k|  const MeshData &mesh_data() const { return mesh_data_; }
_ZN5draco27MeshPredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   35|    316|        mesh_data_(mesh_data) {}
_ZNK5draco27MeshPredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE9mesh_dataEv:
   38|   543k|  const MeshData &mesh_data() const { return mesh_data_; }

_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   37|     75|        predictor_(mesh_data) {}
_ZNK5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE22GetNumParentAttributesEv:
   66|    150|  int GetNumParentAttributes() const override { return 1; }
_ZNK5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE22GetParentAttributeTypeEi:
   68|     75|  GeometryAttribute::Type GetParentAttributeType(int i) const override {
   69|     75|    DRACO_DCHECK_EQ(i, 0);
   70|     75|    (void)i;
   71|     75|    return GeometryAttribute::POSITION;
   72|     75|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE18SetParentAttributeEPKNS_14PointAttributeE:
   74|     75|  bool SetParentAttribute(const PointAttribute *att) override {
   75|     75|    if (att->attribute_type() != GeometryAttribute::POSITION) {
  ------------------
  |  Branch (75:9): [True: 0, False: 75]
  ------------------
   76|      0|      return false;  // Invalid attribute type.
   77|      0|    }
   78|     75|    if (att->num_components() != 3) {
  ------------------
  |  Branch (78:9): [True: 0, False: 75]
  ------------------
   79|      0|      return false;  // Currently works only for 3 component positions.
   80|      0|    }
   81|     75|    predictor_.SetPositionAttribute(*att);
   82|     75|    return true;
   83|     75|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  142|     67|                                                                *buffer) {
  143|       |  // Get data needed for transform
  144|     67|  if (!this->transform().DecodeTransformData(buffer)) {
  ------------------
  |  Branch (144:7): [True: 1, False: 66]
  ------------------
  145|      1|    return false;
  146|      1|  }
  147|       |
  148|     66|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  149|     66|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|     66|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (149:7): [True: 49, False: 17]
  ------------------
  150|     49|    uint8_t prediction_mode;
  151|     49|    if (!buffer->Decode(&prediction_mode)) {
  ------------------
  |  Branch (151:9): [True: 0, False: 49]
  ------------------
  152|      0|      return false;
  153|      0|    }
  154|     49|    if (prediction_mode > TRIANGLE_AREA) {
  ------------------
  |  Branch (154:9): [True: 1, False: 48]
  ------------------
  155|       |      // Invalid prediction mode.
  156|      1|      return false;
  157|      1|    }
  158|       |
  159|     48|    if (!predictor_.SetNormalPredictionMode(
  ------------------
  |  Branch (159:9): [True: 0, False: 48]
  ------------------
  160|     48|            NormalPredictionMode(prediction_mode))) {
  161|      0|      return false;
  162|      0|    }
  163|     48|  }
  164|     65|#endif
  165|       |
  166|       |  // Init normal flips.
  167|     65|  if (!flip_normal_bit_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (167:7): [True: 2, False: 63]
  ------------------
  168|      2|    return false;
  169|      2|  }
  170|       |
  171|     63|  return true;
  172|     65|}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
  102|     63|                                      const PointIndex *entry_to_point_id_map) {
  103|     63|  this->SetQuantizationBits(this->transform().quantization_bits());
  104|     63|  predictor_.SetEntryToPointIdMap(entry_to_point_id_map);
  105|     63|  DRACO_DCHECK(this->IsInitialized());
  106|       |
  107|       |  // Expecting in_data in octahedral coordinates, i.e., portable attribute.
  108|     63|  DRACO_DCHECK_EQ(num_components, 2);
  109|       |
  110|     63|  const int corner_map_size =
  111|     63|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  112|       |
  113|     63|  VectorD<int32_t, 3> pred_normal_3d;
  114|     63|  int32_t pred_normal_oct[2];
  115|       |
  116|  2.32k|  for (int data_id = 0; data_id < corner_map_size; ++data_id) {
  ------------------
  |  Branch (116:25): [True: 2.25k, False: 63]
  ------------------
  117|  2.25k|    const CornerIndex corner_id =
  118|  2.25k|        this->mesh_data().data_to_corner_map()->at(data_id);
  119|  2.25k|    predictor_.ComputePredictedValue(corner_id, pred_normal_3d.data());
  120|       |
  121|       |    // Compute predicted octahedral coordinates.
  122|  2.25k|    octahedron_tool_box_.CanonicalizeIntegerVector(pred_normal_3d.data());
  123|  2.25k|    DRACO_DCHECK_EQ(pred_normal_3d.AbsSum(),
  124|  2.25k|                    octahedron_tool_box_.center_value());
  125|  2.25k|    if (flip_normal_bit_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (125:9): [True: 1.38k, False: 871]
  ------------------
  126|  1.38k|      pred_normal_3d = -pred_normal_3d;
  127|  1.38k|    }
  128|  2.25k|    octahedron_tool_box_.IntegerVectorToQuantizedOctahedralCoords(
  129|  2.25k|        pred_normal_3d.data(), pred_normal_oct, pred_normal_oct + 1);
  130|       |
  131|  2.25k|    const int data_offset = data_id * 2;
  132|  2.25k|    this->transform().ComputeOriginalValue(
  133|  2.25k|        pred_normal_oct, in_corr + data_offset, out_data + data_offset);
  134|  2.25k|  }
  135|     63|  flip_normal_bit_decoder_.EndDecoding();
  136|     63|  return true;
  137|     63|}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE19SetQuantizationBitsEi:
   84|     63|  void SetQuantizationBits(int q) {
   85|     63|    octahedron_tool_box_.SetQuantizationBits(q);
   86|     63|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   37|     69|        predictor_(mesh_data) {}
_ZNK5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE22GetNumParentAttributesEv:
   66|    138|  int GetNumParentAttributes() const override { return 1; }
_ZNK5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE22GetParentAttributeTypeEi:
   68|     69|  GeometryAttribute::Type GetParentAttributeType(int i) const override {
   69|     69|    DRACO_DCHECK_EQ(i, 0);
   70|     69|    (void)i;
   71|     69|    return GeometryAttribute::POSITION;
   72|     69|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE18SetParentAttributeEPKNS_14PointAttributeE:
   74|     69|  bool SetParentAttribute(const PointAttribute *att) override {
   75|     69|    if (att->attribute_type() != GeometryAttribute::POSITION) {
  ------------------
  |  Branch (75:9): [True: 0, False: 69]
  ------------------
   76|      0|      return false;  // Invalid attribute type.
   77|      0|    }
   78|     69|    if (att->num_components() != 3) {
  ------------------
  |  Branch (78:9): [True: 0, False: 69]
  ------------------
   79|      0|      return false;  // Currently works only for 3 component positions.
   80|      0|    }
   81|     69|    predictor_.SetPositionAttribute(*att);
   82|     69|    return true;
   83|     69|  }
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  142|     69|                                                                *buffer) {
  143|       |  // Get data needed for transform
  144|     69|  if (!this->transform().DecodeTransformData(buffer)) {
  ------------------
  |  Branch (144:7): [True: 2, False: 67]
  ------------------
  145|      2|    return false;
  146|      2|  }
  147|       |
  148|     67|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  149|     67|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|     67|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (149:7): [True: 30, False: 37]
  ------------------
  150|     30|    uint8_t prediction_mode;
  151|     30|    if (!buffer->Decode(&prediction_mode)) {
  ------------------
  |  Branch (151:9): [True: 0, False: 30]
  ------------------
  152|      0|      return false;
  153|      0|    }
  154|     30|    if (prediction_mode > TRIANGLE_AREA) {
  ------------------
  |  Branch (154:9): [True: 2, False: 28]
  ------------------
  155|       |      // Invalid prediction mode.
  156|      2|      return false;
  157|      2|    }
  158|       |
  159|     28|    if (!predictor_.SetNormalPredictionMode(
  ------------------
  |  Branch (159:9): [True: 0, False: 28]
  ------------------
  160|     28|            NormalPredictionMode(prediction_mode))) {
  161|      0|      return false;
  162|      0|    }
  163|     28|  }
  164|     65|#endif
  165|       |
  166|       |  // Init normal flips.
  167|     65|  if (!flip_normal_bit_decoder_.StartDecoding(buffer)) {
  ------------------
  |  Branch (167:7): [True: 3, False: 62]
  ------------------
  168|      3|    return false;
  169|      3|  }
  170|       |
  171|     62|  return true;
  172|     65|}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
  102|     62|                                      const PointIndex *entry_to_point_id_map) {
  103|     62|  this->SetQuantizationBits(this->transform().quantization_bits());
  104|     62|  predictor_.SetEntryToPointIdMap(entry_to_point_id_map);
  105|     62|  DRACO_DCHECK(this->IsInitialized());
  106|       |
  107|       |  // Expecting in_data in octahedral coordinates, i.e., portable attribute.
  108|     62|  DRACO_DCHECK_EQ(num_components, 2);
  109|       |
  110|     62|  const int corner_map_size =
  111|     62|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  112|       |
  113|     62|  VectorD<int32_t, 3> pred_normal_3d;
  114|     62|  int32_t pred_normal_oct[2];
  115|       |
  116|  3.53k|  for (int data_id = 0; data_id < corner_map_size; ++data_id) {
  ------------------
  |  Branch (116:25): [True: 3.46k, False: 62]
  ------------------
  117|  3.46k|    const CornerIndex corner_id =
  118|  3.46k|        this->mesh_data().data_to_corner_map()->at(data_id);
  119|  3.46k|    predictor_.ComputePredictedValue(corner_id, pred_normal_3d.data());
  120|       |
  121|       |    // Compute predicted octahedral coordinates.
  122|  3.46k|    octahedron_tool_box_.CanonicalizeIntegerVector(pred_normal_3d.data());
  123|  3.46k|    DRACO_DCHECK_EQ(pred_normal_3d.AbsSum(),
  124|  3.46k|                    octahedron_tool_box_.center_value());
  125|  3.46k|    if (flip_normal_bit_decoder_.DecodeNextBit()) {
  ------------------
  |  Branch (125:9): [True: 2.28k, False: 1.18k]
  ------------------
  126|  2.28k|      pred_normal_3d = -pred_normal_3d;
  127|  2.28k|    }
  128|  3.46k|    octahedron_tool_box_.IntegerVectorToQuantizedOctahedralCoords(
  129|  3.46k|        pred_normal_3d.data(), pred_normal_oct, pred_normal_oct + 1);
  130|       |
  131|  3.46k|    const int data_offset = data_id * 2;
  132|  3.46k|    this->transform().ComputeOriginalValue(
  133|  3.46k|        pred_normal_oct, in_corr + data_offset, out_data + data_offset);
  134|  3.46k|  }
  135|     62|  flip_normal_bit_decoder_.EndDecoding();
  136|     62|  return true;
  137|     62|}
_ZN5draco42MeshPredictionSchemeGeometricNormalDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE19SetQuantizationBitsEi:
   84|     62|  void SetQuantizationBits(int q) {
   85|     62|    octahedron_tool_box_.SetQuantizationBits(q);
   86|     62|  }

_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2ERKS5_:
   34|     75|      : Base(md) {
   35|     75|    this->SetNormalPredictionMode(TRIANGLE_AREA);
   36|     75|  };
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE23SetNormalPredictionModeENS_20NormalPredictionModeE:
  103|    123|  bool SetNormalPredictionMode(NormalPredictionMode mode) override {
  104|    123|    if (mode == ONE_TRIANGLE) {
  ------------------
  |  Branch (104:9): [True: 40, False: 83]
  ------------------
  105|     40|      this->normal_prediction_mode_ = mode;
  106|     40|      return true;
  107|     83|    } else if (mode == TRIANGLE_AREA) {
  ------------------
  |  Branch (107:16): [True: 83, False: 0]
  ------------------
  108|     83|      this->normal_prediction_mode_ = mode;
  109|     83|      return true;
  110|     83|    }
  111|      0|    return false;
  112|    123|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputePredictedValueENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPi:
   41|  2.25k|                             DataTypeT *prediction) override {
   42|  2.25k|    DRACO_DCHECK(this->IsInitialized());
   43|  2.25k|    typedef typename MeshDataT::CornerTable CornerTable;
   44|  2.25k|    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|  2.25k|    VertexCornersIterator<CornerTable> cit(corner_table, corner_id);
   48|       |    // Position of central vertex does not change in loop.
   49|  2.25k|    const VectorD<int64_t, 3> pos_cent = this->GetPositionForCorner(corner_id);
   50|       |    // Computing normals for triangles and adding them up.
   51|       |
   52|  2.25k|    VectorD<int64_t, 3> normal;
   53|  2.25k|    CornerIndex c_next, c_prev;
   54|  11.7k|    while (!cit.End()) {
  ------------------
  |  Branch (54:12): [True: 9.53k, False: 2.25k]
  ------------------
   55|       |      // Getting corners.
   56|  9.53k|      if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
  ------------------
  |  Branch (56:11): [True: 4.94k, False: 4.58k]
  ------------------
   57|  4.94k|        c_next = corner_table->Next(corner_id);
   58|  4.94k|        c_prev = corner_table->Previous(corner_id);
   59|  4.94k|      } else {
   60|  4.58k|        c_next = corner_table->Next(cit.Corner());
   61|  4.58k|        c_prev = corner_table->Previous(cit.Corner());
   62|  4.58k|      }
   63|  9.53k|      const VectorD<int64_t, 3> pos_next = this->GetPositionForCorner(c_next);
   64|  9.53k|      const VectorD<int64_t, 3> pos_prev = this->GetPositionForCorner(c_prev);
   65|       |
   66|       |      // Computing delta vectors to next and prev.
   67|  9.53k|      const VectorD<int64_t, 3> delta_next = pos_next - pos_cent;
   68|  9.53k|      const VectorD<int64_t, 3> delta_prev = pos_prev - pos_cent;
   69|       |
   70|       |      // Computing cross product.
   71|  9.53k|      const VectorD<int64_t, 3> cross = CrossProduct(delta_next, delta_prev);
   72|       |
   73|       |      // Prevent signed integer overflows by doing math as unsigned.
   74|  9.53k|      auto normal_data = reinterpret_cast<uint64_t *>(normal.data());
   75|  9.53k|      auto cross_data = reinterpret_cast<const uint64_t *>(cross.data());
   76|  9.53k|      normal_data[0] = normal_data[0] + cross_data[0];
   77|  9.53k|      normal_data[1] = normal_data[1] + cross_data[1];
   78|  9.53k|      normal_data[2] = normal_data[2] + cross_data[2];
   79|       |
   80|  9.53k|      cit.Next();
   81|  9.53k|    }
   82|       |
   83|       |    // Convert to int32_t, make sure entries are not too large.
   84|  2.25k|    constexpr int64_t upper_bound = 1 << 29;
   85|  2.25k|    if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
  ------------------
  |  Branch (85:9): [True: 919, False: 1.33k]
  ------------------
   86|    919|      const int32_t abs_sum = static_cast<int32_t>(normal.AbsSum());
   87|    919|      if (abs_sum > upper_bound) {
  ------------------
  |  Branch (87:11): [True: 194, False: 725]
  ------------------
   88|    194|        const int64_t quotient = abs_sum / upper_bound;
   89|    194|        normal = normal / quotient;
   90|    194|      }
   91|  1.33k|    } else {
   92|  1.33k|      const int64_t abs_sum = normal.AbsSum();
   93|  1.33k|      if (abs_sum > upper_bound) {
  ------------------
  |  Branch (93:11): [True: 1.04k, False: 298]
  ------------------
   94|  1.04k|        const int64_t quotient = abs_sum / upper_bound;
   95|  1.04k|        normal = normal / quotient;
   96|  1.04k|      }
   97|  1.33k|    }
   98|  2.25k|    DRACO_DCHECK_LE(normal.AbsSum(), upper_bound);
   99|  2.25k|    prediction[0] = static_cast<int32_t>(normal[0]);
  100|  2.25k|    prediction[1] = static_cast<int32_t>(normal[1]);
  101|  2.25k|    prediction[2] = static_cast<int32_t>(normal[2]);
  102|  2.25k|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2ERKS5_:
   34|     69|      : Base(md) {
   35|     69|    this->SetNormalPredictionMode(TRIANGLE_AREA);
   36|     69|  };
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE23SetNormalPredictionModeENS_20NormalPredictionModeE:
  103|     97|  bool SetNormalPredictionMode(NormalPredictionMode mode) override {
  104|     97|    if (mode == ONE_TRIANGLE) {
  ------------------
  |  Branch (104:9): [True: 25, False: 72]
  ------------------
  105|     25|      this->normal_prediction_mode_ = mode;
  106|     25|      return true;
  107|     72|    } else if (mode == TRIANGLE_AREA) {
  ------------------
  |  Branch (107:16): [True: 72, False: 0]
  ------------------
  108|     72|      this->normal_prediction_mode_ = mode;
  109|     72|      return true;
  110|     72|    }
  111|      0|    return false;
  112|     97|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorAreaIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputePredictedValueENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPi:
   41|  3.46k|                             DataTypeT *prediction) override {
   42|  3.46k|    DRACO_DCHECK(this->IsInitialized());
   43|  3.46k|    typedef typename MeshDataT::CornerTable CornerTable;
   44|  3.46k|    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|  3.46k|    VertexCornersIterator<CornerTable> cit(corner_table, corner_id);
   48|       |    // Position of central vertex does not change in loop.
   49|  3.46k|    const VectorD<int64_t, 3> pos_cent = this->GetPositionForCorner(corner_id);
   50|       |    // Computing normals for triangles and adding them up.
   51|       |
   52|  3.46k|    VectorD<int64_t, 3> normal;
   53|  3.46k|    CornerIndex c_next, c_prev;
   54|  16.1k|    while (!cit.End()) {
  ------------------
  |  Branch (54:12): [True: 12.6k, False: 3.46k]
  ------------------
   55|       |      // Getting corners.
   56|  12.6k|      if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
  ------------------
  |  Branch (56:11): [True: 3.52k, False: 9.17k]
  ------------------
   57|  3.52k|        c_next = corner_table->Next(corner_id);
   58|  3.52k|        c_prev = corner_table->Previous(corner_id);
   59|  9.17k|      } else {
   60|  9.17k|        c_next = corner_table->Next(cit.Corner());
   61|  9.17k|        c_prev = corner_table->Previous(cit.Corner());
   62|  9.17k|      }
   63|  12.6k|      const VectorD<int64_t, 3> pos_next = this->GetPositionForCorner(c_next);
   64|  12.6k|      const VectorD<int64_t, 3> pos_prev = this->GetPositionForCorner(c_prev);
   65|       |
   66|       |      // Computing delta vectors to next and prev.
   67|  12.6k|      const VectorD<int64_t, 3> delta_next = pos_next - pos_cent;
   68|  12.6k|      const VectorD<int64_t, 3> delta_prev = pos_prev - pos_cent;
   69|       |
   70|       |      // Computing cross product.
   71|  12.6k|      const VectorD<int64_t, 3> cross = CrossProduct(delta_next, delta_prev);
   72|       |
   73|       |      // Prevent signed integer overflows by doing math as unsigned.
   74|  12.6k|      auto normal_data = reinterpret_cast<uint64_t *>(normal.data());
   75|  12.6k|      auto cross_data = reinterpret_cast<const uint64_t *>(cross.data());
   76|  12.6k|      normal_data[0] = normal_data[0] + cross_data[0];
   77|  12.6k|      normal_data[1] = normal_data[1] + cross_data[1];
   78|  12.6k|      normal_data[2] = normal_data[2] + cross_data[2];
   79|       |
   80|  12.6k|      cit.Next();
   81|  12.6k|    }
   82|       |
   83|       |    // Convert to int32_t, make sure entries are not too large.
   84|  3.46k|    constexpr int64_t upper_bound = 1 << 29;
   85|  3.46k|    if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
  ------------------
  |  Branch (85:9): [True: 683, False: 2.78k]
  ------------------
   86|    683|      const int32_t abs_sum = static_cast<int32_t>(normal.AbsSum());
   87|    683|      if (abs_sum > upper_bound) {
  ------------------
  |  Branch (87:11): [True: 113, False: 570]
  ------------------
   88|    113|        const int64_t quotient = abs_sum / upper_bound;
   89|    113|        normal = normal / quotient;
   90|    113|      }
   91|  2.78k|    } else {
   92|  2.78k|      const int64_t abs_sum = normal.AbsSum();
   93|  2.78k|      if (abs_sum > upper_bound) {
  ------------------
  |  Branch (93:11): [True: 1.33k, False: 1.45k]
  ------------------
   94|  1.33k|        const int64_t quotient = abs_sum / upper_bound;
   95|  1.33k|        normal = normal / quotient;
   96|  1.33k|      }
   97|  2.78k|    }
   98|  3.46k|    DRACO_DCHECK_LE(normal.AbsSum(), upper_bound);
   99|  3.46k|    prediction[0] = static_cast<int32_t>(normal[0]);
  100|  3.46k|    prediction[1] = static_cast<int32_t>(normal[1]);
  101|  3.46k|    prediction[2] = static_cast<int32_t>(normal[2]);
  102|  3.46k|  }

_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2ERKS5_:
   37|     75|        mesh_data_(md) {}
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEED2Ev:
   38|     75|  virtual ~MeshPredictionSchemeGeometricNormalPredictorBase() {}
_ZNK5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20GetPositionForCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   71|  21.3k|  VectorD<int64_t, 3> GetPositionForCorner(CornerIndex ci) const {
   72|  21.3k|    DRACO_DCHECK(this->IsInitialized());
   73|  21.3k|    const auto corner_table = mesh_data_.corner_table();
   74|  21.3k|    const auto vert_id = corner_table->Vertex(ci).value();
   75|  21.3k|    const auto data_id = mesh_data_.vertex_to_data_map()->at(vert_id);
   76|  21.3k|    return GetPositionForDataId(data_id);
   77|  21.3k|  }
_ZNK5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20GetPositionForDataIdEi:
   63|  21.3k|  VectorD<int64_t, 3> GetPositionForDataId(int data_id) const {
   64|  21.3k|    DRACO_DCHECK(this->IsInitialized());
   65|  21.3k|    const auto point_id = entry_to_point_id_map_[data_id];
   66|  21.3k|    const auto pos_val_id = pos_attribute_->mapped_index(point_id);
   67|  21.3k|    VectorD<int64_t, 3> pos;
   68|  21.3k|    pos_attribute_->ConvertValue(pos_val_id, &pos[0]);
   69|  21.3k|    return pos;
   70|  21.3k|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20SetPositionAttributeERKNS_14PointAttributeE:
   41|     75|  void SetPositionAttribute(const PointAttribute &position_attribute) {
   42|     75|    pos_attribute_ = &position_attribute;
   43|     75|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20SetEntryToPointIdMapEPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   44|     63|  void SetEntryToPointIdMap(const PointIndex *map) {
   45|     63|    entry_to_point_id_map_ = map;
   46|     63|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2ERKS5_:
   37|     69|        mesh_data_(md) {}
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEED2Ev:
   38|     69|  virtual ~MeshPredictionSchemeGeometricNormalPredictorBase() {}
_ZNK5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20GetPositionForCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   71|  28.8k|  VectorD<int64_t, 3> GetPositionForCorner(CornerIndex ci) const {
   72|  28.8k|    DRACO_DCHECK(this->IsInitialized());
   73|  28.8k|    const auto corner_table = mesh_data_.corner_table();
   74|  28.8k|    const auto vert_id = corner_table->Vertex(ci).value();
   75|  28.8k|    const auto data_id = mesh_data_.vertex_to_data_map()->at(vert_id);
   76|  28.8k|    return GetPositionForDataId(data_id);
   77|  28.8k|  }
_ZNK5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20GetPositionForDataIdEi:
   63|  28.8k|  VectorD<int64_t, 3> GetPositionForDataId(int data_id) const {
   64|  28.8k|    DRACO_DCHECK(this->IsInitialized());
   65|  28.8k|    const auto point_id = entry_to_point_id_map_[data_id];
   66|  28.8k|    const auto pos_val_id = pos_attribute_->mapped_index(point_id);
   67|  28.8k|    VectorD<int64_t, 3> pos;
   68|  28.8k|    pos_attribute_->ConvertValue(pos_val_id, &pos[0]);
   69|  28.8k|    return pos;
   70|  28.8k|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20SetPositionAttributeERKNS_14PointAttributeE:
   41|     69|  void SetPositionAttribute(const PointAttribute &position_attribute) {
   42|     69|    pos_attribute_ = &position_attribute;
   43|     69|  }
_ZN5draco48MeshPredictionSchemeGeometricNormalPredictorBaseIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20SetEntryToPointIdMapEPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   44|     62|  void SetEntryToPointIdMap(const PointIndex *map) {
   45|     62|    entry_to_point_id_map_ = map;
   46|     62|  }

_ZN5draco45MeshPredictionSchemeMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   44|     34|            attribute, transform, mesh_data) {}
_ZN5draco45MeshPredictionSchemeMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   63|     33|                          const PointIndex * /* entry_to_point_id_map */) {
   64|     33|  this->transform().Init(num_components);
   65|       |
   66|       |  // For storage of prediction values (already initialized to zero).
   67|     33|  std::unique_ptr<DataTypeT[]> pred_vals(new DataTypeT[num_components]());
   68|     33|  std::unique_ptr<DataTypeT[]> parallelogram_pred_vals(
   69|     33|      new DataTypeT[num_components]());
   70|       |
   71|     33|  this->transform().ComputeOriginalValue(pred_vals.get(), in_corr, out_data);
   72|       |
   73|     33|  const CornerTable *const table = this->mesh_data().corner_table();
   74|     33|  const std::vector<int32_t> *const vertex_to_data_map =
   75|     33|      this->mesh_data().vertex_to_data_map();
   76|       |
   77|     33|  const int corner_map_size =
   78|     33|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
   79|  10.3k|  for (int p = 1; p < corner_map_size; ++p) {
  ------------------
  |  Branch (79:19): [True: 10.3k, False: 33]
  ------------------
   80|  10.3k|    const CornerIndex start_corner_id =
   81|  10.3k|        this->mesh_data().data_to_corner_map()->at(p);
   82|       |
   83|  10.3k|    CornerIndex corner_id(start_corner_id);
   84|  10.3k|    int num_parallelograms = 0;
   85|  73.2k|    for (int i = 0; i < num_components; ++i) {
  ------------------
  |  Branch (85:21): [True: 62.9k, False: 10.3k]
  ------------------
   86|  62.9k|      pred_vals[i] = static_cast<DataTypeT>(0);
   87|  62.9k|    }
   88|  42.3k|    while (corner_id != kInvalidCornerIndex) {
  ------------------
  |  Branch (88:12): [True: 32.0k, False: 10.3k]
  ------------------
   89|  32.0k|      if (ComputeParallelogramPrediction(
  ------------------
  |  Branch (89:11): [True: 13.8k, False: 18.1k]
  ------------------
   90|  32.0k|              p, corner_id, table, *vertex_to_data_map, out_data,
   91|  32.0k|              num_components, parallelogram_pred_vals.get())) {
   92|  95.2k|        for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (92:25): [True: 81.3k, False: 13.8k]
  ------------------
   93|  81.3k|          pred_vals[c] =
   94|  81.3k|              AddAsUnsigned(pred_vals[c], parallelogram_pred_vals[c]);
   95|  81.3k|        }
   96|  13.8k|        ++num_parallelograms;
   97|  13.8k|      }
   98|       |
   99|       |      // Proceed to the next corner attached to the vertex.
  100|  32.0k|      corner_id = table->SwingRight(corner_id);
  101|  32.0k|      if (corner_id == start_corner_id) {
  ------------------
  |  Branch (101:11): [True: 3.65k, False: 28.3k]
  ------------------
  102|  3.65k|        corner_id = kInvalidCornerIndex;
  103|  3.65k|      }
  104|  32.0k|    }
  105|       |
  106|  10.3k|    const int dst_offset = p * num_components;
  107|  10.3k|    if (num_parallelograms == 0) {
  ------------------
  |  Branch (107:9): [True: 86, False: 10.2k]
  ------------------
  108|       |      // No parallelogram was valid.
  109|       |      // We use the last decoded point as a reference.
  110|     86|      const int src_offset = (p - 1) * num_components;
  111|     86|      this->transform().ComputeOriginalValue(
  112|     86|          out_data + src_offset, in_corr + dst_offset, out_data + dst_offset);
  113|  10.2k|    } else {
  114|       |      // Compute the correction from the predicted value.
  115|  71.5k|      for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (115:23): [True: 61.2k, False: 10.2k]
  ------------------
  116|  61.2k|        pred_vals[c] /= num_parallelograms;
  117|  61.2k|      }
  118|  10.2k|      this->transform().ComputeOriginalValue(
  119|  10.2k|          pred_vals.get(), in_corr + dst_offset, out_data + dst_offset);
  120|  10.2k|    }
  121|  10.3k|  }
  122|     33|  return true;
  123|     33|}
_ZN5draco45MeshPredictionSchemeMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   44|     77|            attribute, transform, mesh_data) {}
_ZN5draco45MeshPredictionSchemeMultiParallelogramDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   63|     76|                          const PointIndex * /* entry_to_point_id_map */) {
   64|     76|  this->transform().Init(num_components);
   65|       |
   66|       |  // For storage of prediction values (already initialized to zero).
   67|     76|  std::unique_ptr<DataTypeT[]> pred_vals(new DataTypeT[num_components]());
   68|     76|  std::unique_ptr<DataTypeT[]> parallelogram_pred_vals(
   69|     76|      new DataTypeT[num_components]());
   70|       |
   71|     76|  this->transform().ComputeOriginalValue(pred_vals.get(), in_corr, out_data);
   72|       |
   73|     76|  const CornerTable *const table = this->mesh_data().corner_table();
   74|     76|  const std::vector<int32_t> *const vertex_to_data_map =
   75|     76|      this->mesh_data().vertex_to_data_map();
   76|       |
   77|     76|  const int corner_map_size =
   78|     76|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
   79|  9.44k|  for (int p = 1; p < corner_map_size; ++p) {
  ------------------
  |  Branch (79:19): [True: 9.36k, False: 76]
  ------------------
   80|  9.36k|    const CornerIndex start_corner_id =
   81|  9.36k|        this->mesh_data().data_to_corner_map()->at(p);
   82|       |
   83|  9.36k|    CornerIndex corner_id(start_corner_id);
   84|  9.36k|    int num_parallelograms = 0;
   85|  90.6k|    for (int i = 0; i < num_components; ++i) {
  ------------------
  |  Branch (85:21): [True: 81.2k, False: 9.36k]
  ------------------
   86|  81.2k|      pred_vals[i] = static_cast<DataTypeT>(0);
   87|  81.2k|    }
   88|  53.3k|    while (corner_id != kInvalidCornerIndex) {
  ------------------
  |  Branch (88:12): [True: 44.0k, False: 9.36k]
  ------------------
   89|  44.0k|      if (ComputeParallelogramPrediction(
  ------------------
  |  Branch (89:11): [True: 15.7k, False: 28.2k]
  ------------------
   90|  44.0k|              p, corner_id, table, *vertex_to_data_map, out_data,
   91|  44.0k|              num_components, parallelogram_pred_vals.get())) {
   92|   166k|        for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (92:25): [True: 150k, False: 15.7k]
  ------------------
   93|   150k|          pred_vals[c] =
   94|   150k|              AddAsUnsigned(pred_vals[c], parallelogram_pred_vals[c]);
   95|   150k|        }
   96|  15.7k|        ++num_parallelograms;
   97|  15.7k|      }
   98|       |
   99|       |      // Proceed to the next corner attached to the vertex.
  100|  44.0k|      corner_id = table->SwingRight(corner_id);
  101|  44.0k|      if (corner_id == start_corner_id) {
  ------------------
  |  Branch (101:11): [True: 6.69k, False: 37.3k]
  ------------------
  102|  6.69k|        corner_id = kInvalidCornerIndex;
  103|  6.69k|      }
  104|  44.0k|    }
  105|       |
  106|  9.36k|    const int dst_offset = p * num_components;
  107|  9.36k|    if (num_parallelograms == 0) {
  ------------------
  |  Branch (107:9): [True: 184, False: 9.18k]
  ------------------
  108|       |      // No parallelogram was valid.
  109|       |      // We use the last decoded point as a reference.
  110|    184|      const int src_offset = (p - 1) * num_components;
  111|    184|      this->transform().ComputeOriginalValue(
  112|    184|          out_data + src_offset, in_corr + dst_offset, out_data + dst_offset);
  113|  9.18k|    } else {
  114|       |      // Compute the correction from the predicted value.
  115|  89.4k|      for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (115:23): [True: 80.2k, False: 9.18k]
  ------------------
  116|  80.2k|        pred_vals[c] /= num_parallelograms;
  117|  80.2k|      }
  118|  9.18k|      this->transform().ComputeOriginalValue(
  119|  9.18k|          pred_vals.get(), in_corr + dst_offset, out_data + dst_offset);
  120|  9.18k|    }
  121|  9.36k|  }
  122|     76|  return true;
  123|     76|}

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

_ZN5draco30ComputeParallelogramPredictionINS_24MeshAttributeCornerTableEiEEbiNS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPKT_RKNSt3__16vectorIiNS8_9allocatorIiEEEEPKT0_iPSF_:
   48|   147k|    int num_components, DataTypeT *out_prediction) {
   49|   147k|  const CornerIndex oci = table->Opposite(ci);
   50|   147k|  if (oci == kInvalidCornerIndex) {
  ------------------
  |  Branch (50:7): [True: 98.1k, False: 48.8k]
  ------------------
   51|  98.1k|    return false;
   52|  98.1k|  }
   53|  48.8k|  int vert_opp, vert_next, vert_prev;
   54|  48.8k|  GetParallelogramEntries<CornerTableT>(oci, table, vertex_to_data_map,
   55|  48.8k|                                        &vert_opp, &vert_next, &vert_prev);
   56|  48.8k|  if (vert_opp < data_entry_id && vert_next < data_entry_id &&
  ------------------
  |  Branch (56:7): [True: 24.3k, False: 24.5k]
  |  Branch (56:35): [True: 20.8k, False: 3.52k]
  ------------------
   57|  48.8k|      vert_prev < data_entry_id) {
  ------------------
  |  Branch (57:7): [True: 20.5k, False: 236]
  ------------------
   58|       |    // Apply the parallelogram prediction.
   59|  20.5k|    const int v_opp_off = vert_opp * num_components;
   60|  20.5k|    const int v_next_off = vert_next * num_components;
   61|  20.5k|    const int v_prev_off = vert_prev * num_components;
   62|   252k|    for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (62:21): [True: 232k, False: 20.5k]
  ------------------
   63|   232k|      const int64_t in_data_next_off = in_data[v_next_off + c];
   64|   232k|      const int64_t in_data_prev_off = in_data[v_prev_off + c];
   65|   232k|      const int64_t in_data_opp_off = in_data[v_opp_off + c];
   66|   232k|      const int64_t result =
   67|   232k|          (in_data_next_off + in_data_prev_off) - in_data_opp_off;
   68|       |
   69|   232k|      out_prediction[c] = static_cast<DataTypeT>(result);
   70|   232k|    }
   71|  20.5k|    return true;
   72|  20.5k|  }
   73|  28.3k|  return false;  // Not all data is available for prediction
   74|  48.8k|}
_ZN5draco23GetParallelogramEntriesINS_24MeshAttributeCornerTableEEEvNS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPKT_RKNSt3__16vectorIiNS8_9allocatorIiEEEEPiSF_SF_:
   31|  48.8k|    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|  48.8k|  *opp_entry = vertex_to_data_map[table->Vertex(ci).value()];
   36|  48.8k|  *next_entry = vertex_to_data_map[table->Vertex(table->Next(ci)).value()];
   37|  48.8k|  *prev_entry = vertex_to_data_map[table->Vertex(table->Previous(ci)).value()];
   38|  48.8k|}
_ZN5draco30ComputeParallelogramPredictionINS_11CornerTableEiEEbiNS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPKT_RKNSt3__16vectorIiNS8_9allocatorIiEEEEPKT0_iPSF_:
   48|   108k|    int num_components, DataTypeT *out_prediction) {
   49|   108k|  const CornerIndex oci = table->Opposite(ci);
   50|   108k|  if (oci == kInvalidCornerIndex) {
  ------------------
  |  Branch (50:7): [True: 763, False: 108k]
  ------------------
   51|    763|    return false;
   52|    763|  }
   53|   108k|  int vert_opp, vert_next, vert_prev;
   54|   108k|  GetParallelogramEntries<CornerTableT>(oci, table, vertex_to_data_map,
   55|   108k|                                        &vert_opp, &vert_next, &vert_prev);
   56|   108k|  if (vert_opp < data_entry_id && vert_next < data_entry_id &&
  ------------------
  |  Branch (56:7): [True: 85.2k, False: 22.7k]
  |  Branch (56:35): [True: 83.6k, False: 1.57k]
  ------------------
   57|   108k|      vert_prev < data_entry_id) {
  ------------------
  |  Branch (57:7): [True: 78.2k, False: 5.38k]
  ------------------
   58|       |    // Apply the parallelogram prediction.
   59|  78.2k|    const int v_opp_off = vert_opp * num_components;
   60|  78.2k|    const int v_next_off = vert_next * num_components;
   61|  78.2k|    const int v_prev_off = vert_prev * num_components;
   62|   612k|    for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (62:21): [True: 533k, False: 78.2k]
  ------------------
   63|   533k|      const int64_t in_data_next_off = in_data[v_next_off + c];
   64|   533k|      const int64_t in_data_prev_off = in_data[v_prev_off + c];
   65|   533k|      const int64_t in_data_opp_off = in_data[v_opp_off + c];
   66|   533k|      const int64_t result =
   67|   533k|          (in_data_next_off + in_data_prev_off) - in_data_opp_off;
   68|       |
   69|   533k|      out_prediction[c] = static_cast<DataTypeT>(result);
   70|   533k|    }
   71|  78.2k|    return true;
   72|  78.2k|  }
   73|  29.7k|  return false;  // Not all data is available for prediction
   74|   108k|}
_ZN5draco23GetParallelogramEntriesINS_11CornerTableEEEvNS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPKT_RKNSt3__16vectorIiNS8_9allocatorIiEEEEPiSF_SF_:
   31|   108k|    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|   108k|  *opp_entry = vertex_to_data_map[table->Vertex(ci).value()];
   36|   108k|  *next_entry = vertex_to_data_map[table->Vertex(table->Next(ci)).value()];
   37|   108k|  *prev_entry = vertex_to_data_map[table->Vertex(table->Previous(ci)).value()];
   38|   108k|}

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

_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   38|     10|        predictor_(mesh_data) {}
_ZNK5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE22GetNumParentAttributesEv:
   60|     20|  int GetNumParentAttributes() const override { return 1; }
_ZNK5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE22GetParentAttributeTypeEi:
   62|     10|  GeometryAttribute::Type GetParentAttributeType(int i) const override {
   63|     10|    DRACO_DCHECK_EQ(i, 0);
   64|     10|    (void)i;
   65|     10|    return GeometryAttribute::POSITION;
   66|     10|  }
_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE18SetParentAttributeEPKNS_14PointAttributeE:
   68|     10|  bool SetParentAttribute(const PointAttribute *att) override {
   69|     10|    if (!att || att->attribute_type() != GeometryAttribute::POSITION) {
  ------------------
  |  Branch (69:9): [True: 0, False: 10]
  |  Branch (69:17): [True: 0, False: 10]
  ------------------
   70|      0|      return false;  // Invalid attribute type.
   71|      0|    }
   72|     10|    if (att->num_components() != 3) {
  ------------------
  |  Branch (72:9): [True: 0, False: 10]
  ------------------
   73|      0|      return false;  // Currently works only for 3 component positions.
   74|      0|    }
   75|     10|    predictor_.SetPositionAttribute(*att);
   76|     10|    return true;
   77|     10|  }
_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  118|     10|                                                                *buffer) {
  119|       |  // Decode the delta coded orientations.
  120|     10|  int32_t num_orientations = 0;
  121|     10|  if (!buffer->Decode(&num_orientations) || num_orientations < 0) {
  ------------------
  |  Branch (121:7): [True: 0, False: 10]
  |  Branch (121:45): [True: 0, False: 10]
  ------------------
  122|      0|    return false;
  123|      0|  }
  124|     10|  predictor_.ResizeOrientations(num_orientations);
  125|     10|  bool last_orientation = true;
  126|     10|  RAnsBitDecoder decoder;
  127|     10|  if (!decoder.StartDecoding(buffer)) {
  ------------------
  |  Branch (127:7): [True: 0, False: 10]
  ------------------
  128|      0|    return false;
  129|      0|  }
  130|  1.30G|  for (int i = 0; i < num_orientations; ++i) {
  ------------------
  |  Branch (130:19): [True: 1.30G, False: 10]
  ------------------
  131|  1.30G|    if (!decoder.DecodeNextBit()) {
  ------------------
  |  Branch (131:9): [True: 16.8M, False: 1.28G]
  ------------------
  132|  16.8M|      last_orientation = !last_orientation;
  133|  16.8M|    }
  134|  1.30G|    predictor_.set_orientation(i, last_orientation);
  135|  1.30G|  }
  136|     10|  decoder.EndDecoding();
  137|     10|  return MeshPredictionSchemeDecoder<DataTypeT, TransformT,
  138|     10|                                     MeshDataT>::DecodePredictionData(buffer);
  139|     10|}
_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   90|     10|                                      const PointIndex *entry_to_point_id_map) {
   91|     10|  if (num_components != MeshPredictionSchemeTexCoordsPortablePredictor<
  ------------------
  |  Branch (91:7): [True: 1, False: 9]
  ------------------
   92|     10|                            DataTypeT, MeshDataT>::kNumComponents) {
   93|      1|    return false;
   94|      1|  }
   95|      9|  predictor_.SetEntryToPointIdMap(entry_to_point_id_map);
   96|      9|  this->transform().Init(num_components);
   97|       |
   98|      9|  const int corner_map_size =
   99|      9|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  100|  1.05k|  for (int p = 0; p < corner_map_size; ++p) {
  ------------------
  |  Branch (100:19): [True: 1.04k, False: 9]
  ------------------
  101|  1.04k|    const CornerIndex corner_id = this->mesh_data().data_to_corner_map()->at(p);
  102|  1.04k|    if (!predictor_.template ComputePredictedValue<false>(corner_id, out_data,
  ------------------
  |  Branch (102:9): [True: 0, False: 1.04k]
  ------------------
  103|  1.04k|                                                          p)) {
  104|      0|      return false;
  105|      0|    }
  106|       |
  107|  1.04k|    const int dst_offset = p * num_components;
  108|  1.04k|    this->transform().ComputeOriginalValue(predictor_.predicted_value(),
  109|  1.04k|                                           in_corr + dst_offset,
  110|  1.04k|                                           out_data + dst_offset);
  111|  1.04k|  }
  112|      9|  return true;
  113|      9|}
_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2EPKNS_14PointAttributeERKS2_RKS5_:
   38|     20|        predictor_(mesh_data) {}
_ZNK5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE22GetNumParentAttributesEv:
   60|     40|  int GetNumParentAttributes() const override { return 1; }
_ZNK5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE22GetParentAttributeTypeEi:
   62|     20|  GeometryAttribute::Type GetParentAttributeType(int i) const override {
   63|     20|    DRACO_DCHECK_EQ(i, 0);
   64|     20|    (void)i;
   65|     20|    return GeometryAttribute::POSITION;
   66|     20|  }
_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE18SetParentAttributeEPKNS_14PointAttributeE:
   68|     20|  bool SetParentAttribute(const PointAttribute *att) override {
   69|     20|    if (!att || att->attribute_type() != GeometryAttribute::POSITION) {
  ------------------
  |  Branch (69:9): [True: 0, False: 20]
  |  Branch (69:17): [True: 0, False: 20]
  ------------------
   70|      0|      return false;  // Invalid attribute type.
   71|      0|    }
   72|     20|    if (att->num_components() != 3) {
  ------------------
  |  Branch (72:9): [True: 0, False: 20]
  ------------------
   73|      0|      return false;  // Currently works only for 3 component positions.
   74|      0|    }
   75|     20|    predictor_.SetPositionAttribute(*att);
   76|     20|    return true;
   77|     20|  }
_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20DecodePredictionDataEPNS_13DecoderBufferE:
  118|     20|                                                                *buffer) {
  119|       |  // Decode the delta coded orientations.
  120|     20|  int32_t num_orientations = 0;
  121|     20|  if (!buffer->Decode(&num_orientations) || num_orientations < 0) {
  ------------------
  |  Branch (121:7): [True: 0, False: 20]
  |  Branch (121:45): [True: 0, False: 20]
  ------------------
  122|      0|    return false;
  123|      0|  }
  124|     20|  predictor_.ResizeOrientations(num_orientations);
  125|     20|  bool last_orientation = true;
  126|     20|  RAnsBitDecoder decoder;
  127|     20|  if (!decoder.StartDecoding(buffer)) {
  ------------------
  |  Branch (127:7): [True: 0, False: 20]
  ------------------
  128|      0|    return false;
  129|      0|  }
  130|   747M|  for (int i = 0; i < num_orientations; ++i) {
  ------------------
  |  Branch (130:19): [True: 747M, False: 20]
  ------------------
  131|   747M|    if (!decoder.DecodeNextBit()) {
  ------------------
  |  Branch (131:9): [True: 268M, False: 478M]
  ------------------
  132|   268M|      last_orientation = !last_orientation;
  133|   268M|    }
  134|   747M|    predictor_.set_orientation(i, last_orientation);
  135|   747M|  }
  136|     20|  decoder.EndDecoding();
  137|     20|  return MeshPredictionSchemeDecoder<DataTypeT, TransformT,
  138|     20|                                     MeshDataT>::DecodePredictionData(buffer);
  139|     20|}
_ZN5draco44MeshPredictionSchemeTexCoordsPortableDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   90|     17|                                      const PointIndex *entry_to_point_id_map) {
   91|     17|  if (num_components != MeshPredictionSchemeTexCoordsPortablePredictor<
  ------------------
  |  Branch (91:7): [True: 1, False: 16]
  ------------------
   92|     17|                            DataTypeT, MeshDataT>::kNumComponents) {
   93|      1|    return false;
   94|      1|  }
   95|     16|  predictor_.SetEntryToPointIdMap(entry_to_point_id_map);
   96|     16|  this->transform().Init(num_components);
   97|       |
   98|     16|  const int corner_map_size =
   99|     16|      static_cast<int>(this->mesh_data().data_to_corner_map()->size());
  100|  6.42k|  for (int p = 0; p < corner_map_size; ++p) {
  ------------------
  |  Branch (100:19): [True: 6.41k, False: 14]
  ------------------
  101|  6.41k|    const CornerIndex corner_id = this->mesh_data().data_to_corner_map()->at(p);
  102|  6.41k|    if (!predictor_.template ComputePredictedValue<false>(corner_id, out_data,
  ------------------
  |  Branch (102:9): [True: 2, False: 6.41k]
  ------------------
  103|  6.41k|                                                          p)) {
  104|      2|      return false;
  105|      2|    }
  106|       |
  107|  6.41k|    const int dst_offset = p * num_components;
  108|  6.41k|    this->transform().ComputeOriginalValue(predictor_.predicted_value(),
  109|  6.41k|                                           in_corr + dst_offset,
  110|  6.41k|                                           out_data + dst_offset);
  111|  6.41k|  }
  112|     14|  return true;
  113|     16|}

_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEC2ERKS3_:
   40|     10|        mesh_data_(md) {}
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20SetPositionAttributeERKNS_14PointAttributeE:
   41|     10|  void SetPositionAttribute(const PointAttribute &position_attribute) {
   42|     10|    pos_attribute_ = &position_attribute;
   43|     10|  }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE18ResizeOrientationsEi:
   73|     10|  void ResizeOrientations(int num_orientations) {
   74|     10|    orientations_.resize(num_orientations);
   75|     10|  }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE15set_orientationEib:
   71|  1.30G|  void set_orientation(int i, bool v) { orientations_[i] = v; }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE20SetEntryToPointIdMapEPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   44|      9|  void SetEntryToPointIdMap(const PointIndex *map) {
   45|      9|    entry_to_point_id_map_ = map;
   46|      9|  }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21ComputePredictedValueILb0EEEbNS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPKii:
   93|  1.04k|                                                 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.04k|  const CornerIndex next_corner_id = mesh_data_.corner_table()->Next(corner_id);
   98|  1.04k|  const CornerIndex prev_corner_id =
   99|  1.04k|      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.04k|  int next_data_id, prev_data_id;
  103|       |
  104|  1.04k|  int next_vert_id, prev_vert_id;
  105|  1.04k|  next_vert_id = mesh_data_.corner_table()->Vertex(next_corner_id).value();
  106|  1.04k|  prev_vert_id = mesh_data_.corner_table()->Vertex(prev_corner_id).value();
  107|       |
  108|  1.04k|  next_data_id = mesh_data_.vertex_to_data_map()->at(next_vert_id);
  109|  1.04k|  prev_data_id = mesh_data_.vertex_to_data_map()->at(prev_vert_id);
  110|       |
  111|  1.04k|  typedef VectorD<int64_t, 2> Vec2;
  112|  1.04k|  typedef VectorD<int64_t, 3> Vec3;
  113|  1.04k|  typedef VectorD<uint64_t, 2> Vec2u;
  114|       |
  115|  1.04k|  if (prev_data_id < data_id && next_data_id < data_id) {
  ------------------
  |  Branch (115:7): [True: 795, False: 251]
  |  Branch (115:33): [True: 539, False: 256]
  ------------------
  116|       |    // Both other corners have available UV coordinates for prediction.
  117|    539|    const Vec2 n_uv = GetTexCoordForEntryId(next_data_id, data);
  118|    539|    const Vec2 p_uv = GetTexCoordForEntryId(prev_data_id, data);
  119|    539|    if (p_uv == n_uv) {
  ------------------
  |  Branch (119:9): [True: 189, False: 350]
  ------------------
  120|       |      // We cannot do a reliable prediction on degenerated UV triangles.
  121|    189|      predicted_value_[0] = p_uv[0];
  122|    189|      predicted_value_[1] = p_uv[1];
  123|    189|      return true;
  124|    189|    }
  125|       |
  126|       |    // Get positions at all corners.
  127|    350|    const Vec3 tip_pos = GetPositionForEntryId(data_id);
  128|    350|    const Vec3 next_pos = GetPositionForEntryId(next_data_id);
  129|    350|    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|    350|    const Vec3 pn = prev_pos - next_pos;
  146|    350|    const uint64_t pn_norm2_squared = pn.SquaredNorm();
  147|    350|    if (pn_norm2_squared != 0) {
  ------------------
  |  Branch (147:9): [True: 188, False: 162]
  ------------------
  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|    188|      const Vec3 cn = tip_pos - next_pos;
  153|    188|      const int64_t cn_dot_pn = pn.Dot(cn);
  154|       |
  155|    188|      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|    188|      const int64_t n_uv_absmax_element =
  164|    188|          std::max(std::abs(n_uv[0]), std::abs(n_uv[1]));
  165|    188|      if (n_uv_absmax_element >
  ------------------
  |  Branch (165:11): [True: 0, False: 188]
  ------------------
  166|    188|          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|    188|      const int64_t pn_uv_absmax_element =
  171|    188|          std::max(std::abs(pn_uv[0]), std::abs(pn_uv[1]));
  172|    188|      if (std::abs(cn_dot_pn) >
  ------------------
  |  Branch (172:11): [True: 0, False: 188]
  ------------------
  173|    188|          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|    188|      const Vec2 x_uv = n_uv * pn_norm2_squared + (cn_dot_pn * pn_uv);
  178|    188|      const int64_t pn_absmax_element =
  179|    188|          std::max(std::max(std::abs(pn[0]), std::abs(pn[1])), std::abs(pn[2]));
  180|    188|      if (std::abs(cn_dot_pn) >
  ------------------
  |  Branch (180:11): [True: 0, False: 188]
  ------------------
  181|    188|          std::numeric_limits<int64_t>::max() / pn_absmax_element) {
  182|       |        // Return false if squared length calculation would overflow.
  183|      0|        return false;
  184|      0|      }
  185|       |
  186|       |      // Compute squared length of vector CX in position coordinate system:
  187|    188|      const Vec3 x_pos = next_pos + (cn_dot_pn * pn) / pn_norm2_squared;
  188|    188|      const uint64_t cx_norm2_squared = (tip_pos - x_pos).SquaredNorm();
  189|       |
  190|       |      // Compute vector CX_UV in the uv space by rotating vector PN_UV by 90
  191|       |      // degrees and scaling it with factor CX.Norm2() / PN.Norm2():
  192|       |      //
  193|       |      //     CX_UV = (CX.Norm2() / PN.Norm2()) * Rot(PN_UV)
  194|       |      //
  195|       |      // To preserve precision, we perform all operations in scaled space as
  196|       |      // explained above, so we want the final vector to be:
  197|       |      //
  198|       |      //     cx_uv = CX_UV * PN.Norm2Squared()
  199|       |      //
  200|       |      // We can then rewrite the formula as:
  201|       |      //
  202|       |      //     cx_uv = CX.Norm2() * PN.Norm2() * Rot(PN_UV)
  203|       |      //
  204|    188|      Vec2 cx_uv(pn_uv[1], -pn_uv[0]);  // Rotated PN_UV.
  205|       |      // Compute CX.Norm2() * PN.Norm2()
  206|    188|      const uint64_t norm_squared =
  207|    188|          IntSqrt(cx_norm2_squared * pn_norm2_squared);
  208|       |      // Final cx_uv in the scaled coordinate space.
  209|    188|      cx_uv = cx_uv * norm_squared;
  210|       |
  211|       |      // Predicted uv coordinate is then computed by either adding or
  212|       |      // subtracting CX_UV to/from X_UV.
  213|    188|      Vec2 predicted_uv;
  214|    188|      if (is_encoder_t) {
  ------------------
  |  Branch (214:11): [Folded - Ignored]
  ------------------
  215|       |        // When encoding, compute both possible vectors and determine which one
  216|       |        // results in a better prediction.
  217|       |        // Both vectors need to be transformed back from the scaled space to
  218|       |        // the real UV coordinate space.
  219|      0|        const Vec2 predicted_uv_0((x_uv + cx_uv) / pn_norm2_squared);
  220|      0|        const Vec2 predicted_uv_1((x_uv - cx_uv) / pn_norm2_squared);
  221|      0|        const Vec2 c_uv = GetTexCoordForEntryId(data_id, data);
  222|      0|        if ((c_uv - predicted_uv_0).SquaredNorm() <
  ------------------
  |  Branch (222:13): [True: 0, False: 0]
  ------------------
  223|      0|            (c_uv - predicted_uv_1).SquaredNorm()) {
  224|      0|          predicted_uv = predicted_uv_0;
  225|      0|          orientations_.push_back(true);
  226|      0|        } else {
  227|      0|          predicted_uv = predicted_uv_1;
  228|      0|          orientations_.push_back(false);
  229|      0|        }
  230|    188|      } else {
  231|       |        // When decoding the data, we already know which orientation to use.
  232|    188|        if (orientations_.empty()) {
  ------------------
  |  Branch (232:13): [True: 0, False: 188]
  ------------------
  233|      0|          return false;
  234|      0|        }
  235|    188|        const bool orientation = orientations_.back();
  236|    188|        orientations_.pop_back();
  237|       |        // Perform operations in unsigned type to avoid signed integer overflow.
  238|       |        // Note that the result will be the same (for non-overflowing values).
  239|    188|        if (orientation) {
  ------------------
  |  Branch (239:13): [True: 75, False: 113]
  ------------------
  240|     75|          predicted_uv = Vec2(Vec2u(x_uv) + Vec2u(cx_uv)) / pn_norm2_squared;
  241|    113|        } else {
  242|    113|          predicted_uv = Vec2(Vec2u(x_uv) - Vec2u(cx_uv)) / pn_norm2_squared;
  243|    113|        }
  244|    188|      }
  245|    188|      predicted_value_[0] = static_cast<int>(predicted_uv[0]);
  246|    188|      predicted_value_[1] = static_cast<int>(predicted_uv[1]);
  247|    188|      return true;
  248|    188|    }
  249|    350|  }
  250|       |  // Else we don't have available textures on both corners or the position data
  251|       |  // is invalid. For such cases we can't use positions for predicting the uv
  252|       |  // value and we resort to delta coding.
  253|    669|  int data_offset = 0;
  254|    669|  if (prev_data_id < data_id) {
  ------------------
  |  Branch (254:7): [True: 418, False: 251]
  ------------------
  255|       |    // Use the value on the previous corner as the prediction.
  256|    418|    data_offset = prev_data_id * kNumComponents;
  257|    418|  }
  258|    669|  if (next_data_id < data_id) {
  ------------------
  |  Branch (258:7): [True: 162, False: 507]
  ------------------
  259|       |    // Use the value on the next corner as the prediction.
  260|    162|    data_offset = next_data_id * kNumComponents;
  261|    507|  } else {
  262|       |    // None of the other corners have a valid value. Use the last encoded value
  263|       |    // as the prediction if possible.
  264|    507|    if (data_id > 0) {
  ------------------
  |  Branch (264:9): [True: 498, False: 9]
  ------------------
  265|    498|      data_offset = (data_id - 1) * kNumComponents;
  266|    498|    } else {
  267|       |      // We are encoding the first value. Predict 0.
  268|     27|      for (int i = 0; i < kNumComponents; ++i) {
  ------------------
  |  Branch (268:23): [True: 18, False: 9]
  ------------------
  269|     18|        predicted_value_[i] = 0;
  270|     18|      }
  271|      9|      return true;
  272|      9|    }
  273|    507|  }
  274|  1.98k|  for (int i = 0; i < kNumComponents; ++i) {
  ------------------
  |  Branch (274:19): [True: 1.32k, False: 660]
  ------------------
  275|  1.32k|    predicted_value_[i] = data[data_offset + i];
  276|  1.32k|  }
  277|    660|  return true;
  278|    669|}
_ZNK5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21GetTexCoordForEntryIdEiPKi:
   58|  1.07k|                                            const DataTypeT *data) const {
   59|  1.07k|    const int data_offset = entry_id * kNumComponents;
   60|  1.07k|    return VectorD<int64_t, 2>(data[data_offset], data[data_offset + 1]);
   61|  1.07k|  }
_ZNK5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE21GetPositionForEntryIdEi:
   49|  1.05k|  VectorD<int64_t, 3> GetPositionForEntryId(int entry_id) const {
   50|  1.05k|    const PointIndex point_id = entry_to_point_id_map_[entry_id];
   51|  1.05k|    VectorD<int64_t, 3> pos;
   52|  1.05k|    pos_attribute_->ConvertValue(pos_attribute_->mapped_index(point_id),
   53|  1.05k|                                 &pos[0]);
   54|  1.05k|    return pos;
   55|  1.05k|  }
_ZNK5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEE15predicted_valueEv:
   69|  1.04k|  const DataTypeT *predicted_value() const { return predicted_value_; }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEEC2ERKS3_:
   40|     20|        mesh_data_(md) {}
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20SetPositionAttributeERKNS_14PointAttributeE:
   41|     20|  void SetPositionAttribute(const PointAttribute &position_attribute) {
   42|     20|    pos_attribute_ = &position_attribute;
   43|     20|  }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEE18ResizeOrientationsEi:
   73|     20|  void ResizeOrientations(int num_orientations) {
   74|     20|    orientations_.resize(num_orientations);
   75|     20|  }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEE15set_orientationEib:
   71|   747M|  void set_orientation(int i, bool v) { orientations_[i] = v; }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEE20SetEntryToPointIdMapEPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   44|     16|  void SetEntryToPointIdMap(const PointIndex *map) {
   45|     16|    entry_to_point_id_map_ = map;
   46|     16|  }
_ZN5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21ComputePredictedValueILb0EEEbNS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEPKii:
   93|  6.41k|                                                 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|  6.41k|  const CornerIndex next_corner_id = mesh_data_.corner_table()->Next(corner_id);
   98|  6.41k|  const CornerIndex prev_corner_id =
   99|  6.41k|      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|  6.41k|  int next_data_id, prev_data_id;
  103|       |
  104|  6.41k|  int next_vert_id, prev_vert_id;
  105|  6.41k|  next_vert_id = mesh_data_.corner_table()->Vertex(next_corner_id).value();
  106|  6.41k|  prev_vert_id = mesh_data_.corner_table()->Vertex(prev_corner_id).value();
  107|       |
  108|  6.41k|  next_data_id = mesh_data_.vertex_to_data_map()->at(next_vert_id);
  109|  6.41k|  prev_data_id = mesh_data_.vertex_to_data_map()->at(prev_vert_id);
  110|       |
  111|  6.41k|  typedef VectorD<int64_t, 2> Vec2;
  112|  6.41k|  typedef VectorD<int64_t, 3> Vec3;
  113|  6.41k|  typedef VectorD<uint64_t, 2> Vec2u;
  114|       |
  115|  6.41k|  if (prev_data_id < data_id && next_data_id < data_id) {
  ------------------
  |  Branch (115:7): [True: 6.20k, False: 206]
  |  Branch (115:33): [True: 6.00k, False: 206]
  ------------------
  116|       |    // Both other corners have available UV coordinates for prediction.
  117|  6.00k|    const Vec2 n_uv = GetTexCoordForEntryId(next_data_id, data);
  118|  6.00k|    const Vec2 p_uv = GetTexCoordForEntryId(prev_data_id, data);
  119|  6.00k|    if (p_uv == n_uv) {
  ------------------
  |  Branch (119:9): [True: 5.65k, False: 347]
  ------------------
  120|       |      // We cannot do a reliable prediction on degenerated UV triangles.
  121|  5.65k|      predicted_value_[0] = p_uv[0];
  122|  5.65k|      predicted_value_[1] = p_uv[1];
  123|  5.65k|      return true;
  124|  5.65k|    }
  125|       |
  126|       |    // Get positions at all corners.
  127|    347|    const Vec3 tip_pos = GetPositionForEntryId(data_id);
  128|    347|    const Vec3 next_pos = GetPositionForEntryId(next_data_id);
  129|    347|    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|    347|    const Vec3 pn = prev_pos - next_pos;
  146|    347|    const uint64_t pn_norm2_squared = pn.SquaredNorm();
  147|    347|    if (pn_norm2_squared != 0) {
  ------------------
  |  Branch (147:9): [True: 286, False: 61]
  ------------------
  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|    286|      const Vec3 cn = tip_pos - next_pos;
  153|    286|      const int64_t cn_dot_pn = pn.Dot(cn);
  154|       |
  155|    286|      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|    286|      const int64_t n_uv_absmax_element =
  164|    286|          std::max(std::abs(n_uv[0]), std::abs(n_uv[1]));
  165|    286|      if (n_uv_absmax_element >
  ------------------
  |  Branch (165:11): [True: 0, False: 286]
  ------------------
  166|    286|          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|    286|      const int64_t pn_uv_absmax_element =
  171|    286|          std::max(std::abs(pn_uv[0]), std::abs(pn_uv[1]));
  172|    286|      if (std::abs(cn_dot_pn) >
  ------------------
  |  Branch (172:11): [True: 1, False: 285]
  ------------------
  173|    286|          std::numeric_limits<int64_t>::max() / pn_uv_absmax_element) {
  174|       |        // Return false if squared length calculation would overflow.
  175|      1|        return false;
  176|      1|      }
  177|    285|      const Vec2 x_uv = n_uv * pn_norm2_squared + (cn_dot_pn * pn_uv);
  178|    285|      const int64_t pn_absmax_element =
  179|    285|          std::max(std::max(std::abs(pn[0]), std::abs(pn[1])), std::abs(pn[2]));
  180|    285|      if (std::abs(cn_dot_pn) >
  ------------------
  |  Branch (180:11): [True: 1, False: 284]
  ------------------
  181|    285|          std::numeric_limits<int64_t>::max() / pn_absmax_element) {
  182|       |        // Return false if squared length calculation would overflow.
  183|      1|        return false;
  184|      1|      }
  185|       |
  186|       |      // Compute squared length of vector CX in position coordinate system:
  187|    284|      const Vec3 x_pos = next_pos + (cn_dot_pn * pn) / pn_norm2_squared;
  188|    284|      const uint64_t cx_norm2_squared = (tip_pos - x_pos).SquaredNorm();
  189|       |
  190|       |      // Compute vector CX_UV in the uv space by rotating vector PN_UV by 90
  191|       |      // degrees and scaling it with factor CX.Norm2() / PN.Norm2():
  192|       |      //
  193|       |      //     CX_UV = (CX.Norm2() / PN.Norm2()) * Rot(PN_UV)
  194|       |      //
  195|       |      // To preserve precision, we perform all operations in scaled space as
  196|       |      // explained above, so we want the final vector to be:
  197|       |      //
  198|       |      //     cx_uv = CX_UV * PN.Norm2Squared()
  199|       |      //
  200|       |      // We can then rewrite the formula as:
  201|       |      //
  202|       |      //     cx_uv = CX.Norm2() * PN.Norm2() * Rot(PN_UV)
  203|       |      //
  204|    284|      Vec2 cx_uv(pn_uv[1], -pn_uv[0]);  // Rotated PN_UV.
  205|       |      // Compute CX.Norm2() * PN.Norm2()
  206|    284|      const uint64_t norm_squared =
  207|    284|          IntSqrt(cx_norm2_squared * pn_norm2_squared);
  208|       |      // Final cx_uv in the scaled coordinate space.
  209|    284|      cx_uv = cx_uv * norm_squared;
  210|       |
  211|       |      // Predicted uv coordinate is then computed by either adding or
  212|       |      // subtracting CX_UV to/from X_UV.
  213|    284|      Vec2 predicted_uv;
  214|    284|      if (is_encoder_t) {
  ------------------
  |  Branch (214:11): [Folded - Ignored]
  ------------------
  215|       |        // When encoding, compute both possible vectors and determine which one
  216|       |        // results in a better prediction.
  217|       |        // Both vectors need to be transformed back from the scaled space to
  218|       |        // the real UV coordinate space.
  219|      0|        const Vec2 predicted_uv_0((x_uv + cx_uv) / pn_norm2_squared);
  220|      0|        const Vec2 predicted_uv_1((x_uv - cx_uv) / pn_norm2_squared);
  221|      0|        const Vec2 c_uv = GetTexCoordForEntryId(data_id, data);
  222|      0|        if ((c_uv - predicted_uv_0).SquaredNorm() <
  ------------------
  |  Branch (222:13): [True: 0, False: 0]
  ------------------
  223|      0|            (c_uv - predicted_uv_1).SquaredNorm()) {
  224|      0|          predicted_uv = predicted_uv_0;
  225|      0|          orientations_.push_back(true);
  226|      0|        } else {
  227|      0|          predicted_uv = predicted_uv_1;
  228|      0|          orientations_.push_back(false);
  229|      0|        }
  230|    284|      } else {
  231|       |        // When decoding the data, we already know which orientation to use.
  232|    284|        if (orientations_.empty()) {
  ------------------
  |  Branch (232:13): [True: 0, False: 284]
  ------------------
  233|      0|          return false;
  234|      0|        }
  235|    284|        const bool orientation = orientations_.back();
  236|    284|        orientations_.pop_back();
  237|       |        // Perform operations in unsigned type to avoid signed integer overflow.
  238|       |        // Note that the result will be the same (for non-overflowing values).
  239|    284|        if (orientation) {
  ------------------
  |  Branch (239:13): [True: 102, False: 182]
  ------------------
  240|    102|          predicted_uv = Vec2(Vec2u(x_uv) + Vec2u(cx_uv)) / pn_norm2_squared;
  241|    182|        } else {
  242|    182|          predicted_uv = Vec2(Vec2u(x_uv) - Vec2u(cx_uv)) / pn_norm2_squared;
  243|    182|        }
  244|    284|      }
  245|    284|      predicted_value_[0] = static_cast<int>(predicted_uv[0]);
  246|    284|      predicted_value_[1] = static_cast<int>(predicted_uv[1]);
  247|    284|      return true;
  248|    284|    }
  249|    347|  }
  250|       |  // Else we don't have available textures on both corners or the position data
  251|       |  // is invalid. For such cases we can't use positions for predicting the uv
  252|       |  // value and we resort to delta coding.
  253|    473|  int data_offset = 0;
  254|    473|  if (prev_data_id < data_id) {
  ------------------
  |  Branch (254:7): [True: 267, False: 206]
  ------------------
  255|       |    // Use the value on the previous corner as the prediction.
  256|    267|    data_offset = prev_data_id * kNumComponents;
  257|    267|  }
  258|    473|  if (next_data_id < data_id) {
  ------------------
  |  Branch (258:7): [True: 61, False: 412]
  ------------------
  259|       |    // Use the value on the next corner as the prediction.
  260|     61|    data_offset = next_data_id * kNumComponents;
  261|    412|  } else {
  262|       |    // None of the other corners have a valid value. Use the last encoded value
  263|       |    // as the prediction if possible.
  264|    412|    if (data_id > 0) {
  ------------------
  |  Branch (264:9): [True: 396, False: 16]
  ------------------
  265|    396|      data_offset = (data_id - 1) * kNumComponents;
  266|    396|    } else {
  267|       |      // We are encoding the first value. Predict 0.
  268|     48|      for (int i = 0; i < kNumComponents; ++i) {
  ------------------
  |  Branch (268:23): [True: 32, False: 16]
  ------------------
  269|     32|        predicted_value_[i] = 0;
  270|     32|      }
  271|     16|      return true;
  272|     16|    }
  273|    412|  }
  274|  1.37k|  for (int i = 0; i < kNumComponents; ++i) {
  ------------------
  |  Branch (274:19): [True: 914, False: 457]
  ------------------
  275|    914|    predicted_value_[i] = data[data_offset + i];
  276|    914|  }
  277|    457|  return true;
  278|    473|}
_ZNK5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21GetTexCoordForEntryIdEiPKi:
   58|  12.0k|                                            const DataTypeT *data) const {
   59|  12.0k|    const int data_offset = entry_id * kNumComponents;
   60|  12.0k|    return VectorD<int64_t, 2>(data[data_offset], data[data_offset + 1]);
   61|  12.0k|  }
_ZNK5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEE21GetPositionForEntryIdEi:
   49|  1.04k|  VectorD<int64_t, 3> GetPositionForEntryId(int entry_id) const {
   50|  1.04k|    const PointIndex point_id = entry_to_point_id_map_[entry_id];
   51|  1.04k|    VectorD<int64_t, 3> pos;
   52|  1.04k|    pos_attribute_->ConvertValue(pos_attribute_->mapped_index(point_id),
   53|  1.04k|                                 &pos[0]);
   54|  1.04k|    return pos;
   55|  1.04k|  }
_ZNK5draco46MeshPredictionSchemeTexCoordsPortablePredictorIiNS_24MeshPredictionSchemeDataINS_11CornerTableEEEE15predicted_valueEv:
   69|  6.41k|  const DataTypeT *predicted_value() const { return predicted_value_; }

_ZNK5draco23PredictionSchemeDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEE22GetNumParentAttributesEv:
   58|      7|  int GetNumParentAttributes() const override { return 0; }
_ZN5draco23PredictionSchemeDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEE22AreCorrectionsPositiveEv:
   70|      7|  bool AreCorrectionsPositive() override {
   71|      7|    return transform_.AreCorrectionsPositive();
   72|      7|  }
_ZN5draco23PredictionSchemeDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEE20DecodePredictionDataEPNS_13DecoderBufferE:
   48|      7|  bool DecodePredictionData(DecoderBuffer *buffer) override {
   49|      7|    if (!transform_.DecodeTransformData(buffer)) {
  ------------------
  |  Branch (49:9): [True: 3, False: 4]
  ------------------
   50|      3|      return false;
   51|      3|    }
   52|      4|    return true;
   53|      7|  }
_ZN5draco23PredictionSchemeDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEE9transformEv:
   81|    324|  inline Transform &transform() { return transform_; }
_ZNK5draco23PredictionSchemeDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEE22GetNumParentAttributesEv:
   58|     22|  int GetNumParentAttributes() const override { return 0; }
_ZN5draco23PredictionSchemeDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEE22AreCorrectionsPositiveEv:
   70|     19|  bool AreCorrectionsPositive() override {
   71|     19|    return transform_.AreCorrectionsPositive();
   72|     19|  }
_ZN5draco23PredictionSchemeDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEE20DecodePredictionDataEPNS_13DecoderBufferE:
   48|     19|  bool DecodePredictionData(DecoderBuffer *buffer) override {
   49|     19|    if (!transform_.DecodeTransformData(buffer)) {
  ------------------
  |  Branch (49:9): [True: 6, False: 13]
  ------------------
   50|      6|      return false;
   51|      6|    }
   52|     13|    return true;
   53|     19|  }
_ZN5draco23PredictionSchemeDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEE9transformEv:
   81|  14.5k|  inline Transform &transform() { return transform_; }
_ZN5draco23PredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEEC2EPKNS_14PointAttributeERKS2_:
   46|    675|      : attribute_(attribute), transform_(transform) {}
_ZNK5draco23PredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEE22GetNumParentAttributesEv:
   58|    438|  int GetNumParentAttributes() const override { return 0; }
_ZN5draco23PredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEE22AreCorrectionsPositiveEv:
   70|    643|  bool AreCorrectionsPositive() override {
   71|    643|    return transform_.AreCorrectionsPositive();
   72|    643|  }
_ZN5draco23PredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEE20DecodePredictionDataEPNS_13DecoderBufferE:
   48|    453|  bool DecodePredictionData(DecoderBuffer *buffer) override {
   49|    453|    if (!transform_.DecodeTransformData(buffer)) {
  ------------------
  |  Branch (49:9): [True: 20, False: 433]
  ------------------
   50|     20|      return false;
   51|     20|    }
   52|    433|    return true;
   53|    453|  }
_ZN5draco23PredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEE9transformEv:
   81|   258k|  inline Transform &transform() { return transform_; }
_ZN5draco23PredictionSchemeDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEEC2EPKNS_14PointAttributeERKS2_:
   46|      7|      : attribute_(attribute), transform_(transform) {}
_ZN5draco23PredictionSchemeDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEEC2EPKNS_14PointAttributeERKS2_:
   46|     22|      : attribute_(attribute), transform_(transform) {}

_ZN5draco32CreatePredictionSchemeForDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIT_T0_EENS3_14default_deleteIS8_EEEENS_22PredictionSchemeMethodEiPKNS_17PointCloudDecoderE:
  187|      7|                                 const PointCloudDecoder *decoder) {
  188|      7|  return CreatePredictionSchemeForDecoder<DataTypeT, TransformT>(
  189|      7|      method, att_id, decoder, TransformT());
  190|      7|}
_ZN5draco32CreatePredictionSchemeForDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIT_T0_EENS3_14default_deleteIS8_EEEENS_22PredictionSchemeMethodEiPKNS_17PointCloudDecoderERKS7_:
  155|      7|                                 const TransformT &transform) {
  156|      7|  if (method == PREDICTION_NONE) {
  ------------------
  |  Branch (156:7): [True: 0, False: 7]
  ------------------
  157|      0|    return nullptr;
  158|      0|  }
  159|      7|  const PointAttribute *const att = decoder->point_cloud()->attribute(att_id);
  160|      7|  if (decoder->GetGeometryType() == TRIANGULAR_MESH) {
  ------------------
  |  Branch (160:7): [True: 7, False: 0]
  ------------------
  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|      7|    const MeshDecoder *const mesh_decoder =
  167|      7|        static_cast<const MeshDecoder *>(decoder);
  168|       |
  169|      7|    auto ret = CreateMeshPredictionScheme<
  170|      7|        MeshDecoder, PredictionSchemeDecoder<DataTypeT, TransformT>,
  171|      7|        MeshPredictionSchemeDecoderFactory<DataTypeT>>(
  172|      7|        mesh_decoder, method, att_id, transform, decoder->bitstream_version());
  173|      7|    if (ret) {
  ------------------
  |  Branch (173:9): [True: 0, False: 7]
  ------------------
  174|      0|      return ret;
  175|      0|    }
  176|       |    // Otherwise try to create another prediction scheme.
  177|      7|  }
  178|       |  // Create delta decoder.
  179|      7|  return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
  180|      7|      new PredictionSchemeDeltaDecoder<DataTypeT, TransformT>(att, transform));
  181|      7|}
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiEclINS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIiT_EENS8_14default_deleteISC_EEEENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKSB_RKT0_t:
  142|      1|      uint16_t bitstream_version) {
  143|      1|    return DispatchFunctor<TransformT, MeshDataT, TransformT::GetType()>()(
  144|      1|        method, attribute, transform, mesh_data, bitstream_version);
  145|      1|  }
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiE15DispatchFunctorINS_49PredictionSchemeNormalOctahedronDecodingTransformIiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEELNS_29PredictionSchemeTransformTypeE2EEclENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKS4_RKS7_t:
  126|      1|        uint16_t bitstream_version) {
  127|      1|      if (method == MESH_PREDICTION_GEOMETRIC_NORMAL) {
  ------------------
  |  Branch (127:11): [True: 0, False: 1]
  ------------------
  128|      0|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
  129|      0|            new MeshPredictionSchemeGeometricNormalDecoder<
  130|      0|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
  131|      0|                                                  mesh_data));
  132|      0|      }
  133|      1|      return nullptr;
  134|      1|    }
_ZN5draco32CreatePredictionSchemeForDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIT_T0_EENS3_14default_deleteIS8_EEEENS_22PredictionSchemeMethodEiPKNS_17PointCloudDecoderE:
  187|     22|                                 const PointCloudDecoder *decoder) {
  188|     22|  return CreatePredictionSchemeForDecoder<DataTypeT, TransformT>(
  189|     22|      method, att_id, decoder, TransformT());
  190|     22|}
_ZN5draco32CreatePredictionSchemeForDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIT_T0_EENS3_14default_deleteIS8_EEEENS_22PredictionSchemeMethodEiPKNS_17PointCloudDecoderERKS7_:
  155|     22|                                 const TransformT &transform) {
  156|     22|  if (method == PREDICTION_NONE) {
  ------------------
  |  Branch (156:7): [True: 0, False: 22]
  ------------------
  157|      0|    return nullptr;
  158|      0|  }
  159|     22|  const PointAttribute *const att = decoder->point_cloud()->attribute(att_id);
  160|     22|  if (decoder->GetGeometryType() == TRIANGULAR_MESH) {
  ------------------
  |  Branch (160:7): [True: 22, False: 0]
  ------------------
  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|     22|    const MeshDecoder *const mesh_decoder =
  167|     22|        static_cast<const MeshDecoder *>(decoder);
  168|       |
  169|     22|    auto ret = CreateMeshPredictionScheme<
  170|     22|        MeshDecoder, PredictionSchemeDecoder<DataTypeT, TransformT>,
  171|     22|        MeshPredictionSchemeDecoderFactory<DataTypeT>>(
  172|     22|        mesh_decoder, method, att_id, transform, decoder->bitstream_version());
  173|     22|    if (ret) {
  ------------------
  |  Branch (173:9): [True: 0, False: 22]
  ------------------
  174|      0|      return ret;
  175|      0|    }
  176|       |    // Otherwise try to create another prediction scheme.
  177|     22|  }
  178|       |  // Create delta decoder.
  179|     22|  return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
  180|     22|      new PredictionSchemeDeltaDecoder<DataTypeT, TransformT>(att, transform));
  181|     22|}
_ZN5draco32CreatePredictionSchemeForDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIT_T0_EENS3_14default_deleteIS8_EEEENS_22PredictionSchemeMethodEiPKNS_17PointCloudDecoderE:
  187|    675|                                 const PointCloudDecoder *decoder) {
  188|    675|  return CreatePredictionSchemeForDecoder<DataTypeT, TransformT>(
  189|    675|      method, att_id, decoder, TransformT());
  190|    675|}
_ZN5draco32CreatePredictionSchemeForDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIT_T0_EENS3_14default_deleteIS8_EEEENS_22PredictionSchemeMethodEiPKNS_17PointCloudDecoderERKS7_:
  155|    675|                                 const TransformT &transform) {
  156|    675|  if (method == PREDICTION_NONE) {
  ------------------
  |  Branch (156:7): [True: 0, False: 675]
  ------------------
  157|      0|    return nullptr;
  158|      0|  }
  159|    675|  const PointAttribute *const att = decoder->point_cloud()->attribute(att_id);
  160|    675|  if (decoder->GetGeometryType() == TRIANGULAR_MESH) {
  ------------------
  |  Branch (160:7): [True: 675, False: 0]
  ------------------
  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|    675|    const MeshDecoder *const mesh_decoder =
  167|    675|        static_cast<const MeshDecoder *>(decoder);
  168|       |
  169|    675|    auto ret = CreateMeshPredictionScheme<
  170|    675|        MeshDecoder, PredictionSchemeDecoder<DataTypeT, TransformT>,
  171|    675|        MeshPredictionSchemeDecoderFactory<DataTypeT>>(
  172|    675|        mesh_decoder, method, att_id, transform, decoder->bitstream_version());
  173|    675|    if (ret) {
  ------------------
  |  Branch (173:9): [True: 516, False: 159]
  ------------------
  174|    516|      return ret;
  175|    516|    }
  176|       |    // Otherwise try to create another prediction scheme.
  177|    675|  }
  178|       |  // Create delta decoder.
  179|    159|  return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
  180|    159|      new PredictionSchemeDeltaDecoder<DataTypeT, TransformT>(att, transform));
  181|    675|}
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiEclINS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIiT_EENS8_14default_deleteISC_EEEENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKSB_RKT0_t:
  142|    200|      uint16_t bitstream_version) {
  143|    200|    return DispatchFunctor<TransformT, MeshDataT, TransformT::GetType()>()(
  144|    200|        method, attribute, transform, mesh_data, bitstream_version);
  145|    200|  }
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiE15DispatchFunctorINS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_24MeshAttributeCornerTableEEELNS_29PredictionSchemeTransformTypeE1EEclENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKS4_RKS7_t:
   52|    200|        uint16_t bitstream_version) {
   53|    200|      if (method == MESH_PREDICTION_PARALLELOGRAM) {
  ------------------
  |  Branch (53:11): [True: 19, False: 181]
  ------------------
   54|     19|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   55|     19|            new MeshPredictionSchemeParallelogramDecoder<DataTypeT, TransformT,
   56|     19|                                                         MeshDataT>(
   57|     19|                attribute, transform, mesh_data));
   58|     19|      }
   59|    181|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   60|    181|      else if (method == MESH_PREDICTION_MULTI_PARALLELOGRAM) {
  ------------------
  |  Branch (60:16): [True: 34, False: 147]
  ------------------
   61|     34|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   62|     34|            new MeshPredictionSchemeMultiParallelogramDecoder<
   63|     34|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
   64|     34|                                                  mesh_data));
   65|     34|      }
   66|    147|#endif
   67|    147|      else if (method == MESH_PREDICTION_CONSTRAINED_MULTI_PARALLELOGRAM) {
  ------------------
  |  Branch (67:16): [True: 52, False: 95]
  ------------------
   68|     52|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   69|     52|            new MeshPredictionSchemeConstrainedMultiParallelogramDecoder<
   70|     52|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
   71|     52|                                                  mesh_data));
   72|     52|      }
   73|     95|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   74|     95|      else if (method == MESH_PREDICTION_TEX_COORDS_DEPRECATED) {
  ------------------
  |  Branch (74:16): [True: 10, False: 85]
  ------------------
   75|     10|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   76|     10|            new MeshPredictionSchemeTexCoordsDecoder<DataTypeT, TransformT,
   77|     10|                                                     MeshDataT>(
   78|     10|                attribute, transform, mesh_data, bitstream_version));
   79|     10|      }
   80|     85|#endif
   81|     85|      else if (method == MESH_PREDICTION_TEX_COORDS_PORTABLE) {
  ------------------
  |  Branch (81:16): [True: 10, False: 75]
  ------------------
   82|     10|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   83|     10|            new MeshPredictionSchemeTexCoordsPortableDecoder<
   84|     10|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
   85|     10|                                                  mesh_data));
   86|     10|      }
   87|     75|#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
   88|     75|      else if (method == MESH_PREDICTION_GEOMETRIC_NORMAL) {
  ------------------
  |  Branch (88:16): [True: 75, False: 0]
  ------------------
   89|     75|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   90|     75|            new MeshPredictionSchemeGeometricNormalDecoder<
   91|     75|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
   92|     75|                                                  mesh_data));
   93|     75|      }
   94|      0|#endif
   95|      0|      return nullptr;
   96|    200|    }
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiEclINS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEEEENSt3__110unique_ptrINS_23PredictionSchemeDecoderIiT_EENS8_14default_deleteISC_EEEENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKSB_RKT0_t:
  142|    316|      uint16_t bitstream_version) {
  143|    316|    return DispatchFunctor<TransformT, MeshDataT, TransformT::GetType()>()(
  144|    316|        method, attribute, transform, mesh_data, bitstream_version);
  145|    316|  }
_ZN5draco34MeshPredictionSchemeDecoderFactoryIiE15DispatchFunctorINS_37PredictionSchemeWrapDecodingTransformIiiEENS_24MeshPredictionSchemeDataINS_11CornerTableEEELNS_29PredictionSchemeTransformTypeE1EEclENS_22PredictionSchemeMethodEPKNS_14PointAttributeERKS4_RKS7_t:
   52|    316|        uint16_t bitstream_version) {
   53|    316|      if (method == MESH_PREDICTION_PARALLELOGRAM) {
  ------------------
  |  Branch (53:11): [True: 50, False: 266]
  ------------------
   54|     50|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   55|     50|            new MeshPredictionSchemeParallelogramDecoder<DataTypeT, TransformT,
   56|     50|                                                         MeshDataT>(
   57|     50|                attribute, transform, mesh_data));
   58|     50|      }
   59|    266|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   60|    266|      else if (method == MESH_PREDICTION_MULTI_PARALLELOGRAM) {
  ------------------
  |  Branch (60:16): [True: 77, False: 189]
  ------------------
   61|     77|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   62|     77|            new MeshPredictionSchemeMultiParallelogramDecoder<
   63|     77|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
   64|     77|                                                  mesh_data));
   65|     77|      }
   66|    189|#endif
   67|    189|      else if (method == MESH_PREDICTION_CONSTRAINED_MULTI_PARALLELOGRAM) {
  ------------------
  |  Branch (67:16): [True: 47, False: 142]
  ------------------
   68|     47|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   69|     47|            new MeshPredictionSchemeConstrainedMultiParallelogramDecoder<
   70|     47|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
   71|     47|                                                  mesh_data));
   72|     47|      }
   73|    142|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   74|    142|      else if (method == MESH_PREDICTION_TEX_COORDS_DEPRECATED) {
  ------------------
  |  Branch (74:16): [True: 53, False: 89]
  ------------------
   75|     53|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   76|     53|            new MeshPredictionSchemeTexCoordsDecoder<DataTypeT, TransformT,
   77|     53|                                                     MeshDataT>(
   78|     53|                attribute, transform, mesh_data, bitstream_version));
   79|     53|      }
   80|     89|#endif
   81|     89|      else if (method == MESH_PREDICTION_TEX_COORDS_PORTABLE) {
  ------------------
  |  Branch (81:16): [True: 20, False: 69]
  ------------------
   82|     20|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   83|     20|            new MeshPredictionSchemeTexCoordsPortableDecoder<
   84|     20|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
   85|     20|                                                  mesh_data));
   86|     20|      }
   87|     69|#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
   88|     69|      else if (method == MESH_PREDICTION_GEOMETRIC_NORMAL) {
  ------------------
  |  Branch (88:16): [True: 69, False: 0]
  ------------------
   89|     69|        return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
   90|     69|            new MeshPredictionSchemeGeometricNormalDecoder<
   91|     69|                DataTypeT, TransformT, MeshDataT>(attribute, transform,
   92|     69|                                                  mesh_data));
   93|     69|      }
   94|      0|#endif
   95|      0|      return nullptr;
   96|    316|    }

_ZN5draco28PredictionSchemeDeltaDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   49|      4|    const PointIndex *) {
   50|      4|  this->transform().Init(num_components);
   51|       |  // Decode the original value for the first element.
   52|      4|  std::unique_ptr<DataTypeT[]> zero_vals(new DataTypeT[num_components]());
   53|      4|  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|    320|  for (int i = num_components; i < size; i += num_components) {
  ------------------
  |  Branch (56:32): [True: 316, False: 4]
  ------------------
   57|    316|    this->transform().ComputeOriginalValue(out_data + i - num_components,
   58|    316|                                           in_corr + i, out_data + i);
   59|    316|  }
   60|      4|  return true;
   61|      4|}
_ZN5draco28PredictionSchemeDeltaDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   49|     13|    const PointIndex *) {
   50|     13|  this->transform().Init(num_components);
   51|       |  // Decode the original value for the first element.
   52|     13|  std::unique_ptr<DataTypeT[]> zero_vals(new DataTypeT[num_components]());
   53|     13|  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|  14.5k|  for (int i = num_components; i < size; i += num_components) {
  ------------------
  |  Branch (56:32): [True: 14.5k, False: 13]
  ------------------
   57|  14.5k|    this->transform().ComputeOriginalValue(out_data + i - num_components,
   58|  14.5k|                                           in_corr + i, out_data + i);
   59|  14.5k|  }
   60|     13|  return true;
   61|     13|}
_ZN5draco28PredictionSchemeDeltaDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEEC2EPKNS_14PointAttributeERKS2_:
   35|    159|      : PredictionSchemeDecoder<DataTypeT, TransformT>(attribute, transform) {}
_ZN5draco28PredictionSchemeDeltaDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEE21ComputeOriginalValuesEPKiPiiiPKNS_9IndexTypeIjNS_20PointIndex_tag_type_EEE:
   49|    149|    const PointIndex *) {
   50|    149|  this->transform().Init(num_components);
   51|       |  // Decode the original value for the first element.
   52|    149|  std::unique_ptr<DataTypeT[]> zero_vals(new DataTypeT[num_components]());
   53|    149|  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|    782|  for (int i = num_components; i < size; i += num_components) {
  ------------------
  |  Branch (56:32): [True: 633, False: 149]
  ------------------
   57|    633|    this->transform().ComputeOriginalValue(out_data + i - num_components,
   58|    633|                                           in_corr + i, out_data + i);
   59|    633|  }
   60|    149|  return true;
   61|    149|}
_ZN5draco28PredictionSchemeDeltaDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEEC2EPKNS_14PointAttributeERKS2_:
   35|      7|      : PredictionSchemeDecoder<DataTypeT, TransformT>(attribute, transform) {}
_ZN5draco28PredictionSchemeDeltaDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEEC2EPKNS_14PointAttributeERKS2_:
   35|     22|      : PredictionSchemeDecoder<DataTypeT, TransformT>(attribute, transform) {}

_ZN5draco26CreateMeshPredictionSchemeINS_11MeshDecoderENS_23PredictionSchemeDecoderIiNS_49PredictionSchemeNormalOctahedronDecodingTransformIiEEEENS_34MeshPredictionSchemeDecoderFactoryIiEEEENSt3__110unique_ptrIT0_NS8_14default_deleteISA_EEEEPKT_NS_22PredictionSchemeMethodEiRKNSA_9TransformEt:
   37|      7|    uint16_t bitstream_version) {
   38|      7|  const PointAttribute *const att = source->point_cloud()->attribute(att_id);
   39|      7|  if (source->GetGeometryType() == TRIANGULAR_MESH &&
  ------------------
  |  Branch (39:7): [True: 7, False: 0]
  ------------------
   40|      7|      (method == MESH_PREDICTION_PARALLELOGRAM ||
  ------------------
  |  Branch (40:8): [True: 3, False: 4]
  ------------------
   41|      7|       method == MESH_PREDICTION_MULTI_PARALLELOGRAM ||
  ------------------
  |  Branch (41:8): [True: 1, False: 3]
  ------------------
   42|      7|       method == MESH_PREDICTION_CONSTRAINED_MULTI_PARALLELOGRAM ||
  ------------------
  |  Branch (42:8): [True: 0, False: 3]
  ------------------
   43|      7|       method == MESH_PREDICTION_TEX_COORDS_PORTABLE ||
  ------------------
  |  Branch (43:8): [True: 0, False: 3]
  ------------------
   44|      7|       method == MESH_PREDICTION_GEOMETRIC_NORMAL ||
  ------------------
  |  Branch (44:8): [True: 1, False: 2]
  ------------------
   45|      7|       method == MESH_PREDICTION_TEX_COORDS_DEPRECATED)) {
  ------------------
  |  Branch (45:8): [True: 1, False: 1]
  ------------------
   46|      6|    const CornerTable *const ct = source->GetCornerTable();
   47|      6|    const MeshAttributeIndicesEncodingData *const encoding_data =
   48|      6|        source->GetAttributeEncodingData(att_id);
   49|      6|    if (ct == nullptr || encoding_data == nullptr) {
  ------------------
  |  Branch (49:9): [True: 5, False: 1]
  |  Branch (49:26): [True: 0, False: 1]
  ------------------
   50|       |      // No connectivity data found.
   51|      5|      return nullptr;
   52|      5|    }
   53|       |    // Connectivity data exists.
   54|      1|    const MeshAttributeCornerTable *const att_ct =
   55|      1|        source->GetAttributeCornerTable(att_id);
   56|      1|    if (att_ct != nullptr) {
  ------------------
  |  Branch (56:9): [True: 1, False: 0]
  ------------------
   57|      1|      typedef MeshPredictionSchemeData<MeshAttributeCornerTable> MeshData;
   58|      1|      MeshData md;
   59|      1|      md.Set(source->mesh(), att_ct,
   60|      1|             &encoding_data->encoded_attribute_value_index_to_corner_map,
   61|      1|             &encoding_data->vertex_to_encoded_attribute_value_index_map);
   62|      1|      MeshPredictionSchemeFactoryT factory;
   63|      1|      auto ret = factory(method, att, transform, md, bitstream_version);
   64|      1|      if (ret) {
  ------------------
  |  Branch (64:11): [True: 0, False: 1]
  ------------------
   65|      0|        return ret;
   66|      0|      }
   67|      1|    } else {
   68|      0|      typedef MeshPredictionSchemeData<CornerTable> MeshData;
   69|      0|      MeshData md;
   70|      0|      md.Set(source->mesh(), ct,
   71|      0|             &encoding_data->encoded_attribute_value_index_to_corner_map,
   72|      0|             &encoding_data->vertex_to_encoded_attribute_value_index_map);
   73|      0|      MeshPredictionSchemeFactoryT factory;
   74|      0|      auto ret = factory(method, att, transform, md, bitstream_version);
   75|      0|      if (ret) {
  ------------------
  |  Branch (75:11): [True: 0, False: 0]
  ------------------
   76|      0|        return ret;
   77|      0|      }
   78|      0|    }
   79|      1|  }
   80|      2|  return nullptr;
   81|      7|}
_ZN5draco26CreateMeshPredictionSchemeINS_11MeshDecoderENS_23PredictionSchemeDecoderIiNS_62PredictionSchemeNormalOctahedronCanonicalizedDecodingTransformIiEEEENS_34MeshPredictionSchemeDecoderFactoryIiEEEENSt3__110unique_ptrIT0_NS8_14default_deleteISA_EEEEPKT_NS_22PredictionSchemeMethodEiRKNSA_9TransformEt:
   37|     22|    uint16_t bitstream_version) {
   38|     22|  const PointAttribute *const att = source->point_cloud()->attribute(att_id);
   39|     22|  if (source->GetGeometryType() == TRIANGULAR_MESH &&
  ------------------
  |  Branch (39:7): [True: 22, False: 0]
  ------------------
   40|     22|      (method == MESH_PREDICTION_PARALLELOGRAM ||
  ------------------
  |  Branch (40:8): [True: 3, False: 19]
  ------------------
   41|     22|       method == MESH_PREDICTION_MULTI_PARALLELOGRAM ||
  ------------------
  |  Branch (41:8): [True: 2, False: 17]
  ------------------
   42|     22|       method == MESH_PREDICTION_CONSTRAINED_MULTI_PARALLELOGRAM ||
  ------------------
  |  Branch (42:8): [True: 4, False: 13]
  ------------------
   43|     22|       method == MESH_PREDICTION_TEX_COORDS_PORTABLE ||
  ------------------
  |  Branch (43:8): [True: 4, False: 9]
  ------------------
   44|     22|       method == MESH_PREDICTION_GEOMETRIC_NORMAL ||
  ------------------
  |  Branch (44:8): [True: 2, False: 7]
  ------------------
   45|     22|       method == MESH_PREDICTION_TEX_COORDS_DEPRECATED)) {
  ------------------
  |  Branch (45:8): [True: 3, False: 4]
  ------------------
   46|     18|    const CornerTable *const ct = source->GetCornerTable();
   47|     18|    const MeshAttributeIndicesEncodingData *const encoding_data =
   48|     18|        source->GetAttributeEncodingData(att_id);
   49|     18|    if (ct == nullptr || encoding_data == nullptr) {
  ------------------
  |  Branch (49:9): [True: 18, False: 0]
  |  Branch (49:26): [True: 0, False: 0]
  ------------------
   50|       |      // No connectivity data found.
   51|     18|      return nullptr;
   52|     18|    }
   53|       |    // Connectivity data exists.
   54|      0|    const MeshAttributeCornerTable *const att_ct =
   55|      0|        source->GetAttributeCornerTable(att_id);
   56|      0|    if (att_ct != nullptr) {
  ------------------
  |  Branch (56:9): [True: 0, False: 0]
  ------------------
   57|      0|      typedef MeshPredictionSchemeData<MeshAttributeCornerTable> MeshData;
   58|      0|      MeshData md;
   59|      0|      md.Set(source->mesh(), att_ct,
   60|      0|             &encoding_data->encoded_attribute_value_index_to_corner_map,
   61|      0|             &encoding_data->vertex_to_encoded_attribute_value_index_map);
   62|      0|      MeshPredictionSchemeFactoryT factory;
   63|      0|      auto ret = factory(method, att, transform, md, bitstream_version);
   64|      0|      if (ret) {
  ------------------
  |  Branch (64:11): [True: 0, False: 0]
  ------------------
   65|      0|        return ret;
   66|      0|      }
   67|      0|    } else {
   68|      0|      typedef MeshPredictionSchemeData<CornerTable> MeshData;
   69|      0|      MeshData md;
   70|      0|      md.Set(source->mesh(), ct,
   71|      0|             &encoding_data->encoded_attribute_value_index_to_corner_map,
   72|      0|             &encoding_data->vertex_to_encoded_attribute_value_index_map);
   73|      0|      MeshPredictionSchemeFactoryT factory;
   74|      0|      auto ret = factory(method, att, transform, md, bitstream_version);
   75|      0|      if (ret) {
  ------------------
  |  Branch (75:11): [True: 0, False: 0]
  ------------------
   76|      0|        return ret;
   77|      0|      }
   78|      0|    }
   79|      0|  }
   80|      4|  return nullptr;
   81|     22|}
_ZN5draco26CreateMeshPredictionSchemeINS_11MeshDecoderENS_23PredictionSchemeDecoderIiNS_37PredictionSchemeWrapDecodingTransformIiiEEEENS_34MeshPredictionSchemeDecoderFactoryIiEEEENSt3__110unique_ptrIT0_NS8_14default_deleteISA_EEEEPKT_NS_22PredictionSchemeMethodEiRKNSA_9TransformEt:
   37|    675|    uint16_t bitstream_version) {
   38|    675|  const PointAttribute *const att = source->point_cloud()->attribute(att_id);
   39|    675|  if (source->GetGeometryType() == TRIANGULAR_MESH &&
  ------------------
  |  Branch (39:7): [True: 675, False: 0]
  ------------------
   40|    675|      (method == MESH_PREDICTION_PARALLELOGRAM ||
  ------------------
  |  Branch (40:8): [True: 75, False: 600]
  ------------------
   41|    675|       method == MESH_PREDICTION_MULTI_PARALLELOGRAM ||
  ------------------
  |  Branch (41:8): [True: 123, False: 477]
  ------------------
   42|    675|       method == MESH_PREDICTION_CONSTRAINED_MULTI_PARALLELOGRAM ||
  ------------------
  |  Branch (42:8): [True: 99, False: 378]
  ------------------
   43|    675|       method == MESH_PREDICTION_TEX_COORDS_PORTABLE ||
  ------------------
  |  Branch (43:8): [True: 30, False: 348]
  ------------------
   44|    675|       method == MESH_PREDICTION_GEOMETRIC_NORMAL ||
  ------------------
  |  Branch (44:8): [True: 144, False: 204]
  ------------------
   45|    675|       method == MESH_PREDICTION_TEX_COORDS_DEPRECATED)) {
  ------------------
  |  Branch (45:8): [True: 64, False: 140]
  ------------------
   46|    535|    const CornerTable *const ct = source->GetCornerTable();
   47|    535|    const MeshAttributeIndicesEncodingData *const encoding_data =
   48|    535|        source->GetAttributeEncodingData(att_id);
   49|    535|    if (ct == nullptr || encoding_data == nullptr) {
  ------------------
  |  Branch (49:9): [True: 19, False: 516]
  |  Branch (49:26): [True: 0, False: 516]
  ------------------
   50|       |      // No connectivity data found.
   51|     19|      return nullptr;
   52|     19|    }
   53|       |    // Connectivity data exists.
   54|    516|    const MeshAttributeCornerTable *const att_ct =
   55|    516|        source->GetAttributeCornerTable(att_id);
   56|    516|    if (att_ct != nullptr) {
  ------------------
  |  Branch (56:9): [True: 200, False: 316]
  ------------------
   57|    200|      typedef MeshPredictionSchemeData<MeshAttributeCornerTable> MeshData;
   58|    200|      MeshData md;
   59|    200|      md.Set(source->mesh(), att_ct,
   60|    200|             &encoding_data->encoded_attribute_value_index_to_corner_map,
   61|    200|             &encoding_data->vertex_to_encoded_attribute_value_index_map);
   62|    200|      MeshPredictionSchemeFactoryT factory;
   63|    200|      auto ret = factory(method, att, transform, md, bitstream_version);
   64|    200|      if (ret) {
  ------------------
  |  Branch (64:11): [True: 200, False: 0]
  ------------------
   65|    200|        return ret;
   66|    200|      }
   67|    316|    } else {
   68|    316|      typedef MeshPredictionSchemeData<CornerTable> MeshData;
   69|    316|      MeshData md;
   70|    316|      md.Set(source->mesh(), ct,
   71|    316|             &encoding_data->encoded_attribute_value_index_to_corner_map,
   72|    316|             &encoding_data->vertex_to_encoded_attribute_value_index_map);
   73|    316|      MeshPredictionSchemeFactoryT factory;
   74|    316|      auto ret = factory(method, att, transform, md, bitstream_version);
   75|    316|      if (ret) {
  ------------------
  |  Branch (75:11): [True: 316, False: 0]
  ------------------
   76|    316|        return ret;
   77|    316|      }
   78|    316|    }
   79|    516|  }
   80|    140|  return nullptr;
   81|    675|}

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

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

_ZNK5draco58PredictionSchemeNormalOctahedronCanonicalizedTransformBaseIiE14IsInBottomLeftERKNS_7VectorDIiLi2EEE:
   92|  14.5k|  bool IsInBottomLeft(const Point2 &p) const {
   93|  14.5k|    if (p[0] == 0 && p[1] == 0) {
  ------------------
  |  Branch (93:9): [True: 613, False: 13.9k]
  |  Branch (93:22): [True: 329, False: 284]
  ------------------
   94|    329|      return true;
   95|    329|    }
   96|  14.1k|    return (p[0] < 0 && p[1] <= 0);
  ------------------
  |  Branch (96:13): [True: 1.82k, False: 12.3k]
  |  Branch (96:25): [True: 709, False: 1.11k]
  ------------------
   97|  14.5k|  }
_ZNK5draco58PredictionSchemeNormalOctahedronCanonicalizedTransformBaseIiE16GetRotationCountENS_7VectorDIiLi2EEE:
   50|  14.5k|  int32_t GetRotationCount(Point2 pred) const {
   51|  14.5k|    const DataType sign_x = pred[0];
   52|  14.5k|    const DataType sign_y = pred[1];
   53|       |
   54|  14.5k|    int32_t rotation_count = 0;
   55|  14.5k|    if (sign_x == 0) {
  ------------------
  |  Branch (55:9): [True: 613, False: 13.9k]
  ------------------
   56|    613|      if (sign_y == 0) {
  ------------------
  |  Branch (56:11): [True: 329, False: 284]
  ------------------
   57|    329|        rotation_count = 0;
   58|    329|      } else if (sign_y > 0) {
  ------------------
  |  Branch (58:18): [True: 263, False: 21]
  ------------------
   59|    263|        rotation_count = 3;
   60|    263|      } else {
   61|     21|        rotation_count = 1;
   62|     21|      }
   63|  13.9k|    } else if (sign_x > 0) {
  ------------------
  |  Branch (63:16): [True: 12.0k, False: 1.82k]
  ------------------
   64|  12.0k|      if (sign_y >= 0) {
  ------------------
  |  Branch (64:11): [True: 11.3k, False: 778]
  ------------------
   65|  11.3k|        rotation_count = 2;
   66|  11.3k|      } else {
   67|    778|        rotation_count = 1;
   68|    778|      }
   69|  12.0k|    } else {
   70|  1.82k|      if (sign_y <= 0) {
  ------------------
  |  Branch (70:11): [True: 709, False: 1.11k]
  ------------------
   71|    709|        rotation_count = 0;
   72|  1.11k|      } else {
   73|  1.11k|        rotation_count = 3;
   74|  1.11k|      }
   75|  1.82k|    }
   76|  14.5k|    return rotation_count;
   77|  14.5k|  }
_ZNK5draco58PredictionSchemeNormalOctahedronCanonicalizedTransformBaseIiE11RotatePointENS_7VectorDIiLi2EEEi:
   79|  26.9k|  Point2 RotatePoint(Point2 p, int32_t rotation_count) const {
   80|  26.9k|    switch (rotation_count) {
   81|  2.18k|      case 1:
  ------------------
  |  Branch (81:7): [True: 2.18k, False: 24.7k]
  ------------------
   82|  2.18k|        return Point2(p[1], -p[0]);
   83|  22.6k|      case 2:
  ------------------
  |  Branch (83:7): [True: 22.6k, False: 4.36k]
  ------------------
   84|  22.6k|        return Point2(-p[0], -p[1]);
   85|  2.18k|      case 3:
  ------------------
  |  Branch (85:7): [True: 2.18k, False: 24.7k]
  ------------------
   86|  2.18k|        return Point2(-p[1], p[0]);
   87|      0|      default:
  ------------------
  |  Branch (87:7): [True: 0, False: 26.9k]
  ------------------
   88|      0|        return p;
   89|  26.9k|    }
   90|  26.9k|  }
_ZN5draco58PredictionSchemeNormalOctahedronCanonicalizedTransformBaseIiEC2Ev:
   40|     22|  PredictionSchemeNormalOctahedronCanonicalizedTransformBase() : Base() {}

_ZN5draco49PredictionSchemeNormalOctahedronDecodingTransformIiE19DecodeTransformDataEPNS_13DecoderBufferE:
   45|      7|  bool DecodeTransformData(DecoderBuffer *buffer) {
   46|      7|    DataTypeT max_quantized_value, center_value;
   47|      7|    if (!buffer->Decode(&max_quantized_value)) {
  ------------------
  |  Branch (47:9): [True: 0, False: 7]
  ------------------
   48|      0|      return false;
   49|      0|    }
   50|      7|    if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|      7|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (50:9): [True: 1, False: 6]
  ------------------
   51|      1|      if (!buffer->Decode(&center_value)) {
  ------------------
  |  Branch (51:11): [True: 0, False: 1]
  ------------------
   52|      0|        return false;
   53|      0|      }
   54|      1|    }
   55|      7|    (void)center_value;
   56|      7|    return this->set_max_quantized_value(max_quantized_value);
   57|      7|  }
_ZNK5draco49PredictionSchemeNormalOctahedronDecodingTransformIiE20ComputeOriginalValueEPKiS3_Pi:
   61|    320|                                   DataType *out_orig_vals) const {
   62|    320|    DRACO_DCHECK_LE(pred_vals[0], 2 * this->center_value());
   63|    320|    DRACO_DCHECK_LE(pred_vals[1], 2 * this->center_value());
   64|    320|    DRACO_DCHECK_LE(corr_vals[0], 2 * this->center_value());
   65|    320|    DRACO_DCHECK_LE(corr_vals[1], 2 * this->center_value());
   66|       |
   67|    320|    DRACO_DCHECK_LE(0, pred_vals[0]);
   68|    320|    DRACO_DCHECK_LE(0, pred_vals[1]);
   69|    320|    DRACO_DCHECK_LE(0, corr_vals[0]);
   70|    320|    DRACO_DCHECK_LE(0, corr_vals[1]);
   71|       |
   72|    320|    const Point2 pred = Point2(pred_vals[0], pred_vals[1]);
   73|    320|    const Point2 corr = Point2(corr_vals[0], corr_vals[1]);
   74|    320|    const Point2 orig = ComputeOriginalValue(pred, corr);
   75|       |
   76|    320|    out_orig_vals[0] = orig[0];
   77|    320|    out_orig_vals[1] = orig[1];
   78|    320|  }
_ZNK5draco49PredictionSchemeNormalOctahedronDecodingTransformIiE20ComputeOriginalValueENS_7VectorDIiLi2EEERKS3_:
   81|    320|  Point2 ComputeOriginalValue(Point2 pred, const Point2 &corr) const {
   82|    320|    const Point2 t(this->center_value(), this->center_value());
   83|    320|    typedef typename std::make_unsigned<DataTypeT>::type UnsignedDataTypeT;
   84|    320|    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|    320|    pred = Point2(Point2u(pred) - Point2u(t));
   89|       |
   90|    320|    const bool pred_is_in_diamond = this->IsInDiamond(pred[0], pred[1]);
   91|    320|    if (!pred_is_in_diamond) {
  ------------------
  |  Branch (91:9): [True: 239, False: 81]
  ------------------
   92|    239|      this->InvertDiamond(&pred[0], &pred[1]);
   93|    239|    }
   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|    320|    Point2 orig(Point2u(pred) + Point2u(corr));
   98|       |
   99|    320|    orig[0] = this->ModMax(orig[0]);
  100|    320|    orig[1] = this->ModMax(orig[1]);
  101|    320|    if (!pred_is_in_diamond) {
  ------------------
  |  Branch (101:9): [True: 239, False: 81]
  ------------------
  102|    239|      this->InvertDiamond(&orig[0], &orig[1]);
  103|    239|    }
  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|    320|    orig = Point2(Point2u(orig) + Point2u(t));
  108|    320|    return orig;
  109|    320|  }
_ZN5draco49PredictionSchemeNormalOctahedronDecodingTransformIiE4InitEi:
   44|      4|  void Init(int num_components) {}
_ZN5draco49PredictionSchemeNormalOctahedronDecodingTransformIiEC2Ev:
   41|      7|  PredictionSchemeNormalOctahedronDecodingTransform() {}

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

_ZN5draco37PredictionSchemeWrapDecodingTransformIiiE19DecodeTransformDataEPNS_13DecoderBufferE:
   66|    589|  bool DecodeTransformData(DecoderBuffer *buffer) {
   67|    589|    DataTypeT min_value, max_value;
   68|    589|    if (!buffer->Decode(&min_value)) {
  ------------------
  |  Branch (68:9): [True: 0, False: 589]
  ------------------
   69|      0|      return false;
   70|      0|    }
   71|    589|    if (!buffer->Decode(&max_value)) {
  ------------------
  |  Branch (71:9): [True: 1, False: 588]
  ------------------
   72|      1|      return false;
   73|      1|    }
   74|    588|    if (min_value > max_value) {
  ------------------
  |  Branch (74:9): [True: 21, False: 567]
  ------------------
   75|     21|      return false;
   76|     21|    }
   77|    567|    this->set_min_value(min_value);
   78|    567|    this->set_max_value(max_value);
   79|    567|    if (!this->InitCorrectionBounds()) {
  ------------------
  |  Branch (79:9): [True: 1, False: 566]
  ------------------
   80|      1|      return false;
   81|      1|    }
   82|    566|    return true;
   83|    567|  }
_ZNK5draco37PredictionSchemeWrapDecodingTransformIiiE20ComputeOriginalValueEPKiS3_Pi:
   38|   257k|                                   DataTypeT *out_original_vals) const {
   39|       |    // For now we assume both |DataTypeT| and |CorrTypeT| are equal.
   40|   257k|    static_assert(std::is_same<DataTypeT, CorrTypeT>::value,
   41|   257k|                  "Predictions and corrections must have the same type.");
   42|       |
   43|       |    // The only valid implementation right now is for int32_t.
   44|   257k|    static_assert(std::is_same<DataTypeT, int32_t>::value,
   45|   257k|                  "Only int32_t is supported for predicted values.");
   46|       |
   47|   257k|    predicted_vals = this->ClampPredictedValue(predicted_vals);
   48|       |
   49|       |    // Perform the wrapping using unsigned coordinates to avoid potential signed
   50|       |    // integer overflows caused by malformed input.
   51|   257k|    const uint32_t *const uint_predicted_vals =
   52|   257k|        reinterpret_cast<const uint32_t *>(predicted_vals);
   53|   257k|    const uint32_t *const uint_corr_vals =
   54|   257k|        reinterpret_cast<const uint32_t *>(corr_vals);
   55|  2.44M|    for (int i = 0; i < this->num_components(); ++i) {
  ------------------
  |  Branch (55:21): [True: 2.19M, False: 257k]
  ------------------
   56|  2.19M|      out_original_vals[i] =
   57|  2.19M|          static_cast<DataTypeT>(uint_predicted_vals[i] + uint_corr_vals[i]);
   58|  2.19M|      if (out_original_vals[i] > this->max_value()) {
  ------------------
  |  Branch (58:11): [True: 16.8k, False: 2.17M]
  ------------------
   59|  16.8k|        out_original_vals[i] -= this->max_dif();
   60|  2.17M|      } else if (out_original_vals[i] < this->min_value()) {
  ------------------
  |  Branch (60:18): [True: 19.4k, False: 2.15M]
  ------------------
   61|  19.4k|        out_original_vals[i] += this->max_dif();
   62|  19.4k|      }
   63|  2.19M|    }
   64|   257k|  }
_ZN5draco37PredictionSchemeWrapDecodingTransformIiiEC2Ev:
   32|    675|  PredictionSchemeWrapDecodingTransform() {}

_ZNK5draco33PredictionSchemeWrapTransformBaseIiE22AreCorrectionsPositiveEv:
   60|    643|  bool AreCorrectionsPositive() const { return false; }
_ZN5draco33PredictionSchemeWrapTransformBaseIiE13set_min_valueERKi:
  100|    567|  inline void set_min_value(const DataTypeT &v) { min_value_ = v; }
_ZN5draco33PredictionSchemeWrapTransformBaseIiE13set_max_valueERKi:
  102|    567|  inline void set_max_value(const DataTypeT &v) { max_value_ = v; }
_ZN5draco33PredictionSchemeWrapTransformBaseIiE20InitCorrectionBoundsEv:
   83|    567|  bool InitCorrectionBounds() {
   84|    567|    const int64_t dif =
   85|    567|        static_cast<int64_t>(max_value_) - static_cast<int64_t>(min_value_);
   86|    567|    if (dif < 0 || dif >= std::numeric_limits<DataTypeT>::max()) {
  ------------------
  |  Branch (86:9): [True: 0, False: 567]
  |  Branch (86:20): [True: 1, False: 566]
  ------------------
   87|      1|      return false;
   88|      1|    }
   89|    566|    max_dif_ = 1 + static_cast<DataTypeT>(dif);
   90|    566|    max_correction_ = max_dif_ / 2;
   91|    566|    min_correction_ = -max_correction_;
   92|    566|    if ((max_dif_ & 1) == 0) {
  ------------------
  |  Branch (92:9): [True: 296, False: 270]
  ------------------
   93|    296|      max_correction_ -= 1;
   94|    296|    }
   95|    566|    return true;
   96|    567|  }
_ZN5draco33PredictionSchemeWrapTransformBaseIiE4InitEi:
   55|    431|  void Init(int num_components) {
   56|    431|    num_components_ = num_components;
   57|    431|    clamped_value_.resize(num_components);
   58|    431|  }
_ZNK5draco33PredictionSchemeWrapTransformBaseIiE19ClampPredictedValueEPKi:
   63|   257k|      const DataTypeT *predicted_val) const {
   64|  2.44M|    for (int i = 0; i < this->num_components(); ++i) {
  ------------------
  |  Branch (64:21): [True: 2.19M, False: 257k]
  ------------------
   65|  2.19M|      if (predicted_val[i] > max_value_) {
  ------------------
  |  Branch (65:11): [True: 33.6k, False: 2.15M]
  ------------------
   66|  33.6k|        clamped_value_[i] = max_value_;
   67|  2.15M|      } else if (predicted_val[i] < min_value_) {
  ------------------
  |  Branch (67:18): [True: 139k, False: 2.01M]
  ------------------
   68|   139k|        clamped_value_[i] = min_value_;
   69|  2.01M|      } else {
   70|  2.01M|        clamped_value_[i] = predicted_val[i];
   71|  2.01M|      }
   72|  2.19M|    }
   73|   257k|    return clamped_value_.data();
   74|   257k|  }
_ZNK5draco33PredictionSchemeWrapTransformBaseIiE14num_componentsEv:
   98|  4.89M|  inline int num_components() const { return num_components_; }
_ZNK5draco33PredictionSchemeWrapTransformBaseIiE9max_valueEv:
  101|  2.19M|  inline DataTypeT max_value() const { return max_value_; }
_ZNK5draco33PredictionSchemeWrapTransformBaseIiE7max_difEv:
  103|  36.2k|  inline DataTypeT max_dif() const { return max_dif_; }
_ZNK5draco33PredictionSchemeWrapTransformBaseIiE9min_valueEv:
   99|  2.17M|  inline DataTypeT min_value() const { return min_value_; }
_ZNK5draco33PredictionSchemeWrapTransformBaseIiE17quantization_bitsEv:
   77|    125|  int quantization_bits() const {
   78|    125|    DRACO_DCHECK(false);
   79|    125|    return -1;
   80|    125|  }
_ZN5draco33PredictionSchemeWrapTransformBaseIiEC2Ev:
   49|    675|        min_correction_(0) {}

_ZN5draco26SequentialAttributeDecoderC2Ev:
   20|  26.0k|    : decoder_(nullptr), attribute_(nullptr), attribute_id_(-1) {}
_ZN5draco26SequentialAttributeDecoder4InitEPNS_17PointCloudDecoderEi:
   23|  26.0k|                                      int attribute_id) {
   24|  26.0k|  decoder_ = decoder;
   25|  26.0k|  attribute_ = decoder->point_cloud()->attribute(attribute_id);
   26|  26.0k|  attribute_id_ = attribute_id;
   27|  26.0k|  return true;
   28|  26.0k|}
_ZN5draco26SequentialAttributeDecoder23DecodePortableAttributeERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
   38|  2.20k|    const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) {
   39|  2.20k|  if (attribute_->num_components() <= 0 ||
  ------------------
  |  Branch (39:7): [True: 0, False: 2.20k]
  ------------------
   40|  2.20k|      !attribute_->Reset(point_ids.size())) {
  ------------------
  |  Branch (40:7): [True: 0, False: 2.20k]
  ------------------
   41|      0|    return false;
   42|      0|  }
   43|  2.20k|  if (!DecodeValues(point_ids, in_buffer)) {
  ------------------
  |  Branch (43:7): [True: 310, False: 1.89k]
  ------------------
   44|    310|    return false;
   45|    310|  }
   46|  1.89k|  return true;
   47|  2.20k|}
_ZN5draco26SequentialAttributeDecoder35DecodeDataNeededByPortableTransformERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
   50|    896|    const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) {
   51|       |  // Default implementation does not apply any transform.
   52|    896|  return true;
   53|    896|}
_ZN5draco26SequentialAttributeDecoder34TransformAttributeToOriginalFormatERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEE:
   56|    173|    const std::vector<PointIndex> &point_ids) {
   57|       |  // Default implementation does not apply any transform.
   58|    173|  return true;
   59|    173|}
_ZN5draco26SequentialAttributeDecoder20GetPortableAttributeEv:
   61|  1.22k|const PointAttribute *SequentialAttributeDecoder::GetPortableAttribute() {
   62|       |  // If needed, copy point to attribute value index mapping from the final
   63|       |  // attribute to the portable attribute.
   64|  1.22k|  if (!attribute_->is_mapping_identity() && portable_attribute_ &&
  ------------------
  |  Branch (64:7): [True: 813, False: 415]
  |  Branch (64:45): [True: 643, False: 170]
  ------------------
   65|  1.22k|      portable_attribute_->is_mapping_identity()) {
  ------------------
  |  Branch (65:7): [True: 543, False: 100]
  ------------------
   66|    543|    portable_attribute_->SetExplicitMapping(attribute_->indices_map_size());
   67|    543|    for (PointIndex i(0);
   68|   470k|         i < static_cast<uint32_t>(attribute_->indices_map_size()); ++i) {
  ------------------
  |  Branch (68:10): [True: 469k, False: 543]
  ------------------
   69|   469k|      portable_attribute_->SetPointMapEntry(i, attribute_->mapped_index(i));
   70|   469k|    }
   71|    543|  }
   72|  1.22k|  return portable_attribute_.get();
   73|  1.22k|}
_ZN5draco26SequentialAttributeDecoder20InitPredictionSchemeEPNS_25PredictionSchemeInterfaceE:
   76|    704|    PredictionSchemeInterface *ps) {
   77|    939|  for (int i = 0; i < ps->GetNumParentAttributes(); ++i) {
  ------------------
  |  Branch (77:19): [True: 237, False: 702]
  ------------------
   78|    237|    const int att_id = decoder_->point_cloud()->GetNamedAttributeId(
   79|    237|        ps->GetParentAttributeType(i));
   80|    237|    if (att_id == -1) {
  ------------------
  |  Branch (80:9): [True: 0, False: 237]
  ------------------
   81|      0|      return false;  // Requested attribute does not exist.
   82|      0|    }
   83|    237|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   84|    237|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    237|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (84:9): [True: 0, False: 237]
  ------------------
   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|    237|#endif
   90|    237|    {
   91|    237|      const PointAttribute *const pa = decoder_->GetPortableAttribute(att_id);
   92|    237|      if (pa == nullptr || !ps->SetParentAttribute(pa)) {
  ------------------
  |  Branch (92:11): [True: 0, False: 237]
  |  Branch (92:28): [True: 2, False: 235]
  ------------------
   93|      2|        return false;
   94|      2|      }
   95|    237|    }
   96|    237|  }
   97|    702|  return true;
   98|    704|}
_ZN5draco26SequentialAttributeDecoder12DecodeValuesERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
  101|    200|    const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) {
  102|    200|  const int32_t num_values = static_cast<uint32_t>(point_ids.size());
  103|    200|  const int entry_size = static_cast<int>(attribute_->byte_stride());
  104|    200|  std::unique_ptr<uint8_t[]> value_data_ptr(new uint8_t[entry_size]);
  105|    200|  uint8_t *const value_data = value_data_ptr.get();
  106|    200|  int out_byte_pos = 0;
  107|       |  // Decode raw attribute values in their original format.
  108|  1.91k|  for (int i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (108:19): [True: 1.73k, False: 185]
  ------------------
  109|  1.73k|    if (!in_buffer->Decode(value_data, entry_size)) {
  ------------------
  |  Branch (109:9): [True: 15, False: 1.71k]
  ------------------
  110|     15|      return false;
  111|     15|    }
  112|  1.71k|    attribute_->buffer()->Write(out_byte_pos, value_data, entry_size);
  113|  1.71k|    out_byte_pos += entry_size;
  114|  1.71k|  }
  115|    185|  return true;
  116|    200|}

_ZNK5draco26SequentialAttributeDecoder9attributeEv:
   53|  1.86k|  const PointAttribute *attribute() const { return attribute_; }
_ZN5draco26SequentialAttributeDecoder9attributeEv:
   54|  43.3k|  PointAttribute *attribute() { return attribute_; }
_ZNK5draco26SequentialAttributeDecoder12attribute_idEv:
   55|    704|  int attribute_id() const { return attribute_id_; }
_ZNK5draco26SequentialAttributeDecoder7decoderEv:
   56|  5.60k|  PointCloudDecoder *decoder() const { return decoder_; }
_ZN5draco26SequentialAttributeDecoder20SetPortableAttributeENSt3__110unique_ptrINS_14PointAttributeENS1_14default_deleteIS3_EEEE:
   69|  1.89k|  void SetPortableAttribute(std::unique_ptr<PointAttribute> att) {
   70|  1.89k|    portable_attribute_ = std::move(att);
   71|  1.89k|  }
_ZN5draco26SequentialAttributeDecoder18portable_attributeEv:
   73|  6.89k|  PointAttribute *portable_attribute() { return portable_attribute_.get(); }
_ZN5draco26SequentialAttributeDecoderD2Ev:
   29|  26.0k|  virtual ~SequentialAttributeDecoder() = default;

_ZN5draco37SequentialAttributeDecodersControllerC2ENSt3__110unique_ptrINS_15PointsSequencerENS1_14default_deleteIS3_EEEE:
   26|  13.8k|    : sequencer_(std::move(sequencer)) {}
_ZN5draco37SequentialAttributeDecodersController27DecodeAttributesDecoderDataEPNS_13DecoderBufferE:
   29|  4.58k|    DecoderBuffer *buffer) {
   30|  4.58k|  if (!AttributesDecoder::DecodeAttributesDecoderData(buffer)) {
  ------------------
  |  Branch (30:7): [True: 56, False: 4.52k]
  ------------------
   31|     56|    return false;
   32|     56|  }
   33|       |  // Decode unique ids of all sequential encoders and create them.
   34|  4.52k|  const int32_t num_attributes = GetNumAttributes();
   35|  4.52k|  sequential_decoders_.resize(num_attributes);
   36|  30.6k|  for (int i = 0; i < num_attributes; ++i) {
  ------------------
  |  Branch (36:19): [True: 26.0k, False: 4.51k]
  ------------------
   37|  26.0k|    uint8_t decoder_type;
   38|  26.0k|    if (!buffer->Decode(&decoder_type)) {
  ------------------
  |  Branch (38:9): [True: 2, False: 26.0k]
  ------------------
   39|      2|      return false;
   40|      2|    }
   41|       |    // Create the decoder from the id.
   42|  26.0k|    sequential_decoders_[i] = CreateSequentialDecoder(decoder_type);
   43|  26.0k|    if (!sequential_decoders_[i]) {
  ------------------
  |  Branch (43:9): [True: 3, False: 26.0k]
  ------------------
   44|      3|      return false;
   45|      3|    }
   46|  26.0k|    if (!sequential_decoders_[i]->Init(GetDecoder(), GetAttributeId(i))) {
  ------------------
  |  Branch (46:9): [True: 7, False: 26.0k]
  ------------------
   47|      7|      return false;
   48|      7|    }
   49|  26.0k|  }
   50|  4.51k|  return true;
   51|  4.52k|}
_ZN5draco37SequentialAttributeDecodersController16DecodeAttributesEPNS_13DecoderBufferE:
   54|    718|    DecoderBuffer *buffer) {
   55|    718|  if (!sequencer_ || !sequencer_->GenerateSequence(&point_ids_)) {
  ------------------
  |  Branch (55:7): [True: 0, False: 718]
  |  Branch (55:22): [True: 1, False: 717]
  ------------------
   56|      1|    return false;
   57|      1|  }
   58|       |  // Initialize point to attribute value mapping for all decoded attributes.
   59|    717|  const int32_t num_attributes = GetNumAttributes();
   60|  4.87k|  for (int i = 0; i < num_attributes; ++i) {
  ------------------
  |  Branch (60:19): [True: 4.16k, False: 717]
  ------------------
   61|  4.16k|    PointAttribute *const pa =
   62|  4.16k|        GetDecoder()->point_cloud()->attribute(GetAttributeId(i));
   63|  4.16k|    if (!sequencer_->UpdatePointToAttributeIndexMapping(pa)) {
  ------------------
  |  Branch (63:9): [True: 0, False: 4.16k]
  ------------------
   64|      0|      return false;
   65|      0|    }
   66|  4.16k|  }
   67|    717|  return AttributesDecoder::DecodeAttributes(buffer);
   68|    717|}
_ZN5draco37SequentialAttributeDecodersController24DecodePortableAttributesEPNS_13DecoderBufferE:
   71|    717|    DecoderBuffer *in_buffer) {
   72|    717|  const int32_t num_attributes = GetNumAttributes();
   73|  2.61k|  for (int i = 0; i < num_attributes; ++i) {
  ------------------
  |  Branch (73:19): [True: 2.20k, False: 407]
  ------------------
   74|  2.20k|    if (!sequential_decoders_[i]->DecodePortableAttribute(point_ids_,
  ------------------
  |  Branch (74:9): [True: 310, False: 1.89k]
  ------------------
   75|  2.20k|                                                          in_buffer)) {
   76|    310|      return false;
   77|    310|    }
   78|  2.20k|  }
   79|    407|  return true;
   80|    717|}
_ZN5draco37SequentialAttributeDecodersController36DecodeDataNeededByPortableTransformsEPNS_13DecoderBufferE:
   83|    407|    DecodeDataNeededByPortableTransforms(DecoderBuffer *in_buffer) {
   84|    407|  const int32_t num_attributes = GetNumAttributes();
   85|  1.34k|  for (int i = 0; i < num_attributes; ++i) {
  ------------------
  |  Branch (85:19): [True: 962, False: 385]
  ------------------
   86|    962|    if (!sequential_decoders_[i]->DecodeDataNeededByPortableTransform(
  ------------------
  |  Branch (86:9): [True: 22, False: 940]
  ------------------
   87|    962|            point_ids_, in_buffer)) {
   88|     22|      return false;
   89|     22|    }
   90|    962|  }
   91|    385|  return true;
   92|    407|}
_ZN5draco37SequentialAttributeDecodersController35TransformAttributesToOriginalFormatEv:
   95|    385|    TransformAttributesToOriginalFormat() {
   96|    385|  const int32_t num_attributes = GetNumAttributes();
   97|  1.23k|  for (int i = 0; i < num_attributes; ++i) {
  ------------------
  |  Branch (97:19): [True: 884, False: 355]
  ------------------
   98|       |    // Check whether the attribute transform should be skipped.
   99|    884|    if (GetDecoder()->options()) {
  ------------------
  |  Branch (99:9): [True: 884, False: 0]
  ------------------
  100|    884|      const PointAttribute *const attribute =
  101|    884|          sequential_decoders_[i]->attribute();
  102|    884|      const PointAttribute *const portable_attribute =
  103|    884|          sequential_decoders_[i]->GetPortableAttribute();
  104|    884|      if (portable_attribute &&
  ------------------
  |  Branch (104:11): [True: 711, False: 173]
  |  Branch (104:11): [True: 69, False: 815]
  ------------------
  105|    884|          GetDecoder()->options()->GetAttributeBool(
  ------------------
  |  Branch (105:11): [True: 69, False: 642]
  ------------------
  106|    711|              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|     69|        sequential_decoders_[i]->attribute()->CopyFrom(*portable_attribute);
  113|     69|        continue;
  114|     69|      }
  115|    884|    }
  116|    815|    if (!sequential_decoders_[i]->TransformAttributeToOriginalFormat(
  ------------------
  |  Branch (116:9): [True: 30, False: 785]
  ------------------
  117|    815|            point_ids_)) {
  118|     30|      return false;
  119|     30|    }
  120|    815|  }
  121|    355|  return true;
  122|    385|}
_ZN5draco37SequentialAttributeDecodersController23CreateSequentialDecoderEh:
  126|  26.0k|    uint8_t decoder_type) {
  127|  26.0k|  switch (decoder_type) {
  128|  1.26k|    case SEQUENTIAL_ATTRIBUTE_ENCODER_GENERIC:
  ------------------
  |  Branch (128:5): [True: 1.26k, False: 24.8k]
  ------------------
  129|  1.26k|      return std::unique_ptr<SequentialAttributeDecoder>(
  130|  1.26k|          new SequentialAttributeDecoder());
  131|  24.5k|    case SEQUENTIAL_ATTRIBUTE_ENCODER_INTEGER:
  ------------------
  |  Branch (131:5): [True: 24.5k, False: 1.58k]
  ------------------
  132|  24.5k|      return std::unique_ptr<SequentialAttributeDecoder>(
  133|  24.5k|          new SequentialIntegerAttributeDecoder());
  134|     60|    case SEQUENTIAL_ATTRIBUTE_ENCODER_QUANTIZATION:
  ------------------
  |  Branch (134:5): [True: 60, False: 26.0k]
  ------------------
  135|     60|      return std::unique_ptr<SequentialAttributeDecoder>(
  136|     60|          new SequentialQuantizationAttributeDecoder());
  137|      0|#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
  138|    254|    case SEQUENTIAL_ATTRIBUTE_ENCODER_NORMALS:
  ------------------
  |  Branch (138:5): [True: 254, False: 25.8k]
  ------------------
  139|    254|      return std::unique_ptr<SequentialNormalAttributeDecoder>(
  140|    254|          new SequentialNormalAttributeDecoder());
  141|      0|#endif
  142|      3|    default:
  ------------------
  |  Branch (142:5): [True: 3, False: 26.0k]
  ------------------
  143|      3|      break;
  144|  26.0k|  }
  145|       |  // Unknown or unsupported decoder type.
  146|      3|  return nullptr;
  147|  26.0k|}

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

_ZN5draco33SequentialIntegerAttributeDecoderC2Ev:
   23|  24.8k|SequentialIntegerAttributeDecoder::SequentialIntegerAttributeDecoder() {}
_ZN5draco33SequentialIntegerAttributeDecoder4InitEPNS_17PointCloudDecoderEi:
   26|  24.8k|                                             int attribute_id) {
   27|  24.8k|  if (!SequentialAttributeDecoder::Init(decoder, attribute_id)) {
  ------------------
  |  Branch (27:7): [True: 0, False: 24.8k]
  ------------------
   28|      0|    return false;
   29|      0|  }
   30|  24.8k|  return true;
   31|  24.8k|}
_ZN5draco33SequentialIntegerAttributeDecoder34TransformAttributeToOriginalFormatERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEE:
   34|    642|    const std::vector<PointIndex> &point_ids) {
   35|    642|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   36|    642|  if (decoder() &&
  ------------------
  |  Branch (36:7): [True: 642, False: 0]
  ------------------
   37|    642|      decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    642|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (37:7): [True: 2, False: 640]
  ------------------
   38|      2|    return true;  // Don't revert the transform here for older files.
   39|      2|  }
   40|    640|#endif
   41|    640|  return StoreValues(static_cast<uint32_t>(point_ids.size()));
   42|    642|}
_ZN5draco33SequentialIntegerAttributeDecoder12DecodeValuesERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
   45|  2.00k|    const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) {
   46|       |  // Decode prediction scheme.
   47|  2.00k|  int8_t prediction_scheme_method;
   48|  2.00k|  if (!in_buffer->Decode(&prediction_scheme_method)) {
  ------------------
  |  Branch (48:7): [True: 3, False: 2.00k]
  ------------------
   49|      3|    return false;
   50|      3|  }
   51|       |  // Check that decoded prediction scheme method type is valid.
   52|  2.00k|  if (prediction_scheme_method < PREDICTION_NONE ||
  ------------------
  |  Branch (52:7): [True: 8, False: 1.99k]
  ------------------
   53|  2.00k|      prediction_scheme_method >= NUM_PREDICTION_SCHEMES) {
  ------------------
  |  Branch (53:7): [True: 65, False: 1.92k]
  ------------------
   54|     73|    return false;
   55|     73|  }
   56|  1.92k|  if (prediction_scheme_method != PREDICTION_NONE) {
  ------------------
  |  Branch (56:7): [True: 1.90k, False: 26]
  ------------------
   57|  1.90k|    int8_t prediction_transform_type;
   58|  1.90k|    if (!in_buffer->Decode(&prediction_transform_type)) {
  ------------------
  |  Branch (58:9): [True: 17, False: 1.88k]
  ------------------
   59|     17|      return false;
   60|     17|    }
   61|       |    // Check that decoded prediction scheme transform type is valid.
   62|  1.88k|    if (prediction_transform_type < PREDICTION_TRANSFORM_NONE ||
  ------------------
  |  Branch (62:9): [True: 1, False: 1.88k]
  ------------------
   63|  1.88k|        prediction_transform_type >= NUM_PREDICTION_SCHEME_TRANSFORM_TYPES) {
  ------------------
  |  Branch (63:9): [True: 9, False: 1.87k]
  ------------------
   64|     10|      return false;
   65|     10|    }
   66|  1.87k|    prediction_scheme_ = CreateIntPredictionScheme(
   67|  1.87k|        static_cast<PredictionSchemeMethod>(prediction_scheme_method),
   68|  1.87k|        static_cast<PredictionSchemeTransformType>(prediction_transform_type));
   69|  1.87k|  }
   70|       |
   71|  1.90k|  if (prediction_scheme_) {
  ------------------
  |  Branch (71:7): [True: 704, False: 1.19k]
  ------------------
   72|    704|    if (!InitPredictionScheme(prediction_scheme_.get())) {
  ------------------
  |  Branch (72:9): [True: 2, False: 702]
  ------------------
   73|      2|      return false;
   74|      2|    }
   75|    704|  }
   76|       |
   77|  1.89k|  if (!DecodeIntegerValues(point_ids, in_buffer)) {
  ------------------
  |  Branch (77:7): [True: 190, False: 1.70k]
  ------------------
   78|    190|    return false;
   79|    190|  }
   80|       |
   81|  1.70k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   82|  1.70k|  const int32_t num_values = static_cast<uint32_t>(point_ids.size());
   83|  1.70k|  if (decoder() &&
  ------------------
  |  Branch (83:7): [True: 1.70k, False: 0]
  ------------------
   84|  1.70k|      decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|  1.70k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (84:7): [True: 40, False: 1.66k]
  ------------------
   85|       |    // For older files, revert the transform right after we decode the data.
   86|     40|    if (!StoreValues(num_values)) {
  ------------------
  |  Branch (86:9): [True: 0, False: 40]
  ------------------
   87|      0|      return false;
   88|      0|    }
   89|     40|  }
   90|  1.70k|#endif
   91|  1.70k|  return true;
   92|  1.70k|}
_ZN5draco33SequentialIntegerAttributeDecoder25CreateIntPredictionSchemeENS_22PredictionSchemeMethodENS_29PredictionSchemeTransformTypeE:
   97|  1.84k|    PredictionSchemeTransformType transform_type) {
   98|  1.84k|  if (transform_type != PREDICTION_TRANSFORM_WRAP) {
  ------------------
  |  Branch (98:7): [True: 1.16k, False: 675]
  ------------------
   99|  1.16k|    return nullptr;  // For now we support only wrap transform.
  100|  1.16k|  }
  101|    675|  return CreatePredictionSchemeForDecoder<
  102|    675|      int32_t, PredictionSchemeWrapDecodingTransform<int32_t>>(
  103|    675|      method, attribute_id(), decoder());
  104|  1.84k|}
_ZN5draco33SequentialIntegerAttributeDecoder19DecodeIntegerValuesERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
  107|  1.89k|    const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) {
  108|  1.89k|  const int num_components = GetNumValueComponents();
  109|  1.89k|  if (num_components <= 0) {
  ------------------
  |  Branch (109:7): [True: 0, False: 1.89k]
  ------------------
  110|      0|    return false;
  111|      0|  }
  112|  1.89k|  const size_t num_entries = point_ids.size();
  113|  1.89k|  const size_t num_values = num_entries * num_components;
  114|  1.89k|  PreparePortableAttribute(static_cast<int>(num_entries), num_components);
  115|  1.89k|  int32_t *const portable_attribute_data = GetPortableAttributeData();
  116|  1.89k|  if (portable_attribute_data == nullptr) {
  ------------------
  |  Branch (116:7): [True: 1, False: 1.89k]
  ------------------
  117|      1|    return false;
  118|      1|  }
  119|  1.89k|  uint8_t compressed;
  120|  1.89k|  if (!in_buffer->Decode(&compressed)) {
  ------------------
  |  Branch (120:7): [True: 9, False: 1.88k]
  ------------------
  121|      9|    return false;
  122|      9|  }
  123|  1.88k|  if (compressed > 0) {
  ------------------
  |  Branch (123:7): [True: 70, False: 1.81k]
  ------------------
  124|       |    // Decode compressed values.
  125|     70|    if (!DecodeSymbols(static_cast<uint32_t>(num_values), num_components,
  ------------------
  |  Branch (125:9): [True: 43, False: 27]
  ------------------
  126|     70|                       in_buffer,
  127|     70|                       reinterpret_cast<uint32_t *>(portable_attribute_data))) {
  128|     43|      return false;
  129|     43|    }
  130|  1.81k|  } else {
  131|       |    // Decode the integer data directly.
  132|       |    // Get the number of bytes for a given entry.
  133|  1.81k|    uint8_t num_bytes;
  134|  1.81k|    if (!in_buffer->Decode(&num_bytes)) {
  ------------------
  |  Branch (134:9): [True: 1, False: 1.81k]
  ------------------
  135|      1|      return false;
  136|      1|    }
  137|  1.81k|    if (num_bytes == DataTypeLength(DT_INT32)) {
  ------------------
  |  Branch (137:9): [True: 81, False: 1.73k]
  ------------------
  138|     81|      if (portable_attribute()->buffer()->data_size() <
  ------------------
  |  Branch (138:11): [True: 0, False: 81]
  ------------------
  139|     81|          sizeof(int32_t) * num_values) {
  140|      0|        return false;
  141|      0|      }
  142|     81|      if (!in_buffer->Decode(portable_attribute_data,
  ------------------
  |  Branch (142:11): [True: 0, False: 81]
  ------------------
  143|     81|                             sizeof(int32_t) * num_values)) {
  144|      0|        return false;
  145|      0|      }
  146|  1.73k|    } else {
  147|  1.73k|      if (portable_attribute()->buffer()->data_size() <
  ------------------
  |  Branch (147:11): [True: 5, False: 1.73k]
  ------------------
  148|  1.73k|          num_bytes * num_values) {
  149|      5|        return false;
  150|      5|      }
  151|  1.73k|      if (in_buffer->remaining_size() <
  ------------------
  |  Branch (151:11): [True: 2, False: 1.72k]
  ------------------
  152|  1.73k|          static_cast<int64_t>(num_bytes) * static_cast<int64_t>(num_values)) {
  153|      2|        return false;
  154|      2|      }
  155|  12.8M|      for (size_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (155:26): [True: 12.8M, False: 1.72k]
  ------------------
  156|  12.8M|        if (!in_buffer->Decode(portable_attribute_data + i, num_bytes)) {
  ------------------
  |  Branch (156:13): [True: 0, False: 12.8M]
  ------------------
  157|      0|          return false;
  158|      0|        }
  159|  12.8M|      }
  160|  1.72k|    }
  161|  1.81k|  }
  162|       |
  163|  1.83k|  if (num_values > 0 && (prediction_scheme_ == nullptr ||
  ------------------
  |  Branch (163:7): [True: 1.83k, False: 0]
  |  Branch (163:26): [True: 1.16k, False: 669]
  ------------------
  164|  1.83k|                         !prediction_scheme_->AreCorrectionsPositive())) {
  ------------------
  |  Branch (164:26): [True: 643, False: 26]
  ------------------
  165|       |    // Convert the values back to the original signed format.
  166|  1.81k|    ConvertSymbolsToSignedInts(
  167|  1.81k|        reinterpret_cast<const uint32_t *>(portable_attribute_data),
  168|  1.81k|        static_cast<int>(num_values), portable_attribute_data);
  169|  1.81k|  }
  170|       |
  171|       |  // If the data was encoded with a prediction scheme, we must revert it.
  172|  1.83k|  if (prediction_scheme_) {
  ------------------
  |  Branch (172:7): [True: 669, False: 1.16k]
  ------------------
  173|    669|    if (!prediction_scheme_->DecodePredictionData(in_buffer)) {
  ------------------
  |  Branch (173:9): [True: 94, False: 575]
  ------------------
  174|     94|      return false;
  175|     94|    }
  176|       |
  177|    575|    if (num_values > 0) {
  ------------------
  |  Branch (177:9): [True: 575, False: 0]
  ------------------
  178|    575|      if (!prediction_scheme_->ComputeOriginalValues(
  ------------------
  |  Branch (178:11): [True: 35, False: 540]
  ------------------
  179|    575|              portable_attribute_data, portable_attribute_data,
  180|    575|              static_cast<int>(num_values), num_components, point_ids.data())) {
  181|     35|        return false;
  182|     35|      }
  183|    575|    }
  184|    575|  }
  185|  1.70k|  return true;
  186|  1.83k|}
_ZN5draco33SequentialIntegerAttributeDecoder11StoreValuesEj:
  188|    640|bool SequentialIntegerAttributeDecoder::StoreValues(uint32_t num_values) {
  189|    640|  switch (attribute()->data_type()) {
  190|     62|    case DT_UINT8:
  ------------------
  |  Branch (190:5): [True: 62, False: 578]
  ------------------
  191|     62|      StoreTypedValues<uint8_t>(num_values);
  192|     62|      break;
  193|    516|    case DT_INT8:
  ------------------
  |  Branch (193:5): [True: 516, False: 124]
  ------------------
  194|    516|      StoreTypedValues<int8_t>(num_values);
  195|    516|      break;
  196|      0|    case DT_UINT16:
  ------------------
  |  Branch (196:5): [True: 0, False: 640]
  ------------------
  197|      0|      StoreTypedValues<uint16_t>(num_values);
  198|      0|      break;
  199|     26|    case DT_INT16:
  ------------------
  |  Branch (199:5): [True: 26, False: 614]
  ------------------
  200|     26|      StoreTypedValues<int16_t>(num_values);
  201|     26|      break;
  202|      7|    case DT_UINT32:
  ------------------
  |  Branch (202:5): [True: 7, False: 633]
  ------------------
  203|      7|      StoreTypedValues<uint32_t>(num_values);
  204|      7|      break;
  205|     10|    case DT_INT32:
  ------------------
  |  Branch (205:5): [True: 10, False: 630]
  ------------------
  206|     10|      StoreTypedValues<int32_t>(num_values);
  207|     10|      break;
  208|     19|    default:
  ------------------
  |  Branch (208:5): [True: 19, False: 621]
  ------------------
  209|     19|      return false;
  210|    640|  }
  211|    621|  return true;
  212|    640|}
_ZN5draco33SequentialIntegerAttributeDecoder24PreparePortableAttributeEii:
  236|  1.89k|    int num_entries, int num_components) {
  237|  1.89k|  GeometryAttribute ga;
  238|  1.89k|  ga.Init(attribute()->attribute_type(), nullptr, num_components, DT_INT32,
  239|  1.89k|          false, num_components * DataTypeLength(DT_INT32), 0);
  240|  1.89k|  std::unique_ptr<PointAttribute> port_att(new PointAttribute(ga));
  241|  1.89k|  port_att->SetIdentityMapping();
  242|  1.89k|  port_att->Reset(num_entries);
  243|  1.89k|  port_att->set_unique_id(attribute()->unique_id());
  244|  1.89k|  SetPortableAttribute(std::move(port_att));
  245|  1.89k|}
_ZN5draco33SequentialIntegerAttributeDecoder16StoreTypedValuesIhEEvj:
  215|     62|void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) {
  216|     62|  const int num_components = attribute()->num_components();
  217|     62|  const int entry_size = sizeof(AttributeTypeT) * num_components;
  218|     62|  const std::unique_ptr<AttributeTypeT[]> att_val(
  219|     62|      new AttributeTypeT[num_components]);
  220|     62|  const int32_t *const portable_attribute_data = GetPortableAttributeData();
  221|     62|  int val_id = 0;
  222|     62|  int out_byte_pos = 0;
  223|  5.21k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (223:24): [True: 5.15k, False: 62]
  ------------------
  224|  37.7k|    for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (224:21): [True: 32.5k, False: 5.15k]
  ------------------
  225|  32.5k|      const AttributeTypeT value =
  226|  32.5k|          static_cast<AttributeTypeT>(portable_attribute_data[val_id++]);
  227|  32.5k|      att_val[c] = value;
  228|  32.5k|    }
  229|       |    // Store the integer value into the attribute buffer.
  230|  5.15k|    attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
  231|  5.15k|    out_byte_pos += entry_size;
  232|  5.15k|  }
  233|     62|}
_ZN5draco33SequentialIntegerAttributeDecoder16StoreTypedValuesIaEEvj:
  215|    516|void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) {
  216|    516|  const int num_components = attribute()->num_components();
  217|    516|  const int entry_size = sizeof(AttributeTypeT) * num_components;
  218|    516|  const std::unique_ptr<AttributeTypeT[]> att_val(
  219|    516|      new AttributeTypeT[num_components]);
  220|    516|  const int32_t *const portable_attribute_data = GetPortableAttributeData();
  221|    516|  int val_id = 0;
  222|    516|  int out_byte_pos = 0;
  223|  7.32k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (223:24): [True: 6.80k, False: 516]
  ------------------
  224|   144k|    for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (224:21): [True: 137k, False: 6.80k]
  ------------------
  225|   137k|      const AttributeTypeT value =
  226|   137k|          static_cast<AttributeTypeT>(portable_attribute_data[val_id++]);
  227|   137k|      att_val[c] = value;
  228|   137k|    }
  229|       |    // Store the integer value into the attribute buffer.
  230|  6.80k|    attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
  231|  6.80k|    out_byte_pos += entry_size;
  232|  6.80k|  }
  233|    516|}
_ZN5draco33SequentialIntegerAttributeDecoder16StoreTypedValuesIsEEvj:
  215|     26|void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) {
  216|     26|  const int num_components = attribute()->num_components();
  217|     26|  const int entry_size = sizeof(AttributeTypeT) * num_components;
  218|     26|  const std::unique_ptr<AttributeTypeT[]> att_val(
  219|     26|      new AttributeTypeT[num_components]);
  220|     26|  const int32_t *const portable_attribute_data = GetPortableAttributeData();
  221|     26|  int val_id = 0;
  222|     26|  int out_byte_pos = 0;
  223|  11.1k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (223:24): [True: 11.1k, False: 26]
  ------------------
  224|  45.5k|    for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (224:21): [True: 34.3k, False: 11.1k]
  ------------------
  225|  34.3k|      const AttributeTypeT value =
  226|  34.3k|          static_cast<AttributeTypeT>(portable_attribute_data[val_id++]);
  227|  34.3k|      att_val[c] = value;
  228|  34.3k|    }
  229|       |    // Store the integer value into the attribute buffer.
  230|  11.1k|    attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
  231|  11.1k|    out_byte_pos += entry_size;
  232|  11.1k|  }
  233|     26|}
_ZN5draco33SequentialIntegerAttributeDecoder16StoreTypedValuesIjEEvj:
  215|      7|void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) {
  216|      7|  const int num_components = attribute()->num_components();
  217|      7|  const int entry_size = sizeof(AttributeTypeT) * num_components;
  218|      7|  const std::unique_ptr<AttributeTypeT[]> att_val(
  219|      7|      new AttributeTypeT[num_components]);
  220|      7|  const int32_t *const portable_attribute_data = GetPortableAttributeData();
  221|      7|  int val_id = 0;
  222|      7|  int out_byte_pos = 0;
  223|  13.2k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (223:24): [True: 13.2k, False: 7]
  ------------------
  224|  91.8k|    for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (224:21): [True: 78.6k, False: 13.2k]
  ------------------
  225|  78.6k|      const AttributeTypeT value =
  226|  78.6k|          static_cast<AttributeTypeT>(portable_attribute_data[val_id++]);
  227|  78.6k|      att_val[c] = value;
  228|  78.6k|    }
  229|       |    // Store the integer value into the attribute buffer.
  230|  13.2k|    attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
  231|  13.2k|    out_byte_pos += entry_size;
  232|  13.2k|  }
  233|      7|}
_ZN5draco33SequentialIntegerAttributeDecoder16StoreTypedValuesIiEEvj:
  215|     10|void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) {
  216|     10|  const int num_components = attribute()->num_components();
  217|     10|  const int entry_size = sizeof(AttributeTypeT) * num_components;
  218|     10|  const std::unique_ptr<AttributeTypeT[]> att_val(
  219|     10|      new AttributeTypeT[num_components]);
  220|     10|  const int32_t *const portable_attribute_data = GetPortableAttributeData();
  221|     10|  int val_id = 0;
  222|     10|  int out_byte_pos = 0;
  223|    473|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (223:24): [True: 463, False: 10]
  ------------------
  224|  62.5k|    for (int c = 0; c < num_components; ++c) {
  ------------------
  |  Branch (224:21): [True: 62.1k, False: 463]
  ------------------
  225|  62.1k|      const AttributeTypeT value =
  226|  62.1k|          static_cast<AttributeTypeT>(portable_attribute_data[val_id++]);
  227|  62.1k|      att_val[c] = value;
  228|  62.1k|    }
  229|       |    // Store the integer value into the attribute buffer.
  230|    463|    attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
  231|    463|    out_byte_pos += entry_size;
  232|    463|  }
  233|     10|}

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

_ZN5draco32SequentialNormalAttributeDecoderC2Ev:
   21|    254|SequentialNormalAttributeDecoder::SequentialNormalAttributeDecoder() {}
_ZN5draco32SequentialNormalAttributeDecoder4InitEPNS_17PointCloudDecoderEi:
   24|    254|                                            int attribute_id) {
   25|    254|  if (!SequentialIntegerAttributeDecoder::Init(decoder, attribute_id)) {
  ------------------
  |  Branch (25:7): [True: 0, False: 254]
  ------------------
   26|      0|    return false;
   27|      0|  }
   28|       |  // Currently, this encoder works only for 3-component normal vectors.
   29|    254|  if (attribute()->num_components() != 3) {
  ------------------
  |  Branch (29:7): [True: 2, False: 252]
  ------------------
   30|      2|    return false;
   31|      2|  }
   32|       |  // Also the data type must be DT_FLOAT32.
   33|    252|  if (attribute()->data_type() != DT_FLOAT32) {
  ------------------
  |  Branch (33:7): [True: 0, False: 252]
  ------------------
   34|      0|    return false;
   35|      0|  }
   36|    252|  return true;
   37|    252|}
_ZN5draco32SequentialNormalAttributeDecoder19DecodeIntegerValuesERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
   40|     31|    const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) {
   41|     31|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   42|     31|  if (decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     31|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (42:7): [True: 0, False: 31]
  ------------------
   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|     31|#endif
   52|     31|  return SequentialIntegerAttributeDecoder::DecodeIntegerValues(point_ids,
   53|     31|                                                                in_buffer);
   54|     31|}
_ZN5draco32SequentialNormalAttributeDecoder35DecodeDataNeededByPortableTransformERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
   57|     19|    const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) {
   58|     19|  if (decoder()->bitstream_version() >= DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     19|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (58:7): [True: 19, False: 0]
  ------------------
   59|       |    // For newer file version, decode attribute transform data here.
   60|     19|    if (!octahedral_transform_.DecodeParameters(*GetPortableAttribute(),
  ------------------
  |  Branch (60:9): [True: 0, False: 19]
  ------------------
   61|     19|                                                in_buffer)) {
   62|      0|      return false;
   63|      0|    }
   64|     19|  }
   65|       |
   66|       |  // Store the decoded transform data in portable attribute.
   67|     19|  return octahedral_transform_.TransferToAttribute(portable_attribute());
   68|     19|}
_ZN5draco32SequentialNormalAttributeDecoder11StoreValuesEj:
   70|     19|bool SequentialNormalAttributeDecoder::StoreValues(uint32_t num_points) {
   71|       |  // Convert all quantized values back to floats.
   72|     19|  return octahedral_transform_.InverseTransformAttribute(
   73|     19|      *GetPortableAttribute(), attribute());
   74|     19|}

_ZNK5draco32SequentialNormalAttributeDecoder21GetNumValueComponentsEv:
   35|     31|  int32_t GetNumValueComponents() const override {
   36|     31|    return 2;  // We quantize everything into two components.
   37|     31|  }
_ZN5draco32SequentialNormalAttributeDecoder25CreateIntPredictionSchemeENS_22PredictionSchemeMethodENS_29PredictionSchemeTransformTypeE:
   51|     31|      PredictionSchemeTransformType transform_type) override {
   52|     31|    switch (transform_type) {
   53|      0|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   54|      7|      case PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON: {
  ------------------
  |  Branch (54:7): [True: 7, False: 24]
  ------------------
   55|      7|        typedef PredictionSchemeNormalOctahedronDecodingTransform<int32_t>
   56|      7|            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|      7|        return CreatePredictionSchemeForDecoder<int32_t, Transform>(
   61|      7|            method, attribute_id(), decoder());
   62|      0|      }
   63|      0|#endif
   64|     22|      case PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON_CANONICALIZED: {
  ------------------
  |  Branch (64:7): [True: 22, False: 9]
  ------------------
   65|     22|        typedef PredictionSchemeNormalOctahedronCanonicalizedDecodingTransform<
   66|     22|            int32_t>
   67|     22|            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|     22|        return CreatePredictionSchemeForDecoder<int32_t, Transform>(
   72|     22|            method, attribute_id(), decoder());
   73|      0|      }
   74|      2|      default:
  ------------------
  |  Branch (74:7): [True: 2, False: 29]
  ------------------
   75|      2|        return nullptr;  // Currently, we support only octahedron transform and
   76|       |                         // octahedron transform canonicalized.
   77|     31|    }
   78|     31|  }

_ZN5draco38SequentialQuantizationAttributeDecoderC2Ev:
   22|     60|    SequentialQuantizationAttributeDecoder() {}
_ZN5draco38SequentialQuantizationAttributeDecoder4InitEPNS_17PointCloudDecoderEi:
   25|     60|                                                  int attribute_id) {
   26|     60|  if (!SequentialIntegerAttributeDecoder::Init(decoder, attribute_id)) {
  ------------------
  |  Branch (26:7): [True: 0, False: 60]
  ------------------
   27|      0|    return false;
   28|      0|  }
   29|     60|  const PointAttribute *const attribute =
   30|     60|      decoder->point_cloud()->attribute(attribute_id);
   31|       |  // Currently we can quantize only floating point arguments.
   32|     60|  if (attribute->data_type() != DT_FLOAT32) {
  ------------------
  |  Branch (32:7): [True: 5, False: 55]
  ------------------
   33|      5|    return false;
   34|      5|  }
   35|     55|  return true;
   36|     60|}
_ZN5draco38SequentialQuantizationAttributeDecoder19DecodeIntegerValuesERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
   39|     51|    const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) {
   40|     51|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   41|     51|  if (decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0) &&
  ------------------
  |  |  115|    102|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (41:7): [True: 2, False: 49]
  ------------------
   42|     51|      !DecodeQuantizedDataInfo()) {
  ------------------
  |  Branch (42:7): [True: 0, False: 2]
  ------------------
   43|      0|    return false;
   44|      0|  }
   45|     51|#endif
   46|     51|  return SequentialIntegerAttributeDecoder::DecodeIntegerValues(point_ids,
   47|     51|                                                                in_buffer);
   48|     51|}
_ZN5draco38SequentialQuantizationAttributeDecoder35DecodeDataNeededByPortableTransformERKNSt3__16vectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_9allocatorIS5_EEEEPNS_13DecoderBufferE:
   52|     47|        const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) {
   53|     47|  if (decoder()->bitstream_version() >= DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     47|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (53:7): [True: 46, False: 1]
  ------------------
   54|       |    // Decode quantization data here only for files with bitstream version 2.0+
   55|     46|    if (!DecodeQuantizedDataInfo()) {
  ------------------
  |  Branch (55:9): [True: 22, False: 24]
  ------------------
   56|     22|      return false;
   57|     22|    }
   58|     46|  }
   59|       |
   60|       |  // Store the decoded transform data in portable attribute;
   61|     25|  return quantization_transform_.TransferToAttribute(portable_attribute());
   62|     47|}
_ZN5draco38SequentialQuantizationAttributeDecoder11StoreValuesEj:
   64|     21|bool SequentialQuantizationAttributeDecoder::StoreValues(uint32_t num_points) {
   65|     21|  return DequantizeValues(num_points);
   66|     21|}
_ZN5draco38SequentialQuantizationAttributeDecoder23DecodeQuantizedDataInfoEv:
   68|     48|bool SequentialQuantizationAttributeDecoder::DecodeQuantizedDataInfo() {
   69|       |  // Get attribute used as source for decoding.
   70|     48|  auto att = GetPortableAttribute();
   71|     48|  if (att == nullptr) {
  ------------------
  |  Branch (71:7): [True: 2, False: 46]
  ------------------
   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|      2|    att = attribute();
   77|      2|  }
   78|     48|  return quantization_transform_.DecodeParameters(*att, decoder()->buffer());
   79|     48|}
_ZN5draco38SequentialQuantizationAttributeDecoder16DequantizeValuesEj:
   82|     21|    uint32_t num_values) {
   83|       |  // Convert all quantized values back to floats.
   84|     21|  return quantization_transform_.InverseTransformAttribute(
   85|     21|      *GetPortableAttribute(), attribute());
   86|     21|}

_ZN5draco14RAnsBitDecoderC2Ev:
   23|  4.03k|RAnsBitDecoder::RAnsBitDecoder() : prob_zero_(0) {}
_ZN5draco14RAnsBitDecoderD2Ev:
   25|  4.03k|RAnsBitDecoder::~RAnsBitDecoder() { Clear(); }
_ZN5draco14RAnsBitDecoder13StartDecodingEPNS_13DecoderBufferE:
   27|  3.08k|bool RAnsBitDecoder::StartDecoding(DecoderBuffer *source_buffer) {
   28|  3.08k|  Clear();
   29|       |
   30|  3.08k|  if (!source_buffer->Decode(&prob_zero_)) {
  ------------------
  |  Branch (30:7): [True: 1, False: 3.08k]
  ------------------
   31|      1|    return false;
   32|      1|  }
   33|       |
   34|  3.08k|  uint32_t size_in_bytes;
   35|  3.08k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   36|  3.08k|  if (source_buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  3.08k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (36:7): [True: 334, False: 2.74k]
  ------------------
   37|    334|    if (!source_buffer->Decode(&size_in_bytes)) {
  ------------------
  |  Branch (37:9): [True: 0, False: 334]
  ------------------
   38|      0|      return false;
   39|      0|    }
   40|       |
   41|    334|  } else
   42|  2.74k|#endif
   43|  2.74k|  {
   44|  2.74k|    if (!DecodeVarint(&size_in_bytes, source_buffer)) {
  ------------------
  |  Branch (44:9): [True: 2, False: 2.74k]
  ------------------
   45|      2|      return false;
   46|      2|    }
   47|  2.74k|  }
   48|       |
   49|  3.07k|  if (size_in_bytes > source_buffer->remaining_size()) {
  ------------------
  |  Branch (49:7): [True: 10, False: 3.06k]
  ------------------
   50|     10|    return false;
   51|     10|  }
   52|       |
   53|  3.06k|  if (ans_read_init(&ans_decoder_,
  ------------------
  |  Branch (53:7): [True: 6, False: 3.06k]
  ------------------
   54|  3.06k|                    reinterpret_cast<uint8_t *>(
   55|  3.06k|                        const_cast<char *>(source_buffer->data_head())),
   56|  3.06k|                    size_in_bytes) != 0) {
   57|      6|    return false;
   58|      6|  }
   59|  3.06k|  source_buffer->Advance(size_in_bytes);
   60|  3.06k|  return true;
   61|  3.06k|}
_ZN5draco14RAnsBitDecoder13DecodeNextBitEv:
   63|  2.10G|bool RAnsBitDecoder::DecodeNextBit() {
   64|  2.10G|  const uint8_t bit = rabs_read(&ans_decoder_, prob_zero_);
  ------------------
  |  |  246|  2.10G|#define rabs_read rabs_desc_read
  ------------------
   65|  2.10G|  return bit > 0;
   66|  2.10G|}
_ZN5draco14RAnsBitDecoder5ClearEv:
   80|  7.11k|void RAnsBitDecoder::Clear() { ans_read_end(&ans_decoder_); }

_ZN5draco14RAnsBitDecoder11EndDecodingEv:
   44|    674|  void EndDecoding() {}

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

_ZN5draco17CreateMeshDecoderEh:
   45|  1.36k|StatusOr<std::unique_ptr<MeshDecoder>> CreateMeshDecoder(uint8_t method) {
   46|  1.36k|  if (method == MESH_SEQUENTIAL_ENCODING) {
  ------------------
  |  Branch (46:7): [True: 431, False: 935]
  ------------------
   47|    431|    return std::unique_ptr<MeshDecoder>(new MeshSequentialDecoder());
   48|    935|  } else if (method == MESH_EDGEBREAKER_ENCODING) {
  ------------------
  |  Branch (48:14): [True: 935, False: 0]
  ------------------
   49|    935|    return std::unique_ptr<MeshDecoder>(new MeshEdgebreakerDecoder());
   50|    935|  }
   51|      0|  return Status(Status::DRACO_ERROR, "Unsupported encoding method.");
   52|  1.36k|}
_ZN5draco7Decoder20DecodeMeshFromBufferEPNS_13DecoderBufferE:
   87|  1.36k|    DecoderBuffer *in_buffer) {
   88|  1.36k|  std::unique_ptr<Mesh> mesh(new Mesh());
   89|  1.36k|  DRACO_RETURN_IF_ERROR(DecodeBufferToGeometry(in_buffer, mesh.get()))
  ------------------
  |  |   74|  1.36k|  {                                                   \
  |  |   75|  1.36k|    const draco::Status _local_status = (expression); \
  |  |   76|  1.36k|    if (!_local_status.ok()) {                        \
  |  |  ------------------
  |  |  |  Branch (76:9): [True: 1.29k, False: 70]
  |  |  ------------------
  |  |   77|  1.29k|      return _local_status;                           \
  |  |   78|  1.29k|    }                                                 \
  |  |   79|  1.36k|  }
  ------------------
   90|     70|  return std::move(mesh);
   91|  1.36k|}
_ZN5draco7Decoder22DecodeBufferToGeometryEPNS_13DecoderBufferEPNS_4MeshE:
  113|  1.36k|                                       Mesh *out_geometry) {
  114|  1.36k|#ifdef DRACO_MESH_COMPRESSION_SUPPORTED
  115|  1.36k|  DecoderBuffer temp_buffer(*in_buffer);
  116|  1.36k|  DracoHeader header;
  117|  1.36k|  DRACO_RETURN_IF_ERROR(PointCloudDecoder::DecodeHeader(&temp_buffer, &header))
  ------------------
  |  |   74|  1.36k|  {                                                   \
  |  |   75|  1.36k|    const draco::Status _local_status = (expression); \
  |  |   76|  1.36k|    if (!_local_status.ok()) {                        \
  |  |  ------------------
  |  |  |  Branch (76:9): [True: 1, False: 1.36k]
  |  |  ------------------
  |  |   77|      1|      return _local_status;                           \
  |  |   78|      1|    }                                                 \
  |  |   79|  1.36k|  }
  ------------------
  118|  1.36k|  if (header.encoder_type != TRIANGULAR_MESH) {
  ------------------
  |  Branch (118:7): [True: 1, False: 1.36k]
  ------------------
  119|      1|    return Status(Status::DRACO_ERROR, "Input is not a mesh.");
  120|      1|  }
  121|  2.73k|  DRACO_ASSIGN_OR_RETURN(std::unique_ptr<MeshDecoder> decoder,
  ------------------
  |  |   66|  1.36k|  DRACO_ASSIGN_OR_RETURN_IMPL_(DRACO_MACROS_IMPL_CONCAT_(_statusor, __LINE__), \
  |  |  ------------------
  |  |  |  |   71|  1.36k|  auto statusor = (expression);                                             \
  |  |  |  |   72|  1.36k|  if (!statusor.ok()) {                                                     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (72:7): [True: 0, False: 1.36k]
  |  |  |  |  ------------------
  |  |  |  |   73|      0|    auto _status = std::move(statusor.status());                            \
  |  |  |  |   74|      0|    (void)_status; /* error_expression may not use it */                    \
  |  |  |  |   75|      0|    return error_expr;                                                      \
  |  |  |  |   76|      0|  }                                                                         \
  |  |  |  |   77|  1.36k|  lhs = std::move(statusor).value();
  |  |  ------------------
  |  |   67|  1.36k|                               lhs, expression, _status)
  ------------------
  122|  2.73k|                         CreateMeshDecoder(header.encoder_method))
  123|       |
  124|  2.73k|  DRACO_RETURN_IF_ERROR(decoder->Decode(options_, in_buffer, out_geometry))
  ------------------
  |  |   74|  1.36k|  {                                                   \
  |  |   75|  1.36k|    const draco::Status _local_status = (expression); \
  |  |   76|  1.36k|    if (!_local_status.ok()) {                        \
  |  |  ------------------
  |  |  |  Branch (76:9): [True: 1.29k, False: 70]
  |  |  ------------------
  |  |   77|  1.29k|      return _local_status;                           \
  |  |   78|  1.29k|    }                                                 \
  |  |   79|  1.36k|  }
  ------------------
  125|     70|  return OkStatus();
  126|       |#else
  127|       |  return Status(Status::DRACO_ERROR, "Unsupported geometry type.");
  128|       |#endif
  129|  2.73k|}
_ZN5draco7Decoder25SetSkipAttributeTransformENS_17GeometryAttribute4TypeE:
  131|  1.36k|void Decoder::SetSkipAttributeTransform(GeometryAttribute::Type att_type) {
  132|  1.36k|  options_.SetAttributeBool(att_type, "skip_attribute_transform", true);
  133|  1.36k|}

_ZN5draco10AnsDecoderC2Ev:
   56|  4.93k|  AnsDecoder() : buf(nullptr), buf_offset(0), state(0) {}
rans_bit_decoder.cc:_ZN5dracoL13ans_read_initEPNS_10AnsDecoderEPKhi:
  300|  3.06k|                                const uint8_t *const buf, int offset) {
  301|  3.06k|  unsigned x;
  302|  3.06k|  if (offset < 1) {
  ------------------
  |  Branch (302:7): [True: 3, False: 3.06k]
  ------------------
  303|      3|    return 1;
  304|      3|  }
  305|  3.06k|  ans->buf = buf;
  306|  3.06k|  x = buf[offset - 1] >> 6;
  307|  3.06k|  if (x == 0) {
  ------------------
  |  Branch (307:7): [True: 2.31k, False: 754]
  ------------------
  308|  2.31k|    ans->buf_offset = offset - 1;
  309|  2.31k|    ans->state = buf[offset - 1] & 0x3F;
  310|  2.31k|  } else if (x == 1) {
  ------------------
  |  Branch (310:14): [True: 666, False: 88]
  ------------------
  311|    666|    if (offset < 2) {
  ------------------
  |  Branch (311:9): [True: 0, False: 666]
  ------------------
  312|      0|      return 1;
  313|      0|    }
  314|    666|    ans->buf_offset = offset - 2;
  315|    666|    ans->state = mem_get_le16(buf + offset - 2) & 0x3FFF;
  316|    666|  } else if (x == 2) {
  ------------------
  |  Branch (316:14): [True: 86, False: 2]
  ------------------
  317|     86|    if (offset < 3) {
  ------------------
  |  Branch (317:9): [True: 0, False: 86]
  ------------------
  318|      0|      return 1;
  319|      0|    }
  320|     86|    ans->buf_offset = offset - 3;
  321|     86|    ans->state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
  322|     86|  } else {
  323|      2|    return 1;
  324|      2|  }
  325|  3.06k|  ans->state += DRACO_ANS_L_BASE;
  ------------------
  |  |   64|  3.06k|#define DRACO_ANS_L_BASE (4096u)
  ------------------
  326|  3.06k|  if (ans->state >= DRACO_ANS_L_BASE * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   64|  3.06k|#define DRACO_ANS_L_BASE (4096u)
  ------------------
                if (ans->state >= DRACO_ANS_L_BASE * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   65|  3.06k|#define DRACO_ANS_IO_BASE 256
  ------------------
  |  Branch (326:7): [True: 1, False: 3.06k]
  ------------------
  327|      1|    return 1;
  328|      1|  }
  329|  3.06k|  return 0;
  330|  3.06k|}
rans_bit_decoder.cc:_ZN5dracoL12mem_get_le16EPKv:
   67|    666|static uint32_t mem_get_le16(const void *vmem) {
   68|    666|  uint32_t val;
   69|    666|  const uint8_t *mem = (const uint8_t *)vmem;
   70|       |
   71|    666|  val = mem[1] << 8;
   72|    666|  val |= mem[0];
   73|    666|  return val;
   74|    666|}
rans_bit_decoder.cc:_ZN5dracoL12mem_get_le24EPKv:
   76|     86|static uint32_t mem_get_le24(const void *vmem) {
   77|     86|  uint32_t val;
   78|     86|  const uint8_t *mem = (const uint8_t *)vmem;
   79|       |
   80|     86|  val = mem[2] << 16;
   81|     86|  val |= mem[1] << 8;
   82|     86|  val |= mem[0];
   83|     86|  return val;
   84|     86|}
rans_bit_decoder.cc:_ZN5dracoL14rabs_desc_readEPNS_10AnsDecoderEh:
  166|  2.10G|static inline int rabs_desc_read(struct AnsDecoder *ans, AnsP8 p0) {
  167|  2.10G|  int val;
  168|       |#if DRACO_ANS_IMPL1
  169|       |  unsigned l_s;
  170|       |#else
  171|  2.10G|  unsigned quot, rem, x, xn;
  172|  2.10G|#endif
  173|  2.10G|  const AnsP8 p = DRACO_ANS_P8_PRECISION - p0;
  ------------------
  |  |   63|  2.10G|#define DRACO_ANS_P8_PRECISION 256u
  ------------------
  174|  2.10G|  if (ans->state < DRACO_ANS_L_BASE && ans->buf_offset > 0) {
  ------------------
  |  |   64|  4.21G|#define DRACO_ANS_L_BASE (4096u)
  ------------------
  |  Branch (174:7): [True: 1.81G, False: 286M]
  |  Branch (174:40): [True: 13.7k, False: 1.81G]
  ------------------
  175|  13.7k|    ans->state = ans->state * DRACO_ANS_IO_BASE + ans->buf[--ans->buf_offset];
  ------------------
  |  |   65|  13.7k|#define DRACO_ANS_IO_BASE 256
  ------------------
  176|  13.7k|  }
  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|  2.10G|  x = ans->state;
  184|  2.10G|  quot = x / DRACO_ANS_P8_PRECISION;
  ------------------
  |  |   63|  2.10G|#define DRACO_ANS_P8_PRECISION 256u
  ------------------
  185|  2.10G|  rem = x % DRACO_ANS_P8_PRECISION;
  ------------------
  |  |   63|  2.10G|#define DRACO_ANS_P8_PRECISION 256u
  ------------------
  186|  2.10G|  xn = quot * p;
  187|  2.10G|  val = rem < p;
  188|  2.10G|  if (UNPREDICTABLE(val)) {
  ------------------
  |  |  165|  4.21G|#define UNPREDICTABLE(x) x
  |  |  ------------------
  |  |  |  Branch (165:26): [True: 1.81G, False: 286M]
  |  |  ------------------
  ------------------
  189|  1.81G|    ans->state = xn + rem;
  190|  1.81G|  } else {
  191|       |    // ans->state = quot * p0 + rem - p;
  192|   286M|    ans->state = x - xn - p;
  193|   286M|  }
  194|  2.10G|#endif
  195|  2.10G|  return val;
  196|  2.10G|}
rans_bit_decoder.cc:_ZN5dracoL12ans_read_endEPNS_10AnsDecoderE:
  332|  7.11k|static inline int ans_read_end(struct AnsDecoder *const ans) {
  333|  7.11k|  return ans->state == DRACO_ANS_L_BASE;
  ------------------
  |  |   64|  7.11k|#define DRACO_ANS_L_BASE (4096u)
  ------------------
  334|  7.11k|}
_ZN5draco11RAnsDecoderILi12EEC2Ev:
  416|    565|  RAnsDecoder() {}
_ZN5draco11RAnsDecoderILi12EE24rans_build_look_up_tableEPKjj:
  481|    237|                                       uint32_t num_symbols) {
  482|    237|    lut_table_.resize(rans_precision);
  483|    237|    probability_table_.resize(num_symbols);
  484|    237|    uint32_t cum_prob = 0;
  485|    237|    uint32_t act_prob = 0;
  486|  3.70k|    for (uint32_t i = 0; i < num_symbols; ++i) {
  ------------------
  |  Branch (486:26): [True: 3.51k, False: 194]
  ------------------
  487|  3.51k|      probability_table_[i].prob = token_probs[i];
  488|  3.51k|      probability_table_[i].cum_prob = cum_prob;
  489|  3.51k|      cum_prob += token_probs[i];
  490|  3.51k|      if (cum_prob > rans_precision) {
  ------------------
  |  Branch (490:11): [True: 43, False: 3.46k]
  ------------------
  491|     43|        return false;
  492|     43|      }
  493|   661k|      for (uint32_t j = act_prob; j < cum_prob; ++j) {
  ------------------
  |  Branch (493:35): [True: 658k, False: 3.46k]
  ------------------
  494|   658k|        lut_table_[j] = i;
  495|   658k|      }
  496|  3.46k|      act_prob = cum_prob;
  497|  3.46k|    }
  498|    194|    if (cum_prob != rans_precision) {
  ------------------
  |  Branch (498:9): [True: 51, False: 143]
  ------------------
  499|     51|      return false;
  500|     51|    }
  501|    143|    return true;
  502|    194|  }
_ZN5draco11RAnsDecoderILi12EE9read_initEPKhi:
  421|    124|  inline int read_init(const uint8_t *const buf, int offset) {
  422|    124|    unsigned x;
  423|    124|    if (offset < 1) {
  ------------------
  |  Branch (423:9): [True: 6, False: 118]
  ------------------
  424|      6|      return 1;
  425|      6|    }
  426|    118|    ans_.buf = buf;
  427|    118|    x = buf[offset - 1] >> 6;
  428|    118|    if (x == 0) {
  ------------------
  |  Branch (428:9): [True: 86, False: 32]
  ------------------
  429|     86|      ans_.buf_offset = offset - 1;
  430|     86|      ans_.state = buf[offset - 1] & 0x3F;
  431|     86|    } else if (x == 1) {
  ------------------
  |  Branch (431:16): [True: 20, False: 12]
  ------------------
  432|     20|      if (offset < 2) {
  ------------------
  |  Branch (432:11): [True: 1, False: 19]
  ------------------
  433|      1|        return 1;
  434|      1|      }
  435|     19|      ans_.buf_offset = offset - 2;
  436|     19|      ans_.state = mem_get_le16(buf + offset - 2) & 0x3FFF;
  437|     19|    } else if (x == 2) {
  ------------------
  |  Branch (437:16): [True: 3, False: 9]
  ------------------
  438|      3|      if (offset < 3) {
  ------------------
  |  Branch (438:11): [True: 0, False: 3]
  ------------------
  439|      0|        return 1;
  440|      0|      }
  441|      3|      ans_.buf_offset = offset - 3;
  442|      3|      ans_.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
  443|      9|    } else if (x == 3) {
  ------------------
  |  Branch (443:16): [True: 9, False: 0]
  ------------------
  444|      9|      ans_.buf_offset = offset - 4;
  445|      9|      ans_.state = mem_get_le32(buf + offset - 4) & 0x3FFFFFFF;
  446|      9|    } else {
  447|      0|      return 1;
  448|      0|    }
  449|    117|    ans_.state += l_rans_base;
  450|    117|    if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   65|    117|#define DRACO_ANS_IO_BASE 256
  ------------------
  |  Branch (450:9): [True: 9, False: 108]
  ------------------
  451|      9|      return 1;
  452|      9|    }
  453|    108|    return 0;
  454|    117|  }
symbol_decoding.cc:_ZN5dracoL12mem_get_le16EPKv:
   67|     29|static uint32_t mem_get_le16(const void *vmem) {
   68|     29|  uint32_t val;
   69|     29|  const uint8_t *mem = (const uint8_t *)vmem;
   70|       |
   71|     29|  val = mem[1] << 8;
   72|     29|  val |= mem[0];
   73|     29|  return val;
   74|     29|}
symbol_decoding.cc:_ZN5dracoL12mem_get_le24EPKv:
   76|      7|static uint32_t mem_get_le24(const void *vmem) {
   77|      7|  uint32_t val;
   78|      7|  const uint8_t *mem = (const uint8_t *)vmem;
   79|       |
   80|      7|  val = mem[2] << 16;
   81|      7|  val |= mem[1] << 8;
   82|      7|  val |= mem[0];
   83|      7|  return val;
   84|      7|}
symbol_decoding.cc:_ZN5dracoL12mem_get_le32EPKv:
   86|     11|static inline uint32_t mem_get_le32(const void *vmem) {
   87|     11|  uint32_t val;
   88|     11|  const uint8_t *mem = (const uint8_t *)vmem;
   89|       |
   90|     11|  val = mem[3] << 24;
   91|     11|  val |= mem[2] << 16;
   92|     11|  val |= mem[1] << 8;
   93|     11|  val |= mem[0];
   94|     11|  return val;
   95|     11|}
_ZN5draco11RAnsDecoderILi12EE9rans_readEv:
  462|  8.31M|  inline int rans_read() {
  463|  8.31M|    unsigned rem;
  464|  8.31M|    unsigned quo;
  465|  8.31M|    struct rans_dec_sym sym;
  466|  8.32M|    while (ans_.state < l_rans_base && ans_.buf_offset > 0) {
  ------------------
  |  Branch (466:12): [True: 8.01M, False: 314k]
  |  Branch (466:40): [True: 6.86k, False: 8.00M]
  ------------------
  467|  6.86k|      ans_.state = ans_.state * DRACO_ANS_IO_BASE + ans_.buf[--ans_.buf_offset];
  ------------------
  |  |   65|  6.86k|#define DRACO_ANS_IO_BASE 256
  ------------------
  468|  6.86k|    }
  469|       |    // |rans_precision| is a power of two compile time constant, and the below
  470|       |    // division and modulo are going to be optimized by the compiler.
  471|  8.31M|    quo = ans_.state / rans_precision;
  472|  8.31M|    rem = ans_.state % rans_precision;
  473|  8.31M|    fetch_sym(&sym, rem);
  474|  8.31M|    ans_.state = quo * sym.prob + rem - sym.cum_prob;
  475|  8.31M|    return sym.val;
  476|  8.31M|  }
_ZN5draco11RAnsDecoderILi12EE9fetch_symEPNS_12rans_dec_symEj:
  505|  8.31M|  inline void fetch_sym(struct rans_dec_sym *out, uint32_t rem) {
  506|  8.31M|    uint32_t symbol = lut_table_[rem];
  507|  8.31M|    out->val = symbol;
  508|  8.31M|    out->prob = probability_table_[symbol].prob;
  509|  8.31M|    out->cum_prob = probability_table_[symbol].cum_prob;
  510|  8.31M|  }
_ZN5draco11RAnsDecoderILi12EE8read_endEv:
  456|    100|  inline int read_end() { return ans_.state == l_rans_base; }
_ZN5draco11RAnsDecoderILi13EEC2Ev:
  416|     36|  RAnsDecoder() {}
_ZN5draco11RAnsDecoderILi13EE24rans_build_look_up_tableEPKjj:
  481|     26|                                       uint32_t num_symbols) {
  482|     26|    lut_table_.resize(rans_precision);
  483|     26|    probability_table_.resize(num_symbols);
  484|     26|    uint32_t cum_prob = 0;
  485|     26|    uint32_t act_prob = 0;
  486|    431|    for (uint32_t i = 0; i < num_symbols; ++i) {
  ------------------
  |  Branch (486:26): [True: 410, False: 21]
  ------------------
  487|    410|      probability_table_[i].prob = token_probs[i];
  488|    410|      probability_table_[i].cum_prob = cum_prob;
  489|    410|      cum_prob += token_probs[i];
  490|    410|      if (cum_prob > rans_precision) {
  ------------------
  |  Branch (490:11): [True: 5, False: 405]
  ------------------
  491|      5|        return false;
  492|      5|      }
  493|   173k|      for (uint32_t j = act_prob; j < cum_prob; ++j) {
  ------------------
  |  Branch (493:35): [True: 173k, False: 405]
  ------------------
  494|   173k|        lut_table_[j] = i;
  495|   173k|      }
  496|    405|      act_prob = cum_prob;
  497|    405|    }
  498|     21|    if (cum_prob != rans_precision) {
  ------------------
  |  Branch (498:9): [True: 1, False: 20]
  ------------------
  499|      1|      return false;
  500|      1|    }
  501|     20|    return true;
  502|     21|  }
_ZN5draco11RAnsDecoderILi13EE9read_initEPKhi:
  421|     17|  inline int read_init(const uint8_t *const buf, int offset) {
  422|     17|    unsigned x;
  423|     17|    if (offset < 1) {
  ------------------
  |  Branch (423:9): [True: 0, False: 17]
  ------------------
  424|      0|      return 1;
  425|      0|    }
  426|     17|    ans_.buf = buf;
  427|     17|    x = buf[offset - 1] >> 6;
  428|     17|    if (x == 0) {
  ------------------
  |  Branch (428:9): [True: 9, False: 8]
  ------------------
  429|      9|      ans_.buf_offset = offset - 1;
  430|      9|      ans_.state = buf[offset - 1] & 0x3F;
  431|      9|    } else if (x == 1) {
  ------------------
  |  Branch (431:16): [True: 6, False: 2]
  ------------------
  432|      6|      if (offset < 2) {
  ------------------
  |  Branch (432:11): [True: 0, False: 6]
  ------------------
  433|      0|        return 1;
  434|      0|      }
  435|      6|      ans_.buf_offset = offset - 2;
  436|      6|      ans_.state = mem_get_le16(buf + offset - 2) & 0x3FFF;
  437|      6|    } else if (x == 2) {
  ------------------
  |  Branch (437:16): [True: 2, False: 0]
  ------------------
  438|      2|      if (offset < 3) {
  ------------------
  |  Branch (438:11): [True: 0, False: 2]
  ------------------
  439|      0|        return 1;
  440|      0|      }
  441|      2|      ans_.buf_offset = offset - 3;
  442|      2|      ans_.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
  443|      2|    } else if (x == 3) {
  ------------------
  |  Branch (443:16): [True: 0, False: 0]
  ------------------
  444|      0|      ans_.buf_offset = offset - 4;
  445|      0|      ans_.state = mem_get_le32(buf + offset - 4) & 0x3FFFFFFF;
  446|      0|    } else {
  447|      0|      return 1;
  448|      0|    }
  449|     17|    ans_.state += l_rans_base;
  450|     17|    if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   65|     17|#define DRACO_ANS_IO_BASE 256
  ------------------
  |  Branch (450:9): [True: 0, False: 17]
  ------------------
  451|      0|      return 1;
  452|      0|    }
  453|     17|    return 0;
  454|     17|  }
_ZN5draco11RAnsDecoderILi13EE9rans_readEv:
  462|   322k|  inline int rans_read() {
  463|   322k|    unsigned rem;
  464|   322k|    unsigned quo;
  465|   322k|    struct rans_dec_sym sym;
  466|   337k|    while (ans_.state < l_rans_base && ans_.buf_offset > 0) {
  ------------------
  |  Branch (466:12): [True: 274k, False: 63.2k]
  |  Branch (466:40): [True: 14.9k, False: 259k]
  ------------------
  467|  14.9k|      ans_.state = ans_.state * DRACO_ANS_IO_BASE + ans_.buf[--ans_.buf_offset];
  ------------------
  |  |   65|  14.9k|#define DRACO_ANS_IO_BASE 256
  ------------------
  468|  14.9k|    }
  469|       |    // |rans_precision| is a power of two compile time constant, and the below
  470|       |    // division and modulo are going to be optimized by the compiler.
  471|   322k|    quo = ans_.state / rans_precision;
  472|   322k|    rem = ans_.state % rans_precision;
  473|   322k|    fetch_sym(&sym, rem);
  474|   322k|    ans_.state = quo * sym.prob + rem - sym.cum_prob;
  475|   322k|    return sym.val;
  476|   322k|  }
_ZN5draco11RAnsDecoderILi13EE9fetch_symEPNS_12rans_dec_symEj:
  505|   322k|  inline void fetch_sym(struct rans_dec_sym *out, uint32_t rem) {
  506|   322k|    uint32_t symbol = lut_table_[rem];
  507|   322k|    out->val = symbol;
  508|   322k|    out->prob = probability_table_[symbol].prob;
  509|   322k|    out->cum_prob = probability_table_[symbol].cum_prob;
  510|   322k|  }
_ZN5draco11RAnsDecoderILi13EE8read_endEv:
  456|     17|  inline int read_end() { return ans_.state == l_rans_base; }
_ZN5draco11RAnsDecoderILi15EEC2Ev:
  416|     29|  RAnsDecoder() {}
_ZN5draco11RAnsDecoderILi15EE24rans_build_look_up_tableEPKjj:
  481|     17|                                       uint32_t num_symbols) {
  482|     17|    lut_table_.resize(rans_precision);
  483|     17|    probability_table_.resize(num_symbols);
  484|     17|    uint32_t cum_prob = 0;
  485|     17|    uint32_t act_prob = 0;
  486|    144|    for (uint32_t i = 0; i < num_symbols; ++i) {
  ------------------
  |  Branch (486:26): [True: 133, False: 11]
  ------------------
  487|    133|      probability_table_[i].prob = token_probs[i];
  488|    133|      probability_table_[i].cum_prob = cum_prob;
  489|    133|      cum_prob += token_probs[i];
  490|    133|      if (cum_prob > rans_precision) {
  ------------------
  |  Branch (490:11): [True: 6, False: 127]
  ------------------
  491|      6|        return false;
  492|      6|      }
  493|   380k|      for (uint32_t j = act_prob; j < cum_prob; ++j) {
  ------------------
  |  Branch (493:35): [True: 380k, False: 127]
  ------------------
  494|   380k|        lut_table_[j] = i;
  495|   380k|      }
  496|    127|      act_prob = cum_prob;
  497|    127|    }
  498|     11|    if (cum_prob != rans_precision) {
  ------------------
  |  Branch (498:9): [True: 0, False: 11]
  ------------------
  499|      0|      return false;
  500|      0|    }
  501|     11|    return true;
  502|     11|  }
_ZN5draco11RAnsDecoderILi15EE9read_initEPKhi:
  421|      9|  inline int read_init(const uint8_t *const buf, int offset) {
  422|      9|    unsigned x;
  423|      9|    if (offset < 1) {
  ------------------
  |  Branch (423:9): [True: 1, False: 8]
  ------------------
  424|      1|      return 1;
  425|      1|    }
  426|      8|    ans_.buf = buf;
  427|      8|    x = buf[offset - 1] >> 6;
  428|      8|    if (x == 0) {
  ------------------
  |  Branch (428:9): [True: 5, False: 3]
  ------------------
  429|      5|      ans_.buf_offset = offset - 1;
  430|      5|      ans_.state = buf[offset - 1] & 0x3F;
  431|      5|    } else if (x == 1) {
  ------------------
  |  Branch (431:16): [True: 3, False: 0]
  ------------------
  432|      3|      if (offset < 2) {
  ------------------
  |  Branch (432:11): [True: 0, False: 3]
  ------------------
  433|      0|        return 1;
  434|      0|      }
  435|      3|      ans_.buf_offset = offset - 2;
  436|      3|      ans_.state = mem_get_le16(buf + offset - 2) & 0x3FFF;
  437|      3|    } else if (x == 2) {
  ------------------
  |  Branch (437:16): [True: 0, False: 0]
  ------------------
  438|      0|      if (offset < 3) {
  ------------------
  |  Branch (438:11): [True: 0, False: 0]
  ------------------
  439|      0|        return 1;
  440|      0|      }
  441|      0|      ans_.buf_offset = offset - 3;
  442|      0|      ans_.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
  443|      0|    } else if (x == 3) {
  ------------------
  |  Branch (443:16): [True: 0, False: 0]
  ------------------
  444|      0|      ans_.buf_offset = offset - 4;
  445|      0|      ans_.state = mem_get_le32(buf + offset - 4) & 0x3FFFFFFF;
  446|      0|    } else {
  447|      0|      return 1;
  448|      0|    }
  449|      8|    ans_.state += l_rans_base;
  450|      8|    if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   65|      8|#define DRACO_ANS_IO_BASE 256
  ------------------
  |  Branch (450:9): [True: 0, False: 8]
  ------------------
  451|      0|      return 1;
  452|      0|    }
  453|      8|    return 0;
  454|      8|  }
_ZN5draco11RAnsDecoderILi15EE9rans_readEv:
  462|  1.65k|  inline int rans_read() {
  463|  1.65k|    unsigned rem;
  464|  1.65k|    unsigned quo;
  465|  1.65k|    struct rans_dec_sym sym;
  466|  1.78k|    while (ans_.state < l_rans_base && ans_.buf_offset > 0) {
  ------------------
  |  Branch (466:12): [True: 512, False: 1.27k]
  |  Branch (466:40): [True: 126, False: 386]
  ------------------
  467|    126|      ans_.state = ans_.state * DRACO_ANS_IO_BASE + ans_.buf[--ans_.buf_offset];
  ------------------
  |  |   65|    126|#define DRACO_ANS_IO_BASE 256
  ------------------
  468|    126|    }
  469|       |    // |rans_precision| is a power of two compile time constant, and the below
  470|       |    // division and modulo are going to be optimized by the compiler.
  471|  1.65k|    quo = ans_.state / rans_precision;
  472|  1.65k|    rem = ans_.state % rans_precision;
  473|  1.65k|    fetch_sym(&sym, rem);
  474|  1.65k|    ans_.state = quo * sym.prob + rem - sym.cum_prob;
  475|  1.65k|    return sym.val;
  476|  1.65k|  }
_ZN5draco11RAnsDecoderILi15EE9fetch_symEPNS_12rans_dec_symEj:
  505|  1.65k|  inline void fetch_sym(struct rans_dec_sym *out, uint32_t rem) {
  506|  1.65k|    uint32_t symbol = lut_table_[rem];
  507|  1.65k|    out->val = symbol;
  508|  1.65k|    out->prob = probability_table_[symbol].prob;
  509|  1.65k|    out->cum_prob = probability_table_[symbol].cum_prob;
  510|  1.65k|  }
_ZN5draco11RAnsDecoderILi15EE8read_endEv:
  456|      8|  inline int read_end() { return ans_.state == l_rans_base; }
_ZN5draco11RAnsDecoderILi16EEC2Ev:
  416|     15|  RAnsDecoder() {}
_ZN5draco11RAnsDecoderILi16EE24rans_build_look_up_tableEPKjj:
  481|      4|                                       uint32_t num_symbols) {
  482|      4|    lut_table_.resize(rans_precision);
  483|      4|    probability_table_.resize(num_symbols);
  484|      4|    uint32_t cum_prob = 0;
  485|      4|    uint32_t act_prob = 0;
  486|     23|    for (uint32_t i = 0; i < num_symbols; ++i) {
  ------------------
  |  Branch (486:26): [True: 19, False: 4]
  ------------------
  487|     19|      probability_table_[i].prob = token_probs[i];
  488|     19|      probability_table_[i].cum_prob = cum_prob;
  489|     19|      cum_prob += token_probs[i];
  490|     19|      if (cum_prob > rans_precision) {
  ------------------
  |  Branch (490:11): [True: 0, False: 19]
  ------------------
  491|      0|        return false;
  492|      0|      }
  493|   153k|      for (uint32_t j = act_prob; j < cum_prob; ++j) {
  ------------------
  |  Branch (493:35): [True: 153k, False: 19]
  ------------------
  494|   153k|        lut_table_[j] = i;
  495|   153k|      }
  496|     19|      act_prob = cum_prob;
  497|     19|    }
  498|      4|    if (cum_prob != rans_precision) {
  ------------------
  |  Branch (498:9): [True: 2, False: 2]
  ------------------
  499|      2|      return false;
  500|      2|    }
  501|      2|    return true;
  502|      4|  }
_ZN5draco11RAnsDecoderILi16EE9read_initEPKhi:
  421|      2|  inline int read_init(const uint8_t *const buf, int offset) {
  422|      2|    unsigned x;
  423|      2|    if (offset < 1) {
  ------------------
  |  Branch (423:9): [True: 0, False: 2]
  ------------------
  424|      0|      return 1;
  425|      0|    }
  426|      2|    ans_.buf = buf;
  427|      2|    x = buf[offset - 1] >> 6;
  428|      2|    if (x == 0) {
  ------------------
  |  Branch (428:9): [True: 2, False: 0]
  ------------------
  429|      2|      ans_.buf_offset = offset - 1;
  430|      2|      ans_.state = buf[offset - 1] & 0x3F;
  431|      2|    } else if (x == 1) {
  ------------------
  |  Branch (431:16): [True: 0, False: 0]
  ------------------
  432|      0|      if (offset < 2) {
  ------------------
  |  Branch (432:11): [True: 0, False: 0]
  ------------------
  433|      0|        return 1;
  434|      0|      }
  435|      0|      ans_.buf_offset = offset - 2;
  436|      0|      ans_.state = mem_get_le16(buf + offset - 2) & 0x3FFF;
  437|      0|    } else if (x == 2) {
  ------------------
  |  Branch (437:16): [True: 0, False: 0]
  ------------------
  438|      0|      if (offset < 3) {
  ------------------
  |  Branch (438:11): [True: 0, False: 0]
  ------------------
  439|      0|        return 1;
  440|      0|      }
  441|      0|      ans_.buf_offset = offset - 3;
  442|      0|      ans_.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
  443|      0|    } else if (x == 3) {
  ------------------
  |  Branch (443:16): [True: 0, False: 0]
  ------------------
  444|      0|      ans_.buf_offset = offset - 4;
  445|      0|      ans_.state = mem_get_le32(buf + offset - 4) & 0x3FFFFFFF;
  446|      0|    } else {
  447|      0|      return 1;
  448|      0|    }
  449|      2|    ans_.state += l_rans_base;
  450|      2|    if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   65|      2|#define DRACO_ANS_IO_BASE 256
  ------------------
  |  Branch (450:9): [True: 0, False: 2]
  ------------------
  451|      0|      return 1;
  452|      0|    }
  453|      2|    return 0;
  454|      2|  }
_ZN5draco11RAnsDecoderILi16EE9rans_readEv:
  462|  1.54k|  inline int rans_read() {
  463|  1.54k|    unsigned rem;
  464|  1.54k|    unsigned quo;
  465|  1.54k|    struct rans_dec_sym sym;
  466|  2.13k|    while (ans_.state < l_rans_base && ans_.buf_offset > 0) {
  ------------------
  |  Branch (466:12): [True: 604, False: 1.53k]
  |  Branch (466:40): [True: 597, False: 7]
  ------------------
  467|    597|      ans_.state = ans_.state * DRACO_ANS_IO_BASE + ans_.buf[--ans_.buf_offset];
  ------------------
  |  |   65|    597|#define DRACO_ANS_IO_BASE 256
  ------------------
  468|    597|    }
  469|       |    // |rans_precision| is a power of two compile time constant, and the below
  470|       |    // division and modulo are going to be optimized by the compiler.
  471|  1.54k|    quo = ans_.state / rans_precision;
  472|  1.54k|    rem = ans_.state % rans_precision;
  473|  1.54k|    fetch_sym(&sym, rem);
  474|  1.54k|    ans_.state = quo * sym.prob + rem - sym.cum_prob;
  475|  1.54k|    return sym.val;
  476|  1.54k|  }
_ZN5draco11RAnsDecoderILi16EE9fetch_symEPNS_12rans_dec_symEj:
  505|  1.54k|  inline void fetch_sym(struct rans_dec_sym *out, uint32_t rem) {
  506|  1.54k|    uint32_t symbol = lut_table_[rem];
  507|  1.54k|    out->val = symbol;
  508|  1.54k|    out->prob = probability_table_[symbol].prob;
  509|  1.54k|    out->cum_prob = probability_table_[symbol].cum_prob;
  510|  1.54k|  }
_ZN5draco11RAnsDecoderILi16EE8read_endEv:
  456|      2|  inline int read_end() { return ans_.state == l_rans_base; }
_ZN5draco11RAnsDecoderILi18EEC2Ev:
  416|     31|  RAnsDecoder() {}
_ZN5draco11RAnsDecoderILi18EE24rans_build_look_up_tableEPKjj:
  481|     12|                                       uint32_t num_symbols) {
  482|     12|    lut_table_.resize(rans_precision);
  483|     12|    probability_table_.resize(num_symbols);
  484|     12|    uint32_t cum_prob = 0;
  485|     12|    uint32_t act_prob = 0;
  486|  4.74k|    for (uint32_t i = 0; i < num_symbols; ++i) {
  ------------------
  |  Branch (486:26): [True: 4.73k, False: 5]
  ------------------
  487|  4.73k|      probability_table_[i].prob = token_probs[i];
  488|  4.73k|      probability_table_[i].cum_prob = cum_prob;
  489|  4.73k|      cum_prob += token_probs[i];
  490|  4.73k|      if (cum_prob > rans_precision) {
  ------------------
  |  Branch (490:11): [True: 7, False: 4.73k]
  ------------------
  491|      7|        return false;
  492|      7|      }
  493|  1.35M|      for (uint32_t j = act_prob; j < cum_prob; ++j) {
  ------------------
  |  Branch (493:35): [True: 1.34M, False: 4.73k]
  ------------------
  494|  1.34M|        lut_table_[j] = i;
  495|  1.34M|      }
  496|  4.73k|      act_prob = cum_prob;
  497|  4.73k|    }
  498|      5|    if (cum_prob != rans_precision) {
  ------------------
  |  Branch (498:9): [True: 2, False: 3]
  ------------------
  499|      2|      return false;
  500|      2|    }
  501|      3|    return true;
  502|      5|  }
_ZN5draco11RAnsDecoderILi18EE9read_initEPKhi:
  421|      2|  inline int read_init(const uint8_t *const buf, int offset) {
  422|      2|    unsigned x;
  423|      2|    if (offset < 1) {
  ------------------
  |  Branch (423:9): [True: 0, False: 2]
  ------------------
  424|      0|      return 1;
  425|      0|    }
  426|      2|    ans_.buf = buf;
  427|      2|    x = buf[offset - 1] >> 6;
  428|      2|    if (x == 0) {
  ------------------
  |  Branch (428:9): [True: 2, False: 0]
  ------------------
  429|      2|      ans_.buf_offset = offset - 1;
  430|      2|      ans_.state = buf[offset - 1] & 0x3F;
  431|      2|    } else if (x == 1) {
  ------------------
  |  Branch (431:16): [True: 0, False: 0]
  ------------------
  432|      0|      if (offset < 2) {
  ------------------
  |  Branch (432:11): [True: 0, False: 0]
  ------------------
  433|      0|        return 1;
  434|      0|      }
  435|      0|      ans_.buf_offset = offset - 2;
  436|      0|      ans_.state = mem_get_le16(buf + offset - 2) & 0x3FFF;
  437|      0|    } else if (x == 2) {
  ------------------
  |  Branch (437:16): [True: 0, False: 0]
  ------------------
  438|      0|      if (offset < 3) {
  ------------------
  |  Branch (438:11): [True: 0, False: 0]
  ------------------
  439|      0|        return 1;
  440|      0|      }
  441|      0|      ans_.buf_offset = offset - 3;
  442|      0|      ans_.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
  443|      0|    } else if (x == 3) {
  ------------------
  |  Branch (443:16): [True: 0, False: 0]
  ------------------
  444|      0|      ans_.buf_offset = offset - 4;
  445|      0|      ans_.state = mem_get_le32(buf + offset - 4) & 0x3FFFFFFF;
  446|      0|    } else {
  447|      0|      return 1;
  448|      0|    }
  449|      2|    ans_.state += l_rans_base;
  450|      2|    if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   65|      2|#define DRACO_ANS_IO_BASE 256
  ------------------
  |  Branch (450:9): [True: 0, False: 2]
  ------------------
  451|      0|      return 1;
  452|      0|    }
  453|      2|    return 0;
  454|      2|  }
_ZN5draco11RAnsDecoderILi18EE9rans_readEv:
  462|    138|  inline int rans_read() {
  463|    138|    unsigned rem;
  464|    138|    unsigned quo;
  465|    138|    struct rans_dec_sym sym;
  466|    138|    while (ans_.state < l_rans_base && ans_.buf_offset > 0) {
  ------------------
  |  Branch (466:12): [True: 0, False: 138]
  |  Branch (466:40): [True: 0, False: 0]
  ------------------
  467|      0|      ans_.state = ans_.state * DRACO_ANS_IO_BASE + ans_.buf[--ans_.buf_offset];
  ------------------
  |  |   65|      0|#define DRACO_ANS_IO_BASE 256
  ------------------
  468|      0|    }
  469|       |    // |rans_precision| is a power of two compile time constant, and the below
  470|       |    // division and modulo are going to be optimized by the compiler.
  471|    138|    quo = ans_.state / rans_precision;
  472|    138|    rem = ans_.state % rans_precision;
  473|    138|    fetch_sym(&sym, rem);
  474|    138|    ans_.state = quo * sym.prob + rem - sym.cum_prob;
  475|    138|    return sym.val;
  476|    138|  }
_ZN5draco11RAnsDecoderILi18EE9fetch_symEPNS_12rans_dec_symEj:
  505|    138|  inline void fetch_sym(struct rans_dec_sym *out, uint32_t rem) {
  506|    138|    uint32_t symbol = lut_table_[rem];
  507|    138|    out->val = symbol;
  508|    138|    out->prob = probability_table_[symbol].prob;
  509|    138|    out->cum_prob = probability_table_[symbol].cum_prob;
  510|    138|  }
_ZN5draco11RAnsDecoderILi18EE8read_endEv:
  456|      2|  inline int read_end() { return ans_.state == l_rans_base; }
_ZN5draco11RAnsDecoderILi19EEC2Ev:
  416|     16|  RAnsDecoder() {}
_ZN5draco11RAnsDecoderILi19EE24rans_build_look_up_tableEPKjj:
  481|      7|                                       uint32_t num_symbols) {
  482|      7|    lut_table_.resize(rans_precision);
  483|      7|    probability_table_.resize(num_symbols);
  484|      7|    uint32_t cum_prob = 0;
  485|      7|    uint32_t act_prob = 0;
  486|    981|    for (uint32_t i = 0; i < num_symbols; ++i) {
  ------------------
  |  Branch (486:26): [True: 978, False: 3]
  ------------------
  487|    978|      probability_table_[i].prob = token_probs[i];
  488|    978|      probability_table_[i].cum_prob = cum_prob;
  489|    978|      cum_prob += token_probs[i];
  490|    978|      if (cum_prob > rans_precision) {
  ------------------
  |  Branch (490:11): [True: 4, False: 974]
  ------------------
  491|      4|        return false;
  492|      4|      }
  493|  2.42M|      for (uint32_t j = act_prob; j < cum_prob; ++j) {
  ------------------
  |  Branch (493:35): [True: 2.42M, False: 974]
  ------------------
  494|  2.42M|        lut_table_[j] = i;
  495|  2.42M|      }
  496|    974|      act_prob = cum_prob;
  497|    974|    }
  498|      3|    if (cum_prob != rans_precision) {
  ------------------
  |  Branch (498:9): [True: 1, False: 2]
  ------------------
  499|      1|      return false;
  500|      1|    }
  501|      2|    return true;
  502|      3|  }
_ZN5draco11RAnsDecoderILi19EE9read_initEPKhi:
  421|      1|  inline int read_init(const uint8_t *const buf, int offset) {
  422|      1|    unsigned x;
  423|      1|    if (offset < 1) {
  ------------------
  |  Branch (423:9): [True: 0, False: 1]
  ------------------
  424|      0|      return 1;
  425|      0|    }
  426|      1|    ans_.buf = buf;
  427|      1|    x = buf[offset - 1] >> 6;
  428|      1|    if (x == 0) {
  ------------------
  |  Branch (428:9): [True: 1, False: 0]
  ------------------
  429|      1|      ans_.buf_offset = offset - 1;
  430|      1|      ans_.state = buf[offset - 1] & 0x3F;
  431|      1|    } else if (x == 1) {
  ------------------
  |  Branch (431:16): [True: 0, False: 0]
  ------------------
  432|      0|      if (offset < 2) {
  ------------------
  |  Branch (432:11): [True: 0, False: 0]
  ------------------
  433|      0|        return 1;
  434|      0|      }
  435|      0|      ans_.buf_offset = offset - 2;
  436|      0|      ans_.state = mem_get_le16(buf + offset - 2) & 0x3FFF;
  437|      0|    } else if (x == 2) {
  ------------------
  |  Branch (437:16): [True: 0, False: 0]
  ------------------
  438|      0|      if (offset < 3) {
  ------------------
  |  Branch (438:11): [True: 0, False: 0]
  ------------------
  439|      0|        return 1;
  440|      0|      }
  441|      0|      ans_.buf_offset = offset - 3;
  442|      0|      ans_.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
  443|      0|    } else if (x == 3) {
  ------------------
  |  Branch (443:16): [True: 0, False: 0]
  ------------------
  444|      0|      ans_.buf_offset = offset - 4;
  445|      0|      ans_.state = mem_get_le32(buf + offset - 4) & 0x3FFFFFFF;
  446|      0|    } else {
  447|      0|      return 1;
  448|      0|    }
  449|      1|    ans_.state += l_rans_base;
  450|      1|    if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   65|      1|#define DRACO_ANS_IO_BASE 256
  ------------------
  |  Branch (450:9): [True: 0, False: 1]
  ------------------
  451|      0|      return 1;
  452|      0|    }
  453|      1|    return 0;
  454|      1|  }
_ZN5draco11RAnsDecoderILi19EE9rans_readEv:
  462|     61|  inline int rans_read() {
  463|     61|    unsigned rem;
  464|     61|    unsigned quo;
  465|     61|    struct rans_dec_sym sym;
  466|    154|    while (ans_.state < l_rans_base && ans_.buf_offset > 0) {
  ------------------
  |  Branch (466:12): [True: 93, False: 61]
  |  Branch (466:40): [True: 93, False: 0]
  ------------------
  467|     93|      ans_.state = ans_.state * DRACO_ANS_IO_BASE + ans_.buf[--ans_.buf_offset];
  ------------------
  |  |   65|     93|#define DRACO_ANS_IO_BASE 256
  ------------------
  468|     93|    }
  469|       |    // |rans_precision| is a power of two compile time constant, and the below
  470|       |    // division and modulo are going to be optimized by the compiler.
  471|     61|    quo = ans_.state / rans_precision;
  472|     61|    rem = ans_.state % rans_precision;
  473|     61|    fetch_sym(&sym, rem);
  474|     61|    ans_.state = quo * sym.prob + rem - sym.cum_prob;
  475|     61|    return sym.val;
  476|     61|  }
_ZN5draco11RAnsDecoderILi19EE9fetch_symEPNS_12rans_dec_symEj:
  505|     61|  inline void fetch_sym(struct rans_dec_sym *out, uint32_t rem) {
  506|     61|    uint32_t symbol = lut_table_[rem];
  507|     61|    out->val = symbol;
  508|     61|    out->prob = probability_table_[symbol].prob;
  509|     61|    out->cum_prob = probability_table_[symbol].cum_prob;
  510|     61|  }
_ZN5draco11RAnsDecoderILi19EE8read_endEv:
  456|      1|  inline int read_end() { return ans_.state == l_rans_base; }
_ZN5draco11RAnsDecoderILi20EEC2Ev:
  416|    210|  RAnsDecoder() {}
_ZN5draco11RAnsDecoderILi20EE24rans_build_look_up_tableEPKjj:
  481|    109|                                       uint32_t num_symbols) {
  482|    109|    lut_table_.resize(rans_precision);
  483|    109|    probability_table_.resize(num_symbols);
  484|    109|    uint32_t cum_prob = 0;
  485|    109|    uint32_t act_prob = 0;
  486|  6.39k|    for (uint32_t i = 0; i < num_symbols; ++i) {
  ------------------
  |  Branch (486:26): [True: 6.29k, False: 94]
  ------------------
  487|  6.29k|      probability_table_[i].prob = token_probs[i];
  488|  6.29k|      probability_table_[i].cum_prob = cum_prob;
  489|  6.29k|      cum_prob += token_probs[i];
  490|  6.29k|      if (cum_prob > rans_precision) {
  ------------------
  |  Branch (490:11): [True: 15, False: 6.28k]
  ------------------
  491|     15|        return false;
  492|     15|      }
  493|  99.1M|      for (uint32_t j = act_prob; j < cum_prob; ++j) {
  ------------------
  |  Branch (493:35): [True: 99.1M, False: 6.28k]
  ------------------
  494|  99.1M|        lut_table_[j] = i;
  495|  99.1M|      }
  496|  6.28k|      act_prob = cum_prob;
  497|  6.28k|    }
  498|     94|    if (cum_prob != rans_precision) {
  ------------------
  |  Branch (498:9): [True: 4, False: 90]
  ------------------
  499|      4|      return false;
  500|      4|    }
  501|     90|    return true;
  502|     94|  }
_ZN5draco11RAnsDecoderILi20EE9read_initEPKhi:
  421|      9|  inline int read_init(const uint8_t *const buf, int offset) {
  422|      9|    unsigned x;
  423|      9|    if (offset < 1) {
  ------------------
  |  Branch (423:9): [True: 0, False: 9]
  ------------------
  424|      0|      return 1;
  425|      0|    }
  426|      9|    ans_.buf = buf;
  427|      9|    x = buf[offset - 1] >> 6;
  428|      9|    if (x == 0) {
  ------------------
  |  Branch (428:9): [True: 2, False: 7]
  ------------------
  429|      2|      ans_.buf_offset = offset - 1;
  430|      2|      ans_.state = buf[offset - 1] & 0x3F;
  431|      7|    } else if (x == 1) {
  ------------------
  |  Branch (431:16): [True: 3, False: 4]
  ------------------
  432|      3|      if (offset < 2) {
  ------------------
  |  Branch (432:11): [True: 2, False: 1]
  ------------------
  433|      2|        return 1;
  434|      2|      }
  435|      1|      ans_.buf_offset = offset - 2;
  436|      1|      ans_.state = mem_get_le16(buf + offset - 2) & 0x3FFF;
  437|      4|    } else if (x == 2) {
  ------------------
  |  Branch (437:16): [True: 2, False: 2]
  ------------------
  438|      2|      if (offset < 3) {
  ------------------
  |  Branch (438:11): [True: 0, False: 2]
  ------------------
  439|      0|        return 1;
  440|      0|      }
  441|      2|      ans_.buf_offset = offset - 3;
  442|      2|      ans_.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
  443|      2|    } else if (x == 3) {
  ------------------
  |  Branch (443:16): [True: 2, False: 0]
  ------------------
  444|      2|      ans_.buf_offset = offset - 4;
  445|      2|      ans_.state = mem_get_le32(buf + offset - 4) & 0x3FFFFFFF;
  446|      2|    } else {
  447|      0|      return 1;
  448|      0|    }
  449|      7|    ans_.state += l_rans_base;
  450|      7|    if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE) {
  ------------------
  |  |   65|      7|#define DRACO_ANS_IO_BASE 256
  ------------------
  |  Branch (450:9): [True: 1, False: 6]
  ------------------
  451|      1|      return 1;
  452|      1|    }
  453|      6|    return 0;
  454|      7|  }
_ZN5draco11RAnsDecoderILi20EE9rans_readEv:
  462|  18.2k|  inline int rans_read() {
  463|  18.2k|    unsigned rem;
  464|  18.2k|    unsigned quo;
  465|  18.2k|    struct rans_dec_sym sym;
  466|  18.8k|    while (ans_.state < l_rans_base && ans_.buf_offset > 0) {
  ------------------
  |  Branch (466:12): [True: 581, False: 18.2k]
  |  Branch (466:40): [True: 581, False: 0]
  ------------------
  467|    581|      ans_.state = ans_.state * DRACO_ANS_IO_BASE + ans_.buf[--ans_.buf_offset];
  ------------------
  |  |   65|    581|#define DRACO_ANS_IO_BASE 256
  ------------------
  468|    581|    }
  469|       |    // |rans_precision| is a power of two compile time constant, and the below
  470|       |    // division and modulo are going to be optimized by the compiler.
  471|  18.2k|    quo = ans_.state / rans_precision;
  472|  18.2k|    rem = ans_.state % rans_precision;
  473|  18.2k|    fetch_sym(&sym, rem);
  474|  18.2k|    ans_.state = quo * sym.prob + rem - sym.cum_prob;
  475|  18.2k|    return sym.val;
  476|  18.2k|  }
_ZN5draco11RAnsDecoderILi20EE9fetch_symEPNS_12rans_dec_symEj:
  505|  18.2k|  inline void fetch_sym(struct rans_dec_sym *out, uint32_t rem) {
  506|  18.2k|    uint32_t symbol = lut_table_[rem];
  507|  18.2k|    out->val = symbol;
  508|  18.2k|    out->prob = probability_table_[symbol].prob;
  509|  18.2k|    out->cum_prob = probability_table_[symbol].cum_prob;
  510|  18.2k|  }
_ZN5draco11RAnsDecoderILi20EE8read_endEv:
  456|      6|  inline int read_end() { return ans_.state == l_rans_base; }

_ZN5draco17RAnsSymbolDecoderILi5EEC2Ev:
   33|    197|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi5EE6CreateEPNS_13DecoderBufferE:
   59|    197|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|    197|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 197]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|    197|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|    197|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    197|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 71, False: 126]
  ------------------
   67|     71|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 71]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|     71|  } else
   72|    126|#endif
   73|    126|  {
   74|    126|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 126]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|    126|  }
   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|    197|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 28, False: 169]
  ------------------
   83|     28|    return false;
   84|     28|  }
   85|    169|  probability_table_.resize(num_symbols_);
   86|    169|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 30, False: 139]
  ------------------
   87|     30|    return true;
   88|     30|  }
   89|       |  // Decode the table.
   90|  1.76M|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 1.76M, False: 29]
  ------------------
   91|  1.76M|    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.76M|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 20, False: 1.76M]
  ------------------
   95|     20|      return false;
   96|     20|    }
   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.76M|    const int token = prob_data & 3;
  102|  1.76M|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 680k, False: 1.08M]
  ------------------
  103|   680k|      const uint32_t offset = prob_data >> 2;
  104|   680k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 85, False: 680k]
  ------------------
  105|     85|        return false;
  106|     85|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  33.0M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 32.3M, False: 680k]
  ------------------
  109|  32.3M|        probability_table_[i + j] = 0;
  110|  32.3M|      }
  111|   680k|      i += offset;
  112|  1.08M|    } else {
  113|  1.08M|      const int extra_bytes = token;
  114|  1.08M|      uint32_t prob = prob_data >> 2;
  115|  1.86M|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 772k, False: 1.08M]
  ------------------
  116|   772k|        uint8_t eb;
  117|   772k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 5, False: 772k]
  ------------------
  118|      5|          return false;
  119|      5|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|   772k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|   772k|      }
  124|  1.08M|      probability_table_[i] = prob;
  125|  1.08M|    }
  126|  1.76M|  }
  127|     29|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 15, False: 14]
  ------------------
  128|     15|    return false;
  129|     15|  }
  130|     14|  return true;
  131|     29|}
_ZN5draco17RAnsSymbolDecoderILi5EE13StartDecodingEPNS_13DecoderBufferE:
  135|     44|    DecoderBuffer *buffer) {
  136|     44|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|     44|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|     44|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     44|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 13, False: 31]
  ------------------
  140|     13|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 0, False: 13]
  ------------------
  141|      0|      return false;
  142|      0|    }
  143|       |
  144|     13|  } else
  145|     31|#endif
  146|     31|  {
  147|     31|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 31]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|     31|  }
  151|     44|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 16, False: 28]
  ------------------
  152|     16|    return false;
  153|     16|  }
  154|     28|  const uint8_t *const data_head =
  155|     28|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|     28|  buffer->Advance(bytes_encoded);
  158|     28|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 10, False: 18]
  ------------------
  159|     10|    return false;
  160|     10|  }
  161|     18|  return true;
  162|     28|}
_ZNK5draco17RAnsSymbolDecoderILi5EE11num_symbolsEv:
   38|     22|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi5EE12DecodeSymbolEv:
   43|  18.7k|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi5EE11EndDecodingEv:
  165|     10|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|     10|  ans_.read_end();
  167|     10|}
_ZN5draco17RAnsSymbolDecoderILi1EEC2Ev:
   33|     81|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi1EE6CreateEPNS_13DecoderBufferE:
   59|     81|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|     81|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 81]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|     81|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|     81|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     81|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 7, False: 74]
  ------------------
   67|      7|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 7]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|      7|  } else
   72|     74|#endif
   73|     74|  {
   74|     74|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 74]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|     74|  }
   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|     81|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 5, False: 76]
  ------------------
   83|      5|    return false;
   84|      5|  }
   85|     76|  probability_table_.resize(num_symbols_);
   86|     76|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 5, False: 71]
  ------------------
   87|      5|    return true;
   88|      5|  }
   89|       |  // Decode the table.
   90|   999k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 999k, False: 41]
  ------------------
   91|   999k|    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|   999k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 9, False: 999k]
  ------------------
   95|      9|      return false;
   96|      9|    }
   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|   999k|    const int token = prob_data & 3;
  102|   999k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 422k, False: 576k]
  ------------------
  103|   422k|      const uint32_t offset = prob_data >> 2;
  104|   422k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 15, False: 422k]
  ------------------
  105|     15|        return false;
  106|     15|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  21.3M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 20.9M, False: 422k]
  ------------------
  109|  20.9M|        probability_table_[i + j] = 0;
  110|  20.9M|      }
  111|   422k|      i += offset;
  112|   576k|    } else {
  113|   576k|      const int extra_bytes = token;
  114|   576k|      uint32_t prob = prob_data >> 2;
  115|   839k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 262k, False: 576k]
  ------------------
  116|   262k|        uint8_t eb;
  117|   262k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 6, False: 262k]
  ------------------
  118|      6|          return false;
  119|      6|        }
  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|   576k|      probability_table_[i] = prob;
  125|   576k|    }
  126|   999k|  }
  127|     41|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 39, False: 2]
  ------------------
  128|     39|    return false;
  129|     39|  }
  130|      2|  return true;
  131|     41|}
_ZNK5draco17RAnsSymbolDecoderILi1EE11num_symbolsEv:
   38|      7|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi1EE13StartDecodingEPNS_13DecoderBufferE:
  135|      2|    DecoderBuffer *buffer) {
  136|      2|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|      2|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|      2|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|      2|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 0, False: 2]
  ------------------
  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|      2|#endif
  146|      2|  {
  147|      2|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 2]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|      2|  }
  151|      2|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 0, False: 2]
  ------------------
  152|      0|    return false;
  153|      0|  }
  154|      2|  const uint8_t *const data_head =
  155|      2|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|      2|  buffer->Advance(bytes_encoded);
  158|      2|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 0, False: 2]
  ------------------
  159|      0|    return false;
  160|      0|  }
  161|      2|  return true;
  162|      2|}
_ZN5draco17RAnsSymbolDecoderILi1EE12DecodeSymbolEv:
   43|  2.07M|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi1EE11EndDecodingEv:
  165|      2|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|      2|  ans_.read_end();
  167|      2|}
_ZN5draco17RAnsSymbolDecoderILi2EEC2Ev:
   33|     71|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi2EE6CreateEPNS_13DecoderBufferE:
   59|     71|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|     71|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 71]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|     71|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|     71|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     71|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 10, False: 61]
  ------------------
   67|     10|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 10]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|     10|  } else
   72|     61|#endif
   73|     61|  {
   74|     61|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 61]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|     61|  }
   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|     71|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 1, False: 70]
  ------------------
   83|      1|    return false;
   84|      1|  }
   85|     70|  probability_table_.resize(num_symbols_);
   86|     70|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 0, False: 70]
  ------------------
   87|      0|    return true;
   88|      0|  }
   89|       |  // Decode the table.
   90|  99.3k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 99.3k, False: 57]
  ------------------
   91|  99.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|  99.3k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 1, False: 99.2k]
  ------------------
   95|      1|      return false;
   96|      1|    }
   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|  99.2k|    const int token = prob_data & 3;
  102|  99.2k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 15.2k, False: 84.0k]
  ------------------
  103|  15.2k|      const uint32_t offset = prob_data >> 2;
  104|  15.2k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 10, False: 15.2k]
  ------------------
  105|     10|        return false;
  106|     10|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|   850k|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 835k, False: 15.2k]
  ------------------
  109|   835k|        probability_table_[i + j] = 0;
  110|   835k|      }
  111|  15.2k|      i += offset;
  112|  84.0k|    } else {
  113|  84.0k|      const int extra_bytes = token;
  114|  84.0k|      uint32_t prob = prob_data >> 2;
  115|   148k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 64.3k, False: 84.0k]
  ------------------
  116|  64.3k|        uint8_t eb;
  117|  64.3k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 2, False: 64.3k]
  ------------------
  118|      2|          return false;
  119|      2|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  64.3k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  64.3k|      }
  124|  84.0k|      probability_table_[i] = prob;
  125|  84.0k|    }
  126|  99.2k|  }
  127|     57|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 17, False: 40]
  ------------------
  128|     17|    return false;
  129|     17|  }
  130|     40|  return true;
  131|     57|}
_ZNK5draco17RAnsSymbolDecoderILi2EE11num_symbolsEv:
   38|     40|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi2EE13StartDecodingEPNS_13DecoderBufferE:
  135|     40|    DecoderBuffer *buffer) {
  136|     40|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|     40|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|     40|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     40|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 1, False: 39]
  ------------------
  140|      1|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 0, False: 1]
  ------------------
  141|      0|      return false;
  142|      0|    }
  143|       |
  144|      1|  } else
  145|     39|#endif
  146|     39|  {
  147|     39|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 39]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|     39|  }
  151|     40|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 7, False: 33]
  ------------------
  152|      7|    return false;
  153|      7|  }
  154|     33|  const uint8_t *const data_head =
  155|     33|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|     33|  buffer->Advance(bytes_encoded);
  158|     33|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 0, False: 33]
  ------------------
  159|      0|    return false;
  160|      0|  }
  161|     33|  return true;
  162|     33|}
_ZN5draco17RAnsSymbolDecoderILi2EE12DecodeSymbolEv:
   43|  4.71M|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi2EE11EndDecodingEv:
  165|     33|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|     33|  ans_.read_end();
  167|     33|}
_ZN5draco17RAnsSymbolDecoderILi3EEC2Ev:
   33|     51|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi3EE6CreateEPNS_13DecoderBufferE:
   59|     51|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|     51|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 51]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|     51|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|     51|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     51|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 24, False: 27]
  ------------------
   67|     24|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 24]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|     24|  } else
   72|     27|#endif
   73|     27|  {
   74|     27|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 27]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|     27|  }
   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|     51|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 6, False: 45]
  ------------------
   83|      6|    return false;
   84|      6|  }
   85|     45|  probability_table_.resize(num_symbols_);
   86|     45|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 0, False: 45]
  ------------------
   87|      0|    return true;
   88|      0|  }
   89|       |  // Decode the table.
   90|  1.17M|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 1.17M, False: 28]
  ------------------
   91|  1.17M|    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.17M|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 7, False: 1.17M]
  ------------------
   95|      7|      return false;
   96|      7|    }
   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.17M|    const int token = prob_data & 3;
  102|  1.17M|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 713k, False: 460k]
  ------------------
  103|   713k|      const uint32_t offset = prob_data >> 2;
  104|   713k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 5, False: 713k]
  ------------------
  105|      5|        return false;
  106|      5|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  43.8M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 43.1M, False: 713k]
  ------------------
  109|  43.1M|        probability_table_[i + j] = 0;
  110|  43.1M|      }
  111|   713k|      i += offset;
  112|   713k|    } else {
  113|   460k|      const int extra_bytes = token;
  114|   460k|      uint32_t prob = prob_data >> 2;
  115|   871k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 410k, False: 460k]
  ------------------
  116|   410k|        uint8_t eb;
  117|   410k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 5, False: 410k]
  ------------------
  118|      5|          return false;
  119|      5|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|   410k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|   410k|      }
  124|   460k|      probability_table_[i] = prob;
  125|   460k|    }
  126|  1.17M|  }
  127|     28|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 5, False: 23]
  ------------------
  128|      5|    return false;
  129|      5|  }
  130|     23|  return true;
  131|     28|}
_ZNK5draco17RAnsSymbolDecoderILi3EE11num_symbolsEv:
   38|     23|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi3EE13StartDecodingEPNS_13DecoderBufferE:
  135|     23|    DecoderBuffer *buffer) {
  136|     23|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|     23|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|     23|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     23|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 8, False: 15]
  ------------------
  140|      8|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 0, False: 8]
  ------------------
  141|      0|      return false;
  142|      0|    }
  143|       |
  144|      8|  } else
  145|     15|#endif
  146|     15|  {
  147|     15|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 15]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|     15|  }
  151|     23|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 11, False: 12]
  ------------------
  152|     11|    return false;
  153|     11|  }
  154|     12|  const uint8_t *const data_head =
  155|     12|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|     12|  buffer->Advance(bytes_encoded);
  158|     12|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 0, False: 12]
  ------------------
  159|      0|    return false;
  160|      0|  }
  161|     12|  return true;
  162|     12|}
_ZN5draco17RAnsSymbolDecoderILi3EE12DecodeSymbolEv:
   43|   153k|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi3EE11EndDecodingEv:
  165|     12|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|     12|  ans_.read_end();
  167|     12|}
_ZN5draco17RAnsSymbolDecoderILi4EEC2Ev:
   33|     71|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi4EE6CreateEPNS_13DecoderBufferE:
   59|     71|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|     71|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 71]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|     71|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|     71|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     71|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 21, False: 50]
  ------------------
   67|     21|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 21]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|     21|  } else
   72|     50|#endif
   73|     50|  {
   74|     50|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 50]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|     50|  }
   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|     71|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 8, False: 63]
  ------------------
   83|      8|    return false;
   84|      8|  }
   85|     63|  probability_table_.resize(num_symbols_);
   86|     63|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 12, False: 51]
  ------------------
   87|     12|    return true;
   88|     12|  }
   89|       |  // Decode the table.
   90|  4.02k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 3.98k, False: 42]
  ------------------
   91|  3.98k|    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|  3.98k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 2, False: 3.98k]
  ------------------
   95|      2|      return false;
   96|      2|    }
   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|  3.98k|    const int token = prob_data & 3;
  102|  3.98k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 847, False: 3.13k]
  ------------------
  103|    847|      const uint32_t offset = prob_data >> 2;
  104|    847|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 6, False: 841]
  ------------------
  105|      6|        return false;
  106|      6|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  23.9k|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 23.0k, False: 841]
  ------------------
  109|  23.0k|        probability_table_[i + j] = 0;
  110|  23.0k|      }
  111|    841|      i += offset;
  112|  3.13k|    } else {
  113|  3.13k|      const int extra_bytes = token;
  114|  3.13k|      uint32_t prob = prob_data >> 2;
  115|  5.59k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 2.45k, False: 3.13k]
  ------------------
  116|  2.45k|        uint8_t eb;
  117|  2.45k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 1, False: 2.45k]
  ------------------
  118|      1|          return false;
  119|      1|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  2.45k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  2.45k|      }
  124|  3.13k|      probability_table_[i] = prob;
  125|  3.13k|    }
  126|  3.98k|  }
  127|     42|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 8, False: 34]
  ------------------
  128|      8|    return false;
  129|      8|  }
  130|     34|  return true;
  131|     42|}
_ZNK5draco17RAnsSymbolDecoderILi4EE11num_symbolsEv:
   38|     46|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi4EE13StartDecodingEPNS_13DecoderBufferE:
  135|     34|    DecoderBuffer *buffer) {
  136|     34|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|     34|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|     34|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     34|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 0, False: 34]
  ------------------
  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|     34|#endif
  146|     34|  {
  147|     34|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 34]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|     34|  }
  151|     34|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 5, False: 29]
  ------------------
  152|      5|    return false;
  153|      5|  }
  154|     29|  const uint8_t *const data_head =
  155|     29|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|     29|  buffer->Advance(bytes_encoded);
  158|     29|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 0, False: 29]
  ------------------
  159|      0|    return false;
  160|      0|  }
  161|     29|  return true;
  162|     29|}
_ZN5draco17RAnsSymbolDecoderILi4EE12DecodeSymbolEv:
   43|  55.9k|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi4EE11EndDecodingEv:
  165|     29|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|     29|  ans_.read_end();
  167|     29|}
_ZN5draco17RAnsSymbolDecoderILi6EEC2Ev:
   33|      9|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi6EE6CreateEPNS_13DecoderBufferE:
   59|      9|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|      9|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 9]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|      9|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|      9|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|      9|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 2, False: 7]
  ------------------
   67|      2|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 2]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|      2|  } else
   72|      7|#endif
   73|      7|  {
   74|      7|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 7]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|      7|  }
   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|      9|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 0, False: 9]
  ------------------
   83|      0|    return false;
   84|      0|  }
   85|      9|  probability_table_.resize(num_symbols_);
   86|      9|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 0, False: 9]
  ------------------
   87|      0|    return true;
   88|      0|  }
   89|       |  // Decode the table.
   90|   215k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 215k, False: 3]
  ------------------
   91|   215k|    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|   215k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 3, False: 215k]
  ------------------
   95|      3|      return false;
   96|      3|    }
   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|   215k|    const int token = prob_data & 3;
  102|   215k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 147k, False: 68.5k]
  ------------------
  103|   147k|      const uint32_t offset = prob_data >> 2;
  104|   147k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 1, False: 147k]
  ------------------
  105|      1|        return false;
  106|      1|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  8.54M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 8.39M, False: 147k]
  ------------------
  109|  8.39M|        probability_table_[i + j] = 0;
  110|  8.39M|      }
  111|   147k|      i += offset;
  112|   147k|    } else {
  113|  68.5k|      const int extra_bytes = token;
  114|  68.5k|      uint32_t prob = prob_data >> 2;
  115|   124k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 55.9k, False: 68.4k]
  ------------------
  116|  55.9k|        uint8_t eb;
  117|  55.9k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 2, False: 55.9k]
  ------------------
  118|      2|          return false;
  119|      2|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  55.9k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  55.9k|      }
  124|  68.4k|      probability_table_[i] = prob;
  125|  68.4k|    }
  126|   215k|  }
  127|      3|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 0, False: 3]
  ------------------
  128|      0|    return false;
  129|      0|  }
  130|      3|  return true;
  131|      3|}
_ZNK5draco17RAnsSymbolDecoderILi6EE11num_symbolsEv:
   38|      3|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi6EE13StartDecodingEPNS_13DecoderBufferE:
  135|      3|    DecoderBuffer *buffer) {
  136|      3|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|      3|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|      3|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|      3|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 0, False: 3]
  ------------------
  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|      3|#endif
  146|      3|  {
  147|      3|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 3]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|      3|  }
  151|      3|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 2, False: 1]
  ------------------
  152|      2|    return false;
  153|      2|  }
  154|      1|  const uint8_t *const data_head =
  155|      1|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|      1|  buffer->Advance(bytes_encoded);
  158|      1|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 0, False: 1]
  ------------------
  159|      0|    return false;
  160|      0|  }
  161|      1|  return true;
  162|      1|}
_ZN5draco17RAnsSymbolDecoderILi6EE12DecodeSymbolEv:
   43|  1.23k|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi6EE11EndDecodingEv:
  165|      1|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|      1|  ans_.read_end();
  167|      1|}
_ZN5draco17RAnsSymbolDecoderILi7EEC2Ev:
   33|     49|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi7EE6CreateEPNS_13DecoderBufferE:
   59|     49|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|     49|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 49]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|     49|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|     49|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     49|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 15, False: 34]
  ------------------
   67|     15|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 15]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|     15|  } else
   72|     34|#endif
   73|     34|  {
   74|     34|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 34]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|     34|  }
   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|     49|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 6, False: 43]
  ------------------
   83|      6|    return false;
   84|      6|  }
   85|     43|  probability_table_.resize(num_symbols_);
   86|     43|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 1, False: 42]
  ------------------
   87|      1|    return true;
   88|      1|  }
   89|       |  // Decode the table.
   90|   616k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 616k, False: 24]
  ------------------
   91|   616k|    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|   616k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 8, False: 616k]
  ------------------
   95|      8|      return false;
   96|      8|    }
   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|   616k|    const int token = prob_data & 3;
  102|   616k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 66.2k, False: 550k]
  ------------------
  103|  66.2k|      const uint32_t offset = prob_data >> 2;
  104|  66.2k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 8, False: 66.2k]
  ------------------
  105|      8|        return false;
  106|      8|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  2.70M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 2.63M, False: 66.2k]
  ------------------
  109|  2.63M|        probability_table_[i + j] = 0;
  110|  2.63M|      }
  111|  66.2k|      i += offset;
  112|   550k|    } else {
  113|   550k|      const int extra_bytes = token;
  114|   550k|      uint32_t prob = prob_data >> 2;
  115|   814k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 264k, False: 550k]
  ------------------
  116|   264k|        uint8_t eb;
  117|   264k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 2, False: 264k]
  ------------------
  118|      2|          return false;
  119|      2|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|   264k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|   264k|      }
  124|   550k|      probability_table_[i] = prob;
  125|   550k|    }
  126|   616k|  }
  127|     24|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 8, False: 16]
  ------------------
  128|      8|    return false;
  129|      8|  }
  130|     16|  return true;
  131|     24|}
_ZNK5draco17RAnsSymbolDecoderILi7EE11num_symbolsEv:
   38|     17|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi7EE13StartDecodingEPNS_13DecoderBufferE:
  135|     16|    DecoderBuffer *buffer) {
  136|     16|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|     16|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|     16|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     16|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 2, False: 14]
  ------------------
  140|      2|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 0, False: 2]
  ------------------
  141|      0|      return false;
  142|      0|    }
  143|       |
  144|      2|  } else
  145|     14|#endif
  146|     14|  {
  147|     14|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 14]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|     14|  }
  151|     16|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 6, False: 10]
  ------------------
  152|      6|    return false;
  153|      6|  }
  154|     10|  const uint8_t *const data_head =
  155|     10|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|     10|  buffer->Advance(bytes_encoded);
  158|     10|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 5, False: 5]
  ------------------
  159|      5|    return false;
  160|      5|  }
  161|      5|  return true;
  162|     10|}
_ZN5draco17RAnsSymbolDecoderILi7EE12DecodeSymbolEv:
   43|  51.4k|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi7EE11EndDecodingEv:
  165|      5|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|      5|  ans_.read_end();
  167|      5|}
_ZN5draco17RAnsSymbolDecoderILi8EEC2Ev:
   33|     36|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi8EE6CreateEPNS_13DecoderBufferE:
   59|     36|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|     36|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 36]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|     36|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|     36|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     36|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 19, False: 17]
  ------------------
   67|     19|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 19]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|     19|  } else
   72|     17|#endif
   73|     17|  {
   74|     17|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 17]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|     17|  }
   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|     36|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 1, False: 35]
  ------------------
   83|      1|    return false;
   84|      1|  }
   85|     35|  probability_table_.resize(num_symbols_);
   86|     35|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 0, False: 35]
  ------------------
   87|      0|    return true;
   88|      0|  }
   89|       |  // Decode the table.
   90|   713k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 713k, False: 13]
  ------------------
   91|   713k|    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|   713k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 6, False: 713k]
  ------------------
   95|      6|      return false;
   96|      6|    }
   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|   713k|    const int token = prob_data & 3;
  102|   713k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 175k, False: 537k]
  ------------------
  103|   175k|      const uint32_t offset = prob_data >> 2;
  104|   175k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 11, False: 175k]
  ------------------
  105|     11|        return false;
  106|     11|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  9.30M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 9.13M, False: 175k]
  ------------------
  109|  9.13M|        probability_table_[i + j] = 0;
  110|  9.13M|      }
  111|   175k|      i += offset;
  112|   537k|    } else {
  113|   537k|      const int extra_bytes = token;
  114|   537k|      uint32_t prob = prob_data >> 2;
  115|   723k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 185k, False: 537k]
  ------------------
  116|   185k|        uint8_t eb;
  117|   185k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 5, False: 185k]
  ------------------
  118|      5|          return false;
  119|      5|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|   185k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|   185k|      }
  124|   537k|      probability_table_[i] = prob;
  125|   537k|    }
  126|   713k|  }
  127|     13|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 2, False: 11]
  ------------------
  128|      2|    return false;
  129|      2|  }
  130|     11|  return true;
  131|     13|}
_ZNK5draco17RAnsSymbolDecoderILi8EE11num_symbolsEv:
   38|     11|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi8EE13StartDecodingEPNS_13DecoderBufferE:
  135|     11|    DecoderBuffer *buffer) {
  136|     11|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|     11|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|     11|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     11|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 3, False: 8]
  ------------------
  140|      3|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 0, False: 3]
  ------------------
  141|      0|      return false;
  142|      0|    }
  143|       |
  144|      3|  } else
  145|      8|#endif
  146|      8|  {
  147|      8|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 8]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|      8|  }
  151|     11|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 2, False: 9]
  ------------------
  152|      2|    return false;
  153|      2|  }
  154|      9|  const uint8_t *const data_head =
  155|      9|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|      9|  buffer->Advance(bytes_encoded);
  158|      9|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 1, False: 8]
  ------------------
  159|      1|    return false;
  160|      1|  }
  161|      8|  return true;
  162|      9|}
_ZN5draco17RAnsSymbolDecoderILi8EE12DecodeSymbolEv:
   43|  1.24M|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi8EE11EndDecodingEv:
  165|      8|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|      8|  ans_.read_end();
  167|      8|}
_ZN5draco17RAnsSymbolDecoderILi9EEC2Ev:
   33|     36|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi9EE6CreateEPNS_13DecoderBufferE:
   59|     36|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|     36|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 36]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|     36|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|     36|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     36|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 1, False: 35]
  ------------------
   67|      1|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 1]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|      1|  } else
   72|     35|#endif
   73|     35|  {
   74|     35|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 35]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|     35|  }
   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|     36|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 0, False: 36]
  ------------------
   83|      0|    return false;
   84|      0|  }
   85|     36|  probability_table_.resize(num_symbols_);
   86|     36|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 0, False: 36]
  ------------------
   87|      0|    return true;
   88|      0|  }
   89|       |  // Decode the table.
   90|  1.89M|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 1.89M, False: 26]
  ------------------
   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: 5, False: 1.89M]
  ------------------
   95|      5|      return false;
   96|      5|    }
   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: 363k, False: 1.53M]
  ------------------
  103|   363k|      const uint32_t offset = prob_data >> 2;
  104|   363k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 3, False: 363k]
  ------------------
  105|      3|        return false;
  106|      3|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  18.8M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 18.4M, False: 363k]
  ------------------
  109|  18.4M|        probability_table_[i + j] = 0;
  110|  18.4M|      }
  111|   363k|      i += offset;
  112|  1.53M|    } else {
  113|  1.53M|      const int extra_bytes = token;
  114|  1.53M|      uint32_t prob = prob_data >> 2;
  115|  2.23M|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 701k, False: 1.53M]
  ------------------
  116|   701k|        uint8_t eb;
  117|   701k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 2, False: 701k]
  ------------------
  118|      2|          return false;
  119|      2|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|   701k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|   701k|      }
  124|  1.53M|      probability_table_[i] = prob;
  125|  1.53M|    }
  126|  1.89M|  }
  127|     26|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 6, False: 20]
  ------------------
  128|      6|    return false;
  129|      6|  }
  130|     20|  return true;
  131|     26|}
_ZNK5draco17RAnsSymbolDecoderILi9EE11num_symbolsEv:
   38|     20|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi9EE13StartDecodingEPNS_13DecoderBufferE:
  135|     20|    DecoderBuffer *buffer) {
  136|     20|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|     20|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|     20|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     20|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 0, False: 20]
  ------------------
  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|     20|#endif
  146|     20|  {
  147|     20|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 20]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|     20|  }
  151|     20|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 3, False: 17]
  ------------------
  152|      3|    return false;
  153|      3|  }
  154|     17|  const uint8_t *const data_head =
  155|     17|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|     17|  buffer->Advance(bytes_encoded);
  158|     17|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 0, False: 17]
  ------------------
  159|      0|    return false;
  160|      0|  }
  161|     17|  return true;
  162|     17|}
_ZN5draco17RAnsSymbolDecoderILi9EE12DecodeSymbolEv:
   43|   322k|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi9EE11EndDecodingEv:
  165|     17|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|     17|  ans_.read_end();
  167|     17|}
_ZN5draco17RAnsSymbolDecoderILi10EEC2Ev:
   33|     29|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi10EE6CreateEPNS_13DecoderBufferE:
   59|     29|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|     29|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 29]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|     29|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|     29|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     29|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 5, False: 24]
  ------------------
   67|      5|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 5]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|      5|  } else
   72|     24|#endif
   73|     24|  {
   74|     24|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 24]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|     24|  }
   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|     29|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 0, False: 29]
  ------------------
   83|      0|    return false;
   84|      0|  }
   85|     29|  probability_table_.resize(num_symbols_);
   86|     29|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 0, False: 29]
  ------------------
   87|      0|    return true;
   88|      0|  }
   89|       |  // Decode the table.
   90|   220k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 220k, False: 17]
  ------------------
   91|   220k|    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|   220k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 7, False: 220k]
  ------------------
   95|      7|      return false;
   96|      7|    }
   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|   220k|    const int token = prob_data & 3;
  102|   220k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 73.4k, False: 147k]
  ------------------
  103|  73.4k|      const uint32_t offset = prob_data >> 2;
  104|  73.4k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 0, False: 73.4k]
  ------------------
  105|      0|        return false;
  106|      0|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  3.92M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 3.85M, False: 73.4k]
  ------------------
  109|  3.85M|        probability_table_[i + j] = 0;
  110|  3.85M|      }
  111|  73.4k|      i += offset;
  112|   147k|    } else {
  113|   147k|      const int extra_bytes = token;
  114|   147k|      uint32_t prob = prob_data >> 2;
  115|   284k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 137k, False: 147k]
  ------------------
  116|   137k|        uint8_t eb;
  117|   137k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 5, False: 137k]
  ------------------
  118|      5|          return false;
  119|      5|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|   137k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|   137k|      }
  124|   147k|      probability_table_[i] = prob;
  125|   147k|    }
  126|   220k|  }
  127|     17|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 6, False: 11]
  ------------------
  128|      6|    return false;
  129|      6|  }
  130|     11|  return true;
  131|     17|}
_ZNK5draco17RAnsSymbolDecoderILi10EE11num_symbolsEv:
   38|     11|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi10EE13StartDecodingEPNS_13DecoderBufferE:
  135|     11|    DecoderBuffer *buffer) {
  136|     11|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|     11|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|     11|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     11|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 0, False: 11]
  ------------------
  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|     11|#endif
  146|     11|  {
  147|     11|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 11]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|     11|  }
  151|     11|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 2, False: 9]
  ------------------
  152|      2|    return false;
  153|      2|  }
  154|      9|  const uint8_t *const data_head =
  155|      9|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|      9|  buffer->Advance(bytes_encoded);
  158|      9|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 1, False: 8]
  ------------------
  159|      1|    return false;
  160|      1|  }
  161|      8|  return true;
  162|      9|}
_ZN5draco17RAnsSymbolDecoderILi10EE12DecodeSymbolEv:
   43|  1.65k|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi10EE11EndDecodingEv:
  165|      8|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|      8|  ans_.read_end();
  167|      8|}
_ZN5draco17RAnsSymbolDecoderILi11EEC2Ev:
   33|     15|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi11EE6CreateEPNS_13DecoderBufferE:
   59|     15|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|     15|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 15]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|     15|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|     15|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     15|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 3, False: 12]
  ------------------
   67|      3|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 3]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|      3|  } else
   72|     12|#endif
   73|     12|  {
   74|     12|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 12]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|     12|  }
   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|     15|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 1, False: 14]
  ------------------
   83|      1|    return false;
   84|      1|  }
   85|     14|  probability_table_.resize(num_symbols_);
   86|     14|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 0, False: 14]
  ------------------
   87|      0|    return true;
   88|      0|  }
   89|       |  // Decode the table.
   90|  8.24k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 8.24k, False: 4]
  ------------------
   91|  8.24k|    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.24k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 2, False: 8.24k]
  ------------------
   95|      2|      return false;
   96|      2|    }
   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.24k|    const int token = prob_data & 3;
  102|  8.24k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 1.12k, False: 7.12k]
  ------------------
  103|  1.12k|      const uint32_t offset = prob_data >> 2;
  104|  1.12k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 7, False: 1.11k]
  ------------------
  105|      7|        return false;
  106|      7|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  41.1k|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 40.0k, False: 1.11k]
  ------------------
  109|  40.0k|        probability_table_[i + j] = 0;
  110|  40.0k|      }
  111|  1.11k|      i += offset;
  112|  7.12k|    } else {
  113|  7.12k|      const int extra_bytes = token;
  114|  7.12k|      uint32_t prob = prob_data >> 2;
  115|  12.9k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 5.78k, False: 7.12k]
  ------------------
  116|  5.78k|        uint8_t eb;
  117|  5.78k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 1, False: 5.78k]
  ------------------
  118|      1|          return false;
  119|      1|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  5.78k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  5.78k|      }
  124|  7.12k|      probability_table_[i] = prob;
  125|  7.12k|    }
  126|  8.24k|  }
  127|      4|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 2, False: 2]
  ------------------
  128|      2|    return false;
  129|      2|  }
  130|      2|  return true;
  131|      4|}
_ZNK5draco17RAnsSymbolDecoderILi11EE11num_symbolsEv:
   38|      2|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi11EE13StartDecodingEPNS_13DecoderBufferE:
  135|      2|    DecoderBuffer *buffer) {
  136|      2|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|      2|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|      2|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|      2|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 0, False: 2]
  ------------------
  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|      2|#endif
  146|      2|  {
  147|      2|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 2]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|      2|  }
  151|      2|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 0, False: 2]
  ------------------
  152|      0|    return false;
  153|      0|  }
  154|      2|  const uint8_t *const data_head =
  155|      2|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|      2|  buffer->Advance(bytes_encoded);
  158|      2|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 0, False: 2]
  ------------------
  159|      0|    return false;
  160|      0|  }
  161|      2|  return true;
  162|      2|}
_ZN5draco17RAnsSymbolDecoderILi11EE12DecodeSymbolEv:
   43|  1.54k|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi11EE11EndDecodingEv:
  165|      2|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|      2|  ans_.read_end();
  167|      2|}
_ZN5draco17RAnsSymbolDecoderILi12EEC2Ev:
   33|     31|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi12EE6CreateEPNS_13DecoderBufferE:
   59|     31|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|     31|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 31]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|     31|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|     31|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     31|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 11, False: 20]
  ------------------
   67|     11|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 11]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|     11|  } else
   72|     20|#endif
   73|     20|  {
   74|     20|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 20]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|     20|  }
   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|     31|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 2, False: 29]
  ------------------
   83|      2|    return false;
   84|      2|  }
   85|     29|  probability_table_.resize(num_symbols_);
   86|     29|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 0, False: 29]
  ------------------
   87|      0|    return true;
   88|      0|  }
   89|       |  // Decode the table.
   90|  1.55M|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 1.55M, False: 12]
  ------------------
   91|  1.55M|    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.55M|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 11, False: 1.55M]
  ------------------
   95|     11|      return false;
   96|     11|    }
   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.55M|    const int token = prob_data & 3;
  102|  1.55M|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 723k, False: 832k]
  ------------------
  103|   723k|      const uint32_t offset = prob_data >> 2;
  104|   723k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 6, False: 723k]
  ------------------
  105|      6|        return false;
  106|      6|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  22.3M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 21.6M, False: 723k]
  ------------------
  109|  21.6M|        probability_table_[i + j] = 0;
  110|  21.6M|      }
  111|   723k|      i += offset;
  112|   832k|    } else {
  113|   832k|      const int extra_bytes = token;
  114|   832k|      uint32_t prob = prob_data >> 2;
  115|  1.16M|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 332k, False: 832k]
  ------------------
  116|   332k|        uint8_t eb;
  117|   332k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 0, False: 332k]
  ------------------
  118|      0|          return false;
  119|      0|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|   332k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|   332k|      }
  124|   832k|      probability_table_[i] = prob;
  125|   832k|    }
  126|  1.55M|  }
  127|     12|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 9, False: 3]
  ------------------
  128|      9|    return false;
  129|      9|  }
  130|      3|  return true;
  131|     12|}
_ZNK5draco17RAnsSymbolDecoderILi12EE11num_symbolsEv:
   38|      3|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi12EE13StartDecodingEPNS_13DecoderBufferE:
  135|      3|    DecoderBuffer *buffer) {
  136|      3|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|      3|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|      3|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|      3|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 0, False: 3]
  ------------------
  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|      3|#endif
  146|      3|  {
  147|      3|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 3]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|      3|  }
  151|      3|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 1, False: 2]
  ------------------
  152|      1|    return false;
  153|      1|  }
  154|      2|  const uint8_t *const data_head =
  155|      2|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|      2|  buffer->Advance(bytes_encoded);
  158|      2|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 0, False: 2]
  ------------------
  159|      0|    return false;
  160|      0|  }
  161|      2|  return true;
  162|      2|}
_ZN5draco17RAnsSymbolDecoderILi12EE12DecodeSymbolEv:
   43|    138|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi12EE11EndDecodingEv:
  165|      2|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|      2|  ans_.read_end();
  167|      2|}
_ZN5draco17RAnsSymbolDecoderILi13EEC2Ev:
   33|     16|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi13EE6CreateEPNS_13DecoderBufferE:
   59|     16|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|     16|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 16]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|     16|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|     16|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     16|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 2, False: 14]
  ------------------
   67|      2|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 2]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|      2|  } else
   72|     14|#endif
   73|     14|  {
   74|     14|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 14]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|     14|  }
   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|     16|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 0, False: 16]
  ------------------
   83|      0|    return false;
   84|      0|  }
   85|     16|  probability_table_.resize(num_symbols_);
   86|     16|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 0, False: 16]
  ------------------
   87|      0|    return true;
   88|      0|  }
   89|       |  // Decode the table.
   90|   428k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 428k, False: 7]
  ------------------
   91|   428k|    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|   428k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 7, False: 428k]
  ------------------
   95|      7|      return false;
   96|      7|    }
   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|   428k|    const int token = prob_data & 3;
  102|   428k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 150k, False: 278k]
  ------------------
  103|   150k|      const uint32_t offset = prob_data >> 2;
  104|   150k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 2, False: 150k]
  ------------------
  105|      2|        return false;
  106|      2|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  8.14M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 7.99M, False: 150k]
  ------------------
  109|  7.99M|        probability_table_[i + j] = 0;
  110|  7.99M|      }
  111|   150k|      i += offset;
  112|   278k|    } else {
  113|   278k|      const int extra_bytes = token;
  114|   278k|      uint32_t prob = prob_data >> 2;
  115|   499k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 221k, False: 278k]
  ------------------
  116|   221k|        uint8_t eb;
  117|   221k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 0, False: 221k]
  ------------------
  118|      0|          return false;
  119|      0|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|   221k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|   221k|      }
  124|   278k|      probability_table_[i] = prob;
  125|   278k|    }
  126|   428k|  }
  127|      7|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 5, False: 2]
  ------------------
  128|      5|    return false;
  129|      5|  }
  130|      2|  return true;
  131|      7|}
_ZNK5draco17RAnsSymbolDecoderILi13EE11num_symbolsEv:
   38|      2|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi13EE13StartDecodingEPNS_13DecoderBufferE:
  135|      2|    DecoderBuffer *buffer) {
  136|      2|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|      2|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|      2|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|      2|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 0, False: 2]
  ------------------
  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|      2|#endif
  146|      2|  {
  147|      2|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 2]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|      2|  }
  151|      2|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 1, False: 1]
  ------------------
  152|      1|    return false;
  153|      1|  }
  154|      1|  const uint8_t *const data_head =
  155|      1|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|      1|  buffer->Advance(bytes_encoded);
  158|      1|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 0, False: 1]
  ------------------
  159|      0|    return false;
  160|      0|  }
  161|      1|  return true;
  162|      1|}
_ZN5draco17RAnsSymbolDecoderILi13EE12DecodeSymbolEv:
   43|     61|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi13EE11EndDecodingEv:
  165|      1|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|      1|  ans_.read_end();
  167|      1|}
_ZN5draco17RAnsSymbolDecoderILi14EEC2Ev:
   33|     49|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi14EE6CreateEPNS_13DecoderBufferE:
   59|     49|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|     49|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 49]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|     49|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|     49|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     49|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 33, False: 16]
  ------------------
   67|     33|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 33]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|     33|  } else
   72|     16|#endif
   73|     16|  {
   74|     16|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 16]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|     16|  }
   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|     49|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 14, False: 35]
  ------------------
   83|     14|    return false;
   84|     14|  }
   85|     35|  probability_table_.resize(num_symbols_);
   86|     35|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 0, False: 35]
  ------------------
   87|      0|    return true;
   88|      0|  }
   89|       |  // Decode the table.
   90|   595k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 595k, False: 22]
  ------------------
   91|   595k|    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|   595k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 6, False: 595k]
  ------------------
   95|      6|      return false;
   96|      6|    }
   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|   595k|    const int token = prob_data & 3;
  102|   595k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 217k, False: 377k]
  ------------------
  103|   217k|      const uint32_t offset = prob_data >> 2;
  104|   217k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 6, False: 217k]
  ------------------
  105|      6|        return false;
  106|      6|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  9.53M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 9.32M, False: 217k]
  ------------------
  109|  9.32M|        probability_table_[i + j] = 0;
  110|  9.32M|      }
  111|   217k|      i += offset;
  112|   377k|    } else {
  113|   377k|      const int extra_bytes = token;
  114|   377k|      uint32_t prob = prob_data >> 2;
  115|   583k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 205k, False: 377k]
  ------------------
  116|   205k|        uint8_t eb;
  117|   205k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 1, False: 205k]
  ------------------
  118|      1|          return false;
  119|      1|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|   205k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|   205k|      }
  124|   377k|      probability_table_[i] = prob;
  125|   377k|    }
  126|   595k|  }
  127|     22|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 5, False: 17]
  ------------------
  128|      5|    return false;
  129|      5|  }
  130|     17|  return true;
  131|     22|}
_ZNK5draco17RAnsSymbolDecoderILi14EE11num_symbolsEv:
   38|     17|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi14EE13StartDecodingEPNS_13DecoderBufferE:
  135|     17|    DecoderBuffer *buffer) {
  136|     17|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|     17|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|     17|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     17|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 15, False: 2]
  ------------------
  140|     15|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 0, False: 15]
  ------------------
  141|      0|      return false;
  142|      0|    }
  143|       |
  144|     15|  } else
  145|      2|#endif
  146|      2|  {
  147|      2|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 2]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|      2|  }
  151|     17|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 16, False: 1]
  ------------------
  152|     16|    return false;
  153|     16|  }
  154|      1|  const uint8_t *const data_head =
  155|      1|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|      1|  buffer->Advance(bytes_encoded);
  158|      1|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 1, False: 0]
  ------------------
  159|      1|    return false;
  160|      1|  }
  161|      0|  return true;
  162|      1|}
_ZN5draco17RAnsSymbolDecoderILi15EEC2Ev:
   33|     52|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi15EE6CreateEPNS_13DecoderBufferE:
   59|     52|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|     52|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 52]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|     52|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|     52|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     52|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 46, False: 6]
  ------------------
   67|     46|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 46]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|     46|  } else
   72|      6|#endif
   73|      6|  {
   74|      6|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 6]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|      6|  }
   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|     52|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 8, False: 44]
  ------------------
   83|      8|    return false;
   84|      8|  }
   85|     44|  probability_table_.resize(num_symbols_);
   86|     44|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 0, False: 44]
  ------------------
   87|      0|    return true;
   88|      0|  }
   89|       |  // Decode the table.
   90|   149k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 149k, False: 30]
  ------------------
   91|   149k|    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|   149k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 6, False: 149k]
  ------------------
   95|      6|      return false;
   96|      6|    }
   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|   149k|    const int token = prob_data & 3;
  102|   149k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 28.4k, False: 120k]
  ------------------
  103|  28.4k|      const uint32_t offset = prob_data >> 2;
  104|  28.4k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 2, False: 28.4k]
  ------------------
  105|      2|        return false;
  106|      2|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  1.18M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 1.16M, False: 28.4k]
  ------------------
  109|  1.16M|        probability_table_[i + j] = 0;
  110|  1.16M|      }
  111|  28.4k|      i += offset;
  112|   120k|    } else {
  113|   120k|      const int extra_bytes = token;
  114|   120k|      uint32_t prob = prob_data >> 2;
  115|   236k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 115k, False: 120k]
  ------------------
  116|   115k|        uint8_t eb;
  117|   115k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 6, False: 115k]
  ------------------
  118|      6|          return false;
  119|      6|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|   115k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|   115k|      }
  124|   120k|      probability_table_[i] = prob;
  125|   120k|    }
  126|   149k|  }
  127|     30|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 0, False: 30]
  ------------------
  128|      0|    return false;
  129|      0|  }
  130|     30|  return true;
  131|     30|}
_ZNK5draco17RAnsSymbolDecoderILi15EE11num_symbolsEv:
   38|     30|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi15EE13StartDecodingEPNS_13DecoderBufferE:
  135|     30|    DecoderBuffer *buffer) {
  136|     30|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|     30|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|     30|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     30|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 29, False: 1]
  ------------------
  140|     29|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 0, False: 29]
  ------------------
  141|      0|      return false;
  142|      0|    }
  143|       |
  144|     29|  } else
  145|      1|#endif
  146|      1|  {
  147|      1|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 1]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|      1|  }
  151|     30|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 29, False: 1]
  ------------------
  152|     29|    return false;
  153|     29|  }
  154|      1|  const uint8_t *const data_head =
  155|      1|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|      1|  buffer->Advance(bytes_encoded);
  158|      1|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 0, False: 1]
  ------------------
  159|      0|    return false;
  160|      0|  }
  161|      1|  return true;
  162|      1|}
_ZN5draco17RAnsSymbolDecoderILi15EE12DecodeSymbolEv:
   43|      2|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi15EE11EndDecodingEv:
  165|      1|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|      1|  ans_.read_end();
  167|      1|}
_ZN5draco17RAnsSymbolDecoderILi16EEC2Ev:
   33|     28|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi16EE6CreateEPNS_13DecoderBufferE:
   59|     28|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|     28|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 28]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|     28|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|     28|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     28|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 8, False: 20]
  ------------------
   67|      8|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 8]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|      8|  } else
   72|     20|#endif
   73|     20|  {
   74|     20|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 20]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|     20|  }
   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|     28|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 1, False: 27]
  ------------------
   83|      1|    return false;
   84|      1|  }
   85|     27|  probability_table_.resize(num_symbols_);
   86|     27|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 0, False: 27]
  ------------------
   87|      0|    return true;
   88|      0|  }
   89|       |  // Decode the table.
   90|   198k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 198k, False: 15]
  ------------------
   91|   198k|    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|   198k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 3, False: 198k]
  ------------------
   95|      3|      return false;
   96|      3|    }
   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|   198k|    const int token = prob_data & 3;
  102|   198k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 52.8k, False: 145k]
  ------------------
  103|  52.8k|      const uint32_t offset = prob_data >> 2;
  104|  52.8k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 5, False: 52.8k]
  ------------------
  105|      5|        return false;
  106|      5|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  2.53M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 2.47M, False: 52.8k]
  ------------------
  109|  2.47M|        probability_table_[i + j] = 0;
  110|  2.47M|      }
  111|  52.8k|      i += offset;
  112|   145k|    } else {
  113|   145k|      const int extra_bytes = token;
  114|   145k|      uint32_t prob = prob_data >> 2;
  115|   266k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 121k, False: 145k]
  ------------------
  116|   121k|        uint8_t eb;
  117|   121k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 4, False: 121k]
  ------------------
  118|      4|          return false;
  119|      4|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|   121k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|   121k|      }
  124|   145k|      probability_table_[i] = prob;
  125|   145k|    }
  126|   198k|  }
  127|     15|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 6, False: 9]
  ------------------
  128|      6|    return false;
  129|      6|  }
  130|      9|  return true;
  131|     15|}
_ZNK5draco17RAnsSymbolDecoderILi16EE11num_symbolsEv:
   38|      9|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi16EE13StartDecodingEPNS_13DecoderBufferE:
  135|      9|    DecoderBuffer *buffer) {
  136|      9|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|      9|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|      9|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|      9|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 7, False: 2]
  ------------------
  140|      7|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 0, False: 7]
  ------------------
  141|      0|      return false;
  142|      0|    }
  143|       |
  144|      7|  } else
  145|      2|#endif
  146|      2|  {
  147|      2|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 2]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|      2|  }
  151|      9|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 9, False: 0]
  ------------------
  152|      9|    return false;
  153|      9|  }
  154|      0|  const uint8_t *const data_head =
  155|      0|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|      0|  buffer->Advance(bytes_encoded);
  158|      0|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 0, False: 0]
  ------------------
  159|      0|    return false;
  160|      0|  }
  161|      0|  return true;
  162|      0|}
_ZN5draco17RAnsSymbolDecoderILi17EEC2Ev:
   33|     53|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi17EE6CreateEPNS_13DecoderBufferE:
   59|     53|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|     53|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 53]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|     53|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|     53|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     53|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 30, False: 23]
  ------------------
   67|     30|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 30]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|     30|  } else
   72|     23|#endif
   73|     23|  {
   74|     23|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 23]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|     23|  }
   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|     53|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 14, False: 39]
  ------------------
   83|     14|    return false;
   84|     14|  }
   85|     39|  probability_table_.resize(num_symbols_);
   86|     39|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 0, False: 39]
  ------------------
   87|      0|    return true;
   88|      0|  }
   89|       |  // Decode the table.
   90|  28.0k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 28.0k, False: 27]
  ------------------
   91|  28.0k|    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.0k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 5, False: 28.0k]
  ------------------
   95|      5|      return false;
   96|      5|    }
   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.0k|    const int token = prob_data & 3;
  102|  28.0k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 5.29k, False: 22.7k]
  ------------------
  103|  5.29k|      const uint32_t offset = prob_data >> 2;
  104|  5.29k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 6, False: 5.28k]
  ------------------
  105|      6|        return false;
  106|      6|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|   211k|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 205k, False: 5.28k]
  ------------------
  109|   205k|        probability_table_[i + j] = 0;
  110|   205k|      }
  111|  5.28k|      i += offset;
  112|  22.7k|    } else {
  113|  22.7k|      const int extra_bytes = token;
  114|  22.7k|      uint32_t prob = prob_data >> 2;
  115|  38.6k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 15.8k, False: 22.7k]
  ------------------
  116|  15.8k|        uint8_t eb;
  117|  15.8k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 1, False: 15.8k]
  ------------------
  118|      1|          return false;
  119|      1|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  15.8k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  15.8k|      }
  124|  22.7k|      probability_table_[i] = prob;
  125|  22.7k|    }
  126|  28.0k|  }
  127|     27|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 5, False: 22]
  ------------------
  128|      5|    return false;
  129|      5|  }
  130|     22|  return true;
  131|     27|}
_ZNK5draco17RAnsSymbolDecoderILi17EE11num_symbolsEv:
   38|     22|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi17EE13StartDecodingEPNS_13DecoderBufferE:
  135|     22|    DecoderBuffer *buffer) {
  136|     22|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|     22|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|     22|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     22|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 14, False: 8]
  ------------------
  140|     14|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 0, False: 14]
  ------------------
  141|      0|      return false;
  142|      0|    }
  143|       |
  144|     14|  } else
  145|      8|#endif
  146|      8|  {
  147|      8|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 8]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|      8|  }
  151|     22|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 18, False: 4]
  ------------------
  152|     18|    return false;
  153|     18|  }
  154|      4|  const uint8_t *const data_head =
  155|      4|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|      4|  buffer->Advance(bytes_encoded);
  158|      4|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 0, False: 4]
  ------------------
  159|      0|    return false;
  160|      0|  }
  161|      4|  return true;
  162|      4|}
_ZN5draco17RAnsSymbolDecoderILi17EE12DecodeSymbolEv:
   43|  14.0k|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi17EE11EndDecodingEv:
  165|      4|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|      4|  ans_.read_end();
  167|      4|}
_ZN5draco17RAnsSymbolDecoderILi18EEC2Ev:
   33|     28|  RAnsSymbolDecoder() : num_symbols_(0) {}
_ZN5draco17RAnsSymbolDecoderILi18EE6CreateEPNS_13DecoderBufferE:
   59|     28|    DecoderBuffer *buffer) {
   60|       |  // Check that the DecoderBuffer version is set.
   61|     28|  if (buffer->bitstream_version() == 0) {
  ------------------
  |  Branch (61:7): [True: 0, False: 28]
  ------------------
   62|      0|    return false;
   63|      0|  }
   64|       |  // Decode the number of alphabet symbols.
   65|     28|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   66|     28|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     28|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (66:7): [True: 10, False: 18]
  ------------------
   67|     10|    if (!buffer->Decode(&num_symbols_)) {
  ------------------
  |  Branch (67:9): [True: 0, False: 10]
  ------------------
   68|      0|      return false;
   69|      0|    }
   70|       |
   71|     10|  } else
   72|     18|#endif
   73|     18|  {
   74|     18|    if (!DecodeVarint(&num_symbols_, buffer)) {
  ------------------
  |  Branch (74:9): [True: 0, False: 18]
  ------------------
   75|      0|      return false;
   76|      0|    }
   77|     18|  }
   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|     28|  if (num_symbols_ / 64 > buffer->remaining_size()) {
  ------------------
  |  Branch (82:7): [True: 3, False: 25]
  ------------------
   83|      3|    return false;
   84|      3|  }
   85|     25|  probability_table_.resize(num_symbols_);
   86|     25|  if (num_symbols_ == 0) {
  ------------------
  |  Branch (86:7): [True: 0, False: 25]
  ------------------
   87|      0|    return true;
   88|      0|  }
   89|       |  // Decode the table.
   90|  90.3k|  for (uint32_t i = 0; i < num_symbols_; ++i) {
  ------------------
  |  Branch (90:24): [True: 90.3k, False: 15]
  ------------------
   91|  90.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|  90.3k|    if (!buffer->Decode(&prob_data)) {
  ------------------
  |  Branch (94:9): [True: 4, False: 90.3k]
  ------------------
   95|      4|      return false;
   96|      4|    }
   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|  90.3k|    const int token = prob_data & 3;
  102|  90.3k|    if (token == 3) {
  ------------------
  |  Branch (102:9): [True: 64.6k, False: 25.6k]
  ------------------
  103|  64.6k|      const uint32_t offset = prob_data >> 2;
  104|  64.6k|      if (i + offset >= num_symbols_) {
  ------------------
  |  Branch (104:11): [True: 4, False: 64.6k]
  ------------------
  105|      4|        return false;
  106|      4|      }
  107|       |      // Set zero probability for all symbols in the specified range.
  108|  3.37M|      for (uint32_t j = 0; j < offset + 1; ++j) {
  ------------------
  |  Branch (108:28): [True: 3.31M, False: 64.6k]
  ------------------
  109|  3.31M|        probability_table_[i + j] = 0;
  110|  3.31M|      }
  111|  64.6k|      i += offset;
  112|  64.6k|    } else {
  113|  25.6k|      const int extra_bytes = token;
  114|  25.6k|      uint32_t prob = prob_data >> 2;
  115|  49.6k|      for (int b = 0; b < extra_bytes; ++b) {
  ------------------
  |  Branch (115:23): [True: 23.9k, False: 25.6k]
  ------------------
  116|  23.9k|        uint8_t eb;
  117|  23.9k|        if (!buffer->Decode(&eb)) {
  ------------------
  |  Branch (117:13): [True: 2, False: 23.9k]
  ------------------
  118|      2|          return false;
  119|      2|        }
  120|       |        // Shift 8 bits for each extra byte and subtract 2 for the two first
  121|       |        // bits.
  122|  23.9k|        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
  123|  23.9k|      }
  124|  25.6k|      probability_table_[i] = prob;
  125|  25.6k|    }
  126|  90.3k|  }
  127|     15|  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) {
  ------------------
  |  Branch (127:7): [True: 3, False: 12]
  ------------------
  128|      3|    return false;
  129|      3|  }
  130|     12|  return true;
  131|     15|}
_ZNK5draco17RAnsSymbolDecoderILi18EE11num_symbolsEv:
   38|     12|  uint32_t num_symbols() const { return num_symbols_; }
_ZN5draco17RAnsSymbolDecoderILi18EE13StartDecodingEPNS_13DecoderBufferE:
  135|     12|    DecoderBuffer *buffer) {
  136|     12|  uint64_t bytes_encoded;
  137|       |  // Decode the number of bytes encoded by the encoder.
  138|     12|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  139|     12|  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     12|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (139:7): [True: 8, False: 4]
  ------------------
  140|      8|    if (!buffer->Decode(&bytes_encoded)) {
  ------------------
  |  Branch (140:9): [True: 0, False: 8]
  ------------------
  141|      0|      return false;
  142|      0|    }
  143|       |
  144|      8|  } else
  145|      4|#endif
  146|      4|  {
  147|      4|    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) {
  ------------------
  |  Branch (147:9): [True: 0, False: 4]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|      4|  }
  151|     12|  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) {
  ------------------
  |  Branch (151:7): [True: 9, False: 3]
  ------------------
  152|      9|    return false;
  153|      9|  }
  154|      3|  const uint8_t *const data_head =
  155|      3|      reinterpret_cast<const uint8_t *>(buffer->data_head());
  156|       |  // Advance the buffer past the rANS data.
  157|      3|  buffer->Advance(bytes_encoded);
  158|      3|  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) {
  ------------------
  |  Branch (158:7): [True: 2, False: 1]
  ------------------
  159|      2|    return false;
  160|      2|  }
  161|      1|  return true;
  162|      3|}
_ZN5draco17RAnsSymbolDecoderILi18EE12DecodeSymbolEv:
   43|  4.19k|  uint32_t DecodeSymbol() { return ans_.rans_read(); }
_ZN5draco17RAnsSymbolDecoderILi18EE11EndDecodingEv:
  165|      1|void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  166|      1|  ans_.read_end();
  167|      1|}

_ZN5draco13DecodeSymbolsEjiPNS_13DecoderBufferEPj:
   33|  1.48k|                   DecoderBuffer *src_buffer, uint32_t *out_values) {
   34|  1.48k|  if (num_values == 0) {
  ------------------
  |  Branch (34:7): [True: 7, False: 1.47k]
  ------------------
   35|      7|    return true;
   36|      7|  }
   37|       |  // Decode which scheme to use.
   38|  1.47k|  uint8_t scheme;
   39|  1.47k|  if (!src_buffer->Decode(&scheme)) {
  ------------------
  |  Branch (39:7): [True: 1, False: 1.47k]
  ------------------
   40|      1|    return false;
   41|      1|  }
   42|  1.47k|  if (scheme == SYMBOL_CODING_TAGGED) {
  ------------------
  |  Branch (42:7): [True: 188, False: 1.28k]
  ------------------
   43|    188|    return DecodeTaggedSymbols<RAnsSymbolDecoder>(num_values, num_components,
   44|    188|                                                  src_buffer, out_values);
   45|  1.28k|  } else if (scheme == SYMBOL_CODING_RAW) {
  ------------------
  |  Branch (45:14): [True: 833, False: 453]
  ------------------
   46|    833|    return DecodeRawSymbols<RAnsSymbolDecoder>(num_values, src_buffer,
   47|    833|                                               out_values);
   48|    833|  }
   49|    453|  return false;
   50|  1.47k|}
_ZN5draco19DecodeTaggedSymbolsINS_17RAnsSymbolDecoderEEEbjiPNS_13DecoderBufferEPj:
   54|    188|                         DecoderBuffer *src_buffer, uint32_t *out_values) {
   55|       |  // Decode the encoded data.
   56|    188|  SymbolDecoderT<5> tag_decoder;
   57|    188|  if (!tag_decoder.Create(src_buffer)) {
  ------------------
  |  Branch (57:7): [True: 151, False: 37]
  ------------------
   58|    151|    return false;
   59|    151|  }
   60|       |
   61|     37|  if (!tag_decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (61:7): [True: 22, False: 15]
  ------------------
   62|     22|    return false;
   63|     22|  }
   64|       |
   65|     15|  if (num_values > 0 && tag_decoder.num_symbols() == 0) {
  ------------------
  |  Branch (65:7): [True: 15, False: 0]
  |  Branch (65:25): [True: 8, False: 7]
  ------------------
   66|      8|    return false;  // Wrong number of symbols.
   67|      8|  }
   68|       |
   69|       |  // src_buffer now points behind the encoded tag data (to the place where the
   70|       |  // values are encoded).
   71|      7|  src_buffer->StartBitDecoding(false, nullptr);
   72|      7|  int value_id = 0;
   73|  18.5k|  for (uint32_t i = 0; i < num_values; i += num_components) {
  ------------------
  |  Branch (73:24): [True: 18.5k, False: 7]
  ------------------
   74|       |    // Decode the tag.
   75|  18.5k|    const uint32_t bit_length = tag_decoder.DecodeSymbol();
   76|       |    // Decode the actual value.
   77|  55.5k|    for (int j = 0; j < num_components; ++j) {
  ------------------
  |  Branch (77:21): [True: 37.0k, False: 18.5k]
  ------------------
   78|  37.0k|      uint32_t val;
   79|  37.0k|      if (!src_buffer->DecodeLeastSignificantBits32(bit_length, &val)) {
  ------------------
  |  Branch (79:11): [True: 0, False: 37.0k]
  ------------------
   80|      0|        return false;
   81|      0|      }
   82|  37.0k|      out_values[value_id++] = val;
   83|  37.0k|    }
   84|  18.5k|  }
   85|      7|  tag_decoder.EndDecoding();
   86|      7|  src_buffer->EndBitDecoding();
   87|      7|  return true;
   88|      7|}
_ZN5draco16DecodeRawSymbolsINS_17RAnsSymbolDecoderEEEbjPNS_13DecoderBufferEPj:
  116|    833|                      uint32_t *out_values) {
  117|    833|  uint8_t max_bit_length;
  118|    833|  if (!src_buffer->Decode(&max_bit_length)) {
  ------------------
  |  Branch (118:7): [True: 0, False: 833]
  ------------------
  119|      0|    return false;
  120|      0|  }
  121|    833|  switch (max_bit_length) {
  122|     81|    case 1:
  ------------------
  |  Branch (122:5): [True: 81, False: 752]
  ------------------
  123|     81|      return DecodeRawSymbolsInternal<SymbolDecoderT<1>>(num_values, src_buffer,
  124|     81|                                                         out_values);
  125|     71|    case 2:
  ------------------
  |  Branch (125:5): [True: 71, False: 762]
  ------------------
  126|     71|      return DecodeRawSymbolsInternal<SymbolDecoderT<2>>(num_values, src_buffer,
  127|     71|                                                         out_values);
  128|     51|    case 3:
  ------------------
  |  Branch (128:5): [True: 51, False: 782]
  ------------------
  129|     51|      return DecodeRawSymbolsInternal<SymbolDecoderT<3>>(num_values, src_buffer,
  130|     51|                                                         out_values);
  131|     71|    case 4:
  ------------------
  |  Branch (131:5): [True: 71, False: 762]
  ------------------
  132|     71|      return DecodeRawSymbolsInternal<SymbolDecoderT<4>>(num_values, src_buffer,
  133|     71|                                                         out_values);
  134|      9|    case 5:
  ------------------
  |  Branch (134:5): [True: 9, False: 824]
  ------------------
  135|      9|      return DecodeRawSymbolsInternal<SymbolDecoderT<5>>(num_values, src_buffer,
  136|      9|                                                         out_values);
  137|      9|    case 6:
  ------------------
  |  Branch (137:5): [True: 9, False: 824]
  ------------------
  138|      9|      return DecodeRawSymbolsInternal<SymbolDecoderT<6>>(num_values, src_buffer,
  139|      9|                                                         out_values);
  140|     49|    case 7:
  ------------------
  |  Branch (140:5): [True: 49, False: 784]
  ------------------
  141|     49|      return DecodeRawSymbolsInternal<SymbolDecoderT<7>>(num_values, src_buffer,
  142|     49|                                                         out_values);
  143|     36|    case 8:
  ------------------
  |  Branch (143:5): [True: 36, False: 797]
  ------------------
  144|     36|      return DecodeRawSymbolsInternal<SymbolDecoderT<8>>(num_values, src_buffer,
  145|     36|                                                         out_values);
  146|     36|    case 9:
  ------------------
  |  Branch (146:5): [True: 36, False: 797]
  ------------------
  147|     36|      return DecodeRawSymbolsInternal<SymbolDecoderT<9>>(num_values, src_buffer,
  148|     36|                                                         out_values);
  149|     29|    case 10:
  ------------------
  |  Branch (149:5): [True: 29, False: 804]
  ------------------
  150|     29|      return DecodeRawSymbolsInternal<SymbolDecoderT<10>>(
  151|     29|          num_values, src_buffer, out_values);
  152|     15|    case 11:
  ------------------
  |  Branch (152:5): [True: 15, False: 818]
  ------------------
  153|     15|      return DecodeRawSymbolsInternal<SymbolDecoderT<11>>(
  154|     15|          num_values, src_buffer, out_values);
  155|     31|    case 12:
  ------------------
  |  Branch (155:5): [True: 31, False: 802]
  ------------------
  156|     31|      return DecodeRawSymbolsInternal<SymbolDecoderT<12>>(
  157|     31|          num_values, src_buffer, out_values);
  158|     16|    case 13:
  ------------------
  |  Branch (158:5): [True: 16, False: 817]
  ------------------
  159|     16|      return DecodeRawSymbolsInternal<SymbolDecoderT<13>>(
  160|     16|          num_values, src_buffer, out_values);
  161|     49|    case 14:
  ------------------
  |  Branch (161:5): [True: 49, False: 784]
  ------------------
  162|     49|      return DecodeRawSymbolsInternal<SymbolDecoderT<14>>(
  163|     49|          num_values, src_buffer, out_values);
  164|     52|    case 15:
  ------------------
  |  Branch (164:5): [True: 52, False: 781]
  ------------------
  165|     52|      return DecodeRawSymbolsInternal<SymbolDecoderT<15>>(
  166|     52|          num_values, src_buffer, out_values);
  167|     28|    case 16:
  ------------------
  |  Branch (167:5): [True: 28, False: 805]
  ------------------
  168|     28|      return DecodeRawSymbolsInternal<SymbolDecoderT<16>>(
  169|     28|          num_values, src_buffer, out_values);
  170|     53|    case 17:
  ------------------
  |  Branch (170:5): [True: 53, False: 780]
  ------------------
  171|     53|      return DecodeRawSymbolsInternal<SymbolDecoderT<17>>(
  172|     53|          num_values, src_buffer, out_values);
  173|     28|    case 18:
  ------------------
  |  Branch (173:5): [True: 28, False: 805]
  ------------------
  174|     28|      return DecodeRawSymbolsInternal<SymbolDecoderT<18>>(
  175|     28|          num_values, src_buffer, out_values);
  176|    119|    default:
  ------------------
  |  Branch (176:5): [True: 119, False: 714]
  ------------------
  177|    119|      return false;
  178|    833|  }
  179|    833|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi1EEEEEbjPNS_13DecoderBufferEPj:
   92|     81|                              uint32_t *out_values) {
   93|     81|  SymbolDecoderT decoder;
   94|     81|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 74, False: 7]
  ------------------
   95|     74|    return false;
   96|     74|  }
   97|       |
   98|      7|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 7, False: 0]
  |  Branch (98:25): [True: 5, False: 2]
  ------------------
   99|      5|    return false;  // Wrong number of symbols.
  100|      5|  }
  101|       |
  102|      2|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 0, False: 2]
  ------------------
  103|      0|    return false;
  104|      0|  }
  105|  2.07M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 2.07M, False: 2]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  2.07M|    const uint32_t value = decoder.DecodeSymbol();
  108|  2.07M|    out_values[i] = value;
  109|  2.07M|  }
  110|      2|  decoder.EndDecoding();
  111|      2|  return true;
  112|      2|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi2EEEEEbjPNS_13DecoderBufferEPj:
   92|     71|                              uint32_t *out_values) {
   93|     71|  SymbolDecoderT decoder;
   94|     71|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 31, False: 40]
  ------------------
   95|     31|    return false;
   96|     31|  }
   97|       |
   98|     40|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 40, False: 0]
  |  Branch (98:25): [True: 0, False: 40]
  ------------------
   99|      0|    return false;  // Wrong number of symbols.
  100|      0|  }
  101|       |
  102|     40|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 7, False: 33]
  ------------------
  103|      7|    return false;
  104|      7|  }
  105|  4.71M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 4.71M, False: 33]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  4.71M|    const uint32_t value = decoder.DecodeSymbol();
  108|  4.71M|    out_values[i] = value;
  109|  4.71M|  }
  110|     33|  decoder.EndDecoding();
  111|     33|  return true;
  112|     40|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi3EEEEEbjPNS_13DecoderBufferEPj:
   92|     51|                              uint32_t *out_values) {
   93|     51|  SymbolDecoderT decoder;
   94|     51|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 28, False: 23]
  ------------------
   95|     28|    return false;
   96|     28|  }
   97|       |
   98|     23|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 23, False: 0]
  |  Branch (98:25): [True: 0, False: 23]
  ------------------
   99|      0|    return false;  // Wrong number of symbols.
  100|      0|  }
  101|       |
  102|     23|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 11, False: 12]
  ------------------
  103|     11|    return false;
  104|     11|  }
  105|   153k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 153k, False: 12]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|   153k|    const uint32_t value = decoder.DecodeSymbol();
  108|   153k|    out_values[i] = value;
  109|   153k|  }
  110|     12|  decoder.EndDecoding();
  111|     12|  return true;
  112|     23|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi4EEEEEbjPNS_13DecoderBufferEPj:
   92|     71|                              uint32_t *out_values) {
   93|     71|  SymbolDecoderT decoder;
   94|     71|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 25, False: 46]
  ------------------
   95|     25|    return false;
   96|     25|  }
   97|       |
   98|     46|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 46, False: 0]
  |  Branch (98:25): [True: 12, False: 34]
  ------------------
   99|     12|    return false;  // Wrong number of symbols.
  100|     12|  }
  101|       |
  102|     34|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 5, False: 29]
  ------------------
  103|      5|    return false;
  104|      5|  }
  105|  56.0k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 55.9k, False: 29]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  55.9k|    const uint32_t value = decoder.DecodeSymbol();
  108|  55.9k|    out_values[i] = value;
  109|  55.9k|  }
  110|     29|  decoder.EndDecoding();
  111|     29|  return true;
  112|     34|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi5EEEEEbjPNS_13DecoderBufferEPj:
   92|      9|                              uint32_t *out_values) {
   93|      9|  SymbolDecoderT decoder;
   94|      9|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 2, False: 7]
  ------------------
   95|      2|    return false;
   96|      2|  }
   97|       |
   98|      7|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 7, False: 0]
  |  Branch (98:25): [True: 0, False: 7]
  ------------------
   99|      0|    return false;  // Wrong number of symbols.
  100|      0|  }
  101|       |
  102|      7|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 4, False: 3]
  ------------------
  103|      4|    return false;
  104|      4|  }
  105|    207|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 204, False: 3]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|    204|    const uint32_t value = decoder.DecodeSymbol();
  108|    204|    out_values[i] = value;
  109|    204|  }
  110|      3|  decoder.EndDecoding();
  111|      3|  return true;
  112|      7|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi6EEEEEbjPNS_13DecoderBufferEPj:
   92|      9|                              uint32_t *out_values) {
   93|      9|  SymbolDecoderT decoder;
   94|      9|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 6, False: 3]
  ------------------
   95|      6|    return false;
   96|      6|  }
   97|       |
   98|      3|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 3, False: 0]
  |  Branch (98:25): [True: 0, False: 3]
  ------------------
   99|      0|    return false;  // Wrong number of symbols.
  100|      0|  }
  101|       |
  102|      3|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 2, False: 1]
  ------------------
  103|      2|    return false;
  104|      2|  }
  105|  1.23k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 1.23k, False: 1]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  1.23k|    const uint32_t value = decoder.DecodeSymbol();
  108|  1.23k|    out_values[i] = value;
  109|  1.23k|  }
  110|      1|  decoder.EndDecoding();
  111|      1|  return true;
  112|      3|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi7EEEEEbjPNS_13DecoderBufferEPj:
   92|     49|                              uint32_t *out_values) {
   93|     49|  SymbolDecoderT decoder;
   94|     49|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 32, False: 17]
  ------------------
   95|     32|    return false;
   96|     32|  }
   97|       |
   98|     17|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 17, False: 0]
  |  Branch (98:25): [True: 1, False: 16]
  ------------------
   99|      1|    return false;  // Wrong number of symbols.
  100|      1|  }
  101|       |
  102|     16|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 11, False: 5]
  ------------------
  103|     11|    return false;
  104|     11|  }
  105|  51.4k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 51.4k, False: 5]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  51.4k|    const uint32_t value = decoder.DecodeSymbol();
  108|  51.4k|    out_values[i] = value;
  109|  51.4k|  }
  110|      5|  decoder.EndDecoding();
  111|      5|  return true;
  112|     16|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi8EEEEEbjPNS_13DecoderBufferEPj:
   92|     36|                              uint32_t *out_values) {
   93|     36|  SymbolDecoderT decoder;
   94|     36|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 25, False: 11]
  ------------------
   95|     25|    return false;
   96|     25|  }
   97|       |
   98|     11|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 11, False: 0]
  |  Branch (98:25): [True: 0, False: 11]
  ------------------
   99|      0|    return false;  // Wrong number of symbols.
  100|      0|  }
  101|       |
  102|     11|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 3, False: 8]
  ------------------
  103|      3|    return false;
  104|      3|  }
  105|  1.24M|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 1.24M, False: 8]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  1.24M|    const uint32_t value = decoder.DecodeSymbol();
  108|  1.24M|    out_values[i] = value;
  109|  1.24M|  }
  110|      8|  decoder.EndDecoding();
  111|      8|  return true;
  112|     11|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi9EEEEEbjPNS_13DecoderBufferEPj:
   92|     36|                              uint32_t *out_values) {
   93|     36|  SymbolDecoderT decoder;
   94|     36|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 16, False: 20]
  ------------------
   95|     16|    return false;
   96|     16|  }
   97|       |
   98|     20|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 20, False: 0]
  |  Branch (98:25): [True: 0, False: 20]
  ------------------
   99|      0|    return false;  // Wrong number of symbols.
  100|      0|  }
  101|       |
  102|     20|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 3, False: 17]
  ------------------
  103|      3|    return false;
  104|      3|  }
  105|   322k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 322k, False: 17]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|   322k|    const uint32_t value = decoder.DecodeSymbol();
  108|   322k|    out_values[i] = value;
  109|   322k|  }
  110|     17|  decoder.EndDecoding();
  111|     17|  return true;
  112|     20|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi10EEEEEbjPNS_13DecoderBufferEPj:
   92|     29|                              uint32_t *out_values) {
   93|     29|  SymbolDecoderT decoder;
   94|     29|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 18, False: 11]
  ------------------
   95|     18|    return false;
   96|     18|  }
   97|       |
   98|     11|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 11, False: 0]
  |  Branch (98:25): [True: 0, False: 11]
  ------------------
   99|      0|    return false;  // Wrong number of symbols.
  100|      0|  }
  101|       |
  102|     11|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 3, False: 8]
  ------------------
  103|      3|    return false;
  104|      3|  }
  105|  1.66k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 1.65k, False: 8]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  1.65k|    const uint32_t value = decoder.DecodeSymbol();
  108|  1.65k|    out_values[i] = value;
  109|  1.65k|  }
  110|      8|  decoder.EndDecoding();
  111|      8|  return true;
  112|     11|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi11EEEEEbjPNS_13DecoderBufferEPj:
   92|     15|                              uint32_t *out_values) {
   93|     15|  SymbolDecoderT decoder;
   94|     15|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 13, False: 2]
  ------------------
   95|     13|    return false;
   96|     13|  }
   97|       |
   98|      2|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 2, False: 0]
  |  Branch (98:25): [True: 0, False: 2]
  ------------------
   99|      0|    return false;  // Wrong number of symbols.
  100|      0|  }
  101|       |
  102|      2|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 0, False: 2]
  ------------------
  103|      0|    return false;
  104|      0|  }
  105|  1.54k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 1.54k, False: 2]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  1.54k|    const uint32_t value = decoder.DecodeSymbol();
  108|  1.54k|    out_values[i] = value;
  109|  1.54k|  }
  110|      2|  decoder.EndDecoding();
  111|      2|  return true;
  112|      2|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi12EEEEEbjPNS_13DecoderBufferEPj:
   92|     31|                              uint32_t *out_values) {
   93|     31|  SymbolDecoderT decoder;
   94|     31|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 28, False: 3]
  ------------------
   95|     28|    return false;
   96|     28|  }
   97|       |
   98|      3|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 3, False: 0]
  |  Branch (98:25): [True: 0, False: 3]
  ------------------
   99|      0|    return false;  // Wrong number of symbols.
  100|      0|  }
  101|       |
  102|      3|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 1, False: 2]
  ------------------
  103|      1|    return false;
  104|      1|  }
  105|    140|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 138, False: 2]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|    138|    const uint32_t value = decoder.DecodeSymbol();
  108|    138|    out_values[i] = value;
  109|    138|  }
  110|      2|  decoder.EndDecoding();
  111|      2|  return true;
  112|      3|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi13EEEEEbjPNS_13DecoderBufferEPj:
   92|     16|                              uint32_t *out_values) {
   93|     16|  SymbolDecoderT decoder;
   94|     16|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 14, False: 2]
  ------------------
   95|     14|    return false;
   96|     14|  }
   97|       |
   98|      2|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 2, False: 0]
  |  Branch (98:25): [True: 0, False: 2]
  ------------------
   99|      0|    return false;  // Wrong number of symbols.
  100|      0|  }
  101|       |
  102|      2|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 1, False: 1]
  ------------------
  103|      1|    return false;
  104|      1|  }
  105|     62|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 61, False: 1]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|     61|    const uint32_t value = decoder.DecodeSymbol();
  108|     61|    out_values[i] = value;
  109|     61|  }
  110|      1|  decoder.EndDecoding();
  111|      1|  return true;
  112|      2|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi14EEEEEbjPNS_13DecoderBufferEPj:
   92|     49|                              uint32_t *out_values) {
   93|     49|  SymbolDecoderT decoder;
   94|     49|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 32, False: 17]
  ------------------
   95|     32|    return false;
   96|     32|  }
   97|       |
   98|     17|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 17, False: 0]
  |  Branch (98:25): [True: 0, False: 17]
  ------------------
   99|      0|    return false;  // Wrong number of symbols.
  100|      0|  }
  101|       |
  102|     17|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 17, False: 0]
  ------------------
  103|     17|    return false;
  104|     17|  }
  105|      0|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 0, False: 0]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|      0|    const uint32_t value = decoder.DecodeSymbol();
  108|      0|    out_values[i] = value;
  109|      0|  }
  110|      0|  decoder.EndDecoding();
  111|      0|  return true;
  112|     17|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi15EEEEEbjPNS_13DecoderBufferEPj:
   92|     52|                              uint32_t *out_values) {
   93|     52|  SymbolDecoderT decoder;
   94|     52|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 22, False: 30]
  ------------------
   95|     22|    return false;
   96|     22|  }
   97|       |
   98|     30|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 30, False: 0]
  |  Branch (98:25): [True: 0, False: 30]
  ------------------
   99|      0|    return false;  // Wrong number of symbols.
  100|      0|  }
  101|       |
  102|     30|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 29, False: 1]
  ------------------
  103|     29|    return false;
  104|     29|  }
  105|      3|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 2, False: 1]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|      2|    const uint32_t value = decoder.DecodeSymbol();
  108|      2|    out_values[i] = value;
  109|      2|  }
  110|      1|  decoder.EndDecoding();
  111|      1|  return true;
  112|     30|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi16EEEEEbjPNS_13DecoderBufferEPj:
   92|     28|                              uint32_t *out_values) {
   93|     28|  SymbolDecoderT decoder;
   94|     28|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 19, False: 9]
  ------------------
   95|     19|    return false;
   96|     19|  }
   97|       |
   98|      9|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 9, False: 0]
  |  Branch (98:25): [True: 0, False: 9]
  ------------------
   99|      0|    return false;  // Wrong number of symbols.
  100|      0|  }
  101|       |
  102|      9|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 9, False: 0]
  ------------------
  103|      9|    return false;
  104|      9|  }
  105|      0|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 0, False: 0]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|      0|    const uint32_t value = decoder.DecodeSymbol();
  108|      0|    out_values[i] = value;
  109|      0|  }
  110|      0|  decoder.EndDecoding();
  111|      0|  return true;
  112|      9|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi17EEEEEbjPNS_13DecoderBufferEPj:
   92|     53|                              uint32_t *out_values) {
   93|     53|  SymbolDecoderT decoder;
   94|     53|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 31, False: 22]
  ------------------
   95|     31|    return false;
   96|     31|  }
   97|       |
   98|     22|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 22, False: 0]
  |  Branch (98:25): [True: 0, False: 22]
  ------------------
   99|      0|    return false;  // Wrong number of symbols.
  100|      0|  }
  101|       |
  102|     22|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 18, False: 4]
  ------------------
  103|     18|    return false;
  104|     18|  }
  105|  14.0k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 14.0k, False: 4]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  14.0k|    const uint32_t value = decoder.DecodeSymbol();
  108|  14.0k|    out_values[i] = value;
  109|  14.0k|  }
  110|      4|  decoder.EndDecoding();
  111|      4|  return true;
  112|     22|}
_ZN5draco24DecodeRawSymbolsInternalINS_17RAnsSymbolDecoderILi18EEEEEbjPNS_13DecoderBufferEPj:
   92|     28|                              uint32_t *out_values) {
   93|     28|  SymbolDecoderT decoder;
   94|     28|  if (!decoder.Create(src_buffer)) {
  ------------------
  |  Branch (94:7): [True: 16, False: 12]
  ------------------
   95|     16|    return false;
   96|     16|  }
   97|       |
   98|     12|  if (num_values > 0 && decoder.num_symbols() == 0) {
  ------------------
  |  Branch (98:7): [True: 12, False: 0]
  |  Branch (98:25): [True: 0, False: 12]
  ------------------
   99|      0|    return false;  // Wrong number of symbols.
  100|      0|  }
  101|       |
  102|     12|  if (!decoder.StartDecoding(src_buffer)) {
  ------------------
  |  Branch (102:7): [True: 11, False: 1]
  ------------------
  103|     11|    return false;
  104|     11|  }
  105|  4.20k|  for (uint32_t i = 0; i < num_values; ++i) {
  ------------------
  |  Branch (105:24): [True: 4.19k, False: 1]
  ------------------
  106|       |    // Decode a symbol into the value.
  107|  4.19k|    const uint32_t value = decoder.DecodeSymbol();
  108|  4.19k|    out_values[i] = value;
  109|  4.19k|  }
  110|      1|  decoder.EndDecoding();
  111|      1|  return true;
  112|     12|}

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

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

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

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

_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEEC2Ev:
   54|    312|      pos_data_decoder_id_(-1) {}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE4InitEPNS_22MeshEdgebreakerDecoderE:
   58|    312|    MeshEdgebreakerDecoder *decoder) {
   59|    312|  decoder_ = decoder;
   60|    312|  return true;
   61|    312|}
_ZNK5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE23GetAttributeCornerTableEi:
   66|    206|    int att_id) const {
   67|    251|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (67:24): [True: 223, False: 28]
  ------------------
   68|    223|    const int decoder_id = attribute_data_[i].decoder_id;
   69|    223|    if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) {
  ------------------
  |  Branch (69:9): [True: 45, False: 178]
  |  Branch (69:27): [True: 0, False: 178]
  ------------------
   70|     45|      continue;
   71|     45|    }
   72|    178|    const AttributesDecoderInterface *const dec =
   73|    178|        decoder_->attributes_decoder(decoder_id);
   74|    721|    for (int j = 0; j < dec->GetNumAttributes(); ++j) {
  ------------------
  |  Branch (74:21): [True: 721, False: 0]
  ------------------
   75|    721|      if (dec->GetAttributeId(j) == att_id) {
  ------------------
  |  Branch (75:11): [True: 178, False: 543]
  ------------------
   76|    178|        if (attribute_data_[i].is_connectivity_used) {
  ------------------
  |  Branch (76:13): [True: 107, False: 71]
  ------------------
   77|    107|          return &attribute_data_[i].connectivity_data;
   78|    107|        }
   79|     71|        return nullptr;
   80|    178|      }
   81|    721|    }
   82|    178|  }
   83|     28|  return nullptr;
   84|    206|}
_ZNK5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE24GetAttributeEncodingDataEi:
   89|    206|    int att_id) const {
   90|    251|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (90:24): [True: 223, False: 28]
  ------------------
   91|    223|    const int decoder_id = attribute_data_[i].decoder_id;
   92|    223|    if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) {
  ------------------
  |  Branch (92:9): [True: 45, False: 178]
  |  Branch (92:27): [True: 0, False: 178]
  ------------------
   93|     45|      continue;
   94|     45|    }
   95|    178|    const AttributesDecoderInterface *const dec =
   96|    178|        decoder_->attributes_decoder(decoder_id);
   97|    721|    for (int j = 0; j < dec->GetNumAttributes(); ++j) {
  ------------------
  |  Branch (97:21): [True: 721, False: 0]
  ------------------
   98|    721|      if (dec->GetAttributeId(j) == att_id) {
  ------------------
  |  Branch (98:11): [True: 178, False: 543]
  ------------------
   99|    178|        return &attribute_data_[i].encoding_data;
  100|    178|      }
  101|    721|    }
  102|    178|  }
  103|     28|  return &pos_encoding_data_;
  104|    206|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE23CreateAttributesDecoderEi:
  130|    212|    int32_t att_decoder_id) {
  131|    212|  int8_t att_data_id;
  132|    212|  if (!decoder_->buffer()->Decode(&att_data_id)) {
  ------------------
  |  Branch (132:7): [True: 1, False: 211]
  ------------------
  133|      1|    return false;
  134|      1|  }
  135|    211|  uint8_t decoder_type;
  136|    211|  if (!decoder_->buffer()->Decode(&decoder_type)) {
  ------------------
  |  Branch (136:7): [True: 0, False: 211]
  ------------------
  137|      0|    return false;
  138|      0|  }
  139|       |
  140|    211|  if (att_data_id >= 0) {
  ------------------
  |  Branch (140:7): [True: 179, False: 32]
  ------------------
  141|    179|    if (att_data_id >= attribute_data_.size()) {
  ------------------
  |  Branch (141:9): [True: 18, False: 161]
  ------------------
  142|     18|      return false;  // Unexpected attribute data.
  143|     18|    }
  144|       |
  145|       |    // Ensure that the attribute data is not mapped to a different attributes
  146|       |    // decoder already.
  147|    161|    if (attribute_data_[att_data_id].decoder_id >= 0) {
  ------------------
  |  Branch (147:9): [True: 0, False: 161]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|       |
  151|    161|    attribute_data_[att_data_id].decoder_id = att_decoder_id;
  152|    161|  } else {
  153|       |    // Assign the attributes decoder to |pos_encoding_data_|.
  154|     32|    if (pos_data_decoder_id_ >= 0) {
  ------------------
  |  Branch (154:9): [True: 0, False: 32]
  ------------------
  155|      0|      return false;  // Some other decoder is already using the data. Error.
  156|      0|    }
  157|     32|    pos_data_decoder_id_ = att_decoder_id;
  158|     32|  }
  159|       |
  160|    193|  MeshTraversalMethod traversal_method = MESH_TRAVERSAL_DEPTH_FIRST;
  161|    193|  if (decoder_->bitstream_version() >= DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|    193|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (161:7): [True: 192, False: 1]
  ------------------
  162|    192|    uint8_t traversal_method_encoded;
  163|    192|    if (!decoder_->buffer()->Decode(&traversal_method_encoded)) {
  ------------------
  |  Branch (163:9): [True: 0, False: 192]
  ------------------
  164|      0|      return false;
  165|      0|    }
  166|       |    // Check that decoded traversal method is valid.
  167|    192|    if (traversal_method_encoded >= NUM_TRAVERSAL_METHODS) {
  ------------------
  |  Branch (167:9): [True: 5, False: 187]
  ------------------
  168|      5|      return false;
  169|      5|    }
  170|    187|    traversal_method =
  171|    187|        static_cast<MeshTraversalMethod>(traversal_method_encoded);
  172|    187|  }
  173|       |
  174|    188|  const Mesh *mesh = decoder_->mesh();
  175|    188|  std::unique_ptr<PointsSequencer> sequencer;
  176|       |
  177|    188|  if (decoder_type == MESH_VERTEX_ATTRIBUTE) {
  ------------------
  |  Branch (177:7): [True: 84, False: 104]
  ------------------
  178|       |    // Per-vertex attribute decoder.
  179|       |
  180|     84|    MeshAttributeIndicesEncodingData *encoding_data = nullptr;
  181|     84|    if (att_data_id < 0) {
  ------------------
  |  Branch (181:9): [True: 28, False: 56]
  ------------------
  182|     28|      encoding_data = &pos_encoding_data_;
  183|     56|    } else {
  184|     56|      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|     56|      attribute_data_[att_data_id].is_connectivity_used = false;
  188|     56|    }
  189|       |    // Defining sequencer via a traversal scheme.
  190|     84|    if (traversal_method == MESH_TRAVERSAL_PREDICTION_DEGREE) {
  ------------------
  |  Branch (190:9): [True: 9, False: 75]
  ------------------
  191|      9|      typedef MeshAttributeIndicesEncodingObserver<CornerTable> AttObserver;
  192|      9|      typedef MaxPredictionDegreeTraverser<CornerTable, AttObserver>
  193|      9|          AttTraverser;
  194|      9|      sequencer = CreateVertexTraversalSequencer<AttTraverser>(encoding_data);
  195|     75|    } else if (traversal_method == MESH_TRAVERSAL_DEPTH_FIRST) {
  ------------------
  |  Branch (195:16): [True: 75, False: 0]
  ------------------
  196|     75|      typedef MeshAttributeIndicesEncodingObserver<CornerTable> AttObserver;
  197|     75|      typedef DepthFirstTraverser<CornerTable, AttObserver> AttTraverser;
  198|     75|      sequencer = CreateVertexTraversalSequencer<AttTraverser>(encoding_data);
  199|     75|    } else {
  200|      0|      return false;  // Unsupported method
  201|      0|    }
  202|    104|  } else {
  203|    104|    if (traversal_method != MESH_TRAVERSAL_DEPTH_FIRST) {
  ------------------
  |  Branch (203:9): [True: 5, False: 99]
  ------------------
  204|      5|      return false;  // Unsupported method.
  205|      5|    }
  206|     99|    if (att_data_id < 0) {
  ------------------
  |  Branch (206:9): [True: 1, False: 98]
  ------------------
  207|      1|      return false;  // Attribute data must be specified.
  208|      1|    }
  209|       |
  210|       |    // Per-corner attribute decoder.
  211|       |
  212|     98|    typedef MeshAttributeIndicesEncodingObserver<MeshAttributeCornerTable>
  213|     98|        AttObserver;
  214|     98|    typedef DepthFirstTraverser<MeshAttributeCornerTable, AttObserver>
  215|     98|        AttTraverser;
  216|       |
  217|     98|    MeshAttributeIndicesEncodingData *const encoding_data =
  218|     98|        &attribute_data_[att_data_id].encoding_data;
  219|     98|    const MeshAttributeCornerTable *const corner_table =
  220|     98|        &attribute_data_[att_data_id].connectivity_data;
  221|       |
  222|     98|    std::unique_ptr<MeshTraversalSequencer<AttTraverser>> traversal_sequencer(
  223|     98|        new MeshTraversalSequencer<AttTraverser>(mesh, encoding_data));
  224|       |
  225|     98|    AttObserver att_observer(corner_table, mesh, traversal_sequencer.get(),
  226|     98|                             encoding_data);
  227|       |
  228|     98|    AttTraverser att_traverser;
  229|     98|    att_traverser.Init(corner_table, att_observer);
  230|       |
  231|     98|    traversal_sequencer->SetTraverser(att_traverser);
  232|     98|    sequencer = std::move(traversal_sequencer);
  233|     98|  }
  234|       |
  235|    182|  if (!sequencer) {
  ------------------
  |  Branch (235:7): [True: 0, False: 182]
  ------------------
  236|      0|    return false;
  237|      0|  }
  238|       |
  239|    182|  std::unique_ptr<SequentialAttributeDecodersController> att_controller(
  240|    182|      new SequentialAttributeDecodersController(std::move(sequencer)));
  241|       |
  242|    182|  return decoder_->SetAttributesDecoder(att_decoder_id,
  243|    182|                                        std::move(att_controller));
  244|    182|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE18DecodeConnectivityEv:
  247|    312|bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
  248|    312|  num_new_vertices_ = 0;
  249|    312|  new_to_parent_vertex_map_.clear();
  250|    312|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  251|    312|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    312|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (251:7): [True: 46, False: 266]
  ------------------
  252|     46|    uint32_t num_new_verts;
  253|     46|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     46|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (253:9): [True: 33, False: 13]
  ------------------
  254|     33|      if (!decoder_->buffer()->Decode(&num_new_verts)) {
  ------------------
  |  Branch (254:11): [True: 0, False: 33]
  ------------------
  255|      0|        return false;
  256|      0|      }
  257|     33|    } else {
  258|     13|      if (!DecodeVarint(&num_new_verts, decoder_->buffer())) {
  ------------------
  |  Branch (258:11): [True: 0, False: 13]
  ------------------
  259|      0|        return false;
  260|      0|      }
  261|     13|    }
  262|     46|    num_new_vertices_ = num_new_verts;
  263|     46|  }
  264|    312|#endif
  265|       |
  266|    312|  uint32_t num_encoded_vertices;
  267|    312|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  268|    312|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    312|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (268:7): [True: 33, False: 279]
  ------------------
  269|     33|    if (!decoder_->buffer()->Decode(&num_encoded_vertices)) {
  ------------------
  |  Branch (269:9): [True: 0, False: 33]
  ------------------
  270|      0|      return false;
  271|      0|    }
  272|       |
  273|     33|  } else
  274|    279|#endif
  275|    279|  {
  276|    279|    if (!DecodeVarint(&num_encoded_vertices, decoder_->buffer())) {
  ------------------
  |  Branch (276:9): [True: 0, False: 279]
  ------------------
  277|      0|      return false;
  278|      0|    }
  279|    279|  }
  280|    312|  num_encoded_vertices_ = num_encoded_vertices;
  281|       |
  282|    312|  uint32_t num_faces;
  283|    312|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  284|    312|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    312|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (284:7): [True: 33, False: 279]
  ------------------
  285|     33|    if (!decoder_->buffer()->Decode(&num_faces)) {
  ------------------
  |  Branch (285:9): [True: 0, False: 33]
  ------------------
  286|      0|      return false;
  287|      0|    }
  288|       |
  289|     33|  } else
  290|    279|#endif
  291|    279|  {
  292|    279|    if (!DecodeVarint(&num_faces, decoder_->buffer())) {
  ------------------
  |  Branch (292:9): [True: 0, False: 279]
  ------------------
  293|      0|      return false;
  294|      0|    }
  295|    279|  }
  296|    312|  if (num_faces > std::numeric_limits<CornerIndex::ValueType>::max() / 3) {
  ------------------
  |  Branch (296:7): [True: 0, False: 312]
  ------------------
  297|      0|    return false;  // Draco cannot handle this many faces.
  298|      0|  }
  299|       |
  300|    312|  if (static_cast<uint32_t>(num_encoded_vertices_) > num_faces * 3) {
  ------------------
  |  Branch (300:7): [True: 1, False: 311]
  ------------------
  301|      1|    return false;  // There cannot be more vertices than 3 * num_faces.
  302|      1|  }
  303|       |
  304|       |  // Minimum number of edges of the mesh assuming each edge is shared between
  305|       |  // two faces.
  306|    311|  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|    311|  const uint64_t num_encoded_vertices_64 =
  311|    311|      static_cast<uint64_t>(num_encoded_vertices_);
  312|    311|  const uint64_t max_num_vertex_edges =
  313|    311|      num_encoded_vertices_64 * (num_encoded_vertices_64 - 1) / 2;
  314|    311|  if (max_num_vertex_edges < min_num_face_edges) {
  ------------------
  |  Branch (314:7): [True: 0, False: 311]
  ------------------
  315|       |    // It is impossible to construct a manifold mesh with these properties.
  316|      0|    return false;
  317|      0|  }
  318|       |
  319|    311|  uint8_t num_attribute_data;
  320|    311|  if (!decoder_->buffer()->Decode(&num_attribute_data)) {
  ------------------
  |  Branch (320:7): [True: 0, False: 311]
  ------------------
  321|      0|    return false;
  322|      0|  }
  323|       |
  324|    311|  uint32_t num_encoded_symbols;
  325|    311|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  326|    311|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    311|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (326:7): [True: 32, False: 279]
  ------------------
  327|     32|    if (!decoder_->buffer()->Decode(&num_encoded_symbols)) {
  ------------------
  |  Branch (327:9): [True: 0, False: 32]
  ------------------
  328|      0|      return false;
  329|      0|    }
  330|       |
  331|     32|  } else
  332|    279|#endif
  333|    279|  {
  334|    279|    if (!DecodeVarint(&num_encoded_symbols, decoder_->buffer())) {
  ------------------
  |  Branch (334:9): [True: 0, False: 279]
  ------------------
  335|      0|      return false;
  336|      0|    }
  337|    279|  }
  338|       |
  339|    311|  if (num_faces < num_encoded_symbols) {
  ------------------
  |  Branch (339:7): [True: 2, False: 309]
  ------------------
  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|      2|    return false;
  344|      2|  }
  345|    309|  const uint32_t max_encoded_faces =
  346|    309|      num_encoded_symbols + (num_encoded_symbols / 3);
  347|    309|  if (num_faces > max_encoded_faces) {
  ------------------
  |  Branch (347:7): [True: 1, False: 308]
  ------------------
  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|      1|    return false;
  352|      1|  }
  353|       |
  354|    308|  uint32_t num_encoded_split_symbols;
  355|    308|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  356|    308|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    308|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (356:7): [True: 30, False: 278]
  ------------------
  357|     30|    if (!decoder_->buffer()->Decode(&num_encoded_split_symbols)) {
  ------------------
  |  Branch (357:9): [True: 0, False: 30]
  ------------------
  358|      0|      return false;
  359|      0|    }
  360|       |
  361|     30|  } else
  362|    278|#endif
  363|    278|  {
  364|    278|    if (!DecodeVarint(&num_encoded_split_symbols, decoder_->buffer())) {
  ------------------
  |  Branch (364:9): [True: 0, False: 278]
  ------------------
  365|      0|      return false;
  366|      0|    }
  367|    278|  }
  368|       |
  369|    308|  if (num_encoded_split_symbols > num_encoded_symbols) {
  ------------------
  |  Branch (369:7): [True: 1, False: 307]
  ------------------
  370|      1|    return false;  // Split symbols are a sub-set of all symbols.
  371|      1|  }
  372|       |
  373|       |  // Decode topology (connectivity).
  374|    307|  vertex_traversal_length_.clear();
  375|    307|  corner_table_ = std::unique_ptr<CornerTable>(new CornerTable());
  376|    307|  if (corner_table_ == nullptr) {
  ------------------
  |  Branch (376:7): [True: 0, False: 307]
  ------------------
  377|      0|    return false;
  378|      0|  }
  379|    307|  processed_corner_ids_.clear();
  380|    307|  processed_corner_ids_.reserve(num_faces);
  381|    307|  processed_connectivity_corners_.clear();
  382|    307|  processed_connectivity_corners_.reserve(num_faces);
  383|    307|  topology_split_data_.clear();
  384|    307|  hole_event_data_.clear();
  385|    307|  init_face_configurations_.clear();
  386|    307|  init_corners_.clear();
  387|       |
  388|    307|  last_symbol_id_ = -1;
  389|    307|  last_face_id_ = -1;
  390|    307|  last_vert_id_ = -1;
  391|       |
  392|    307|  attribute_data_.clear();
  393|       |  // Add one attribute data for each attribute decoder.
  394|    307|  attribute_data_.resize(num_attribute_data);
  395|       |
  396|    307|  if (!corner_table_->Reset(
  ------------------
  |  Branch (396:7): [True: 0, False: 307]
  ------------------
  397|    307|          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|    307|  is_vert_hole_.assign(num_encoded_vertices_ + num_encoded_split_symbols, true);
  407|       |
  408|    307|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  409|    307|  int32_t topology_split_decoded_bytes = -1;
  410|    307|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    307|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (410:7): [True: 42, False: 265]
  ------------------
  411|     42|    uint32_t encoded_connectivity_size;
  412|     42|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|     42|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (412:9): [True: 30, False: 12]
  ------------------
  413|     30|      if (!decoder_->buffer()->Decode(&encoded_connectivity_size)) {
  ------------------
  |  Branch (413:11): [True: 0, False: 30]
  ------------------
  414|      0|        return false;
  415|      0|      }
  416|     30|    } else {
  417|     12|      if (!DecodeVarint(&encoded_connectivity_size, decoder_->buffer())) {
  ------------------
  |  Branch (417:11): [True: 0, False: 12]
  ------------------
  418|      0|        return false;
  419|      0|      }
  420|     12|    }
  421|     42|    if (encoded_connectivity_size == 0 ||
  ------------------
  |  Branch (421:9): [True: 3, False: 39]
  ------------------
  422|     42|        encoded_connectivity_size > decoder_->buffer()->remaining_size()) {
  ------------------
  |  Branch (422:9): [True: 2, False: 37]
  ------------------
  423|      5|      return false;
  424|      5|    }
  425|     37|    DecoderBuffer event_buffer;
  426|     37|    event_buffer.Init(
  427|     37|        decoder_->buffer()->data_head() + encoded_connectivity_size,
  428|     37|        decoder_->buffer()->remaining_size() - encoded_connectivity_size,
  429|     37|        decoder_->buffer()->bitstream_version());
  430|       |    // Decode hole and topology split events.
  431|     37|    topology_split_decoded_bytes =
  432|     37|        DecodeHoleAndTopologySplitEvents(&event_buffer);
  433|     37|    if (topology_split_decoded_bytes == -1) {
  ------------------
  |  Branch (433:9): [True: 29, False: 8]
  ------------------
  434|     29|      return false;
  435|     29|    }
  436|       |
  437|     37|  } else
  438|    265|#endif
  439|    265|  {
  440|    265|    if (DecodeHoleAndTopologySplitEvents(decoder_->buffer()) == -1) {
  ------------------
  |  Branch (440:9): [True: 0, False: 265]
  ------------------
  441|      0|      return false;
  442|      0|    }
  443|    265|  }
  444|       |
  445|    273|  traversal_decoder_.Init(this);
  446|       |  // Add one extra vertex for each split symbol.
  447|    273|  traversal_decoder_.SetNumEncodedVertices(num_encoded_vertices_ +
  448|    273|                                           num_encoded_split_symbols);
  449|    273|  traversal_decoder_.SetNumAttributeData(num_attribute_data);
  450|       |
  451|    273|  DecoderBuffer traversal_end_buffer;
  452|    273|  if (!traversal_decoder_.Start(&traversal_end_buffer)) {
  ------------------
  |  Branch (452:7): [True: 10, False: 263]
  ------------------
  453|     10|    return false;
  454|     10|  }
  455|       |
  456|    263|  const int num_connectivity_verts = DecodeConnectivity(num_encoded_symbols);
  457|    263|  if (num_connectivity_verts == -1) {
  ------------------
  |  Branch (457:7): [True: 51, False: 212]
  ------------------
  458|     51|    return false;
  459|     51|  }
  460|       |
  461|       |  // Set the main buffer to the end of the traversal.
  462|    212|  decoder_->buffer()->Init(traversal_end_buffer.data_head(),
  463|    212|                           traversal_end_buffer.remaining_size(),
  464|    212|                           decoder_->buffer()->bitstream_version());
  465|       |
  466|    212|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  467|    212|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    212|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (467:7): [True: 3, False: 209]
  ------------------
  468|       |    // Skip topology split data that was already decoded earlier.
  469|      3|    decoder_->buffer()->Advance(topology_split_decoded_bytes);
  470|      3|  }
  471|    212|#endif
  472|       |
  473|       |  // Decode connectivity of non-position attributes.
  474|    212|  if (!attribute_data_.empty()) {
  ------------------
  |  Branch (474:7): [True: 203, False: 9]
  ------------------
  475|    203|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  476|    203|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
  ------------------
  |  |  115|    203|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (476:9): [True: 2, False: 201]
  ------------------
  477|     50|      for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
  ------------------
  |  Branch (477:31): [True: 48, False: 2]
  ------------------
  478|     48|        if (!DecodeAttributeConnectivitiesOnFaceLegacy(ci)) {
  ------------------
  |  Branch (478:13): [True: 0, False: 48]
  ------------------
  479|      0|          return false;
  480|      0|        }
  481|     48|      }
  482|       |
  483|      2|    } else
  484|    201|#endif
  485|    201|    {
  486|   135k|      for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
  ------------------
  |  Branch (486:31): [True: 135k, False: 201]
  ------------------
  487|   135k|        if (!DecodeAttributeConnectivitiesOnFace(ci)) {
  ------------------
  |  Branch (487:13): [True: 0, False: 135k]
  ------------------
  488|      0|          return false;
  489|      0|        }
  490|   135k|      }
  491|    201|    }
  492|    203|  }
  493|    212|  traversal_decoder_.Done();
  494|       |
  495|       |  // Decode attribute connectivity.
  496|       |  // Prepare data structure for decoding non-position attribute connectivity.
  497|  1.70k|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (497:24): [True: 1.49k, False: 212]
  ------------------
  498|  1.49k|    attribute_data_[i].connectivity_data.InitEmpty(corner_table_.get());
  499|       |    // Add all seams.
  500|   260k|    for (int32_t c : attribute_data_[i].attribute_seam_corners) {
  ------------------
  |  Branch (500:20): [True: 260k, False: 1.49k]
  ------------------
  501|   260k|      attribute_data_[i].connectivity_data.AddSeamEdge(CornerIndex(c));
  502|   260k|    }
  503|       |    // Recompute vertices from the newly added seam edges.
  504|  1.49k|    if (!attribute_data_[i].connectivity_data.RecomputeVertices(nullptr,
  ------------------
  |  Branch (504:9): [True: 0, False: 1.49k]
  ------------------
  505|  1.49k|                                                                nullptr)) {
  506|      0|      return false;
  507|      0|    }
  508|  1.49k|  }
  509|       |
  510|    212|  pos_encoding_data_.Init(corner_table_->num_vertices());
  511|  1.70k|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (511:24): [True: 1.49k, False: 212]
  ------------------
  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|  1.49k|    int32_t att_connectivity_verts =
  517|  1.49k|        attribute_data_[i].connectivity_data.num_vertices();
  518|  1.49k|    if (att_connectivity_verts < corner_table_->num_vertices()) {
  ------------------
  |  Branch (518:9): [True: 145, False: 1.35k]
  ------------------
  519|    145|      att_connectivity_verts = corner_table_->num_vertices();
  520|    145|    }
  521|  1.49k|    attribute_data_[i].encoding_data.Init(att_connectivity_verts);
  522|  1.49k|  }
  523|    212|  if (!AssignPointsToCorners(num_connectivity_verts)) {
  ------------------
  |  Branch (523:7): [True: 1, False: 211]
  ------------------
  524|      1|    return false;
  525|      1|  }
  526|    211|  return true;
  527|    212|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE19OnAttributesDecodedEv:
  530|     32|bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::OnAttributesDecoded() {
  531|     32|  return true;
  532|     32|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE18DecodeConnectivityEi:
  536|    263|    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|    263|  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|    263|  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|    263|  std::vector<VertexIndex> invalid_vertices;
  558|    263|  const bool remove_invalid_vertices = attribute_data_.empty();
  559|       |
  560|    263|  int max_num_vertices = static_cast<int>(is_vert_hole_.size());
  561|    263|  int num_faces = 0;
  562|  4.25M|  for (int symbol_id = 0; symbol_id < num_symbols; ++symbol_id) {
  ------------------
  |  Branch (562:27): [True: 4.25M, False: 225]
  ------------------
  563|  4.25M|    const FaceIndex face(num_faces++);
  564|       |    // Used to flag cases where we need to look for topology split events.
  565|  4.25M|    bool check_topology_split = false;
  566|  4.25M|    const uint32_t symbol = traversal_decoder_.DecodeSymbol();
  567|  4.25M|    if (symbol == TOPOLOGY_C) {
  ------------------
  |  Branch (567:9): [True: 2.04M, False: 2.21M]
  ------------------
  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|  2.04M|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (587:11): [True: 0, False: 2.04M]
  ------------------
  588|      0|        return -1;
  589|      0|      }
  590|       |
  591|  2.04M|      const CornerIndex corner_a = active_corner_stack.back();
  592|  2.04M|      const VertexIndex vertex_x =
  593|  2.04M|          corner_table_->Vertex(corner_table_->Next(corner_a));
  594|  2.04M|      const CornerIndex corner_b =
  595|  2.04M|          corner_table_->Next(corner_table_->LeftMostCorner(vertex_x));
  596|       |
  597|  2.04M|      if (corner_a == corner_b) {
  ------------------
  |  Branch (597:11): [True: 33, False: 2.04M]
  ------------------
  598|       |        // All matched corners must be different.
  599|     33|        return -1;
  600|     33|      }
  601|  2.04M|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex ||
  ------------------
  |  Branch (601:11): [True: 0, False: 2.04M]
  |  Branch (601:11): [True: 0, False: 2.04M]
  ------------------
  602|  2.04M|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex) {
  ------------------
  |  Branch (602:11): [True: 0, False: 2.04M]
  ------------------
  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|  2.04M|      const CornerIndex corner(3 * face.value());
  610|       |      // Update opposite corner mappings.
  611|  2.04M|      SetOppositeCorners(corner_a, corner + 1);
  612|  2.04M|      SetOppositeCorners(corner_b, corner + 2);
  613|       |
  614|       |      // Update vertex mapping.
  615|  2.04M|      const VertexIndex vert_a_prev =
  616|  2.04M|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  617|  2.04M|      const VertexIndex vert_b_next =
  618|  2.04M|          corner_table_->Vertex(corner_table_->Next(corner_b));
  619|  2.04M|      if (vertex_x == vert_a_prev || vertex_x == vert_b_next) {
  ------------------
  |  Branch (619:11): [True: 0, False: 2.04M]
  |  Branch (619:38): [True: 0, False: 2.04M]
  ------------------
  620|       |        // Encoding is invalid, because face vertices are degenerate.
  621|      0|        return -1;
  622|      0|      }
  623|  2.04M|      corner_table_->MapCornerToVertex(corner, vertex_x);
  624|  2.04M|      corner_table_->MapCornerToVertex(corner + 1, vert_b_next);
  625|  2.04M|      corner_table_->MapCornerToVertex(corner + 2, vert_a_prev);
  626|  2.04M|      corner_table_->SetLeftMostCorner(vert_a_prev, corner + 2);
  627|       |      // Mark the vertex |x| as interior.
  628|  2.04M|      is_vert_hole_[vertex_x.value()] = false;
  629|       |      // Update the corner on the active stack.
  630|  2.04M|      active_corner_stack.back() = corner;
  631|  2.21M|    } else if (symbol == TOPOLOGY_R || symbol == TOPOLOGY_L) {
  ------------------
  |  Branch (631:16): [True: 277k, False: 1.93M]
  |  Branch (631:40): [True: 449k, False: 1.48M]
  ------------------
  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|   727k|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (646:11): [True: 0, False: 727k]
  ------------------
  647|      0|        return -1;
  648|      0|      }
  649|   727k|      const CornerIndex corner_a = active_corner_stack.back();
  650|   727k|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex) {
  ------------------
  |  Branch (650:11): [True: 0, False: 727k]
  ------------------
  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|   727k|      const CornerIndex corner(3 * face.value());
  658|   727k|      CornerIndex opp_corner, corner_l, corner_r;
  659|   727k|      if (symbol == TOPOLOGY_R) {
  ------------------
  |  Branch (659:11): [True: 277k, False: 449k]
  ------------------
  660|       |        // "r" is the new first corner.
  661|   277k|        opp_corner = corner + 2;
  662|   277k|        corner_l = corner + 1;
  663|   277k|        corner_r = corner;
  664|   449k|      } else {
  665|       |        // "l" is the new first corner.
  666|   449k|        opp_corner = corner + 1;
  667|   449k|        corner_l = corner;
  668|   449k|        corner_r = corner + 2;
  669|   449k|      }
  670|   727k|      SetOppositeCorners(opp_corner, corner_a);
  671|       |      // Update vertex mapping.
  672|   727k|      const VertexIndex new_vert_index = corner_table_->AddNewVertex();
  673|       |
  674|   727k|      if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (674:11): [True: 0, False: 727k]
  ------------------
  675|      0|        return -1;  // Unexpected number of decoded vertices.
  676|      0|      }
  677|       |
  678|   727k|      corner_table_->MapCornerToVertex(opp_corner, new_vert_index);
  679|   727k|      corner_table_->SetLeftMostCorner(new_vert_index, opp_corner);
  680|       |
  681|   727k|      const VertexIndex vertex_r =
  682|   727k|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  683|   727k|      corner_table_->MapCornerToVertex(corner_r, vertex_r);
  684|       |      // Update left-most corner on the vertex on the |corner_r|.
  685|   727k|      corner_table_->SetLeftMostCorner(vertex_r, corner_r);
  686|       |
  687|   727k|      corner_table_->MapCornerToVertex(
  688|   727k|          corner_l, corner_table_->Vertex(corner_table_->Next(corner_a)));
  689|   727k|      active_corner_stack.back() = corner;
  690|   727k|      check_topology_split = true;
  691|  1.48M|    } else if (symbol == TOPOLOGY_S) {
  ------------------
  |  Branch (691:16): [True: 519k, False: 964k]
  ------------------
  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|   519k|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (702:11): [True: 0, False: 519k]
  ------------------
  703|      0|        return -1;
  704|      0|      }
  705|   519k|      const CornerIndex corner_b = active_corner_stack.back();
  706|   519k|      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|   519k|      const auto it = topology_split_active_corners.find(symbol_id);
  711|   519k|      if (it != topology_split_active_corners.end()) {
  ------------------
  |  Branch (711:11): [True: 2, False: 519k]
  ------------------
  712|       |        // Topology split event. Move the retrieved edge to the stack.
  713|      2|        active_corner_stack.push_back(it->second);
  714|      2|      }
  715|   519k|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (715:11): [True: 1, False: 519k]
  ------------------
  716|      1|        return -1;
  717|      1|      }
  718|   519k|      const CornerIndex corner_a = active_corner_stack.back();
  719|       |
  720|   519k|      if (corner_a == corner_b) {
  ------------------
  |  Branch (720:11): [True: 0, False: 519k]
  ------------------
  721|       |        // All matched corners must be different.
  722|      0|        return -1;
  723|      0|      }
  724|   519k|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex ||
  ------------------
  |  Branch (724:11): [True: 1, False: 519k]
  |  Branch (724:11): [True: 1, False: 519k]
  ------------------
  725|   519k|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex) {
  ------------------
  |  Branch (725:11): [True: 0, False: 519k]
  ------------------
  726|       |        // One of the corners is already opposite to an existing face, which
  727|       |        // should not happen unless the input was tampered with.
  728|      1|        return -1;
  729|      1|      }
  730|       |
  731|       |      // First corner on the new face is corner "x" from the image above.
  732|   519k|      const CornerIndex corner(3 * face.value());
  733|       |      // Update the opposite corner mapping.
  734|   519k|      SetOppositeCorners(corner_a, corner + 2);
  735|   519k|      SetOppositeCorners(corner_b, corner + 1);
  736|       |      // Update vertices. For the vertex at corner "x", use the vertex id from
  737|       |      // the corner "p".
  738|   519k|      const VertexIndex vertex_p =
  739|   519k|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  740|   519k|      corner_table_->MapCornerToVertex(corner, vertex_p);
  741|   519k|      corner_table_->MapCornerToVertex(
  742|   519k|          corner + 1, corner_table_->Vertex(corner_table_->Next(corner_a)));
  743|   519k|      const VertexIndex vert_b_prev =
  744|   519k|          corner_table_->Vertex(corner_table_->Previous(corner_b));
  745|   519k|      corner_table_->MapCornerToVertex(corner + 2, vert_b_prev);
  746|   519k|      corner_table_->SetLeftMostCorner(vert_b_prev, corner + 2);
  747|   519k|      CornerIndex corner_n = corner_table_->Next(corner_b);
  748|   519k|      const VertexIndex vertex_n = corner_table_->Vertex(corner_n);
  749|   519k|      traversal_decoder_.MergeVertices(vertex_p, vertex_n);
  750|       |      // Update the left most corner on the newly merged vertex.
  751|   519k|      corner_table_->SetLeftMostCorner(vertex_p,
  752|   519k|                                       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|   519k|      const CornerIndex first_corner = corner_n;
  757|  29.3M|      while (corner_n != kInvalidCornerIndex) {
  ------------------
  |  Branch (757:14): [True: 28.7M, False: 519k]
  ------------------
  758|  28.7M|        corner_table_->MapCornerToVertex(corner_n, vertex_p);
  759|  28.7M|        corner_n = corner_table_->SwingLeft(corner_n);
  760|  28.7M|        if (corner_n == first_corner) {
  ------------------
  |  Branch (760:13): [True: 0, False: 28.7M]
  ------------------
  761|       |          // We reached the start again which should not happen for split
  762|       |          // symbols.
  763|      0|          return -1;
  764|      0|        }
  765|  28.7M|      }
  766|       |      // Make sure the old vertex n is now mapped to an invalid corner (make it
  767|       |      // isolated).
  768|   519k|      corner_table_->MakeVertexIsolated(vertex_n);
  769|   519k|      if (remove_invalid_vertices) {
  ------------------
  |  Branch (769:11): [True: 507k, False: 12.7k]
  ------------------
  770|   507k|        invalid_vertices.push_back(vertex_n);
  771|   507k|      }
  772|   519k|      active_corner_stack.back() = corner;
  773|   964k|    } else if (symbol == TOPOLOGY_E) {
  ------------------
  |  Branch (773:16): [True: 964k, False: 0]
  ------------------
  774|   964k|      const CornerIndex corner(3 * face.value());
  775|   964k|      const VertexIndex first_vert_index = corner_table_->AddNewVertex();
  776|       |      // Create three new vertices at the corners of the new face.
  777|   964k|      corner_table_->MapCornerToVertex(corner, first_vert_index);
  778|   964k|      corner_table_->MapCornerToVertex(corner + 1,
  779|   964k|                                       corner_table_->AddNewVertex());
  780|   964k|      corner_table_->MapCornerToVertex(corner + 2,
  781|   964k|                                       corner_table_->AddNewVertex());
  782|       |
  783|   964k|      if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (783:11): [True: 1, False: 964k]
  ------------------
  784|      1|        return -1;  // Unexpected number of decoded vertices.
  785|      1|      }
  786|       |
  787|   964k|      corner_table_->SetLeftMostCorner(first_vert_index, corner);
  788|   964k|      corner_table_->SetLeftMostCorner(first_vert_index + 1, corner + 1);
  789|   964k|      corner_table_->SetLeftMostCorner(first_vert_index + 2, corner + 2);
  790|       |      // Add the tip corner to the active stack.
  791|   964k|      active_corner_stack.push_back(corner);
  792|   964k|      check_topology_split = true;
  793|   964k|    } 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|  4.25M|    traversal_decoder_.NewActiveCornerReached(active_corner_stack.back());
  799|       |
  800|  4.25M|    if (check_topology_split) {
  ------------------
  |  Branch (800:9): [True: 1.69M, False: 2.56M]
  ------------------
  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|  1.69M|      const int encoder_symbol_id = num_symbols - symbol_id - 1;
  811|  1.69M|      EdgeFaceName split_edge;
  812|  1.69M|      int encoder_split_symbol_id;
  813|  1.69M|      while (IsTopologySplit(encoder_symbol_id, &split_edge,
  ------------------
  |  Branch (813:14): [True: 103, False: 1.69M]
  ------------------
  814|  1.69M|                             &encoder_split_symbol_id)) {
  815|    103|        if (encoder_split_symbol_id < 0) {
  ------------------
  |  Branch (815:13): [True: 2, False: 101]
  ------------------
  816|      2|          return -1;  // Wrong split symbol id.
  817|      2|        }
  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|    101|        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|    101|        CornerIndex new_active_corner;
  831|    101|        if (split_edge == RIGHT_FACE_EDGE) {
  ------------------
  |  Branch (831:13): [True: 61, False: 40]
  ------------------
  832|     61|          new_active_corner = corner_table_->Next(act_top_corner);
  833|     61|        } else {
  834|     40|          new_active_corner = corner_table_->Previous(act_top_corner);
  835|     40|        }
  836|       |        // Add the new active edge.
  837|       |        // Convert the encoder split symbol id to decoder symbol id.
  838|    101|        const int decoder_split_symbol_id =
  839|    101|            num_symbols - encoder_split_symbol_id - 1;
  840|    101|        topology_split_active_corners[decoder_split_symbol_id] =
  841|    101|            new_active_corner;
  842|    101|      }
  843|  1.69M|    }
  844|  4.25M|  }
  845|    225|  if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (845:7): [True: 0, False: 225]
  ------------------
  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|  5.72k|  while (!active_corner_stack.empty()) {
  ------------------
  |  Branch (849:10): [True: 5.51k, False: 212]
  ------------------
  850|  5.51k|    const CornerIndex corner = active_corner_stack.back();
  851|  5.51k|    active_corner_stack.pop_back();
  852|  5.51k|    const bool interior_face =
  853|  5.51k|        traversal_decoder_.DecodeStartFaceConfiguration();
  854|  5.51k|    if (interior_face) {
  ------------------
  |  Branch (854:9): [True: 3.55k, False: 1.95k]
  ------------------
  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|  3.55k|      if (num_faces >= corner_table_->num_faces()) {
  ------------------
  |  Branch (876:11): [True: 0, False: 3.55k]
  ------------------
  877|      0|        return -1;  // More faces than expected added to the mesh.
  878|      0|      }
  879|       |
  880|  3.55k|      const CornerIndex corner_a = corner;
  881|  3.55k|      const VertexIndex vert_n =
  882|  3.55k|          corner_table_->Vertex(corner_table_->Next(corner_a));
  883|  3.55k|      const CornerIndex corner_b =
  884|  3.55k|          corner_table_->Next(corner_table_->LeftMostCorner(vert_n));
  885|       |
  886|  3.55k|      const VertexIndex vert_x =
  887|  3.55k|          corner_table_->Vertex(corner_table_->Next(corner_b));
  888|  3.55k|      const CornerIndex corner_c =
  889|  3.55k|          corner_table_->Next(corner_table_->LeftMostCorner(vert_x));
  890|       |
  891|  3.55k|      if (corner == corner_b || corner == corner_c || corner_b == corner_c) {
  ------------------
  |  Branch (891:11): [True: 0, False: 3.55k]
  |  Branch (891:33): [True: 13, False: 3.54k]
  |  Branch (891:55): [True: 0, False: 3.54k]
  ------------------
  892|       |        // All matched corners must be different.
  893|     13|        return -1;
  894|     13|      }
  895|  3.54k|      if (corner_table_->Opposite(corner) != kInvalidCornerIndex ||
  ------------------
  |  Branch (895:11): [True: 0, False: 3.54k]
  |  Branch (895:11): [True: 0, False: 3.54k]
  ------------------
  896|  3.54k|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex ||
  ------------------
  |  Branch (896:11): [True: 0, False: 3.54k]
  ------------------
  897|  3.54k|          corner_table_->Opposite(corner_c) != kInvalidCornerIndex) {
  ------------------
  |  Branch (897:11): [True: 0, False: 3.54k]
  ------------------
  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|  3.54k|      const VertexIndex vert_p =
  904|  3.54k|          corner_table_->Vertex(corner_table_->Next(corner_c));
  905|       |
  906|  3.54k|      const FaceIndex face(num_faces++);
  907|       |      // The first corner of the initial face is the corner opposite to "a".
  908|  3.54k|      const CornerIndex new_corner(3 * face.value());
  909|  3.54k|      SetOppositeCorners(new_corner, corner);
  910|  3.54k|      SetOppositeCorners(new_corner + 1, corner_b);
  911|  3.54k|      SetOppositeCorners(new_corner + 2, corner_c);
  912|       |
  913|       |      // Map new corners to existing vertices.
  914|  3.54k|      corner_table_->MapCornerToVertex(new_corner, vert_x);
  915|  3.54k|      corner_table_->MapCornerToVertex(new_corner + 1, vert_p);
  916|  3.54k|      corner_table_->MapCornerToVertex(new_corner + 2, vert_n);
  917|       |
  918|       |      // Mark all three vertices as interior.
  919|  14.1k|      for (int ci = 0; ci < 3; ++ci) {
  ------------------
  |  Branch (919:24): [True: 10.6k, False: 3.54k]
  ------------------
  920|  10.6k|        is_vert_hole_[corner_table_->Vertex(new_corner + ci).value()] = false;
  921|  10.6k|      }
  922|       |
  923|  3.54k|      init_face_configurations_.push_back(true);
  924|  3.54k|      init_corners_.push_back(new_corner);
  925|  3.54k|    } 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|  1.95k|      init_face_configurations_.push_back(false);
  930|  1.95k|      init_corners_.push_back(corner);
  931|  1.95k|    }
  932|  5.51k|  }
  933|    212|  if (num_faces != corner_table_->num_faces()) {
  ------------------
  |  Branch (933:7): [True: 0, False: 212]
  ------------------
  934|      0|    return -1;  // Unexpected number of decoded faces.
  935|      0|  }
  936|       |
  937|    212|  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|  8.54k|  for (const VertexIndex invalid_vert : invalid_vertices) {
  ------------------
  |  Branch (940:39): [True: 8.54k, False: 212]
  ------------------
  941|       |    // Find the last valid vertex and swap it with the isolated vertex.
  942|  8.54k|    VertexIndex src_vert(num_vertices - 1);
  943|  9.87k|    while (corner_table_->LeftMostCorner(src_vert) == kInvalidCornerIndex) {
  ------------------
  |  Branch (943:12): [True: 1.33k, False: 8.54k]
  ------------------
  944|       |      // The last vertex is invalid, proceed to the previous one.
  945|  1.33k|      src_vert = VertexIndex(--num_vertices - 1);
  946|  1.33k|    }
  947|  8.54k|    if (src_vert < invalid_vert) {
  ------------------
  |  Branch (947:9): [True: 1.33k, False: 7.21k]
  ------------------
  948|  1.33k|      continue;  // No need to swap anything.
  949|  1.33k|    }
  950|       |
  951|       |    // Remap all corners mapped to |src_vert| to |invalid_vert|.
  952|  7.21k|    VertexCornersIterator<CornerTable> vcit(corner_table_.get(), src_vert);
  953|  50.2k|    for (; !vcit.End(); ++vcit) {
  ------------------
  |  Branch (953:12): [True: 43.0k, False: 7.21k]
  ------------------
  954|  43.0k|      const CornerIndex cid = vcit.Corner();
  955|  43.0k|      if (corner_table_->Vertex(cid) != src_vert) {
  ------------------
  |  Branch (955:11): [True: 0, False: 43.0k]
  ------------------
  956|       |        // Vertex mapped to |cid| was not |src_vert|. This indicates corrupted
  957|       |        // data and we should terminate the decoding.
  958|      0|        return -1;
  959|      0|      }
  960|  43.0k|      corner_table_->MapCornerToVertex(cid, invalid_vert);
  961|  43.0k|    }
  962|  7.21k|    corner_table_->SetLeftMostCorner(invalid_vert,
  963|  7.21k|                                     corner_table_->LeftMostCorner(src_vert));
  964|       |
  965|       |    // Make the |src_vert| invalid.
  966|  7.21k|    corner_table_->MakeVertexIsolated(src_vert);
  967|  7.21k|    is_vert_hole_[invalid_vert.value()] = is_vert_hole_[src_vert.value()];
  968|  7.21k|    is_vert_hole_[src_vert.value()] = false;
  969|       |
  970|       |    // The last vertex is now invalid.
  971|  7.21k|    num_vertices--;
  972|  7.21k|  }
  973|    212|  return num_vertices;
  974|    212|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE32DecodeHoleAndTopologySplitEventsEPNS_13DecoderBufferE:
  979|    302|    DecoderBuffer *decoder_buffer) {
  980|       |  // Prepare a new decoder from the provided buffer offset.
  981|    302|  uint32_t num_topology_splits;
  982|    302|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  983|    302|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    302|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (983:7): [True: 25, False: 277]
  ------------------
  984|     25|    if (!decoder_buffer->Decode(&num_topology_splits)) {
  ------------------
  |  Branch (984:9): [True: 0, False: 25]
  ------------------
  985|      0|      return -1;
  986|      0|    }
  987|       |
  988|     25|  } else
  989|    277|#endif
  990|    277|  {
  991|    277|    if (!DecodeVarint(&num_topology_splits, decoder_buffer)) {
  ------------------
  |  Branch (991:9): [True: 0, False: 277]
  ------------------
  992|      0|      return -1;
  993|      0|    }
  994|    277|  }
  995|    302|  if (num_topology_splits > 0) {
  ------------------
  |  Branch (995:7): [True: 65, False: 237]
  ------------------
  996|     65|    if (num_topology_splits >
  ------------------
  |  Branch (996:9): [True: 1, False: 64]
  ------------------
  997|     65|        static_cast<uint32_t>(corner_table_->num_faces())) {
  998|      1|      return -1;
  999|      1|    }
 1000|     64|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1001|     64|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|     64|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1001:9): [True: 15, False: 49]
  ------------------
 1002|   151k|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1002:28): [True: 151k, False: 4]
  ------------------
 1003|   151k|        TopologySplitEventData event_data;
 1004|   151k|        if (!decoder_buffer->Decode(&event_data.split_symbol_id)) {
  ------------------
  |  Branch (1004:13): [True: 8, False: 151k]
  ------------------
 1005|      8|          return -1;
 1006|      8|        }
 1007|   151k|        if (!decoder_buffer->Decode(&event_data.source_symbol_id)) {
  ------------------
  |  Branch (1007:13): [True: 2, False: 151k]
  ------------------
 1008|      2|          return -1;
 1009|      2|        }
 1010|   151k|        uint8_t edge_data;
 1011|   151k|        if (!decoder_buffer->Decode(&edge_data)) {
  ------------------
  |  Branch (1011:13): [True: 1, False: 151k]
  ------------------
 1012|      1|          return -1;
 1013|      1|        }
 1014|   151k|        event_data.source_edge = edge_data & 1;
 1015|   151k|        topology_split_data_.push_back(event_data);
 1016|   151k|      }
 1017|       |
 1018|     15|    } else
 1019|     49|#endif
 1020|     49|    {
 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|     49|      int last_source_symbol_id = 0;
 1024|    525|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1024:28): [True: 476, False: 49]
  ------------------
 1025|    476|        TopologySplitEventData event_data;
 1026|    476|        uint32_t delta;
 1027|    476|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1027:13): [True: 0, False: 476]
  ------------------
 1028|      0|          return -1;
 1029|      0|        }
 1030|    476|        event_data.source_symbol_id = delta + last_source_symbol_id;
 1031|    476|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1031:13): [True: 0, False: 476]
  ------------------
 1032|      0|          return -1;
 1033|      0|        }
 1034|    476|        if (delta > event_data.source_symbol_id) {
  ------------------
  |  Branch (1034:13): [True: 0, False: 476]
  ------------------
 1035|      0|          return -1;
 1036|      0|        }
 1037|    476|        event_data.split_symbol_id =
 1038|    476|            event_data.source_symbol_id - static_cast<int32_t>(delta);
 1039|    476|        last_source_symbol_id = event_data.source_symbol_id;
 1040|    476|        topology_split_data_.push_back(event_data);
 1041|    476|      }
 1042|       |      // Split edges are decoded from a direct bit decoder.
 1043|     49|      decoder_buffer->StartBitDecoding(false, nullptr);
 1044|    525|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1044:28): [True: 476, False: 49]
  ------------------
 1045|    476|        uint32_t edge_data;
 1046|    476|        if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    476|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1046:13): [True: 220, False: 256]
  ------------------
 1047|    220|          decoder_buffer->DecodeLeastSignificantBits32(2, &edge_data);
 1048|    256|        } else {
 1049|    256|          decoder_buffer->DecodeLeastSignificantBits32(1, &edge_data);
 1050|    256|        }
 1051|    476|        TopologySplitEventData &event_data = topology_split_data_[i];
 1052|    476|        event_data.source_edge = edge_data & 1;
 1053|    476|      }
 1054|     49|      decoder_buffer->EndBitDecoding();
 1055|     49|    }
 1056|     64|  }
 1057|    290|  uint32_t num_hole_events = 0;
 1058|    290|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1059|    290|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    290|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1059:7): [True: 13, False: 277]
  ------------------
 1060|     13|    if (!decoder_buffer->Decode(&num_hole_events)) {
  ------------------
  |  Branch (1060:9): [True: 0, False: 13]
  ------------------
 1061|      0|      return -1;
 1062|      0|    }
 1063|    277|  } else if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
  ------------------
  |  |  115|    277|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1063:14): [True: 12, False: 265]
  ------------------
 1064|     12|    if (!DecodeVarint(&num_hole_events, decoder_buffer)) {
  ------------------
  |  Branch (1064:9): [True: 1, False: 11]
  ------------------
 1065|      1|      return -1;
 1066|      1|    }
 1067|     12|  }
 1068|    289|#endif
 1069|    289|  if (num_hole_events > 0) {
  ------------------
  |  Branch (1069:7): [True: 17, False: 272]
  ------------------
 1070|     17|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1071|     17|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|     17|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1071:9): [True: 8, False: 9]
  ------------------
 1072|  9.40k|      for (uint32_t i = 0; i < num_hole_events; ++i) {
  ------------------
  |  Branch (1072:28): [True: 9.40k, False: 1]
  ------------------
 1073|  9.40k|        HoleEventData event_data;
 1074|  9.40k|        if (!decoder_buffer->Decode(&event_data)) {
  ------------------
  |  Branch (1074:13): [True: 7, False: 9.39k]
  ------------------
 1075|      7|          return -1;
 1076|      7|        }
 1077|  9.39k|        hole_event_data_.push_back(event_data);
 1078|  9.39k|      }
 1079|       |
 1080|      8|    } else
 1081|      9|#endif
 1082|      9|    {
 1083|       |      // Decode hole symbol ids using delta and varint coding.
 1084|      9|      int last_symbol_id = 0;
 1085|   102k|      for (uint32_t i = 0; i < num_hole_events; ++i) {
  ------------------
  |  Branch (1085:28): [True: 102k, False: 0]
  ------------------
 1086|   102k|        HoleEventData event_data;
 1087|   102k|        uint32_t delta;
 1088|   102k|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1088:13): [True: 9, False: 102k]
  ------------------
 1089|      9|          return -1;
 1090|      9|        }
 1091|   102k|        event_data.symbol_id = delta + last_symbol_id;
 1092|   102k|        last_symbol_id = event_data.symbol_id;
 1093|   102k|        hole_event_data_.push_back(event_data);
 1094|   102k|      }
 1095|      9|    }
 1096|     17|  }
 1097|    273|  return static_cast<int32_t>(decoder_buffer->decoded_size());
 1098|    289|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE41DecodeAttributeConnectivitiesOnFaceLegacyENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
 1103|     48|    DecodeAttributeConnectivitiesOnFaceLegacy(CornerIndex corner) {
 1104|       |  // Three corners of the face.
 1105|     48|  const CornerIndex corners[3] = {corner, corner_table_->Next(corner),
 1106|     48|                                  corner_table_->Previous(corner)};
 1107|       |
 1108|    192|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1108:19): [True: 144, False: 48]
  ------------------
 1109|    144|    const CornerIndex opp_corner = corner_table_->Opposite(corners[c]);
 1110|    144|    if (opp_corner == kInvalidCornerIndex) {
  ------------------
  |  Branch (1110:9): [True: 8, False: 136]
  ------------------
 1111|       |      // Don't decode attribute seams on boundary edges (every boundary edge
 1112|       |      // is automatically an attribute seam).
 1113|     21|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1113:28): [True: 13, False: 8]
  ------------------
 1114|     13|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1115|     13|      }
 1116|      8|      continue;
 1117|      8|    }
 1118|       |
 1119|    408|    for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1119:26): [True: 272, False: 136]
  ------------------
 1120|    272|      const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i);
 1121|    272|      if (is_seam) {
  ------------------
  |  Branch (1121:11): [True: 116, False: 156]
  ------------------
 1122|    116|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1123|    116|      }
 1124|    272|    }
 1125|    136|  }
 1126|     48|  return true;
 1127|     48|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE35DecodeAttributeConnectivitiesOnFaceENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
 1132|   135k|    TraversalDecoder>::DecodeAttributeConnectivitiesOnFace(CornerIndex corner) {
 1133|       |  // Three corners of the face.
 1134|   135k|  const CornerIndex corners[3] = {corner, corner_table_->Next(corner),
 1135|   135k|                                  corner_table_->Previous(corner)};
 1136|       |
 1137|   135k|  const FaceIndex src_face_id = corner_table_->Face(corner);
 1138|   540k|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1138:19): [True: 405k, False: 135k]
  ------------------
 1139|   405k|    const CornerIndex opp_corner = corner_table_->Opposite(corners[c]);
 1140|   405k|    if (opp_corner == kInvalidCornerIndex) {
  ------------------
  |  Branch (1140:9): [True: 12.7k, False: 392k]
  ------------------
 1141|       |      // Don't decode attribute seams on boundary edges (every boundary edge
 1142|       |      // is automatically an attribute seam).
 1143|  59.6k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1143:28): [True: 46.8k, False: 12.7k]
  ------------------
 1144|  46.8k|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1145|  46.8k|      }
 1146|  12.7k|      continue;
 1147|  12.7k|    }
 1148|   392k|    const FaceIndex opp_face_id = corner_table_->Face(opp_corner);
 1149|       |    // Don't decode edges when the opposite face has been already processed.
 1150|   392k|    if (opp_face_id < src_face_id) {
  ------------------
  |  Branch (1150:9): [True: 196k, False: 196k]
  ------------------
 1151|   196k|      continue;
 1152|   196k|    }
 1153|       |
 1154|   607k|    for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1154:26): [True: 410k, False: 196k]
  ------------------
 1155|   410k|      const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i);
 1156|   410k|      if (is_seam) {
  ------------------
  |  Branch (1156:11): [True: 213k, False: 197k]
  ------------------
 1157|   213k|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1158|   213k|      }
 1159|   410k|    }
 1160|   196k|  }
 1161|   135k|  return true;
 1162|   135k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE21AssignPointsToCornersEi:
 1166|    212|    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|    212|  decoder_->mesh()->SetNumFaces(corner_table_->num_faces());
 1171|       |
 1172|    212|  if (attribute_data_.empty()) {
  ------------------
  |  Branch (1172:7): [True: 9, False: 203]
  ------------------
 1173|       |    // We have connectivity for position only. In this case all vertex indices
 1174|       |    // are equal to point indices.
 1175|  73.8k|    for (FaceIndex f(0); f < decoder_->mesh()->num_faces(); ++f) {
  ------------------
  |  Branch (1175:26): [True: 73.8k, False: 9]
  ------------------
 1176|  73.8k|      Mesh::Face face;
 1177|  73.8k|      const CornerIndex start_corner(3 * f.value());
 1178|   295k|      for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1178:23): [True: 221k, False: 73.8k]
  ------------------
 1179|       |        // Get the vertex index on the corner and use it as a point index.
 1180|   221k|        const int32_t vert_id = corner_table_->Vertex(start_corner + c).value();
 1181|   221k|        face[c] = vert_id;
 1182|   221k|      }
 1183|  73.8k|      decoder_->mesh()->SetFace(f, face);
 1184|  73.8k|    }
 1185|      9|    decoder_->point_cloud()->set_num_points(num_connectivity_verts);
 1186|      9|    return true;
 1187|      9|  }
 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|    203|  std::vector<int32_t> point_to_corner_map;
 1194|       |  // Map between every corner and their new point ids.
 1195|    203|  std::vector<int32_t> corner_to_point_map(corner_table_->num_corners());
 1196|  87.2k|  for (int v = 0; v < corner_table_->num_vertices(); ++v) {
  ------------------
  |  Branch (1196:19): [True: 87.0k, False: 202]
  ------------------
 1197|  87.0k|    CornerIndex c = corner_table_->LeftMostCorner(VertexIndex(v));
 1198|  87.0k|    if (c == kInvalidCornerIndex) {
  ------------------
  |  Branch (1198:9): [True: 12.0k, False: 75.0k]
  ------------------
 1199|  12.0k|      continue;  // Isolated vertex.
 1200|  12.0k|    }
 1201|  75.0k|    CornerIndex deduplication_first_corner = c;
 1202|  75.0k|    if (is_vert_hole_[v]) {
  ------------------
  |  Branch (1202:9): [True: 12.7k, False: 62.2k]
  ------------------
 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|  12.7k|      deduplication_first_corner = c;
 1206|  62.2k|    } else {
 1207|       |      // If we are not on the boundary we need to find the first seam (of any
 1208|       |      // attribute).
 1209|   124k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1209:28): [True: 114k, False: 10.5k]
  ------------------
 1210|   114k|        if (!attribute_data_[i].connectivity_data.IsCornerOnSeam(c)) {
  ------------------
  |  Branch (1210:13): [True: 57.6k, False: 56.6k]
  ------------------
 1211|  57.6k|          continue;  // No seam for this attribute, ignore it.
 1212|  57.6k|        }
 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|  56.6k|        const VertexIndex vert_id =
 1217|  56.6k|            attribute_data_[i].connectivity_data.Vertex(c);
 1218|  56.6k|        CornerIndex act_c = corner_table_->SwingRight(c);
 1219|  56.6k|        bool seam_found = false;
 1220|  91.2k|        while (act_c != c) {
  ------------------
  |  Branch (1220:16): [True: 86.2k, False: 5.00k]
  ------------------
 1221|  86.2k|          if (act_c == kInvalidCornerIndex) {
  ------------------
  |  Branch (1221:15): [True: 1, False: 86.2k]
  ------------------
 1222|      1|            return false;
 1223|      1|          }
 1224|  86.2k|          if (attribute_data_[i].connectivity_data.Vertex(act_c) != vert_id) {
  ------------------
  |  Branch (1224:15): [True: 51.6k, False: 34.5k]
  ------------------
 1225|       |            // Attribute seam found. Stop.
 1226|  51.6k|            deduplication_first_corner = act_c;
 1227|  51.6k|            seam_found = true;
 1228|  51.6k|            break;
 1229|  51.6k|          }
 1230|  34.5k|          act_c = corner_table_->SwingRight(act_c);
 1231|  34.5k|        }
 1232|  56.6k|        if (seam_found) {
  ------------------
  |  Branch (1232:13): [True: 51.6k, False: 5.00k]
  ------------------
 1233|  51.6k|          break;  // No reason to process other attributes if we found a seam.
 1234|  51.6k|        }
 1235|  56.6k|      }
 1236|  62.2k|    }
 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|  75.0k|    c = deduplication_first_corner;
 1244|       |    // Create a new point.
 1245|  75.0k|    corner_to_point_map[c.value()] =
 1246|  75.0k|        static_cast<uint32_t>(point_to_corner_map.size());
 1247|  75.0k|    point_to_corner_map.push_back(c.value());
 1248|       |    // Traverse in CW direction.
 1249|  75.0k|    CornerIndex prev_c = c;
 1250|  75.0k|    c = corner_table_->SwingRight(c);
 1251|   405k|    while (c != kInvalidCornerIndex && c != deduplication_first_corner) {
  ------------------
  |  Branch (1251:12): [True: 392k, False: 12.8k]
  |  Branch (1251:40): [True: 330k, False: 62.1k]
  ------------------
 1252|   330k|      bool attribute_seam = false;
 1253|   655k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1253:28): [True: 599k, False: 55.0k]
  ------------------
 1254|   599k|        if (attribute_data_[i].connectivity_data.Vertex(c) !=
  ------------------
  |  Branch (1254:13): [True: 274k, False: 325k]
  ------------------
 1255|   599k|            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|   274k|          attribute_seam = true;
 1259|   274k|          break;
 1260|   274k|        }
 1261|   599k|      }
 1262|   330k|      if (attribute_seam) {
  ------------------
  |  Branch (1262:11): [True: 274k, False: 55.0k]
  ------------------
 1263|   274k|        corner_to_point_map[c.value()] =
 1264|   274k|            static_cast<uint32_t>(point_to_corner_map.size());
 1265|   274k|        point_to_corner_map.push_back(c.value());
 1266|   274k|      } else {
 1267|  55.0k|        corner_to_point_map[c.value()] = corner_to_point_map[prev_c.value()];
 1268|  55.0k|      }
 1269|   330k|      prev_c = c;
 1270|   330k|      c = corner_table_->SwingRight(c);
 1271|   330k|    }
 1272|  75.0k|  }
 1273|       |  // Add faces.
 1274|   135k|  for (FaceIndex f(0); f < decoder_->mesh()->num_faces(); ++f) {
  ------------------
  |  Branch (1274:24): [True: 134k, False: 202]
  ------------------
 1275|   134k|    Mesh::Face face;
 1276|   539k|    for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1276:21): [True: 404k, False: 134k]
  ------------------
 1277|       |      // Remap old points to the new ones.
 1278|   404k|      face[c] = corner_to_point_map[3 * f.value() + c];
 1279|   404k|    }
 1280|   134k|    decoder_->mesh()->SetFace(f, face);
 1281|   134k|  }
 1282|    202|  decoder_->point_cloud()->set_num_points(
 1283|    202|      static_cast<uint32_t>(point_to_corner_map.size()));
 1284|    202|  return true;
 1285|    203|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEEC2Ev:
   54|    187|      pos_data_decoder_id_(-1) {}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE4InitEPNS_22MeshEdgebreakerDecoderE:
   58|    187|    MeshEdgebreakerDecoder *decoder) {
   59|    187|  decoder_ = decoder;
   60|    187|  return true;
   61|    187|}
_ZNK5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE23GetAttributeCornerTableEi:
   66|    188|    int att_id) const {
   67|    241|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (67:24): [True: 178, False: 63]
  ------------------
   68|    178|    const int decoder_id = attribute_data_[i].decoder_id;
   69|    178|    if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) {
  ------------------
  |  Branch (69:9): [True: 51, False: 127]
  |  Branch (69:27): [True: 0, False: 127]
  ------------------
   70|     51|      continue;
   71|     51|    }
   72|    127|    const AttributesDecoderInterface *const dec =
   73|    127|        decoder_->attributes_decoder(decoder_id);
   74|    251|    for (int j = 0; j < dec->GetNumAttributes(); ++j) {
  ------------------
  |  Branch (74:21): [True: 249, False: 2]
  ------------------
   75|    249|      if (dec->GetAttributeId(j) == att_id) {
  ------------------
  |  Branch (75:11): [True: 125, False: 124]
  ------------------
   76|    125|        if (attribute_data_[i].is_connectivity_used) {
  ------------------
  |  Branch (76:13): [True: 89, False: 36]
  ------------------
   77|     89|          return &attribute_data_[i].connectivity_data;
   78|     89|        }
   79|     36|        return nullptr;
   80|    125|      }
   81|    249|    }
   82|    127|  }
   83|     63|  return nullptr;
   84|    188|}
_ZNK5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE24GetAttributeEncodingDataEi:
   89|    188|    int att_id) const {
   90|    241|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (90:24): [True: 178, False: 63]
  ------------------
   91|    178|    const int decoder_id = attribute_data_[i].decoder_id;
   92|    178|    if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) {
  ------------------
  |  Branch (92:9): [True: 51, False: 127]
  |  Branch (92:27): [True: 0, False: 127]
  ------------------
   93|     51|      continue;
   94|     51|    }
   95|    127|    const AttributesDecoderInterface *const dec =
   96|    127|        decoder_->attributes_decoder(decoder_id);
   97|    251|    for (int j = 0; j < dec->GetNumAttributes(); ++j) {
  ------------------
  |  Branch (97:21): [True: 249, False: 2]
  ------------------
   98|    249|      if (dec->GetAttributeId(j) == att_id) {
  ------------------
  |  Branch (98:11): [True: 125, False: 124]
  ------------------
   99|    125|        return &attribute_data_[i].encoding_data;
  100|    125|      }
  101|    249|    }
  102|    127|  }
  103|     63|  return &pos_encoding_data_;
  104|    188|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE23CreateAttributesDecoderEi:
  130|    129|    int32_t att_decoder_id) {
  131|    129|  int8_t att_data_id;
  132|    129|  if (!decoder_->buffer()->Decode(&att_data_id)) {
  ------------------
  |  Branch (132:7): [True: 0, False: 129]
  ------------------
  133|      0|    return false;
  134|      0|  }
  135|    129|  uint8_t decoder_type;
  136|    129|  if (!decoder_->buffer()->Decode(&decoder_type)) {
  ------------------
  |  Branch (136:7): [True: 0, False: 129]
  ------------------
  137|      0|    return false;
  138|      0|  }
  139|       |
  140|    129|  if (att_data_id >= 0) {
  ------------------
  |  Branch (140:7): [True: 92, False: 37]
  ------------------
  141|     92|    if (att_data_id >= attribute_data_.size()) {
  ------------------
  |  Branch (141:9): [True: 0, False: 92]
  ------------------
  142|      0|      return false;  // Unexpected attribute data.
  143|      0|    }
  144|       |
  145|       |    // Ensure that the attribute data is not mapped to a different attributes
  146|       |    // decoder already.
  147|     92|    if (attribute_data_[att_data_id].decoder_id >= 0) {
  ------------------
  |  Branch (147:9): [True: 1, False: 91]
  ------------------
  148|      1|      return false;
  149|      1|    }
  150|       |
  151|     91|    attribute_data_[att_data_id].decoder_id = att_decoder_id;
  152|     91|  } else {
  153|       |    // Assign the attributes decoder to |pos_encoding_data_|.
  154|     37|    if (pos_data_decoder_id_ >= 0) {
  ------------------
  |  Branch (154:9): [True: 0, False: 37]
  ------------------
  155|      0|      return false;  // Some other decoder is already using the data. Error.
  156|      0|    }
  157|     37|    pos_data_decoder_id_ = att_decoder_id;
  158|     37|  }
  159|       |
  160|    128|  MeshTraversalMethod traversal_method = MESH_TRAVERSAL_DEPTH_FIRST;
  161|    128|  if (decoder_->bitstream_version() >= DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|    128|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (161:7): [True: 128, False: 0]
  ------------------
  162|    128|    uint8_t traversal_method_encoded;
  163|    128|    if (!decoder_->buffer()->Decode(&traversal_method_encoded)) {
  ------------------
  |  Branch (163:9): [True: 0, False: 128]
  ------------------
  164|      0|      return false;
  165|      0|    }
  166|       |    // Check that decoded traversal method is valid.
  167|    128|    if (traversal_method_encoded >= NUM_TRAVERSAL_METHODS) {
  ------------------
  |  Branch (167:9): [True: 2, False: 126]
  ------------------
  168|      2|      return false;
  169|      2|    }
  170|    126|    traversal_method =
  171|    126|        static_cast<MeshTraversalMethod>(traversal_method_encoded);
  172|    126|  }
  173|       |
  174|    126|  const Mesh *mesh = decoder_->mesh();
  175|    126|  std::unique_ptr<PointsSequencer> sequencer;
  176|       |
  177|    126|  if (decoder_type == MESH_VERTEX_ATTRIBUTE) {
  ------------------
  |  Branch (177:7): [True: 58, False: 68]
  ------------------
  178|       |    // Per-vertex attribute decoder.
  179|       |
  180|     58|    MeshAttributeIndicesEncodingData *encoding_data = nullptr;
  181|     58|    if (att_data_id < 0) {
  ------------------
  |  Branch (181:9): [True: 36, False: 22]
  ------------------
  182|     36|      encoding_data = &pos_encoding_data_;
  183|     36|    } else {
  184|     22|      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|     22|      attribute_data_[att_data_id].is_connectivity_used = false;
  188|     22|    }
  189|       |    // Defining sequencer via a traversal scheme.
  190|     58|    if (traversal_method == MESH_TRAVERSAL_PREDICTION_DEGREE) {
  ------------------
  |  Branch (190:9): [True: 6, False: 52]
  ------------------
  191|      6|      typedef MeshAttributeIndicesEncodingObserver<CornerTable> AttObserver;
  192|      6|      typedef MaxPredictionDegreeTraverser<CornerTable, AttObserver>
  193|      6|          AttTraverser;
  194|      6|      sequencer = CreateVertexTraversalSequencer<AttTraverser>(encoding_data);
  195|     52|    } else if (traversal_method == MESH_TRAVERSAL_DEPTH_FIRST) {
  ------------------
  |  Branch (195:16): [True: 52, False: 0]
  ------------------
  196|     52|      typedef MeshAttributeIndicesEncodingObserver<CornerTable> AttObserver;
  197|     52|      typedef DepthFirstTraverser<CornerTable, AttObserver> AttTraverser;
  198|     52|      sequencer = CreateVertexTraversalSequencer<AttTraverser>(encoding_data);
  199|     52|    } else {
  200|      0|      return false;  // Unsupported method
  201|      0|    }
  202|     68|  } else {
  203|     68|    if (traversal_method != MESH_TRAVERSAL_DEPTH_FIRST) {
  ------------------
  |  Branch (203:9): [True: 0, False: 68]
  ------------------
  204|      0|      return false;  // Unsupported method.
  205|      0|    }
  206|     68|    if (att_data_id < 0) {
  ------------------
  |  Branch (206:9): [True: 0, False: 68]
  ------------------
  207|      0|      return false;  // Attribute data must be specified.
  208|      0|    }
  209|       |
  210|       |    // Per-corner attribute decoder.
  211|       |
  212|     68|    typedef MeshAttributeIndicesEncodingObserver<MeshAttributeCornerTable>
  213|     68|        AttObserver;
  214|     68|    typedef DepthFirstTraverser<MeshAttributeCornerTable, AttObserver>
  215|     68|        AttTraverser;
  216|       |
  217|     68|    MeshAttributeIndicesEncodingData *const encoding_data =
  218|     68|        &attribute_data_[att_data_id].encoding_data;
  219|     68|    const MeshAttributeCornerTable *const corner_table =
  220|     68|        &attribute_data_[att_data_id].connectivity_data;
  221|       |
  222|     68|    std::unique_ptr<MeshTraversalSequencer<AttTraverser>> traversal_sequencer(
  223|     68|        new MeshTraversalSequencer<AttTraverser>(mesh, encoding_data));
  224|       |
  225|     68|    AttObserver att_observer(corner_table, mesh, traversal_sequencer.get(),
  226|     68|                             encoding_data);
  227|       |
  228|     68|    AttTraverser att_traverser;
  229|     68|    att_traverser.Init(corner_table, att_observer);
  230|       |
  231|     68|    traversal_sequencer->SetTraverser(att_traverser);
  232|     68|    sequencer = std::move(traversal_sequencer);
  233|     68|  }
  234|       |
  235|    126|  if (!sequencer) {
  ------------------
  |  Branch (235:7): [True: 0, False: 126]
  ------------------
  236|      0|    return false;
  237|      0|  }
  238|       |
  239|    126|  std::unique_ptr<SequentialAttributeDecodersController> att_controller(
  240|    126|      new SequentialAttributeDecodersController(std::move(sequencer)));
  241|       |
  242|    126|  return decoder_->SetAttributesDecoder(att_decoder_id,
  243|    126|                                        std::move(att_controller));
  244|    126|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE18DecodeConnectivityEv:
  247|    187|bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
  248|    187|  num_new_vertices_ = 0;
  249|    187|  new_to_parent_vertex_map_.clear();
  250|    187|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  251|    187|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    187|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (251:7): [True: 163, False: 24]
  ------------------
  252|    163|    uint32_t num_new_verts;
  253|    163|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    163|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (253:9): [True: 38, False: 125]
  ------------------
  254|     38|      if (!decoder_->buffer()->Decode(&num_new_verts)) {
  ------------------
  |  Branch (254:11): [True: 0, False: 38]
  ------------------
  255|      0|        return false;
  256|      0|      }
  257|    125|    } else {
  258|    125|      if (!DecodeVarint(&num_new_verts, decoder_->buffer())) {
  ------------------
  |  Branch (258:11): [True: 0, False: 125]
  ------------------
  259|      0|        return false;
  260|      0|      }
  261|    125|    }
  262|    163|    num_new_vertices_ = num_new_verts;
  263|    163|  }
  264|    187|#endif
  265|       |
  266|    187|  uint32_t num_encoded_vertices;
  267|    187|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  268|    187|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    187|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (268:7): [True: 38, False: 149]
  ------------------
  269|     38|    if (!decoder_->buffer()->Decode(&num_encoded_vertices)) {
  ------------------
  |  Branch (269:9): [True: 0, False: 38]
  ------------------
  270|      0|      return false;
  271|      0|    }
  272|       |
  273|     38|  } else
  274|    149|#endif
  275|    149|  {
  276|    149|    if (!DecodeVarint(&num_encoded_vertices, decoder_->buffer())) {
  ------------------
  |  Branch (276:9): [True: 0, False: 149]
  ------------------
  277|      0|      return false;
  278|      0|    }
  279|    149|  }
  280|    187|  num_encoded_vertices_ = num_encoded_vertices;
  281|       |
  282|    187|  uint32_t num_faces;
  283|    187|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  284|    187|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    187|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (284:7): [True: 38, False: 149]
  ------------------
  285|     38|    if (!decoder_->buffer()->Decode(&num_faces)) {
  ------------------
  |  Branch (285:9): [True: 0, False: 38]
  ------------------
  286|      0|      return false;
  287|      0|    }
  288|       |
  289|     38|  } else
  290|    149|#endif
  291|    149|  {
  292|    149|    if (!DecodeVarint(&num_faces, decoder_->buffer())) {
  ------------------
  |  Branch (292:9): [True: 0, False: 149]
  ------------------
  293|      0|      return false;
  294|      0|    }
  295|    149|  }
  296|    187|  if (num_faces > std::numeric_limits<CornerIndex::ValueType>::max() / 3) {
  ------------------
  |  Branch (296:7): [True: 0, False: 187]
  ------------------
  297|      0|    return false;  // Draco cannot handle this many faces.
  298|      0|  }
  299|       |
  300|    187|  if (static_cast<uint32_t>(num_encoded_vertices_) > num_faces * 3) {
  ------------------
  |  Branch (300:7): [True: 0, False: 187]
  ------------------
  301|      0|    return false;  // There cannot be more vertices than 3 * num_faces.
  302|      0|  }
  303|       |
  304|       |  // Minimum number of edges of the mesh assuming each edge is shared between
  305|       |  // two faces.
  306|    187|  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|    187|  const uint64_t num_encoded_vertices_64 =
  311|    187|      static_cast<uint64_t>(num_encoded_vertices_);
  312|    187|  const uint64_t max_num_vertex_edges =
  313|    187|      num_encoded_vertices_64 * (num_encoded_vertices_64 - 1) / 2;
  314|    187|  if (max_num_vertex_edges < min_num_face_edges) {
  ------------------
  |  Branch (314:7): [True: 0, False: 187]
  ------------------
  315|       |    // It is impossible to construct a manifold mesh with these properties.
  316|      0|    return false;
  317|      0|  }
  318|       |
  319|    187|  uint8_t num_attribute_data;
  320|    187|  if (!decoder_->buffer()->Decode(&num_attribute_data)) {
  ------------------
  |  Branch (320:7): [True: 0, False: 187]
  ------------------
  321|      0|    return false;
  322|      0|  }
  323|       |
  324|    187|  uint32_t num_encoded_symbols;
  325|    187|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  326|    187|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    187|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (326:7): [True: 38, False: 149]
  ------------------
  327|     38|    if (!decoder_->buffer()->Decode(&num_encoded_symbols)) {
  ------------------
  |  Branch (327:9): [True: 0, False: 38]
  ------------------
  328|      0|      return false;
  329|      0|    }
  330|       |
  331|     38|  } else
  332|    149|#endif
  333|    149|  {
  334|    149|    if (!DecodeVarint(&num_encoded_symbols, decoder_->buffer())) {
  ------------------
  |  Branch (334:9): [True: 0, False: 149]
  ------------------
  335|      0|      return false;
  336|      0|    }
  337|    149|  }
  338|       |
  339|    187|  if (num_faces < num_encoded_symbols) {
  ------------------
  |  Branch (339:7): [True: 2, False: 185]
  ------------------
  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|      2|    return false;
  344|      2|  }
  345|    185|  const uint32_t max_encoded_faces =
  346|    185|      num_encoded_symbols + (num_encoded_symbols / 3);
  347|    185|  if (num_faces > max_encoded_faces) {
  ------------------
  |  Branch (347:7): [True: 1, False: 184]
  ------------------
  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|      1|    return false;
  352|      1|  }
  353|       |
  354|    184|  uint32_t num_encoded_split_symbols;
  355|    184|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  356|    184|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    184|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (356:7): [True: 35, False: 149]
  ------------------
  357|     35|    if (!decoder_->buffer()->Decode(&num_encoded_split_symbols)) {
  ------------------
  |  Branch (357:9): [True: 0, False: 35]
  ------------------
  358|      0|      return false;
  359|      0|    }
  360|       |
  361|     35|  } else
  362|    149|#endif
  363|    149|  {
  364|    149|    if (!DecodeVarint(&num_encoded_split_symbols, decoder_->buffer())) {
  ------------------
  |  Branch (364:9): [True: 0, False: 149]
  ------------------
  365|      0|      return false;
  366|      0|    }
  367|    149|  }
  368|       |
  369|    184|  if (num_encoded_split_symbols > num_encoded_symbols) {
  ------------------
  |  Branch (369:7): [True: 3, False: 181]
  ------------------
  370|      3|    return false;  // Split symbols are a sub-set of all symbols.
  371|      3|  }
  372|       |
  373|       |  // Decode topology (connectivity).
  374|    181|  vertex_traversal_length_.clear();
  375|    181|  corner_table_ = std::unique_ptr<CornerTable>(new CornerTable());
  376|    181|  if (corner_table_ == nullptr) {
  ------------------
  |  Branch (376:7): [True: 0, False: 181]
  ------------------
  377|      0|    return false;
  378|      0|  }
  379|    181|  processed_corner_ids_.clear();
  380|    181|  processed_corner_ids_.reserve(num_faces);
  381|    181|  processed_connectivity_corners_.clear();
  382|    181|  processed_connectivity_corners_.reserve(num_faces);
  383|    181|  topology_split_data_.clear();
  384|    181|  hole_event_data_.clear();
  385|    181|  init_face_configurations_.clear();
  386|    181|  init_corners_.clear();
  387|       |
  388|    181|  last_symbol_id_ = -1;
  389|    181|  last_face_id_ = -1;
  390|    181|  last_vert_id_ = -1;
  391|       |
  392|    181|  attribute_data_.clear();
  393|       |  // Add one attribute data for each attribute decoder.
  394|    181|  attribute_data_.resize(num_attribute_data);
  395|       |
  396|    181|  if (!corner_table_->Reset(
  ------------------
  |  Branch (396:7): [True: 0, False: 181]
  ------------------
  397|    181|          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|    181|  is_vert_hole_.assign(num_encoded_vertices_ + num_encoded_split_symbols, true);
  407|       |
  408|    181|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  409|    181|  int32_t topology_split_decoded_bytes = -1;
  410|    181|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    181|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (410:7): [True: 158, False: 23]
  ------------------
  411|    158|    uint32_t encoded_connectivity_size;
  412|    158|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    158|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (412:9): [True: 33, False: 125]
  ------------------
  413|     33|      if (!decoder_->buffer()->Decode(&encoded_connectivity_size)) {
  ------------------
  |  Branch (413:11): [True: 0, False: 33]
  ------------------
  414|      0|        return false;
  415|      0|      }
  416|    125|    } else {
  417|    125|      if (!DecodeVarint(&encoded_connectivity_size, decoder_->buffer())) {
  ------------------
  |  Branch (417:11): [True: 0, False: 125]
  ------------------
  418|      0|        return false;
  419|      0|      }
  420|    125|    }
  421|    158|    if (encoded_connectivity_size == 0 ||
  ------------------
  |  Branch (421:9): [True: 0, False: 158]
  ------------------
  422|    158|        encoded_connectivity_size > decoder_->buffer()->remaining_size()) {
  ------------------
  |  Branch (422:9): [True: 3, False: 155]
  ------------------
  423|      3|      return false;
  424|      3|    }
  425|    155|    DecoderBuffer event_buffer;
  426|    155|    event_buffer.Init(
  427|    155|        decoder_->buffer()->data_head() + encoded_connectivity_size,
  428|    155|        decoder_->buffer()->remaining_size() - encoded_connectivity_size,
  429|    155|        decoder_->buffer()->bitstream_version());
  430|       |    // Decode hole and topology split events.
  431|    155|    topology_split_decoded_bytes =
  432|    155|        DecodeHoleAndTopologySplitEvents(&event_buffer);
  433|    155|    if (topology_split_decoded_bytes == -1) {
  ------------------
  |  Branch (433:9): [True: 28, False: 127]
  ------------------
  434|     28|      return false;
  435|     28|    }
  436|       |
  437|    155|  } else
  438|     23|#endif
  439|     23|  {
  440|     23|    if (DecodeHoleAndTopologySplitEvents(decoder_->buffer()) == -1) {
  ------------------
  |  Branch (440:9): [True: 1, False: 22]
  ------------------
  441|      1|      return false;
  442|      1|    }
  443|     23|  }
  444|       |
  445|    149|  traversal_decoder_.Init(this);
  446|       |  // Add one extra vertex for each split symbol.
  447|    149|  traversal_decoder_.SetNumEncodedVertices(num_encoded_vertices_ +
  448|    149|                                           num_encoded_split_symbols);
  449|    149|  traversal_decoder_.SetNumAttributeData(num_attribute_data);
  450|       |
  451|    149|  DecoderBuffer traversal_end_buffer;
  452|    149|  if (!traversal_decoder_.Start(&traversal_end_buffer)) {
  ------------------
  |  Branch (452:7): [True: 10, False: 139]
  ------------------
  453|     10|    return false;
  454|     10|  }
  455|       |
  456|    139|  const int num_connectivity_verts = DecodeConnectivity(num_encoded_symbols);
  457|    139|  if (num_connectivity_verts == -1) {
  ------------------
  |  Branch (457:7): [True: 9, False: 130]
  ------------------
  458|      9|    return false;
  459|      9|  }
  460|       |
  461|       |  // Set the main buffer to the end of the traversal.
  462|    130|  decoder_->buffer()->Init(traversal_end_buffer.data_head(),
  463|    130|                           traversal_end_buffer.remaining_size(),
  464|    130|                           decoder_->buffer()->bitstream_version());
  465|       |
  466|    130|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  467|    130|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    130|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (467:7): [True: 112, False: 18]
  ------------------
  468|       |    // Skip topology split data that was already decoded earlier.
  469|    112|    decoder_->buffer()->Advance(topology_split_decoded_bytes);
  470|    112|  }
  471|    130|#endif
  472|       |
  473|       |  // Decode connectivity of non-position attributes.
  474|    130|  if (!attribute_data_.empty()) {
  ------------------
  |  Branch (474:7): [True: 117, False: 13]
  ------------------
  475|    117|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  476|    117|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
  ------------------
  |  |  115|    117|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (476:9): [True: 105, False: 12]
  ------------------
  477|   162k|      for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
  ------------------
  |  Branch (477:31): [True: 162k, False: 105]
  ------------------
  478|   162k|        if (!DecodeAttributeConnectivitiesOnFaceLegacy(ci)) {
  ------------------
  |  Branch (478:13): [True: 0, False: 162k]
  ------------------
  479|      0|          return false;
  480|      0|        }
  481|   162k|      }
  482|       |
  483|    105|    } else
  484|     12|#endif
  485|     12|    {
  486|  95.6k|      for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
  ------------------
  |  Branch (486:31): [True: 95.6k, False: 12]
  ------------------
  487|  95.6k|        if (!DecodeAttributeConnectivitiesOnFace(ci)) {
  ------------------
  |  Branch (487:13): [True: 0, False: 95.6k]
  ------------------
  488|      0|          return false;
  489|      0|        }
  490|  95.6k|      }
  491|     12|    }
  492|    117|  }
  493|    130|  traversal_decoder_.Done();
  494|       |
  495|       |  // Decode attribute connectivity.
  496|       |  // Prepare data structure for decoding non-position attribute connectivity.
  497|    253|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (497:24): [True: 123, False: 130]
  ------------------
  498|    123|    attribute_data_[i].connectivity_data.InitEmpty(corner_table_.get());
  499|       |    // Add all seams.
  500|   340k|    for (int32_t c : attribute_data_[i].attribute_seam_corners) {
  ------------------
  |  Branch (500:20): [True: 340k, False: 123]
  ------------------
  501|   340k|      attribute_data_[i].connectivity_data.AddSeamEdge(CornerIndex(c));
  502|   340k|    }
  503|       |    // Recompute vertices from the newly added seam edges.
  504|    123|    if (!attribute_data_[i].connectivity_data.RecomputeVertices(nullptr,
  ------------------
  |  Branch (504:9): [True: 0, False: 123]
  ------------------
  505|    123|                                                                nullptr)) {
  506|      0|      return false;
  507|      0|    }
  508|    123|  }
  509|       |
  510|    130|  pos_encoding_data_.Init(corner_table_->num_vertices());
  511|    253|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (511:24): [True: 123, False: 130]
  ------------------
  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|    123|    int32_t att_connectivity_verts =
  517|    123|        attribute_data_[i].connectivity_data.num_vertices();
  518|    123|    if (att_connectivity_verts < corner_table_->num_vertices()) {
  ------------------
  |  Branch (518:9): [True: 28, False: 95]
  ------------------
  519|     28|      att_connectivity_verts = corner_table_->num_vertices();
  520|     28|    }
  521|    123|    attribute_data_[i].encoding_data.Init(att_connectivity_verts);
  522|    123|  }
  523|    130|  if (!AssignPointsToCorners(num_connectivity_verts)) {
  ------------------
  |  Branch (523:7): [True: 0, False: 130]
  ------------------
  524|      0|    return false;
  525|      0|  }
  526|    130|  return true;
  527|    130|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE19OnAttributesDecodedEv:
  530|     13|bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::OnAttributesDecoded() {
  531|     13|  return true;
  532|     13|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE18DecodeConnectivityEi:
  536|    139|    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|    139|  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|    139|  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|    139|  std::vector<VertexIndex> invalid_vertices;
  558|    139|  const bool remove_invalid_vertices = attribute_data_.empty();
  559|       |
  560|    139|  int max_num_vertices = static_cast<int>(is_vert_hole_.size());
  561|    139|  int num_faces = 0;
  562|  55.7M|  for (int symbol_id = 0; symbol_id < num_symbols; ++symbol_id) {
  ------------------
  |  Branch (562:27): [True: 55.7M, False: 134]
  ------------------
  563|  55.7M|    const FaceIndex face(num_faces++);
  564|       |    // Used to flag cases where we need to look for topology split events.
  565|  55.7M|    bool check_topology_split = false;
  566|  55.7M|    const uint32_t symbol = traversal_decoder_.DecodeSymbol();
  567|  55.7M|    if (symbol == TOPOLOGY_C) {
  ------------------
  |  Branch (567:9): [True: 27.8M, False: 27.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|  27.8M|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (587:11): [True: 0, False: 27.8M]
  ------------------
  588|      0|        return -1;
  589|      0|      }
  590|       |
  591|  27.8M|      const CornerIndex corner_a = active_corner_stack.back();
  592|  27.8M|      const VertexIndex vertex_x =
  593|  27.8M|          corner_table_->Vertex(corner_table_->Next(corner_a));
  594|  27.8M|      const CornerIndex corner_b =
  595|  27.8M|          corner_table_->Next(corner_table_->LeftMostCorner(vertex_x));
  596|       |
  597|  27.8M|      if (corner_a == corner_b) {
  ------------------
  |  Branch (597:11): [True: 0, False: 27.8M]
  ------------------
  598|       |        // All matched corners must be different.
  599|      0|        return -1;
  600|      0|      }
  601|  27.8M|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex ||
  ------------------
  |  Branch (601:11): [True: 0, False: 27.8M]
  |  Branch (601:11): [True: 0, False: 27.8M]
  ------------------
  602|  27.8M|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex) {
  ------------------
  |  Branch (602:11): [True: 0, False: 27.8M]
  ------------------
  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|  27.8M|      const CornerIndex corner(3 * face.value());
  610|       |      // Update opposite corner mappings.
  611|  27.8M|      SetOppositeCorners(corner_a, corner + 1);
  612|  27.8M|      SetOppositeCorners(corner_b, corner + 2);
  613|       |
  614|       |      // Update vertex mapping.
  615|  27.8M|      const VertexIndex vert_a_prev =
  616|  27.8M|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  617|  27.8M|      const VertexIndex vert_b_next =
  618|  27.8M|          corner_table_->Vertex(corner_table_->Next(corner_b));
  619|  27.8M|      if (vertex_x == vert_a_prev || vertex_x == vert_b_next) {
  ------------------
  |  Branch (619:11): [True: 0, False: 27.8M]
  |  Branch (619:38): [True: 0, False: 27.8M]
  ------------------
  620|       |        // Encoding is invalid, because face vertices are degenerate.
  621|      0|        return -1;
  622|      0|      }
  623|  27.8M|      corner_table_->MapCornerToVertex(corner, vertex_x);
  624|  27.8M|      corner_table_->MapCornerToVertex(corner + 1, vert_b_next);
  625|  27.8M|      corner_table_->MapCornerToVertex(corner + 2, vert_a_prev);
  626|  27.8M|      corner_table_->SetLeftMostCorner(vert_a_prev, corner + 2);
  627|       |      // Mark the vertex |x| as interior.
  628|  27.8M|      is_vert_hole_[vertex_x.value()] = false;
  629|       |      // Update the corner on the active stack.
  630|  27.8M|      active_corner_stack.back() = corner;
  631|  27.8M|    } else if (symbol == TOPOLOGY_R || symbol == TOPOLOGY_L) {
  ------------------
  |  Branch (631:16): [True: 27.8M, False: 2.46k]
  |  Branch (631:40): [True: 420, False: 2.04k]
  ------------------
  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|  27.8M|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (646:11): [True: 0, False: 27.8M]
  ------------------
  647|      0|        return -1;
  648|      0|      }
  649|  27.8M|      const CornerIndex corner_a = active_corner_stack.back();
  650|  27.8M|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex) {
  ------------------
  |  Branch (650:11): [True: 0, False: 27.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|  27.8M|      const CornerIndex corner(3 * face.value());
  658|  27.8M|      CornerIndex opp_corner, corner_l, corner_r;
  659|  27.8M|      if (symbol == TOPOLOGY_R) {
  ------------------
  |  Branch (659:11): [True: 27.8M, False: 420]
  ------------------
  660|       |        // "r" is the new first corner.
  661|  27.8M|        opp_corner = corner + 2;
  662|  27.8M|        corner_l = corner + 1;
  663|  27.8M|        corner_r = corner;
  664|  27.8M|      } else {
  665|       |        // "l" is the new first corner.
  666|    420|        opp_corner = corner + 1;
  667|    420|        corner_l = corner;
  668|    420|        corner_r = corner + 2;
  669|    420|      }
  670|  27.8M|      SetOppositeCorners(opp_corner, corner_a);
  671|       |      // Update vertex mapping.
  672|  27.8M|      const VertexIndex new_vert_index = corner_table_->AddNewVertex();
  673|       |
  674|  27.8M|      if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (674:11): [True: 0, False: 27.8M]
  ------------------
  675|      0|        return -1;  // Unexpected number of decoded vertices.
  676|      0|      }
  677|       |
  678|  27.8M|      corner_table_->MapCornerToVertex(opp_corner, new_vert_index);
  679|  27.8M|      corner_table_->SetLeftMostCorner(new_vert_index, opp_corner);
  680|       |
  681|  27.8M|      const VertexIndex vertex_r =
  682|  27.8M|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  683|  27.8M|      corner_table_->MapCornerToVertex(corner_r, vertex_r);
  684|       |      // Update left-most corner on the vertex on the |corner_r|.
  685|  27.8M|      corner_table_->SetLeftMostCorner(vertex_r, corner_r);
  686|       |
  687|  27.8M|      corner_table_->MapCornerToVertex(
  688|  27.8M|          corner_l, corner_table_->Vertex(corner_table_->Next(corner_a)));
  689|  27.8M|      active_corner_stack.back() = corner;
  690|  27.8M|      check_topology_split = true;
  691|  27.8M|    } else if (symbol == TOPOLOGY_S) {
  ------------------
  |  Branch (691:16): [True: 708, False: 1.33k]
  ------------------
  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|    708|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (702:11): [True: 0, False: 708]
  ------------------
  703|      0|        return -1;
  704|      0|      }
  705|    708|      const CornerIndex corner_b = active_corner_stack.back();
  706|    708|      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|    708|      const auto it = topology_split_active_corners.find(symbol_id);
  711|    708|      if (it != topology_split_active_corners.end()) {
  ------------------
  |  Branch (711:11): [True: 0, False: 708]
  ------------------
  712|       |        // Topology split event. Move the retrieved edge to the stack.
  713|      0|        active_corner_stack.push_back(it->second);
  714|      0|      }
  715|    708|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (715:11): [True: 0, False: 708]
  ------------------
  716|      0|        return -1;
  717|      0|      }
  718|    708|      const CornerIndex corner_a = active_corner_stack.back();
  719|       |
  720|    708|      if (corner_a == corner_b) {
  ------------------
  |  Branch (720:11): [True: 0, False: 708]
  ------------------
  721|       |        // All matched corners must be different.
  722|      0|        return -1;
  723|      0|      }
  724|    708|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex ||
  ------------------
  |  Branch (724:11): [True: 0, False: 708]
  |  Branch (724:11): [True: 0, False: 708]
  ------------------
  725|    708|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex) {
  ------------------
  |  Branch (725:11): [True: 0, False: 708]
  ------------------
  726|       |        // One of the corners is already opposite to an existing face, which
  727|       |        // should not happen unless the input was tampered with.
  728|      0|        return -1;
  729|      0|      }
  730|       |
  731|       |      // First corner on the new face is corner "x" from the image above.
  732|    708|      const CornerIndex corner(3 * face.value());
  733|       |      // Update the opposite corner mapping.
  734|    708|      SetOppositeCorners(corner_a, corner + 2);
  735|    708|      SetOppositeCorners(corner_b, corner + 1);
  736|       |      // Update vertices. For the vertex at corner "x", use the vertex id from
  737|       |      // the corner "p".
  738|    708|      const VertexIndex vertex_p =
  739|    708|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  740|    708|      corner_table_->MapCornerToVertex(corner, vertex_p);
  741|    708|      corner_table_->MapCornerToVertex(
  742|    708|          corner + 1, corner_table_->Vertex(corner_table_->Next(corner_a)));
  743|    708|      const VertexIndex vert_b_prev =
  744|    708|          corner_table_->Vertex(corner_table_->Previous(corner_b));
  745|    708|      corner_table_->MapCornerToVertex(corner + 2, vert_b_prev);
  746|    708|      corner_table_->SetLeftMostCorner(vert_b_prev, corner + 2);
  747|    708|      CornerIndex corner_n = corner_table_->Next(corner_b);
  748|    708|      const VertexIndex vertex_n = corner_table_->Vertex(corner_n);
  749|    708|      traversal_decoder_.MergeVertices(vertex_p, vertex_n);
  750|       |      // Update the left most corner on the newly merged vertex.
  751|    708|      corner_table_->SetLeftMostCorner(vertex_p,
  752|    708|                                       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|    708|      const CornerIndex first_corner = corner_n;
  757|  2.62k|      while (corner_n != kInvalidCornerIndex) {
  ------------------
  |  Branch (757:14): [True: 1.91k, False: 708]
  ------------------
  758|  1.91k|        corner_table_->MapCornerToVertex(corner_n, vertex_p);
  759|  1.91k|        corner_n = corner_table_->SwingLeft(corner_n);
  760|  1.91k|        if (corner_n == first_corner) {
  ------------------
  |  Branch (760:13): [True: 0, False: 1.91k]
  ------------------
  761|       |          // We reached the start again which should not happen for split
  762|       |          // symbols.
  763|      0|          return -1;
  764|      0|        }
  765|  1.91k|      }
  766|       |      // Make sure the old vertex n is now mapped to an invalid corner (make it
  767|       |      // isolated).
  768|    708|      corner_table_->MakeVertexIsolated(vertex_n);
  769|    708|      if (remove_invalid_vertices) {
  ------------------
  |  Branch (769:11): [True: 559, False: 149]
  ------------------
  770|    559|        invalid_vertices.push_back(vertex_n);
  771|    559|      }
  772|    708|      active_corner_stack.back() = corner;
  773|  1.33k|    } else if (symbol == TOPOLOGY_E) {
  ------------------
  |  Branch (773:16): [True: 1.33k, False: 0]
  ------------------
  774|  1.33k|      const CornerIndex corner(3 * face.value());
  775|  1.33k|      const VertexIndex first_vert_index = corner_table_->AddNewVertex();
  776|       |      // Create three new vertices at the corners of the new face.
  777|  1.33k|      corner_table_->MapCornerToVertex(corner, first_vert_index);
  778|  1.33k|      corner_table_->MapCornerToVertex(corner + 1,
  779|  1.33k|                                       corner_table_->AddNewVertex());
  780|  1.33k|      corner_table_->MapCornerToVertex(corner + 2,
  781|  1.33k|                                       corner_table_->AddNewVertex());
  782|       |
  783|  1.33k|      if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (783:11): [True: 0, False: 1.33k]
  ------------------
  784|      0|        return -1;  // Unexpected number of decoded vertices.
  785|      0|      }
  786|       |
  787|  1.33k|      corner_table_->SetLeftMostCorner(first_vert_index, corner);
  788|  1.33k|      corner_table_->SetLeftMostCorner(first_vert_index + 1, corner + 1);
  789|  1.33k|      corner_table_->SetLeftMostCorner(first_vert_index + 2, corner + 2);
  790|       |      // Add the tip corner to the active stack.
  791|  1.33k|      active_corner_stack.push_back(corner);
  792|  1.33k|      check_topology_split = true;
  793|  1.33k|    } 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|  55.7M|    traversal_decoder_.NewActiveCornerReached(active_corner_stack.back());
  799|       |
  800|  55.7M|    if (check_topology_split) {
  ------------------
  |  Branch (800:9): [True: 27.8M, False: 27.8M]
  ------------------
  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|  27.8M|      const int encoder_symbol_id = num_symbols - symbol_id - 1;
  811|  27.8M|      EdgeFaceName split_edge;
  812|  27.8M|      int encoder_split_symbol_id;
  813|  27.8M|      while (IsTopologySplit(encoder_symbol_id, &split_edge,
  ------------------
  |  Branch (813:14): [True: 801, False: 27.8M]
  ------------------
  814|  27.8M|                             &encoder_split_symbol_id)) {
  815|    801|        if (encoder_split_symbol_id < 0) {
  ------------------
  |  Branch (815:13): [True: 5, False: 796]
  ------------------
  816|      5|          return -1;  // Wrong split symbol id.
  817|      5|        }
  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|    796|        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|    796|        CornerIndex new_active_corner;
  831|    796|        if (split_edge == RIGHT_FACE_EDGE) {
  ------------------
  |  Branch (831:13): [True: 230, False: 566]
  ------------------
  832|    230|          new_active_corner = corner_table_->Next(act_top_corner);
  833|    566|        } else {
  834|    566|          new_active_corner = corner_table_->Previous(act_top_corner);
  835|    566|        }
  836|       |        // Add the new active edge.
  837|       |        // Convert the encoder split symbol id to decoder symbol id.
  838|    796|        const int decoder_split_symbol_id =
  839|    796|            num_symbols - encoder_split_symbol_id - 1;
  840|    796|        topology_split_active_corners[decoder_split_symbol_id] =
  841|    796|            new_active_corner;
  842|    796|      }
  843|  27.8M|    }
  844|  55.7M|  }
  845|    134|  if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (845:7): [True: 0, False: 134]
  ------------------
  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|    725|  while (!active_corner_stack.empty()) {
  ------------------
  |  Branch (849:10): [True: 591, False: 134]
  ------------------
  850|    591|    const CornerIndex corner = active_corner_stack.back();
  851|    591|    active_corner_stack.pop_back();
  852|    591|    const bool interior_face =
  853|    591|        traversal_decoder_.DecodeStartFaceConfiguration();
  854|    591|    if (interior_face) {
  ------------------
  |  Branch (854:9): [True: 14, False: 577]
  ------------------
  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|     14|      if (num_faces >= corner_table_->num_faces()) {
  ------------------
  |  Branch (876:11): [True: 0, False: 14]
  ------------------
  877|      0|        return -1;  // More faces than expected added to the mesh.
  878|      0|      }
  879|       |
  880|     14|      const CornerIndex corner_a = corner;
  881|     14|      const VertexIndex vert_n =
  882|     14|          corner_table_->Vertex(corner_table_->Next(corner_a));
  883|     14|      const CornerIndex corner_b =
  884|     14|          corner_table_->Next(corner_table_->LeftMostCorner(vert_n));
  885|       |
  886|     14|      const VertexIndex vert_x =
  887|     14|          corner_table_->Vertex(corner_table_->Next(corner_b));
  888|     14|      const CornerIndex corner_c =
  889|     14|          corner_table_->Next(corner_table_->LeftMostCorner(vert_x));
  890|       |
  891|     14|      if (corner == corner_b || corner == corner_c || corner_b == corner_c) {
  ------------------
  |  Branch (891:11): [True: 0, False: 14]
  |  Branch (891:33): [True: 0, False: 14]
  |  Branch (891:55): [True: 0, False: 14]
  ------------------
  892|       |        // All matched corners must be different.
  893|      0|        return -1;
  894|      0|      }
  895|     14|      if (corner_table_->Opposite(corner) != kInvalidCornerIndex ||
  ------------------
  |  Branch (895:11): [True: 0, False: 14]
  |  Branch (895:11): [True: 0, False: 14]
  ------------------
  896|     14|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex ||
  ------------------
  |  Branch (896:11): [True: 0, False: 14]
  ------------------
  897|     14|          corner_table_->Opposite(corner_c) != kInvalidCornerIndex) {
  ------------------
  |  Branch (897:11): [True: 0, False: 14]
  ------------------
  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|     14|      const VertexIndex vert_p =
  904|     14|          corner_table_->Vertex(corner_table_->Next(corner_c));
  905|       |
  906|     14|      const FaceIndex face(num_faces++);
  907|       |      // The first corner of the initial face is the corner opposite to "a".
  908|     14|      const CornerIndex new_corner(3 * face.value());
  909|     14|      SetOppositeCorners(new_corner, corner);
  910|     14|      SetOppositeCorners(new_corner + 1, corner_b);
  911|     14|      SetOppositeCorners(new_corner + 2, corner_c);
  912|       |
  913|       |      // Map new corners to existing vertices.
  914|     14|      corner_table_->MapCornerToVertex(new_corner, vert_x);
  915|     14|      corner_table_->MapCornerToVertex(new_corner + 1, vert_p);
  916|     14|      corner_table_->MapCornerToVertex(new_corner + 2, vert_n);
  917|       |
  918|       |      // Mark all three vertices as interior.
  919|     56|      for (int ci = 0; ci < 3; ++ci) {
  ------------------
  |  Branch (919:24): [True: 42, False: 14]
  ------------------
  920|     42|        is_vert_hole_[corner_table_->Vertex(new_corner + ci).value()] = false;
  921|     42|      }
  922|       |
  923|     14|      init_face_configurations_.push_back(true);
  924|     14|      init_corners_.push_back(new_corner);
  925|    577|    } 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|    577|      init_face_configurations_.push_back(false);
  930|    577|      init_corners_.push_back(corner);
  931|    577|    }
  932|    591|  }
  933|    134|  if (num_faces != corner_table_->num_faces()) {
  ------------------
  |  Branch (933:7): [True: 4, False: 130]
  ------------------
  934|      4|    return -1;  // Unexpected number of decoded faces.
  935|      4|  }
  936|       |
  937|    130|  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|    540|  for (const VertexIndex invalid_vert : invalid_vertices) {
  ------------------
  |  Branch (940:39): [True: 540, False: 130]
  ------------------
  941|       |    // Find the last valid vertex and swap it with the isolated vertex.
  942|    540|    VertexIndex src_vert(num_vertices - 1);
  943|    622|    while (corner_table_->LeftMostCorner(src_vert) == kInvalidCornerIndex) {
  ------------------
  |  Branch (943:12): [True: 82, False: 540]
  ------------------
  944|       |      // The last vertex is invalid, proceed to the previous one.
  945|     82|      src_vert = VertexIndex(--num_vertices - 1);
  946|     82|    }
  947|    540|    if (src_vert < invalid_vert) {
  ------------------
  |  Branch (947:9): [True: 82, False: 458]
  ------------------
  948|     82|      continue;  // No need to swap anything.
  949|     82|    }
  950|       |
  951|       |    // Remap all corners mapped to |src_vert| to |invalid_vert|.
  952|    458|    VertexCornersIterator<CornerTable> vcit(corner_table_.get(), src_vert);
  953|  2.06k|    for (; !vcit.End(); ++vcit) {
  ------------------
  |  Branch (953:12): [True: 1.60k, False: 458]
  ------------------
  954|  1.60k|      const CornerIndex cid = vcit.Corner();
  955|  1.60k|      if (corner_table_->Vertex(cid) != src_vert) {
  ------------------
  |  Branch (955:11): [True: 0, False: 1.60k]
  ------------------
  956|       |        // Vertex mapped to |cid| was not |src_vert|. This indicates corrupted
  957|       |        // data and we should terminate the decoding.
  958|      0|        return -1;
  959|      0|      }
  960|  1.60k|      corner_table_->MapCornerToVertex(cid, invalid_vert);
  961|  1.60k|    }
  962|    458|    corner_table_->SetLeftMostCorner(invalid_vert,
  963|    458|                                     corner_table_->LeftMostCorner(src_vert));
  964|       |
  965|       |    // Make the |src_vert| invalid.
  966|    458|    corner_table_->MakeVertexIsolated(src_vert);
  967|    458|    is_vert_hole_[invalid_vert.value()] = is_vert_hole_[src_vert.value()];
  968|    458|    is_vert_hole_[src_vert.value()] = false;
  969|       |
  970|       |    // The last vertex is now invalid.
  971|    458|    num_vertices--;
  972|    458|  }
  973|    130|  return num_vertices;
  974|    130|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE32DecodeHoleAndTopologySplitEventsEPNS_13DecoderBufferE:
  979|    178|    DecoderBuffer *decoder_buffer) {
  980|       |  // Prepare a new decoder from the provided buffer offset.
  981|    178|  uint32_t num_topology_splits;
  982|    178|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  983|    178|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    178|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (983:7): [True: 30, False: 148]
  ------------------
  984|     30|    if (!decoder_buffer->Decode(&num_topology_splits)) {
  ------------------
  |  Branch (984:9): [True: 0, False: 30]
  ------------------
  985|      0|      return -1;
  986|      0|    }
  987|       |
  988|     30|  } else
  989|    148|#endif
  990|    148|  {
  991|    148|    if (!DecodeVarint(&num_topology_splits, decoder_buffer)) {
  ------------------
  |  Branch (991:9): [True: 0, False: 148]
  ------------------
  992|      0|      return -1;
  993|      0|    }
  994|    148|  }
  995|    178|  if (num_topology_splits > 0) {
  ------------------
  |  Branch (995:7): [True: 132, False: 46]
  ------------------
  996|    132|    if (num_topology_splits >
  ------------------
  |  Branch (996:9): [True: 5, False: 127]
  ------------------
  997|    132|        static_cast<uint32_t>(corner_table_->num_faces())) {
  998|      5|      return -1;
  999|      5|    }
 1000|    127|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1001|    127|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|    127|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1001:9): [True: 10, False: 117]
  ------------------
 1002|  4.87k|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1002:28): [True: 4.87k, False: 3]
  ------------------
 1003|  4.87k|        TopologySplitEventData event_data;
 1004|  4.87k|        if (!decoder_buffer->Decode(&event_data.split_symbol_id)) {
  ------------------
  |  Branch (1004:13): [True: 3, False: 4.86k]
  ------------------
 1005|      3|          return -1;
 1006|      3|        }
 1007|  4.86k|        if (!decoder_buffer->Decode(&event_data.source_symbol_id)) {
  ------------------
  |  Branch (1007:13): [True: 4, False: 4.86k]
  ------------------
 1008|      4|          return -1;
 1009|      4|        }
 1010|  4.86k|        uint8_t edge_data;
 1011|  4.86k|        if (!decoder_buffer->Decode(&edge_data)) {
  ------------------
  |  Branch (1011:13): [True: 0, False: 4.86k]
  ------------------
 1012|      0|          return -1;
 1013|      0|        }
 1014|  4.86k|        event_data.source_edge = edge_data & 1;
 1015|  4.86k|        topology_split_data_.push_back(event_data);
 1016|  4.86k|      }
 1017|       |
 1018|     10|    } else
 1019|    117|#endif
 1020|    117|    {
 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|    117|      int last_source_symbol_id = 0;
 1024|  1.35k|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1024:28): [True: 1.23k, False: 115]
  ------------------
 1025|  1.23k|        TopologySplitEventData event_data;
 1026|  1.23k|        uint32_t delta;
 1027|  1.23k|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1027:13): [True: 0, False: 1.23k]
  ------------------
 1028|      0|          return -1;
 1029|      0|        }
 1030|  1.23k|        event_data.source_symbol_id = delta + last_source_symbol_id;
 1031|  1.23k|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1031:13): [True: 0, False: 1.23k]
  ------------------
 1032|      0|          return -1;
 1033|      0|        }
 1034|  1.23k|        if (delta > event_data.source_symbol_id) {
  ------------------
  |  Branch (1034:13): [True: 2, False: 1.23k]
  ------------------
 1035|      2|          return -1;
 1036|      2|        }
 1037|  1.23k|        event_data.split_symbol_id =
 1038|  1.23k|            event_data.source_symbol_id - static_cast<int32_t>(delta);
 1039|  1.23k|        last_source_symbol_id = event_data.source_symbol_id;
 1040|  1.23k|        topology_split_data_.push_back(event_data);
 1041|  1.23k|      }
 1042|       |      // Split edges are decoded from a direct bit decoder.
 1043|    115|      decoder_buffer->StartBitDecoding(false, nullptr);
 1044|  1.34k|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1044:28): [True: 1.23k, False: 115]
  ------------------
 1045|  1.23k|        uint32_t edge_data;
 1046|  1.23k|        if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  1.23k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1046:13): [True: 1.23k, False: 0]
  ------------------
 1047|  1.23k|          decoder_buffer->DecodeLeastSignificantBits32(2, &edge_data);
 1048|  1.23k|        } else {
 1049|      0|          decoder_buffer->DecodeLeastSignificantBits32(1, &edge_data);
 1050|      0|        }
 1051|  1.23k|        TopologySplitEventData &event_data = topology_split_data_[i];
 1052|  1.23k|        event_data.source_edge = edge_data & 1;
 1053|  1.23k|      }
 1054|    115|      decoder_buffer->EndBitDecoding();
 1055|    115|    }
 1056|    127|  }
 1057|    164|  uint32_t num_hole_events = 0;
 1058|    164|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1059|    164|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    164|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1059:7): [True: 20, False: 144]
  ------------------
 1060|     20|    if (!decoder_buffer->Decode(&num_hole_events)) {
  ------------------
  |  Branch (1060:9): [True: 0, False: 20]
  ------------------
 1061|      0|      return -1;
 1062|      0|    }
 1063|    144|  } else if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
  ------------------
  |  |  115|    144|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1063:14): [True: 115, False: 29]
  ------------------
 1064|    115|    if (!DecodeVarint(&num_hole_events, decoder_buffer)) {
  ------------------
  |  Branch (1064:9): [True: 1, False: 114]
  ------------------
 1065|      1|      return -1;
 1066|      1|    }
 1067|    115|  }
 1068|    163|#endif
 1069|    163|  if (num_hole_events > 0) {
  ------------------
  |  Branch (1069:7): [True: 24, False: 139]
  ------------------
 1070|     24|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1071|     24|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|     24|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1071:9): [True: 15, False: 9]
  ------------------
 1072|   451k|      for (uint32_t i = 0; i < num_hole_events; ++i) {
  ------------------
  |  Branch (1072:28): [True: 451k, False: 2]
  ------------------
 1073|   451k|        HoleEventData event_data;
 1074|   451k|        if (!decoder_buffer->Decode(&event_data)) {
  ------------------
  |  Branch (1074:13): [True: 13, False: 451k]
  ------------------
 1075|     13|          return -1;
 1076|     13|        }
 1077|   451k|        hole_event_data_.push_back(event_data);
 1078|   451k|      }
 1079|       |
 1080|     15|    } else
 1081|      9|#endif
 1082|      9|    {
 1083|       |      // Decode hole symbol ids using delta and varint coding.
 1084|      9|      int last_symbol_id = 0;
 1085|  2.43k|      for (uint32_t i = 0; i < num_hole_events; ++i) {
  ------------------
  |  Branch (1085:28): [True: 2.42k, False: 8]
  ------------------
 1086|  2.42k|        HoleEventData event_data;
 1087|  2.42k|        uint32_t delta;
 1088|  2.42k|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1088:13): [True: 1, False: 2.42k]
  ------------------
 1089|      1|          return -1;
 1090|      1|        }
 1091|  2.42k|        event_data.symbol_id = delta + last_symbol_id;
 1092|  2.42k|        last_symbol_id = event_data.symbol_id;
 1093|  2.42k|        hole_event_data_.push_back(event_data);
 1094|  2.42k|      }
 1095|      9|    }
 1096|     24|  }
 1097|    149|  return static_cast<int32_t>(decoder_buffer->decoded_size());
 1098|    163|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE41DecodeAttributeConnectivitiesOnFaceLegacyENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
 1103|   162k|    DecodeAttributeConnectivitiesOnFaceLegacy(CornerIndex corner) {
 1104|       |  // Three corners of the face.
 1105|   162k|  const CornerIndex corners[3] = {corner, corner_table_->Next(corner),
 1106|   162k|                                  corner_table_->Previous(corner)};
 1107|       |
 1108|   651k|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1108:19): [True: 488k, False: 162k]
  ------------------
 1109|   488k|    const CornerIndex opp_corner = corner_table_->Opposite(corners[c]);
 1110|   488k|    if (opp_corner == kInvalidCornerIndex) {
  ------------------
  |  Branch (1110:9): [True: 2.10k, False: 486k]
  ------------------
 1111|       |      // Don't decode attribute seams on boundary edges (every boundary edge
 1112|       |      // is automatically an attribute seam).
 1113|  4.23k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1113:28): [True: 2.12k, False: 2.10k]
  ------------------
 1114|  2.12k|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1115|  2.12k|      }
 1116|  2.10k|      continue;
 1117|  2.10k|    }
 1118|       |
 1119|   973k|    for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1119:26): [True: 486k, False: 486k]
  ------------------
 1120|   486k|      const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i);
 1121|   486k|      if (is_seam) {
  ------------------
  |  Branch (1121:11): [True: 165k, False: 320k]
  ------------------
 1122|   165k|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1123|   165k|      }
 1124|   486k|    }
 1125|   486k|  }
 1126|   162k|  return true;
 1127|   162k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE35DecodeAttributeConnectivitiesOnFaceENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
 1132|  95.6k|    TraversalDecoder>::DecodeAttributeConnectivitiesOnFace(CornerIndex corner) {
 1133|       |  // Three corners of the face.
 1134|  95.6k|  const CornerIndex corners[3] = {corner, corner_table_->Next(corner),
 1135|  95.6k|                                  corner_table_->Previous(corner)};
 1136|       |
 1137|  95.6k|  const FaceIndex src_face_id = corner_table_->Face(corner);
 1138|   382k|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1138:19): [True: 286k, False: 95.6k]
  ------------------
 1139|   286k|    const CornerIndex opp_corner = corner_table_->Opposite(corners[c]);
 1140|   286k|    if (opp_corner == kInvalidCornerIndex) {
  ------------------
  |  Branch (1140:9): [True: 2.97k, False: 283k]
  ------------------
 1141|       |      // Don't decode attribute seams on boundary edges (every boundary edge
 1142|       |      // is automatically an attribute seam).
 1143|  7.70k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1143:28): [True: 4.72k, False: 2.97k]
  ------------------
 1144|  4.72k|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1145|  4.72k|      }
 1146|  2.97k|      continue;
 1147|  2.97k|    }
 1148|   283k|    const FaceIndex opp_face_id = corner_table_->Face(opp_corner);
 1149|       |    // Don't decode edges when the opposite face has been already processed.
 1150|   283k|    if (opp_face_id < src_face_id) {
  ------------------
  |  Branch (1150:9): [True: 141k, False: 141k]
  ------------------
 1151|   141k|      continue;
 1152|   141k|    }
 1153|       |
 1154|   362k|    for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1154:26): [True: 220k, False: 141k]
  ------------------
 1155|   220k|      const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i);
 1156|   220k|      if (is_seam) {
  ------------------
  |  Branch (1156:11): [True: 167k, False: 52.5k]
  ------------------
 1157|   167k|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1158|   167k|      }
 1159|   220k|    }
 1160|   141k|  }
 1161|  95.6k|  return true;
 1162|  95.6k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE21AssignPointsToCornersEi:
 1166|    130|    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|    130|  decoder_->mesh()->SetNumFaces(corner_table_->num_faces());
 1171|       |
 1172|    130|  if (attribute_data_.empty()) {
  ------------------
  |  Branch (1172:7): [True: 13, False: 117]
  ------------------
 1173|       |    // We have connectivity for position only. In this case all vertex indices
 1174|       |    // are equal to point indices.
 1175|   137k|    for (FaceIndex f(0); f < decoder_->mesh()->num_faces(); ++f) {
  ------------------
  |  Branch (1175:26): [True: 137k, False: 13]
  ------------------
 1176|   137k|      Mesh::Face face;
 1177|   137k|      const CornerIndex start_corner(3 * f.value());
 1178|   548k|      for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1178:23): [True: 411k, False: 137k]
  ------------------
 1179|       |        // Get the vertex index on the corner and use it as a point index.
 1180|   411k|        const int32_t vert_id = corner_table_->Vertex(start_corner + c).value();
 1181|   411k|        face[c] = vert_id;
 1182|   411k|      }
 1183|   137k|      decoder_->mesh()->SetFace(f, face);
 1184|   137k|    }
 1185|     13|    decoder_->point_cloud()->set_num_points(num_connectivity_verts);
 1186|     13|    return true;
 1187|     13|  }
 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|    117|  std::vector<int32_t> point_to_corner_map;
 1194|       |  // Map between every corner and their new point ids.
 1195|    117|  std::vector<int32_t> corner_to_point_map(corner_table_->num_corners());
 1196|   132k|  for (int v = 0; v < corner_table_->num_vertices(); ++v) {
  ------------------
  |  Branch (1196:19): [True: 132k, False: 117]
  ------------------
 1197|   132k|    CornerIndex c = corner_table_->LeftMostCorner(VertexIndex(v));
 1198|   132k|    if (c == kInvalidCornerIndex) {
  ------------------
  |  Branch (1198:9): [True: 144, False: 132k]
  ------------------
 1199|    144|      continue;  // Isolated vertex.
 1200|    144|    }
 1201|   132k|    CornerIndex deduplication_first_corner = c;
 1202|   132k|    if (is_vert_hole_[v]) {
  ------------------
  |  Branch (1202:9): [True: 5.08k, False: 126k]
  ------------------
 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|  5.08k|      deduplication_first_corner = c;
 1206|   126k|    } else {
 1207|       |      // If we are not on the boundary we need to find the first seam (of any
 1208|       |      // attribute).
 1209|   187k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1209:28): [True: 132k, False: 55.4k]
  ------------------
 1210|   132k|        if (!attribute_data_[i].connectivity_data.IsCornerOnSeam(c)) {
  ------------------
  |  Branch (1210:13): [True: 59.9k, False: 72.2k]
  ------------------
 1211|  59.9k|          continue;  // No seam for this attribute, ignore it.
 1212|  59.9k|        }
 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|  72.2k|        const VertexIndex vert_id =
 1217|  72.2k|            attribute_data_[i].connectivity_data.Vertex(c);
 1218|  72.2k|        CornerIndex act_c = corner_table_->SwingRight(c);
 1219|  72.2k|        bool seam_found = false;
 1220|  78.6k|        while (act_c != c) {
  ------------------
  |  Branch (1220:16): [True: 77.8k, False: 759]
  ------------------
 1221|  77.8k|          if (act_c == kInvalidCornerIndex) {
  ------------------
  |  Branch (1221:15): [True: 0, False: 77.8k]
  ------------------
 1222|      0|            return false;
 1223|      0|          }
 1224|  77.8k|          if (attribute_data_[i].connectivity_data.Vertex(act_c) != vert_id) {
  ------------------
  |  Branch (1224:15): [True: 71.4k, False: 6.42k]
  ------------------
 1225|       |            // Attribute seam found. Stop.
 1226|  71.4k|            deduplication_first_corner = act_c;
 1227|  71.4k|            seam_found = true;
 1228|  71.4k|            break;
 1229|  71.4k|          }
 1230|  6.42k|          act_c = corner_table_->SwingRight(act_c);
 1231|  6.42k|        }
 1232|  72.2k|        if (seam_found) {
  ------------------
  |  Branch (1232:13): [True: 71.4k, False: 759]
  ------------------
 1233|  71.4k|          break;  // No reason to process other attributes if we found a seam.
 1234|  71.4k|        }
 1235|  72.2k|      }
 1236|   126k|    }
 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|   132k|    c = deduplication_first_corner;
 1244|       |    // Create a new point.
 1245|   132k|    corner_to_point_map[c.value()] =
 1246|   132k|        static_cast<uint32_t>(point_to_corner_map.size());
 1247|   132k|    point_to_corner_map.push_back(c.value());
 1248|       |    // Traverse in CW direction.
 1249|   132k|    CornerIndex prev_c = c;
 1250|   132k|    c = corner_table_->SwingRight(c);
 1251|   775k|    while (c != kInvalidCornerIndex && c != deduplication_first_corner) {
  ------------------
  |  Branch (1251:12): [True: 770k, False: 5.08k]
  |  Branch (1251:40): [True: 643k, False: 126k]
  ------------------
 1252|   643k|      bool attribute_seam = false;
 1253|   958k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1253:28): [True: 669k, False: 288k]
  ------------------
 1254|   669k|        if (attribute_data_[i].connectivity_data.Vertex(c) !=
  ------------------
  |  Branch (1254:13): [True: 355k, False: 314k]
  ------------------
 1255|   669k|            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|   355k|          attribute_seam = true;
 1259|   355k|          break;
 1260|   355k|        }
 1261|   669k|      }
 1262|   643k|      if (attribute_seam) {
  ------------------
  |  Branch (1262:11): [True: 355k, False: 288k]
  ------------------
 1263|   355k|        corner_to_point_map[c.value()] =
 1264|   355k|            static_cast<uint32_t>(point_to_corner_map.size());
 1265|   355k|        point_to_corner_map.push_back(c.value());
 1266|   355k|      } else {
 1267|   288k|        corner_to_point_map[c.value()] = corner_to_point_map[prev_c.value()];
 1268|   288k|      }
 1269|   643k|      prev_c = c;
 1270|   643k|      c = corner_table_->SwingRight(c);
 1271|   643k|    }
 1272|   132k|  }
 1273|       |  // Add faces.
 1274|   258k|  for (FaceIndex f(0); f < decoder_->mesh()->num_faces(); ++f) {
  ------------------
  |  Branch (1274:24): [True: 258k, False: 117]
  ------------------
 1275|   258k|    Mesh::Face face;
 1276|  1.03M|    for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1276:21): [True: 775k, False: 258k]
  ------------------
 1277|       |      // Remap old points to the new ones.
 1278|   775k|      face[c] = corner_to_point_map[3 * f.value() + c];
 1279|   775k|    }
 1280|   258k|    decoder_->mesh()->SetFace(f, face);
 1281|   258k|  }
 1282|    117|  decoder_->point_cloud()->set_num_points(
 1283|    117|      static_cast<uint32_t>(point_to_corner_map.size()));
 1284|    117|  return true;
 1285|    117|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEEC2Ev:
   54|    348|      pos_data_decoder_id_(-1) {}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE4InitEPNS_22MeshEdgebreakerDecoderE:
   58|    348|    MeshEdgebreakerDecoder *decoder) {
   59|    348|  decoder_ = decoder;
   60|    348|  return true;
   61|    348|}
_ZNK5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE23GetAttributeCornerTableEi:
   66|    123|    int att_id) const {
   67|    142|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (67:24): [True: 25, False: 117]
  ------------------
   68|     25|    const int decoder_id = attribute_data_[i].decoder_id;
   69|     25|    if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) {
  ------------------
  |  Branch (69:9): [True: 19, False: 6]
  |  Branch (69:27): [True: 0, False: 6]
  ------------------
   70|     19|      continue;
   71|     19|    }
   72|      6|    const AttributesDecoderInterface *const dec =
   73|      6|        decoder_->attributes_decoder(decoder_id);
   74|      6|    for (int j = 0; j < dec->GetNumAttributes(); ++j) {
  ------------------
  |  Branch (74:21): [True: 6, False: 0]
  ------------------
   75|      6|      if (dec->GetAttributeId(j) == att_id) {
  ------------------
  |  Branch (75:11): [True: 6, False: 0]
  ------------------
   76|      6|        if (attribute_data_[i].is_connectivity_used) {
  ------------------
  |  Branch (76:13): [True: 5, False: 1]
  ------------------
   77|      5|          return &attribute_data_[i].connectivity_data;
   78|      5|        }
   79|      1|        return nullptr;
   80|      6|      }
   81|      6|    }
   82|      6|  }
   83|    117|  return nullptr;
   84|    123|}
_ZNK5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE24GetAttributeEncodingDataEi:
   89|    123|    int att_id) const {
   90|    142|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (90:24): [True: 25, False: 117]
  ------------------
   91|     25|    const int decoder_id = attribute_data_[i].decoder_id;
   92|     25|    if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) {
  ------------------
  |  Branch (92:9): [True: 19, False: 6]
  |  Branch (92:27): [True: 0, False: 6]
  ------------------
   93|     19|      continue;
   94|     19|    }
   95|      6|    const AttributesDecoderInterface *const dec =
   96|      6|        decoder_->attributes_decoder(decoder_id);
   97|      6|    for (int j = 0; j < dec->GetNumAttributes(); ++j) {
  ------------------
  |  Branch (97:21): [True: 6, False: 0]
  ------------------
   98|      6|      if (dec->GetAttributeId(j) == att_id) {
  ------------------
  |  Branch (98:11): [True: 6, False: 0]
  ------------------
   99|      6|        return &attribute_data_[i].encoding_data;
  100|      6|      }
  101|      6|    }
  102|      6|  }
  103|    117|  return &pos_encoding_data_;
  104|    123|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE23CreateAttributesDecoderEi:
  130|     76|    int32_t att_decoder_id) {
  131|     76|  int8_t att_data_id;
  132|     76|  if (!decoder_->buffer()->Decode(&att_data_id)) {
  ------------------
  |  Branch (132:7): [True: 0, False: 76]
  ------------------
  133|      0|    return false;
  134|      0|  }
  135|     76|  uint8_t decoder_type;
  136|     76|  if (!decoder_->buffer()->Decode(&decoder_type)) {
  ------------------
  |  Branch (136:7): [True: 0, False: 76]
  ------------------
  137|      0|    return false;
  138|      0|  }
  139|       |
  140|     76|  if (att_data_id >= 0) {
  ------------------
  |  Branch (140:7): [True: 11, False: 65]
  ------------------
  141|     11|    if (att_data_id >= attribute_data_.size()) {
  ------------------
  |  Branch (141:9): [True: 4, False: 7]
  ------------------
  142|      4|      return false;  // Unexpected attribute data.
  143|      4|    }
  144|       |
  145|       |    // Ensure that the attribute data is not mapped to a different attributes
  146|       |    // decoder already.
  147|      7|    if (attribute_data_[att_data_id].decoder_id >= 0) {
  ------------------
  |  Branch (147:9): [True: 0, False: 7]
  ------------------
  148|      0|      return false;
  149|      0|    }
  150|       |
  151|      7|    attribute_data_[att_data_id].decoder_id = att_decoder_id;
  152|     65|  } else {
  153|       |    // Assign the attributes decoder to |pos_encoding_data_|.
  154|     65|    if (pos_data_decoder_id_ >= 0) {
  ------------------
  |  Branch (154:9): [True: 1, False: 64]
  ------------------
  155|      1|      return false;  // Some other decoder is already using the data. Error.
  156|      1|    }
  157|     64|    pos_data_decoder_id_ = att_decoder_id;
  158|     64|  }
  159|       |
  160|     71|  MeshTraversalMethod traversal_method = MESH_TRAVERSAL_DEPTH_FIRST;
  161|     71|  if (decoder_->bitstream_version() >= DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|     71|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (161:7): [True: 71, False: 0]
  ------------------
  162|     71|    uint8_t traversal_method_encoded;
  163|     71|    if (!decoder_->buffer()->Decode(&traversal_method_encoded)) {
  ------------------
  |  Branch (163:9): [True: 0, False: 71]
  ------------------
  164|      0|      return false;
  165|      0|    }
  166|       |    // Check that decoded traversal method is valid.
  167|     71|    if (traversal_method_encoded >= NUM_TRAVERSAL_METHODS) {
  ------------------
  |  Branch (167:9): [True: 2, False: 69]
  ------------------
  168|      2|      return false;
  169|      2|    }
  170|     69|    traversal_method =
  171|     69|        static_cast<MeshTraversalMethod>(traversal_method_encoded);
  172|     69|  }
  173|       |
  174|     69|  const Mesh *mesh = decoder_->mesh();
  175|     69|  std::unique_ptr<PointsSequencer> sequencer;
  176|       |
  177|     69|  if (decoder_type == MESH_VERTEX_ATTRIBUTE) {
  ------------------
  |  Branch (177:7): [True: 64, False: 5]
  ------------------
  178|       |    // Per-vertex attribute decoder.
  179|       |
  180|     64|    MeshAttributeIndicesEncodingData *encoding_data = nullptr;
  181|     64|    if (att_data_id < 0) {
  ------------------
  |  Branch (181:9): [True: 62, False: 2]
  ------------------
  182|     62|      encoding_data = &pos_encoding_data_;
  183|     62|    } else {
  184|      2|      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|      2|      attribute_data_[att_data_id].is_connectivity_used = false;
  188|      2|    }
  189|       |    // Defining sequencer via a traversal scheme.
  190|     64|    if (traversal_method == MESH_TRAVERSAL_PREDICTION_DEGREE) {
  ------------------
  |  Branch (190:9): [True: 17, False: 47]
  ------------------
  191|     17|      typedef MeshAttributeIndicesEncodingObserver<CornerTable> AttObserver;
  192|     17|      typedef MaxPredictionDegreeTraverser<CornerTable, AttObserver>
  193|     17|          AttTraverser;
  194|     17|      sequencer = CreateVertexTraversalSequencer<AttTraverser>(encoding_data);
  195|     47|    } else if (traversal_method == MESH_TRAVERSAL_DEPTH_FIRST) {
  ------------------
  |  Branch (195:16): [True: 47, False: 0]
  ------------------
  196|     47|      typedef MeshAttributeIndicesEncodingObserver<CornerTable> AttObserver;
  197|     47|      typedef DepthFirstTraverser<CornerTable, AttObserver> AttTraverser;
  198|     47|      sequencer = CreateVertexTraversalSequencer<AttTraverser>(encoding_data);
  199|     47|    } else {
  200|      0|      return false;  // Unsupported method
  201|      0|    }
  202|     64|  } else {
  203|      5|    if (traversal_method != MESH_TRAVERSAL_DEPTH_FIRST) {
  ------------------
  |  Branch (203:9): [True: 0, False: 5]
  ------------------
  204|      0|      return false;  // Unsupported method.
  205|      0|    }
  206|      5|    if (att_data_id < 0) {
  ------------------
  |  Branch (206:9): [True: 0, False: 5]
  ------------------
  207|      0|      return false;  // Attribute data must be specified.
  208|      0|    }
  209|       |
  210|       |    // Per-corner attribute decoder.
  211|       |
  212|      5|    typedef MeshAttributeIndicesEncodingObserver<MeshAttributeCornerTable>
  213|      5|        AttObserver;
  214|      5|    typedef DepthFirstTraverser<MeshAttributeCornerTable, AttObserver>
  215|      5|        AttTraverser;
  216|       |
  217|      5|    MeshAttributeIndicesEncodingData *const encoding_data =
  218|      5|        &attribute_data_[att_data_id].encoding_data;
  219|      5|    const MeshAttributeCornerTable *const corner_table =
  220|      5|        &attribute_data_[att_data_id].connectivity_data;
  221|       |
  222|      5|    std::unique_ptr<MeshTraversalSequencer<AttTraverser>> traversal_sequencer(
  223|      5|        new MeshTraversalSequencer<AttTraverser>(mesh, encoding_data));
  224|       |
  225|      5|    AttObserver att_observer(corner_table, mesh, traversal_sequencer.get(),
  226|      5|                             encoding_data);
  227|       |
  228|      5|    AttTraverser att_traverser;
  229|      5|    att_traverser.Init(corner_table, att_observer);
  230|       |
  231|      5|    traversal_sequencer->SetTraverser(att_traverser);
  232|      5|    sequencer = std::move(traversal_sequencer);
  233|      5|  }
  234|       |
  235|     69|  if (!sequencer) {
  ------------------
  |  Branch (235:7): [True: 0, False: 69]
  ------------------
  236|      0|    return false;
  237|      0|  }
  238|       |
  239|     69|  std::unique_ptr<SequentialAttributeDecodersController> att_controller(
  240|     69|      new SequentialAttributeDecodersController(std::move(sequencer)));
  241|       |
  242|     69|  return decoder_->SetAttributesDecoder(att_decoder_id,
  243|     69|                                        std::move(att_controller));
  244|     69|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE18DecodeConnectivityEv:
  247|    348|bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
  248|    348|  num_new_vertices_ = 0;
  249|    348|  new_to_parent_vertex_map_.clear();
  250|    348|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  251|    348|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    348|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (251:7): [True: 135, False: 213]
  ------------------
  252|    135|    uint32_t num_new_verts;
  253|    135|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    135|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (253:9): [True: 119, False: 16]
  ------------------
  254|    119|      if (!decoder_->buffer()->Decode(&num_new_verts)) {
  ------------------
  |  Branch (254:11): [True: 0, False: 119]
  ------------------
  255|      0|        return false;
  256|      0|      }
  257|    119|    } else {
  258|     16|      if (!DecodeVarint(&num_new_verts, decoder_->buffer())) {
  ------------------
  |  Branch (258:11): [True: 0, False: 16]
  ------------------
  259|      0|        return false;
  260|      0|      }
  261|     16|    }
  262|    135|    num_new_vertices_ = num_new_verts;
  263|    135|  }
  264|    348|#endif
  265|       |
  266|    348|  uint32_t num_encoded_vertices;
  267|    348|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  268|    348|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    348|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (268:7): [True: 119, False: 229]
  ------------------
  269|    119|    if (!decoder_->buffer()->Decode(&num_encoded_vertices)) {
  ------------------
  |  Branch (269:9): [True: 0, False: 119]
  ------------------
  270|      0|      return false;
  271|      0|    }
  272|       |
  273|    119|  } else
  274|    229|#endif
  275|    229|  {
  276|    229|    if (!DecodeVarint(&num_encoded_vertices, decoder_->buffer())) {
  ------------------
  |  Branch (276:9): [True: 0, False: 229]
  ------------------
  277|      0|      return false;
  278|      0|    }
  279|    229|  }
  280|    348|  num_encoded_vertices_ = num_encoded_vertices;
  281|       |
  282|    348|  uint32_t num_faces;
  283|    348|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  284|    348|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    348|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (284:7): [True: 119, False: 229]
  ------------------
  285|    119|    if (!decoder_->buffer()->Decode(&num_faces)) {
  ------------------
  |  Branch (285:9): [True: 0, False: 119]
  ------------------
  286|      0|      return false;
  287|      0|    }
  288|       |
  289|    119|  } else
  290|    229|#endif
  291|    229|  {
  292|    229|    if (!DecodeVarint(&num_faces, decoder_->buffer())) {
  ------------------
  |  Branch (292:9): [True: 0, False: 229]
  ------------------
  293|      0|      return false;
  294|      0|    }
  295|    229|  }
  296|    348|  if (num_faces > std::numeric_limits<CornerIndex::ValueType>::max() / 3) {
  ------------------
  |  Branch (296:7): [True: 0, False: 348]
  ------------------
  297|      0|    return false;  // Draco cannot handle this many faces.
  298|      0|  }
  299|       |
  300|    348|  if (static_cast<uint32_t>(num_encoded_vertices_) > num_faces * 3) {
  ------------------
  |  Branch (300:7): [True: 2, False: 346]
  ------------------
  301|      2|    return false;  // There cannot be more vertices than 3 * num_faces.
  302|      2|  }
  303|       |
  304|       |  // Minimum number of edges of the mesh assuming each edge is shared between
  305|       |  // two faces.
  306|    346|  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|    346|  const uint64_t num_encoded_vertices_64 =
  311|    346|      static_cast<uint64_t>(num_encoded_vertices_);
  312|    346|  const uint64_t max_num_vertex_edges =
  313|    346|      num_encoded_vertices_64 * (num_encoded_vertices_64 - 1) / 2;
  314|    346|  if (max_num_vertex_edges < min_num_face_edges) {
  ------------------
  |  Branch (314:7): [True: 0, False: 346]
  ------------------
  315|       |    // It is impossible to construct a manifold mesh with these properties.
  316|      0|    return false;
  317|      0|  }
  318|       |
  319|    346|  uint8_t num_attribute_data;
  320|    346|  if (!decoder_->buffer()->Decode(&num_attribute_data)) {
  ------------------
  |  Branch (320:7): [True: 0, False: 346]
  ------------------
  321|      0|    return false;
  322|      0|  }
  323|       |
  324|    346|  uint32_t num_encoded_symbols;
  325|    346|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  326|    346|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    346|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (326:7): [True: 117, False: 229]
  ------------------
  327|    117|    if (!decoder_->buffer()->Decode(&num_encoded_symbols)) {
  ------------------
  |  Branch (327:9): [True: 0, False: 117]
  ------------------
  328|      0|      return false;
  329|      0|    }
  330|       |
  331|    117|  } else
  332|    229|#endif
  333|    229|  {
  334|    229|    if (!DecodeVarint(&num_encoded_symbols, decoder_->buffer())) {
  ------------------
  |  Branch (334:9): [True: 0, False: 229]
  ------------------
  335|      0|      return false;
  336|      0|    }
  337|    229|  }
  338|       |
  339|    346|  if (num_faces < num_encoded_symbols) {
  ------------------
  |  Branch (339:7): [True: 1, False: 345]
  ------------------
  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|      1|    return false;
  344|      1|  }
  345|    345|  const uint32_t max_encoded_faces =
  346|    345|      num_encoded_symbols + (num_encoded_symbols / 3);
  347|    345|  if (num_faces > max_encoded_faces) {
  ------------------
  |  Branch (347:7): [True: 0, False: 345]
  ------------------
  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|      0|    return false;
  352|      0|  }
  353|       |
  354|    345|  uint32_t num_encoded_split_symbols;
  355|    345|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  356|    345|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    345|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (356:7): [True: 117, False: 228]
  ------------------
  357|    117|    if (!decoder_->buffer()->Decode(&num_encoded_split_symbols)) {
  ------------------
  |  Branch (357:9): [True: 0, False: 117]
  ------------------
  358|      0|      return false;
  359|      0|    }
  360|       |
  361|    117|  } else
  362|    228|#endif
  363|    228|  {
  364|    228|    if (!DecodeVarint(&num_encoded_split_symbols, decoder_->buffer())) {
  ------------------
  |  Branch (364:9): [True: 0, False: 228]
  ------------------
  365|      0|      return false;
  366|      0|    }
  367|    228|  }
  368|       |
  369|    345|  if (num_encoded_split_symbols > num_encoded_symbols) {
  ------------------
  |  Branch (369:7): [True: 0, False: 345]
  ------------------
  370|      0|    return false;  // Split symbols are a sub-set of all symbols.
  371|      0|  }
  372|       |
  373|       |  // Decode topology (connectivity).
  374|    345|  vertex_traversal_length_.clear();
  375|    345|  corner_table_ = std::unique_ptr<CornerTable>(new CornerTable());
  376|    345|  if (corner_table_ == nullptr) {
  ------------------
  |  Branch (376:7): [True: 0, False: 345]
  ------------------
  377|      0|    return false;
  378|      0|  }
  379|    345|  processed_corner_ids_.clear();
  380|    345|  processed_corner_ids_.reserve(num_faces);
  381|    345|  processed_connectivity_corners_.clear();
  382|    345|  processed_connectivity_corners_.reserve(num_faces);
  383|    345|  topology_split_data_.clear();
  384|    345|  hole_event_data_.clear();
  385|    345|  init_face_configurations_.clear();
  386|    345|  init_corners_.clear();
  387|       |
  388|    345|  last_symbol_id_ = -1;
  389|    345|  last_face_id_ = -1;
  390|    345|  last_vert_id_ = -1;
  391|       |
  392|    345|  attribute_data_.clear();
  393|       |  // Add one attribute data for each attribute decoder.
  394|    345|  attribute_data_.resize(num_attribute_data);
  395|       |
  396|    345|  if (!corner_table_->Reset(
  ------------------
  |  Branch (396:7): [True: 0, False: 345]
  ------------------
  397|    345|          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|    345|  is_vert_hole_.assign(num_encoded_vertices_ + num_encoded_split_symbols, true);
  407|       |
  408|    345|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  409|    345|  int32_t topology_split_decoded_bytes = -1;
  410|    345|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    345|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (410:7): [True: 133, False: 212]
  ------------------
  411|    133|    uint32_t encoded_connectivity_size;
  412|    133|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    133|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (412:9): [True: 117, False: 16]
  ------------------
  413|    117|      if (!decoder_->buffer()->Decode(&encoded_connectivity_size)) {
  ------------------
  |  Branch (413:11): [True: 0, False: 117]
  ------------------
  414|      0|        return false;
  415|      0|      }
  416|    117|    } else {
  417|     16|      if (!DecodeVarint(&encoded_connectivity_size, decoder_->buffer())) {
  ------------------
  |  Branch (417:11): [True: 0, False: 16]
  ------------------
  418|      0|        return false;
  419|      0|      }
  420|     16|    }
  421|    133|    if (encoded_connectivity_size == 0 ||
  ------------------
  |  Branch (421:9): [True: 1, False: 132]
  ------------------
  422|    133|        encoded_connectivity_size > decoder_->buffer()->remaining_size()) {
  ------------------
  |  Branch (422:9): [True: 0, False: 132]
  ------------------
  423|      1|      return false;
  424|      1|    }
  425|    132|    DecoderBuffer event_buffer;
  426|    132|    event_buffer.Init(
  427|    132|        decoder_->buffer()->data_head() + encoded_connectivity_size,
  428|    132|        decoder_->buffer()->remaining_size() - encoded_connectivity_size,
  429|    132|        decoder_->buffer()->bitstream_version());
  430|       |    // Decode hole and topology split events.
  431|    132|    topology_split_decoded_bytes =
  432|    132|        DecodeHoleAndTopologySplitEvents(&event_buffer);
  433|    132|    if (topology_split_decoded_bytes == -1) {
  ------------------
  |  Branch (433:9): [True: 22, False: 110]
  ------------------
  434|     22|      return false;
  435|     22|    }
  436|       |
  437|    132|  } else
  438|    212|#endif
  439|    212|  {
  440|    212|    if (DecodeHoleAndTopologySplitEvents(decoder_->buffer()) == -1) {
  ------------------
  |  Branch (440:9): [True: 1, False: 211]
  ------------------
  441|      1|      return false;
  442|      1|    }
  443|    212|  }
  444|       |
  445|    321|  traversal_decoder_.Init(this);
  446|       |  // Add one extra vertex for each split symbol.
  447|    321|  traversal_decoder_.SetNumEncodedVertices(num_encoded_vertices_ +
  448|    321|                                           num_encoded_split_symbols);
  449|    321|  traversal_decoder_.SetNumAttributeData(num_attribute_data);
  450|       |
  451|    321|  DecoderBuffer traversal_end_buffer;
  452|    321|  if (!traversal_decoder_.Start(&traversal_end_buffer)) {
  ------------------
  |  Branch (452:7): [True: 134, False: 187]
  ------------------
  453|    134|    return false;
  454|    134|  }
  455|       |
  456|    187|  const int num_connectivity_verts = DecodeConnectivity(num_encoded_symbols);
  457|    187|  if (num_connectivity_verts == -1) {
  ------------------
  |  Branch (457:7): [True: 109, False: 78]
  ------------------
  458|    109|    return false;
  459|    109|  }
  460|       |
  461|       |  // Set the main buffer to the end of the traversal.
  462|     78|  decoder_->buffer()->Init(traversal_end_buffer.data_head(),
  463|     78|                           traversal_end_buffer.remaining_size(),
  464|     78|                           decoder_->buffer()->bitstream_version());
  465|       |
  466|     78|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  467|     78|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|     78|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (467:7): [True: 0, False: 78]
  ------------------
  468|       |    // Skip topology split data that was already decoded earlier.
  469|      0|    decoder_->buffer()->Advance(topology_split_decoded_bytes);
  470|      0|  }
  471|     78|#endif
  472|       |
  473|       |  // Decode connectivity of non-position attributes.
  474|     78|  if (!attribute_data_.empty()) {
  ------------------
  |  Branch (474:7): [True: 18, False: 60]
  ------------------
  475|     18|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  476|     18|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
  ------------------
  |  |  115|     18|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (476:9): [True: 0, False: 18]
  ------------------
  477|      0|      for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
  ------------------
  |  Branch (477:31): [True: 0, False: 0]
  ------------------
  478|      0|        if (!DecodeAttributeConnectivitiesOnFaceLegacy(ci)) {
  ------------------
  |  Branch (478:13): [True: 0, False: 0]
  ------------------
  479|      0|          return false;
  480|      0|        }
  481|      0|      }
  482|       |
  483|      0|    } else
  484|     18|#endif
  485|     18|    {
  486|   102k|      for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
  ------------------
  |  Branch (486:31): [True: 102k, False: 18]
  ------------------
  487|   102k|        if (!DecodeAttributeConnectivitiesOnFace(ci)) {
  ------------------
  |  Branch (487:13): [True: 0, False: 102k]
  ------------------
  488|      0|          return false;
  489|      0|        }
  490|   102k|      }
  491|     18|    }
  492|     18|  }
  493|     78|  traversal_decoder_.Done();
  494|       |
  495|       |  // Decode attribute connectivity.
  496|       |  // Prepare data structure for decoding non-position attribute connectivity.
  497|    116|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (497:24): [True: 38, False: 78]
  ------------------
  498|     38|    attribute_data_[i].connectivity_data.InitEmpty(corner_table_.get());
  499|       |    // Add all seams.
  500|   164k|    for (int32_t c : attribute_data_[i].attribute_seam_corners) {
  ------------------
  |  Branch (500:20): [True: 164k, False: 38]
  ------------------
  501|   164k|      attribute_data_[i].connectivity_data.AddSeamEdge(CornerIndex(c));
  502|   164k|    }
  503|       |    // Recompute vertices from the newly added seam edges.
  504|     38|    if (!attribute_data_[i].connectivity_data.RecomputeVertices(nullptr,
  ------------------
  |  Branch (504:9): [True: 0, False: 38]
  ------------------
  505|     38|                                                                nullptr)) {
  506|      0|      return false;
  507|      0|    }
  508|     38|  }
  509|       |
  510|     78|  pos_encoding_data_.Init(corner_table_->num_vertices());
  511|    116|  for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (511:24): [True: 38, False: 78]
  ------------------
  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|     38|    int32_t att_connectivity_verts =
  517|     38|        attribute_data_[i].connectivity_data.num_vertices();
  518|     38|    if (att_connectivity_verts < corner_table_->num_vertices()) {
  ------------------
  |  Branch (518:9): [True: 0, False: 38]
  ------------------
  519|      0|      att_connectivity_verts = corner_table_->num_vertices();
  520|      0|    }
  521|     38|    attribute_data_[i].encoding_data.Init(att_connectivity_verts);
  522|     38|  }
  523|     78|  if (!AssignPointsToCorners(num_connectivity_verts)) {
  ------------------
  |  Branch (523:7): [True: 0, False: 78]
  ------------------
  524|      0|    return false;
  525|      0|  }
  526|     78|  return true;
  527|     78|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE19OnAttributesDecodedEv:
  530|     10|bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::OnAttributesDecoded() {
  531|     10|  return true;
  532|     10|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE18DecodeConnectivityEi:
  536|    187|    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|    187|  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|    187|  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|    187|  std::vector<VertexIndex> invalid_vertices;
  558|    187|  const bool remove_invalid_vertices = attribute_data_.empty();
  559|       |
  560|    187|  int max_num_vertices = static_cast<int>(is_vert_hole_.size());
  561|    187|  int num_faces = 0;
  562|   953k|  for (int symbol_id = 0; symbol_id < num_symbols; ++symbol_id) {
  ------------------
  |  Branch (562:27): [True: 953k, False: 79]
  ------------------
  563|   953k|    const FaceIndex face(num_faces++);
  564|       |    // Used to flag cases where we need to look for topology split events.
  565|   953k|    bool check_topology_split = false;
  566|   953k|    const uint32_t symbol = traversal_decoder_.DecodeSymbol();
  567|   953k|    if (symbol == TOPOLOGY_C) {
  ------------------
  |  Branch (567:9): [True: 27.7k, False: 925k]
  ------------------
  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|  27.7k|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (587:11): [True: 45, False: 27.6k]
  ------------------
  588|     45|        return -1;
  589|     45|      }
  590|       |
  591|  27.6k|      const CornerIndex corner_a = active_corner_stack.back();
  592|  27.6k|      const VertexIndex vertex_x =
  593|  27.6k|          corner_table_->Vertex(corner_table_->Next(corner_a));
  594|  27.6k|      const CornerIndex corner_b =
  595|  27.6k|          corner_table_->Next(corner_table_->LeftMostCorner(vertex_x));
  596|       |
  597|  27.6k|      if (corner_a == corner_b) {
  ------------------
  |  Branch (597:11): [True: 35, False: 27.6k]
  ------------------
  598|       |        // All matched corners must be different.
  599|     35|        return -1;
  600|     35|      }
  601|  27.6k|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex ||
  ------------------
  |  Branch (601:11): [True: 0, False: 27.6k]
  |  Branch (601:11): [True: 0, False: 27.6k]
  ------------------
  602|  27.6k|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex) {
  ------------------
  |  Branch (602:11): [True: 0, False: 27.6k]
  ------------------
  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|  27.6k|      const CornerIndex corner(3 * face.value());
  610|       |      // Update opposite corner mappings.
  611|  27.6k|      SetOppositeCorners(corner_a, corner + 1);
  612|  27.6k|      SetOppositeCorners(corner_b, corner + 2);
  613|       |
  614|       |      // Update vertex mapping.
  615|  27.6k|      const VertexIndex vert_a_prev =
  616|  27.6k|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  617|  27.6k|      const VertexIndex vert_b_next =
  618|  27.6k|          corner_table_->Vertex(corner_table_->Next(corner_b));
  619|  27.6k|      if (vertex_x == vert_a_prev || vertex_x == vert_b_next) {
  ------------------
  |  Branch (619:11): [True: 0, False: 27.6k]
  |  Branch (619:38): [True: 0, False: 27.6k]
  ------------------
  620|       |        // Encoding is invalid, because face vertices are degenerate.
  621|      0|        return -1;
  622|      0|      }
  623|  27.6k|      corner_table_->MapCornerToVertex(corner, vertex_x);
  624|  27.6k|      corner_table_->MapCornerToVertex(corner + 1, vert_b_next);
  625|  27.6k|      corner_table_->MapCornerToVertex(corner + 2, vert_a_prev);
  626|  27.6k|      corner_table_->SetLeftMostCorner(vert_a_prev, corner + 2);
  627|       |      // Mark the vertex |x| as interior.
  628|  27.6k|      is_vert_hole_[vertex_x.value()] = false;
  629|       |      // Update the corner on the active stack.
  630|  27.6k|      active_corner_stack.back() = corner;
  631|   925k|    } else if (symbol == TOPOLOGY_R || symbol == TOPOLOGY_L) {
  ------------------
  |  Branch (631:16): [True: 75, False: 925k]
  |  Branch (631:40): [True: 923k, False: 1.42k]
  ------------------
  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|   924k|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (646:11): [True: 0, False: 924k]
  ------------------
  647|      0|        return -1;
  648|      0|      }
  649|   924k|      const CornerIndex corner_a = active_corner_stack.back();
  650|   924k|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex) {
  ------------------
  |  Branch (650:11): [True: 0, False: 924k]
  ------------------
  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|   924k|      const CornerIndex corner(3 * face.value());
  658|   924k|      CornerIndex opp_corner, corner_l, corner_r;
  659|   924k|      if (symbol == TOPOLOGY_R) {
  ------------------
  |  Branch (659:11): [True: 75, False: 923k]
  ------------------
  660|       |        // "r" is the new first corner.
  661|     75|        opp_corner = corner + 2;
  662|     75|        corner_l = corner + 1;
  663|     75|        corner_r = corner;
  664|   923k|      } else {
  665|       |        // "l" is the new first corner.
  666|   923k|        opp_corner = corner + 1;
  667|   923k|        corner_l = corner;
  668|   923k|        corner_r = corner + 2;
  669|   923k|      }
  670|   924k|      SetOppositeCorners(opp_corner, corner_a);
  671|       |      // Update vertex mapping.
  672|   924k|      const VertexIndex new_vert_index = corner_table_->AddNewVertex();
  673|       |
  674|   924k|      if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (674:11): [True: 1, False: 924k]
  ------------------
  675|      1|        return -1;  // Unexpected number of decoded vertices.
  676|      1|      }
  677|       |
  678|   924k|      corner_table_->MapCornerToVertex(opp_corner, new_vert_index);
  679|   924k|      corner_table_->SetLeftMostCorner(new_vert_index, opp_corner);
  680|       |
  681|   924k|      const VertexIndex vertex_r =
  682|   924k|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  683|   924k|      corner_table_->MapCornerToVertex(corner_r, vertex_r);
  684|       |      // Update left-most corner on the vertex on the |corner_r|.
  685|   924k|      corner_table_->SetLeftMostCorner(vertex_r, corner_r);
  686|       |
  687|   924k|      corner_table_->MapCornerToVertex(
  688|   924k|          corner_l, corner_table_->Vertex(corner_table_->Next(corner_a)));
  689|   924k|      active_corner_stack.back() = corner;
  690|   924k|      check_topology_split = true;
  691|   924k|    } else if (symbol == TOPOLOGY_S) {
  ------------------
  |  Branch (691:16): [True: 4, False: 1.41k]
  ------------------
  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|      4|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (702:11): [True: 0, False: 4]
  ------------------
  703|      0|        return -1;
  704|      0|      }
  705|      4|      const CornerIndex corner_b = active_corner_stack.back();
  706|      4|      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|      4|      const auto it = topology_split_active_corners.find(symbol_id);
  711|      4|      if (it != topology_split_active_corners.end()) {
  ------------------
  |  Branch (711:11): [True: 0, False: 4]
  ------------------
  712|       |        // Topology split event. Move the retrieved edge to the stack.
  713|      0|        active_corner_stack.push_back(it->second);
  714|      0|      }
  715|      4|      if (active_corner_stack.empty()) {
  ------------------
  |  Branch (715:11): [True: 2, False: 2]
  ------------------
  716|      2|        return -1;
  717|      2|      }
  718|      2|      const CornerIndex corner_a = active_corner_stack.back();
  719|       |
  720|      2|      if (corner_a == corner_b) {
  ------------------
  |  Branch (720:11): [True: 0, False: 2]
  ------------------
  721|       |        // All matched corners must be different.
  722|      0|        return -1;
  723|      0|      }
  724|      2|      if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex ||
  ------------------
  |  Branch (724:11): [True: 0, False: 2]
  |  Branch (724:11): [True: 0, False: 2]
  ------------------
  725|      2|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex) {
  ------------------
  |  Branch (725:11): [True: 0, False: 2]
  ------------------
  726|       |        // One of the corners is already opposite to an existing face, which
  727|       |        // should not happen unless the input was tampered with.
  728|      0|        return -1;
  729|      0|      }
  730|       |
  731|       |      // First corner on the new face is corner "x" from the image above.
  732|      2|      const CornerIndex corner(3 * face.value());
  733|       |      // Update the opposite corner mapping.
  734|      2|      SetOppositeCorners(corner_a, corner + 2);
  735|      2|      SetOppositeCorners(corner_b, corner + 1);
  736|       |      // Update vertices. For the vertex at corner "x", use the vertex id from
  737|       |      // the corner "p".
  738|      2|      const VertexIndex vertex_p =
  739|      2|          corner_table_->Vertex(corner_table_->Previous(corner_a));
  740|      2|      corner_table_->MapCornerToVertex(corner, vertex_p);
  741|      2|      corner_table_->MapCornerToVertex(
  742|      2|          corner + 1, corner_table_->Vertex(corner_table_->Next(corner_a)));
  743|      2|      const VertexIndex vert_b_prev =
  744|      2|          corner_table_->Vertex(corner_table_->Previous(corner_b));
  745|      2|      corner_table_->MapCornerToVertex(corner + 2, vert_b_prev);
  746|      2|      corner_table_->SetLeftMostCorner(vert_b_prev, corner + 2);
  747|      2|      CornerIndex corner_n = corner_table_->Next(corner_b);
  748|      2|      const VertexIndex vertex_n = corner_table_->Vertex(corner_n);
  749|      2|      traversal_decoder_.MergeVertices(vertex_p, vertex_n);
  750|       |      // Update the left most corner on the newly merged vertex.
  751|      2|      corner_table_->SetLeftMostCorner(vertex_p,
  752|      2|                                       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|      2|      const CornerIndex first_corner = corner_n;
  757|      6|      while (corner_n != kInvalidCornerIndex) {
  ------------------
  |  Branch (757:14): [True: 4, False: 2]
  ------------------
  758|      4|        corner_table_->MapCornerToVertex(corner_n, vertex_p);
  759|      4|        corner_n = corner_table_->SwingLeft(corner_n);
  760|      4|        if (corner_n == first_corner) {
  ------------------
  |  Branch (760:13): [True: 0, False: 4]
  ------------------
  761|       |          // We reached the start again which should not happen for split
  762|       |          // symbols.
  763|      0|          return -1;
  764|      0|        }
  765|      4|      }
  766|       |      // Make sure the old vertex n is now mapped to an invalid corner (make it
  767|       |      // isolated).
  768|      2|      corner_table_->MakeVertexIsolated(vertex_n);
  769|      2|      if (remove_invalid_vertices) {
  ------------------
  |  Branch (769:11): [True: 2, False: 0]
  ------------------
  770|      2|        invalid_vertices.push_back(vertex_n);
  771|      2|      }
  772|      2|      active_corner_stack.back() = corner;
  773|  1.41k|    } else if (symbol == TOPOLOGY_E) {
  ------------------
  |  Branch (773:16): [True: 1.39k, False: 25]
  ------------------
  774|  1.39k|      const CornerIndex corner(3 * face.value());
  775|  1.39k|      const VertexIndex first_vert_index = corner_table_->AddNewVertex();
  776|       |      // Create three new vertices at the corners of the new face.
  777|  1.39k|      corner_table_->MapCornerToVertex(corner, first_vert_index);
  778|  1.39k|      corner_table_->MapCornerToVertex(corner + 1,
  779|  1.39k|                                       corner_table_->AddNewVertex());
  780|  1.39k|      corner_table_->MapCornerToVertex(corner + 2,
  781|  1.39k|                                       corner_table_->AddNewVertex());
  782|       |
  783|  1.39k|      if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (783:11): [True: 0, False: 1.39k]
  ------------------
  784|      0|        return -1;  // Unexpected number of decoded vertices.
  785|      0|      }
  786|       |
  787|  1.39k|      corner_table_->SetLeftMostCorner(first_vert_index, corner);
  788|  1.39k|      corner_table_->SetLeftMostCorner(first_vert_index + 1, corner + 1);
  789|  1.39k|      corner_table_->SetLeftMostCorner(first_vert_index + 2, corner + 2);
  790|       |      // Add the tip corner to the active stack.
  791|  1.39k|      active_corner_stack.push_back(corner);
  792|  1.39k|      check_topology_split = true;
  793|  1.39k|    } else {
  794|       |      // Error. Unknown symbol decoded.
  795|     25|      return -1;
  796|     25|    }
  797|       |    // Inform the traversal decoder that a new corner has been reached.
  798|   953k|    traversal_decoder_.NewActiveCornerReached(active_corner_stack.back());
  799|       |
  800|   953k|    if (check_topology_split) {
  ------------------
  |  Branch (800:9): [True: 925k, False: 27.6k]
  ------------------
  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|   925k|      const int encoder_symbol_id = num_symbols - symbol_id - 1;
  811|   925k|      EdgeFaceName split_edge;
  812|   925k|      int encoder_split_symbol_id;
  813|   925k|      while (IsTopologySplit(encoder_symbol_id, &split_edge,
  ------------------
  |  Branch (813:14): [True: 376, False: 925k]
  ------------------
  814|   925k|                             &encoder_split_symbol_id)) {
  815|    376|        if (encoder_split_symbol_id < 0) {
  ------------------
  |  Branch (815:13): [True: 0, False: 376]
  ------------------
  816|      0|          return -1;  // Wrong split symbol id.
  817|      0|        }
  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|    376|        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|    376|        CornerIndex new_active_corner;
  831|    376|        if (split_edge == RIGHT_FACE_EDGE) {
  ------------------
  |  Branch (831:13): [True: 100, False: 276]
  ------------------
  832|    100|          new_active_corner = corner_table_->Next(act_top_corner);
  833|    276|        } else {
  834|    276|          new_active_corner = corner_table_->Previous(act_top_corner);
  835|    276|        }
  836|       |        // Add the new active edge.
  837|       |        // Convert the encoder split symbol id to decoder symbol id.
  838|    376|        const int decoder_split_symbol_id =
  839|    376|            num_symbols - encoder_split_symbol_id - 1;
  840|    376|        topology_split_active_corners[decoder_split_symbol_id] =
  841|    376|            new_active_corner;
  842|    376|      }
  843|   925k|    }
  844|   953k|  }
  845|     79|  if (corner_table_->num_vertices() > max_num_vertices) {
  ------------------
  |  Branch (845:7): [True: 0, False: 79]
  ------------------
  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|    156|  while (!active_corner_stack.empty()) {
  ------------------
  |  Branch (849:10): [True: 78, False: 78]
  ------------------
  850|     78|    const CornerIndex corner = active_corner_stack.back();
  851|     78|    active_corner_stack.pop_back();
  852|     78|    const bool interior_face =
  853|     78|        traversal_decoder_.DecodeStartFaceConfiguration();
  854|     78|    if (interior_face) {
  ------------------
  |  Branch (854:9): [True: 1, False: 77]
  ------------------
  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|      1|      if (num_faces >= corner_table_->num_faces()) {
  ------------------
  |  Branch (876:11): [True: 1, False: 0]
  ------------------
  877|      1|        return -1;  // More faces than expected added to the mesh.
  878|      1|      }
  879|       |
  880|      0|      const CornerIndex corner_a = corner;
  881|      0|      const VertexIndex vert_n =
  882|      0|          corner_table_->Vertex(corner_table_->Next(corner_a));
  883|      0|      const CornerIndex corner_b =
  884|      0|          corner_table_->Next(corner_table_->LeftMostCorner(vert_n));
  885|       |
  886|      0|      const VertexIndex vert_x =
  887|      0|          corner_table_->Vertex(corner_table_->Next(corner_b));
  888|      0|      const CornerIndex corner_c =
  889|      0|          corner_table_->Next(corner_table_->LeftMostCorner(vert_x));
  890|       |
  891|      0|      if (corner == corner_b || corner == corner_c || corner_b == corner_c) {
  ------------------
  |  Branch (891:11): [True: 0, False: 0]
  |  Branch (891:33): [True: 0, False: 0]
  |  Branch (891:55): [True: 0, False: 0]
  ------------------
  892|       |        // All matched corners must be different.
  893|      0|        return -1;
  894|      0|      }
  895|      0|      if (corner_table_->Opposite(corner) != kInvalidCornerIndex ||
  ------------------
  |  Branch (895:11): [True: 0, False: 0]
  |  Branch (895:11): [True: 0, False: 0]
  ------------------
  896|      0|          corner_table_->Opposite(corner_b) != kInvalidCornerIndex ||
  ------------------
  |  Branch (896:11): [True: 0, False: 0]
  ------------------
  897|      0|          corner_table_->Opposite(corner_c) != kInvalidCornerIndex) {
  ------------------
  |  Branch (897:11): [True: 0, False: 0]
  ------------------
  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|      0|      const VertexIndex vert_p =
  904|      0|          corner_table_->Vertex(corner_table_->Next(corner_c));
  905|       |
  906|      0|      const FaceIndex face(num_faces++);
  907|       |      // The first corner of the initial face is the corner opposite to "a".
  908|      0|      const CornerIndex new_corner(3 * face.value());
  909|      0|      SetOppositeCorners(new_corner, corner);
  910|      0|      SetOppositeCorners(new_corner + 1, corner_b);
  911|      0|      SetOppositeCorners(new_corner + 2, corner_c);
  912|       |
  913|       |      // Map new corners to existing vertices.
  914|      0|      corner_table_->MapCornerToVertex(new_corner, vert_x);
  915|      0|      corner_table_->MapCornerToVertex(new_corner + 1, vert_p);
  916|      0|      corner_table_->MapCornerToVertex(new_corner + 2, vert_n);
  917|       |
  918|       |      // Mark all three vertices as interior.
  919|      0|      for (int ci = 0; ci < 3; ++ci) {
  ------------------
  |  Branch (919:24): [True: 0, False: 0]
  ------------------
  920|      0|        is_vert_hole_[corner_table_->Vertex(new_corner + ci).value()] = false;
  921|      0|      }
  922|       |
  923|      0|      init_face_configurations_.push_back(true);
  924|      0|      init_corners_.push_back(new_corner);
  925|     77|    } 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|     77|      init_face_configurations_.push_back(false);
  930|     77|      init_corners_.push_back(corner);
  931|     77|    }
  932|     78|  }
  933|     78|  if (num_faces != corner_table_->num_faces()) {
  ------------------
  |  Branch (933:7): [True: 0, False: 78]
  ------------------
  934|      0|    return -1;  // Unexpected number of decoded faces.
  935|      0|  }
  936|       |
  937|     78|  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|     78|  for (const VertexIndex invalid_vert : invalid_vertices) {
  ------------------
  |  Branch (940:39): [True: 2, False: 78]
  ------------------
  941|       |    // Find the last valid vertex and swap it with the isolated vertex.
  942|      2|    VertexIndex src_vert(num_vertices - 1);
  943|      2|    while (corner_table_->LeftMostCorner(src_vert) == kInvalidCornerIndex) {
  ------------------
  |  Branch (943:12): [True: 0, False: 2]
  ------------------
  944|       |      // The last vertex is invalid, proceed to the previous one.
  945|      0|      src_vert = VertexIndex(--num_vertices - 1);
  946|      0|    }
  947|      2|    if (src_vert < invalid_vert) {
  ------------------
  |  Branch (947:9): [True: 0, False: 2]
  ------------------
  948|      0|      continue;  // No need to swap anything.
  949|      0|    }
  950|       |
  951|       |    // Remap all corners mapped to |src_vert| to |invalid_vert|.
  952|      2|    VertexCornersIterator<CornerTable> vcit(corner_table_.get(), src_vert);
  953|     20|    for (; !vcit.End(); ++vcit) {
  ------------------
  |  Branch (953:12): [True: 18, False: 2]
  ------------------
  954|     18|      const CornerIndex cid = vcit.Corner();
  955|     18|      if (corner_table_->Vertex(cid) != src_vert) {
  ------------------
  |  Branch (955:11): [True: 0, False: 18]
  ------------------
  956|       |        // Vertex mapped to |cid| was not |src_vert|. This indicates corrupted
  957|       |        // data and we should terminate the decoding.
  958|      0|        return -1;
  959|      0|      }
  960|     18|      corner_table_->MapCornerToVertex(cid, invalid_vert);
  961|     18|    }
  962|      2|    corner_table_->SetLeftMostCorner(invalid_vert,
  963|      2|                                     corner_table_->LeftMostCorner(src_vert));
  964|       |
  965|       |    // Make the |src_vert| invalid.
  966|      2|    corner_table_->MakeVertexIsolated(src_vert);
  967|      2|    is_vert_hole_[invalid_vert.value()] = is_vert_hole_[src_vert.value()];
  968|      2|    is_vert_hole_[src_vert.value()] = false;
  969|       |
  970|       |    // The last vertex is now invalid.
  971|      2|    num_vertices--;
  972|      2|  }
  973|     78|  return num_vertices;
  974|     78|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE32DecodeHoleAndTopologySplitEventsEPNS_13DecoderBufferE:
  979|    344|    DecoderBuffer *decoder_buffer) {
  980|       |  // Prepare a new decoder from the provided buffer offset.
  981|    344|  uint32_t num_topology_splits;
  982|    344|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  983|    344|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    344|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (983:7): [True: 116, False: 228]
  ------------------
  984|    116|    if (!decoder_buffer->Decode(&num_topology_splits)) {
  ------------------
  |  Branch (984:9): [True: 0, False: 116]
  ------------------
  985|      0|      return -1;
  986|      0|    }
  987|       |
  988|    116|  } else
  989|    228|#endif
  990|    228|  {
  991|    228|    if (!DecodeVarint(&num_topology_splits, decoder_buffer)) {
  ------------------
  |  Branch (991:9): [True: 0, False: 228]
  ------------------
  992|      0|      return -1;
  993|      0|    }
  994|    228|  }
  995|    344|  if (num_topology_splits > 0) {
  ------------------
  |  Branch (995:7): [True: 99, False: 245]
  ------------------
  996|     99|    if (num_topology_splits >
  ------------------
  |  Branch (996:9): [True: 1, False: 98]
  ------------------
  997|     99|        static_cast<uint32_t>(corner_table_->num_faces())) {
  998|      1|      return -1;
  999|      1|    }
 1000|     98|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1001|     98|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|     98|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1001:9): [True: 13, False: 85]
  ------------------
 1002|  33.5k|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1002:28): [True: 33.5k, False: 5]
  ------------------
 1003|  33.5k|        TopologySplitEventData event_data;
 1004|  33.5k|        if (!decoder_buffer->Decode(&event_data.split_symbol_id)) {
  ------------------
  |  Branch (1004:13): [True: 3, False: 33.5k]
  ------------------
 1005|      3|          return -1;
 1006|      3|        }
 1007|  33.5k|        if (!decoder_buffer->Decode(&event_data.source_symbol_id)) {
  ------------------
  |  Branch (1007:13): [True: 5, False: 33.5k]
  ------------------
 1008|      5|          return -1;
 1009|      5|        }
 1010|  33.5k|        uint8_t edge_data;
 1011|  33.5k|        if (!decoder_buffer->Decode(&edge_data)) {
  ------------------
  |  Branch (1011:13): [True: 0, False: 33.5k]
  ------------------
 1012|      0|          return -1;
 1013|      0|        }
 1014|  33.5k|        event_data.source_edge = edge_data & 1;
 1015|  33.5k|        topology_split_data_.push_back(event_data);
 1016|  33.5k|      }
 1017|       |
 1018|     13|    } else
 1019|     85|#endif
 1020|     85|    {
 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|     85|      int last_source_symbol_id = 0;
 1024|  1.87k|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1024:28): [True: 1.79k, False: 84]
  ------------------
 1025|  1.79k|        TopologySplitEventData event_data;
 1026|  1.79k|        uint32_t delta;
 1027|  1.79k|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1027:13): [True: 0, False: 1.79k]
  ------------------
 1028|      0|          return -1;
 1029|      0|        }
 1030|  1.79k|        event_data.source_symbol_id = delta + last_source_symbol_id;
 1031|  1.79k|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1031:13): [True: 1, False: 1.79k]
  ------------------
 1032|      1|          return -1;
 1033|      1|        }
 1034|  1.79k|        if (delta > event_data.source_symbol_id) {
  ------------------
  |  Branch (1034:13): [True: 0, False: 1.79k]
  ------------------
 1035|      0|          return -1;
 1036|      0|        }
 1037|  1.79k|        event_data.split_symbol_id =
 1038|  1.79k|            event_data.source_symbol_id - static_cast<int32_t>(delta);
 1039|  1.79k|        last_source_symbol_id = event_data.source_symbol_id;
 1040|  1.79k|        topology_split_data_.push_back(event_data);
 1041|  1.79k|      }
 1042|       |      // Split edges are decoded from a direct bit decoder.
 1043|     84|      decoder_buffer->StartBitDecoding(false, nullptr);
 1044|  1.38k|      for (uint32_t i = 0; i < num_topology_splits; ++i) {
  ------------------
  |  Branch (1044:28): [True: 1.30k, False: 84]
  ------------------
 1045|  1.30k|        uint32_t edge_data;
 1046|  1.30k|        if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  1.30k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1046:13): [True: 456, False: 846]
  ------------------
 1047|    456|          decoder_buffer->DecodeLeastSignificantBits32(2, &edge_data);
 1048|    846|        } else {
 1049|    846|          decoder_buffer->DecodeLeastSignificantBits32(1, &edge_data);
 1050|    846|        }
 1051|  1.30k|        TopologySplitEventData &event_data = topology_split_data_[i];
 1052|  1.30k|        event_data.source_edge = edge_data & 1;
 1053|  1.30k|      }
 1054|     84|      decoder_buffer->EndBitDecoding();
 1055|     84|    }
 1056|     98|  }
 1057|    334|  uint32_t num_hole_events = 0;
 1058|    334|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1059|    334|  if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
  ------------------
  |  |  115|    334|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1059:7): [True: 107, False: 227]
  ------------------
 1060|    107|    if (!decoder_buffer->Decode(&num_hole_events)) {
  ------------------
  |  Branch (1060:9): [True: 0, False: 107]
  ------------------
 1061|      0|      return -1;
 1062|      0|    }
 1063|    227|  } else if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
  ------------------
  |  |  115|    227|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1063:14): [True: 16, False: 211]
  ------------------
 1064|     16|    if (!DecodeVarint(&num_hole_events, decoder_buffer)) {
  ------------------
  |  Branch (1064:9): [True: 1, False: 15]
  ------------------
 1065|      1|      return -1;
 1066|      1|    }
 1067|     16|  }
 1068|    333|#endif
 1069|    333|  if (num_hole_events > 0) {
  ------------------
  |  Branch (1069:7): [True: 14, False: 319]
  ------------------
 1070|     14|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
 1071|     14|    if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) {
  ------------------
  |  |  115|     14|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (1071:9): [True: 11, False: 3]
  ------------------
 1072|   135k|      for (uint32_t i = 0; i < num_hole_events; ++i) {
  ------------------
  |  Branch (1072:28): [True: 135k, False: 0]
  ------------------
 1073|   135k|        HoleEventData event_data;
 1074|   135k|        if (!decoder_buffer->Decode(&event_data)) {
  ------------------
  |  Branch (1074:13): [True: 11, False: 135k]
  ------------------
 1075|     11|          return -1;
 1076|     11|        }
 1077|   135k|        hole_event_data_.push_back(event_data);
 1078|   135k|      }
 1079|       |
 1080|     11|    } else
 1081|      3|#endif
 1082|      3|    {
 1083|       |      // Decode hole symbol ids using delta and varint coding.
 1084|      3|      int last_symbol_id = 0;
 1085|  9.47k|      for (uint32_t i = 0; i < num_hole_events; ++i) {
  ------------------
  |  Branch (1085:28): [True: 9.47k, False: 2]
  ------------------
 1086|  9.47k|        HoleEventData event_data;
 1087|  9.47k|        uint32_t delta;
 1088|  9.47k|        if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
  ------------------
  |  Branch (1088:13): [True: 1, False: 9.47k]
  ------------------
 1089|      1|          return -1;
 1090|      1|        }
 1091|  9.47k|        event_data.symbol_id = delta + last_symbol_id;
 1092|  9.47k|        last_symbol_id = event_data.symbol_id;
 1093|  9.47k|        hole_event_data_.push_back(event_data);
 1094|  9.47k|      }
 1095|      3|    }
 1096|     14|  }
 1097|    321|  return static_cast<int32_t>(decoder_buffer->decoded_size());
 1098|    333|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE35DecodeAttributeConnectivitiesOnFaceENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
 1132|   102k|    TraversalDecoder>::DecodeAttributeConnectivitiesOnFace(CornerIndex corner) {
 1133|       |  // Three corners of the face.
 1134|   102k|  const CornerIndex corners[3] = {corner, corner_table_->Next(corner),
 1135|   102k|                                  corner_table_->Previous(corner)};
 1136|       |
 1137|   102k|  const FaceIndex src_face_id = corner_table_->Face(corner);
 1138|   411k|  for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1138:19): [True: 308k, False: 102k]
  ------------------
 1139|   308k|    const CornerIndex opp_corner = corner_table_->Opposite(corners[c]);
 1140|   308k|    if (opp_corner == kInvalidCornerIndex) {
  ------------------
  |  Branch (1140:9): [True: 50.4k, False: 258k]
  ------------------
 1141|       |      // Don't decode attribute seams on boundary edges (every boundary edge
 1142|       |      // is automatically an attribute seam).
 1143|   151k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1143:28): [True: 100k, False: 50.4k]
  ------------------
 1144|   100k|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1145|   100k|      }
 1146|  50.4k|      continue;
 1147|  50.4k|    }
 1148|   258k|    const FaceIndex opp_face_id = corner_table_->Face(opp_corner);
 1149|       |    // Don't decode edges when the opposite face has been already processed.
 1150|   258k|    if (opp_face_id < src_face_id) {
  ------------------
  |  Branch (1150:9): [True: 129k, False: 129k]
  ------------------
 1151|   129k|      continue;
 1152|   129k|    }
 1153|       |
 1154|   387k|    for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1154:26): [True: 258k, False: 129k]
  ------------------
 1155|   258k|      const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i);
 1156|   258k|      if (is_seam) {
  ------------------
  |  Branch (1156:11): [True: 63.6k, False: 194k]
  ------------------
 1157|  63.6k|        attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
 1158|  63.6k|      }
 1159|   258k|    }
 1160|   129k|  }
 1161|   102k|  return true;
 1162|   102k|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE21AssignPointsToCornersEi:
 1166|     78|    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|     78|  decoder_->mesh()->SetNumFaces(corner_table_->num_faces());
 1171|       |
 1172|     78|  if (attribute_data_.empty()) {
  ------------------
  |  Branch (1172:7): [True: 60, False: 18]
  ------------------
 1173|       |    // We have connectivity for position only. In this case all vertex indices
 1174|       |    // are equal to point indices.
 1175|  5.01k|    for (FaceIndex f(0); f < decoder_->mesh()->num_faces(); ++f) {
  ------------------
  |  Branch (1175:26): [True: 4.95k, False: 60]
  ------------------
 1176|  4.95k|      Mesh::Face face;
 1177|  4.95k|      const CornerIndex start_corner(3 * f.value());
 1178|  19.8k|      for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1178:23): [True: 14.8k, False: 4.95k]
  ------------------
 1179|       |        // Get the vertex index on the corner and use it as a point index.
 1180|  14.8k|        const int32_t vert_id = corner_table_->Vertex(start_corner + c).value();
 1181|  14.8k|        face[c] = vert_id;
 1182|  14.8k|      }
 1183|  4.95k|      decoder_->mesh()->SetFace(f, face);
 1184|  4.95k|    }
 1185|     60|    decoder_->point_cloud()->set_num_points(num_connectivity_verts);
 1186|     60|    return true;
 1187|     60|  }
 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|     18|  std::vector<int32_t> point_to_corner_map;
 1194|       |  // Map between every corner and their new point ids.
 1195|     18|  std::vector<int32_t> corner_to_point_map(corner_table_->num_corners());
 1196|  76.7k|  for (int v = 0; v < corner_table_->num_vertices(); ++v) {
  ------------------
  |  Branch (1196:19): [True: 76.6k, False: 18]
  ------------------
 1197|  76.6k|    CornerIndex c = corner_table_->LeftMostCorner(VertexIndex(v));
 1198|  76.6k|    if (c == kInvalidCornerIndex) {
  ------------------
  |  Branch (1198:9): [True: 0, False: 76.6k]
  ------------------
 1199|      0|      continue;  // Isolated vertex.
 1200|      0|    }
 1201|  76.6k|    CornerIndex deduplication_first_corner = c;
 1202|  76.6k|    if (is_vert_hole_[v]) {
  ------------------
  |  Branch (1202:9): [True: 50.4k, False: 26.2k]
  ------------------
 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|  50.4k|      deduplication_first_corner = c;
 1206|  50.4k|    } else {
 1207|       |      // If we are not on the boundary we need to find the first seam (of any
 1208|       |      // attribute).
 1209|  66.3k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1209:28): [True: 52.4k, False: 13.9k]
  ------------------
 1210|  52.4k|        if (!attribute_data_[i].connectivity_data.IsCornerOnSeam(c)) {
  ------------------
  |  Branch (1210:13): [True: 40.1k, False: 12.2k]
  ------------------
 1211|  40.1k|          continue;  // No seam for this attribute, ignore it.
 1212|  40.1k|        }
 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|  12.2k|        const VertexIndex vert_id =
 1217|  12.2k|            attribute_data_[i].connectivity_data.Vertex(c);
 1218|  12.2k|        CornerIndex act_c = corner_table_->SwingRight(c);
 1219|  12.2k|        bool seam_found = false;
 1220|  12.2k|        while (act_c != c) {
  ------------------
  |  Branch (1220:16): [True: 12.2k, False: 0]
  ------------------
 1221|  12.2k|          if (act_c == kInvalidCornerIndex) {
  ------------------
  |  Branch (1221:15): [True: 0, False: 12.2k]
  ------------------
 1222|      0|            return false;
 1223|      0|          }
 1224|  12.2k|          if (attribute_data_[i].connectivity_data.Vertex(act_c) != vert_id) {
  ------------------
  |  Branch (1224:15): [True: 12.2k, False: 0]
  ------------------
 1225|       |            // Attribute seam found. Stop.
 1226|  12.2k|            deduplication_first_corner = act_c;
 1227|  12.2k|            seam_found = true;
 1228|  12.2k|            break;
 1229|  12.2k|          }
 1230|      0|          act_c = corner_table_->SwingRight(act_c);
 1231|      0|        }
 1232|  12.2k|        if (seam_found) {
  ------------------
  |  Branch (1232:13): [True: 12.2k, False: 0]
  ------------------
 1233|  12.2k|          break;  // No reason to process other attributes if we found a seam.
 1234|  12.2k|        }
 1235|  12.2k|      }
 1236|  26.2k|    }
 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|  76.6k|    c = deduplication_first_corner;
 1244|       |    // Create a new point.
 1245|  76.6k|    corner_to_point_map[c.value()] =
 1246|  76.6k|        static_cast<uint32_t>(point_to_corner_map.size());
 1247|  76.6k|    point_to_corner_map.push_back(c.value());
 1248|       |    // Traverse in CW direction.
 1249|  76.6k|    CornerIndex prev_c = c;
 1250|  76.6k|    c = corner_table_->SwingRight(c);
 1251|   308k|    while (c != kInvalidCornerIndex && c != deduplication_first_corner) {
  ------------------
  |  Branch (1251:12): [True: 258k, False: 50.4k]
  |  Branch (1251:40): [True: 231k, False: 26.2k]
  ------------------
 1252|   231k|      bool attribute_seam = false;
 1253|   580k|      for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
  ------------------
  |  Branch (1253:28): [True: 463k, False: 116k]
  ------------------
 1254|   463k|        if (attribute_data_[i].connectivity_data.Vertex(c) !=
  ------------------
  |  Branch (1254:13): [True: 115k, False: 348k]
  ------------------
 1255|   463k|            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|   115k|          attribute_seam = true;
 1259|   115k|          break;
 1260|   115k|        }
 1261|   463k|      }
 1262|   231k|      if (attribute_seam) {
  ------------------
  |  Branch (1262:11): [True: 115k, False: 116k]
  ------------------
 1263|   115k|        corner_to_point_map[c.value()] =
 1264|   115k|            static_cast<uint32_t>(point_to_corner_map.size());
 1265|   115k|        point_to_corner_map.push_back(c.value());
 1266|   116k|      } else {
 1267|   116k|        corner_to_point_map[c.value()] = corner_to_point_map[prev_c.value()];
 1268|   116k|      }
 1269|   231k|      prev_c = c;
 1270|   231k|      c = corner_table_->SwingRight(c);
 1271|   231k|    }
 1272|  76.6k|  }
 1273|       |  // Add faces.
 1274|   102k|  for (FaceIndex f(0); f < decoder_->mesh()->num_faces(); ++f) {
  ------------------
  |  Branch (1274:24): [True: 102k, False: 18]
  ------------------
 1275|   102k|    Mesh::Face face;
 1276|   411k|    for (int c = 0; c < 3; ++c) {
  ------------------
  |  Branch (1276:21): [True: 308k, False: 102k]
  ------------------
 1277|       |      // Remap old points to the new ones.
 1278|   308k|      face[c] = corner_to_point_map[3 * f.value() + c];
 1279|   308k|    }
 1280|   102k|    decoder_->mesh()->SetFace(f, face);
 1281|   102k|  }
 1282|     18|  decoder_->point_cloud()->set_num_points(
 1283|     18|      static_cast<uint32_t>(point_to_corner_map.size()));
 1284|     18|  return true;
 1285|     18|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE30CreateVertexTraversalSequencerINS_28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS5_EEEEEENSt3__110unique_ptrINS_15PointsSequencerENS9_14default_deleteISB_EEEEPNS_32MeshAttributeIndicesEncodingDataE:
  110|      9|    MeshAttributeIndicesEncodingData *encoding_data) {
  111|      9|  typedef typename TraverserT::TraversalObserver AttObserver;
  112|      9|  typedef typename TraverserT::CornerTable CornerTable;
  113|       |
  114|      9|  const Mesh *mesh = decoder_->mesh();
  115|      9|  std::unique_ptr<MeshTraversalSequencer<TraverserT>> traversal_sequencer(
  116|      9|      new MeshTraversalSequencer<TraverserT>(mesh, encoding_data));
  117|       |
  118|      9|  AttObserver att_observer(corner_table_.get(), mesh, traversal_sequencer.get(),
  119|      9|                           encoding_data);
  120|       |
  121|      9|  TraverserT att_traverser;
  122|      9|  att_traverser.Init(corner_table_.get(), att_observer);
  123|       |
  124|      9|  traversal_sequencer->SetTraverser(att_traverser);
  125|      9|  return std::move(traversal_sequencer);
  126|      9|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE30CreateVertexTraversalSequencerINS_19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS5_EEEEEENSt3__110unique_ptrINS_15PointsSequencerENS9_14default_deleteISB_EEEEPNS_32MeshAttributeIndicesEncodingDataE:
  110|     75|    MeshAttributeIndicesEncodingData *encoding_data) {
  111|     75|  typedef typename TraverserT::TraversalObserver AttObserver;
  112|     75|  typedef typename TraverserT::CornerTable CornerTable;
  113|       |
  114|     75|  const Mesh *mesh = decoder_->mesh();
  115|     75|  std::unique_ptr<MeshTraversalSequencer<TraverserT>> traversal_sequencer(
  116|     75|      new MeshTraversalSequencer<TraverserT>(mesh, encoding_data));
  117|       |
  118|     75|  AttObserver att_observer(corner_table_.get(), mesh, traversal_sequencer.get(),
  119|     75|                           encoding_data);
  120|       |
  121|     75|  TraverserT att_traverser;
  122|     75|  att_traverser.Init(corner_table_.get(), att_observer);
  123|       |
  124|     75|  traversal_sequencer->SetTraverser(att_traverser);
  125|     75|  return std::move(traversal_sequencer);
  126|     75|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE30CreateVertexTraversalSequencerINS_28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS5_EEEEEENSt3__110unique_ptrINS_15PointsSequencerENS9_14default_deleteISB_EEEEPNS_32MeshAttributeIndicesEncodingDataE:
  110|      6|    MeshAttributeIndicesEncodingData *encoding_data) {
  111|      6|  typedef typename TraverserT::TraversalObserver AttObserver;
  112|      6|  typedef typename TraverserT::CornerTable CornerTable;
  113|       |
  114|      6|  const Mesh *mesh = decoder_->mesh();
  115|      6|  std::unique_ptr<MeshTraversalSequencer<TraverserT>> traversal_sequencer(
  116|      6|      new MeshTraversalSequencer<TraverserT>(mesh, encoding_data));
  117|       |
  118|      6|  AttObserver att_observer(corner_table_.get(), mesh, traversal_sequencer.get(),
  119|      6|                           encoding_data);
  120|       |
  121|      6|  TraverserT att_traverser;
  122|      6|  att_traverser.Init(corner_table_.get(), att_observer);
  123|       |
  124|      6|  traversal_sequencer->SetTraverser(att_traverser);
  125|      6|  return std::move(traversal_sequencer);
  126|      6|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE30CreateVertexTraversalSequencerINS_19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS5_EEEEEENSt3__110unique_ptrINS_15PointsSequencerENS9_14default_deleteISB_EEEEPNS_32MeshAttributeIndicesEncodingDataE:
  110|     52|    MeshAttributeIndicesEncodingData *encoding_data) {
  111|     52|  typedef typename TraverserT::TraversalObserver AttObserver;
  112|     52|  typedef typename TraverserT::CornerTable CornerTable;
  113|       |
  114|     52|  const Mesh *mesh = decoder_->mesh();
  115|     52|  std::unique_ptr<MeshTraversalSequencer<TraverserT>> traversal_sequencer(
  116|     52|      new MeshTraversalSequencer<TraverserT>(mesh, encoding_data));
  117|       |
  118|     52|  AttObserver att_observer(corner_table_.get(), mesh, traversal_sequencer.get(),
  119|     52|                           encoding_data);
  120|       |
  121|     52|  TraverserT att_traverser;
  122|     52|  att_traverser.Init(corner_table_.get(), att_observer);
  123|       |
  124|     52|  traversal_sequencer->SetTraverser(att_traverser);
  125|     52|  return std::move(traversal_sequencer);
  126|     52|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE30CreateVertexTraversalSequencerINS_28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS5_EEEEEENSt3__110unique_ptrINS_15PointsSequencerENS9_14default_deleteISB_EEEEPNS_32MeshAttributeIndicesEncodingDataE:
  110|     17|    MeshAttributeIndicesEncodingData *encoding_data) {
  111|     17|  typedef typename TraverserT::TraversalObserver AttObserver;
  112|     17|  typedef typename TraverserT::CornerTable CornerTable;
  113|       |
  114|     17|  const Mesh *mesh = decoder_->mesh();
  115|     17|  std::unique_ptr<MeshTraversalSequencer<TraverserT>> traversal_sequencer(
  116|     17|      new MeshTraversalSequencer<TraverserT>(mesh, encoding_data));
  117|       |
  118|     17|  AttObserver att_observer(corner_table_.get(), mesh, traversal_sequencer.get(),
  119|     17|                           encoding_data);
  120|       |
  121|     17|  TraverserT att_traverser;
  122|     17|  att_traverser.Init(corner_table_.get(), att_observer);
  123|       |
  124|     17|  traversal_sequencer->SetTraverser(att_traverser);
  125|     17|  return std::move(traversal_sequencer);
  126|     17|}
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE30CreateVertexTraversalSequencerINS_19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS5_EEEEEENSt3__110unique_ptrINS_15PointsSequencerENS9_14default_deleteISB_EEEEPNS_32MeshAttributeIndicesEncodingDataE:
  110|     47|    MeshAttributeIndicesEncodingData *encoding_data) {
  111|     47|  typedef typename TraverserT::TraversalObserver AttObserver;
  112|     47|  typedef typename TraverserT::CornerTable CornerTable;
  113|       |
  114|     47|  const Mesh *mesh = decoder_->mesh();
  115|     47|  std::unique_ptr<MeshTraversalSequencer<TraverserT>> traversal_sequencer(
  116|     47|      new MeshTraversalSequencer<TraverserT>(mesh, encoding_data));
  117|       |
  118|     47|  AttObserver att_observer(corner_table_.get(), mesh, traversal_sequencer.get(),
  119|     47|                           encoding_data);
  120|       |
  121|     47|  TraverserT att_traverser;
  122|     47|  att_traverser.Init(corner_table_.get(), att_observer);
  123|       |
  124|     47|  traversal_sequencer->SetTraverser(att_traverser);
  125|     47|  return std::move(traversal_sequencer);
  126|     47|}

_ZNK5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE10GetDecoderEv:
   65|    819|  MeshEdgebreakerDecoder *GetDecoder() const override { return decoder_; }
_ZNK5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE14GetCornerTableEv:
   66|    206|  const CornerTable *GetCornerTable() const override {
   67|    206|    return corner_table_.get();
   68|    206|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE15IsTopologySplitEiPNS_12EdgeFaceNameEPi:
   86|  1.69M|                       int *out_encoder_split_symbol_id) {
   87|  1.69M|    if (topology_split_data_.size() == 0) {
  ------------------
  |  Branch (87:9): [True: 1.68M, False: 6.48k]
  ------------------
   88|  1.68M|      return false;
   89|  1.68M|    }
   90|  6.48k|    if (topology_split_data_.back().source_symbol_id >
  ------------------
  |  Branch (90:9): [True: 2, False: 6.48k]
  ------------------
   91|  6.48k|        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|      2|      *out_encoder_split_symbol_id = -1;
   98|      2|      return true;
   99|      2|    }
  100|  6.48k|    if (topology_split_data_.back().source_symbol_id != encoder_symbol_id) {
  ------------------
  |  Branch (100:9): [True: 6.38k, False: 101]
  ------------------
  101|  6.38k|      return false;
  102|  6.38k|    }
  103|    101|    *out_face_edge =
  104|    101|        static_cast<EdgeFaceName>(topology_split_data_.back().source_edge);
  105|    101|    *out_encoder_split_symbol_id = topology_split_data_.back().split_symbol_id;
  106|       |    // Remove the latest split event.
  107|    101|    topology_split_data_.pop_back();
  108|    101|    return true;
  109|  6.48k|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE18SetOppositeCornersENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEES5_:
  133|  5.87M|  void SetOppositeCorners(CornerIndex corner_0, CornerIndex corner_1) {
  134|  5.87M|    corner_table_->SetOppositeCorner(corner_0, corner_1);
  135|  5.87M|    corner_table_->SetOppositeCorner(corner_1, corner_0);
  136|  5.87M|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_31MeshEdgebreakerTraversalDecoderEE13AttributeDataC2Ev:
  210|  2.42k|    AttributeData() : decoder_id(-1), is_connectivity_used(true) {}
_ZNK5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE10GetDecoderEv:
   65|    447|  MeshEdgebreakerDecoder *GetDecoder() const override { return decoder_; }
_ZNK5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE14GetCornerTableEv:
   66|    337|  const CornerTable *GetCornerTable() const override {
   67|    337|    return corner_table_.get();
   68|    337|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE15IsTopologySplitEiPNS_12EdgeFaceNameEPi:
   86|  27.8M|                       int *out_encoder_split_symbol_id) {
   87|  27.8M|    if (topology_split_data_.size() == 0) {
  ------------------
  |  Branch (87:9): [True: 131k, False: 27.7M]
  ------------------
   88|   131k|      return false;
   89|   131k|    }
   90|  27.7M|    if (topology_split_data_.back().source_symbol_id >
  ------------------
  |  Branch (90:9): [True: 5, False: 27.7M]
  ------------------
   91|  27.7M|        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|      5|      *out_encoder_split_symbol_id = -1;
   98|      5|      return true;
   99|      5|    }
  100|  27.7M|    if (topology_split_data_.back().source_symbol_id != encoder_symbol_id) {
  ------------------
  |  Branch (100:9): [True: 27.7M, False: 796]
  ------------------
  101|  27.7M|      return false;
  102|  27.7M|    }
  103|    796|    *out_face_edge =
  104|    796|        static_cast<EdgeFaceName>(topology_split_data_.back().source_edge);
  105|    796|    *out_encoder_split_symbol_id = topology_split_data_.back().split_symbol_id;
  106|       |    // Remove the latest split event.
  107|    796|    topology_split_data_.pop_back();
  108|    796|    return true;
  109|  27.7M|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE18SetOppositeCornersENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEES5_:
  133|  83.6M|  void SetOppositeCorners(CornerIndex corner_0, CornerIndex corner_1) {
  134|  83.6M|    corner_table_->SetOppositeCorner(corner_0, corner_1);
  135|  83.6M|    corner_table_->SetOppositeCorner(corner_1, corner_0);
  136|  83.6M|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_41MeshEdgebreakerTraversalPredictiveDecoderEE13AttributeDataC2Ev:
  210|    301|    AttributeData() : decoder_id(-1), is_connectivity_used(true) {}
_ZNK5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE10GetDecoderEv:
   65|  1.86k|  MeshEdgebreakerDecoder *GetDecoder() const override { return decoder_; }
_ZNK5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE14GetCornerTableEv:
   66|    444|  const CornerTable *GetCornerTable() const override {
   67|    444|    return corner_table_.get();
   68|    444|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE15IsTopologySplitEiPNS_12EdgeFaceNameEPi:
   86|   925k|                       int *out_encoder_split_symbol_id) {
   87|   925k|    if (topology_split_data_.size() == 0) {
  ------------------
  |  Branch (87:9): [True: 912k, False: 13.2k]
  ------------------
   88|   912k|      return false;
   89|   912k|    }
   90|  13.2k|    if (topology_split_data_.back().source_symbol_id >
  ------------------
  |  Branch (90:9): [True: 0, False: 13.2k]
  ------------------
   91|  13.2k|        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|      0|      *out_encoder_split_symbol_id = -1;
   98|      0|      return true;
   99|      0|    }
  100|  13.2k|    if (topology_split_data_.back().source_symbol_id != encoder_symbol_id) {
  ------------------
  |  Branch (100:9): [True: 12.8k, False: 376]
  ------------------
  101|  12.8k|      return false;
  102|  12.8k|    }
  103|    376|    *out_face_edge =
  104|    376|        static_cast<EdgeFaceName>(topology_split_data_.back().source_edge);
  105|    376|    *out_encoder_split_symbol_id = topology_split_data_.back().split_symbol_id;
  106|       |    // Remove the latest split event.
  107|    376|    topology_split_data_.pop_back();
  108|    376|    return true;
  109|  13.2k|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE18SetOppositeCornersENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEES5_:
  133|   979k|  void SetOppositeCorners(CornerIndex corner_0, CornerIndex corner_1) {
  134|   979k|    corner_table_->SetOppositeCorner(corner_0, corner_1);
  135|   979k|    corner_table_->SetOppositeCorner(corner_1, corner_0);
  136|   979k|  }
_ZN5draco26MeshEdgebreakerDecoderImplINS_38MeshEdgebreakerTraversalValenceDecoderEE13AttributeDataC2Ev:
  210|  2.11k|    AttributeData() : decoder_id(-1), is_connectivity_used(true) {}

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

_ZN5draco13HoleEventDataC2Ev:
  118|   711k|  HoleEventData() : symbol_id(0) {}

_ZN5draco31MeshEdgebreakerTraversalDecoderC2Ev:
   35|    847|        decoder_impl_(nullptr) {}
_ZN5draco31MeshEdgebreakerTraversalDecoder4InitEPNS_35MeshEdgebreakerDecoderImplInterfaceE:
   36|    743|  void Init(MeshEdgebreakerDecoderImplInterface *decoder) {
   37|    743|    decoder_impl_ = decoder;
   38|    743|    buffer_.Init(decoder->GetDecoder()->buffer()->data_head(),
   39|    743|                 decoder->GetDecoder()->buffer()->remaining_size(),
   40|    743|                 decoder->GetDecoder()->buffer()->bitstream_version());
   41|    743|  }
_ZNK5draco31MeshEdgebreakerTraversalDecoder16BitstreamVersionEv:
   44|    905|  uint16_t BitstreamVersion() const {
   45|    905|    return decoder_impl_->GetDecoder()->bitstream_version();
   46|    905|  }
_ZN5draco31MeshEdgebreakerTraversalDecoder21SetNumEncodedVerticesEi:
   50|    273|  void SetNumEncodedVertices(int /* num_vertices */) {}
_ZN5draco31MeshEdgebreakerTraversalDecoder19SetNumAttributeDataEi:
   54|    743|  void SetNumAttributeData(int num_data) { num_attribute_data_ = num_data; }
_ZN5draco31MeshEdgebreakerTraversalDecoder5StartEPNS_13DecoderBufferE:
   59|    422|  bool Start(DecoderBuffer *out_buffer) {
   60|       |    // Decode symbols from the main buffer decoder and face configurations from
   61|       |    // the start_face_buffer decoder.
   62|    422|    if (!DecodeTraversalSymbols()) {
  ------------------
  |  Branch (62:9): [True: 7, False: 415]
  ------------------
   63|      7|      return false;
   64|      7|    }
   65|       |
   66|    415|    if (!DecodeStartFaces()) {
  ------------------
  |  Branch (66:9): [True: 7, False: 408]
  ------------------
   67|      7|      return false;
   68|      7|    }
   69|       |
   70|    408|    if (!DecodeAttributeSeams()) {
  ------------------
  |  Branch (70:9): [True: 5, False: 403]
  ------------------
   71|      5|      return false;
   72|      5|    }
   73|    403|    *out_buffer = buffer_;
   74|    403|    return true;
   75|    408|  }
_ZN5draco31MeshEdgebreakerTraversalDecoder28DecodeStartFaceConfigurationEv:
   78|  6.18k|  inline bool DecodeStartFaceConfiguration() {
   79|  6.18k|    uint32_t face_configuration;
   80|  6.18k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   81|  6.18k|    if (buffer_.bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|  6.18k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (81:9): [True: 160, False: 6.02k]
  ------------------
   82|    160|      start_face_buffer_.DecodeLeastSignificantBits32(1, &face_configuration);
   83|       |
   84|    160|    } else
   85|  6.02k|#endif
   86|  6.02k|    {
   87|  6.02k|      face_configuration = start_face_decoder_.DecodeNextBit();
   88|  6.02k|    }
   89|  6.18k|    return face_configuration;
   90|  6.18k|  }
_ZN5draco31MeshEdgebreakerTraversalDecoder12DecodeSymbolEv:
   93|  4.26M|  inline uint32_t DecodeSymbol() {
   94|  4.26M|    uint32_t symbol;
   95|  4.26M|    symbol_buffer_.DecodeLeastSignificantBits32(1, &symbol);
   96|  4.26M|    if (symbol == TOPOLOGY_C) {
  ------------------
  |  Branch (96:9): [True: 2.05M, False: 2.21M]
  ------------------
   97|  2.05M|      return symbol;
   98|  2.05M|    }
   99|       |    // Else decode two additional bits.
  100|  2.21M|    uint32_t symbol_suffix;
  101|  2.21M|    symbol_buffer_.DecodeLeastSignificantBits32(2, &symbol_suffix);
  102|  2.21M|    symbol |= (symbol_suffix << 1);
  103|  2.21M|    return symbol;
  104|  4.26M|  }
_ZN5draco31MeshEdgebreakerTraversalDecoder22NewActiveCornerReachedENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  107|  4.25M|  inline void NewActiveCornerReached(CornerIndex /* corner */) {}
_ZN5draco31MeshEdgebreakerTraversalDecoder13MergeVerticesENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEES3_:
  111|   519k|  inline void MergeVertices(VertexIndex /* dest */, VertexIndex /* source */) {}
_ZN5draco31MeshEdgebreakerTraversalDecoder19DecodeAttributeSeamEi:
  117|  1.37M|  inline bool DecodeAttributeSeam(int attribute) {
  118|  1.37M|    return attribute_connectivity_decoders_[attribute].DecodeNextBit();
  119|  1.37M|  }
_ZN5draco31MeshEdgebreakerTraversalDecoder4DoneEv:
  122|    420|  void Done() {
  123|    420|    if (symbol_buffer_.bit_decoder_active()) {
  ------------------
  |  Branch (123:9): [True: 342, False: 78]
  ------------------
  124|    342|      symbol_buffer_.EndBitDecoding();
  125|    342|    }
  126|    420|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  127|    420|    if (buffer_.bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    420|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (127:9): [True: 115, False: 305]
  ------------------
  128|    115|      start_face_buffer_.EndBitDecoding();
  129|       |
  130|    115|    } else
  131|    305|#endif
  132|    305|    {
  133|    305|      start_face_decoder_.EndDecoding();
  134|    305|    }
  135|    420|  }
_ZN5draco31MeshEdgebreakerTraversalDecoder6bufferEv:
  138|    304|  DecoderBuffer *buffer() { return &buffer_; }
_ZN5draco31MeshEdgebreakerTraversalDecoder22DecodeTraversalSymbolsEv:
  140|    532|  bool DecodeTraversalSymbols() {
  141|    532|    uint64_t traversal_size;
  142|    532|    symbol_buffer_ = buffer_;
  143|    532|    if (!symbol_buffer_.StartBitDecoding(true, &traversal_size)) {
  ------------------
  |  Branch (143:9): [True: 0, False: 532]
  ------------------
  144|      0|      return false;
  145|      0|    }
  146|    532|    buffer_ = symbol_buffer_;
  147|    532|    if (traversal_size > static_cast<uint64_t>(buffer_.remaining_size())) {
  ------------------
  |  Branch (147:9): [True: 16, False: 516]
  ------------------
  148|     16|      return false;
  149|     16|    }
  150|    516|    buffer_.Advance(traversal_size);
  151|    516|    return true;
  152|    532|  }
_ZN5draco31MeshEdgebreakerTraversalDecoder16DecodeStartFacesEv:
  154|    727|  bool DecodeStartFaces() {
  155|       |    // Create a decoder that is set to the end of the encoded traversal data.
  156|    727|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  157|    727|    if (buffer_.bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    727|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (157:9): [True: 231, False: 496]
  ------------------
  158|    231|      start_face_buffer_ = buffer_;
  159|    231|      uint64_t traversal_size;
  160|    231|      if (!start_face_buffer_.StartBitDecoding(true, &traversal_size)) {
  ------------------
  |  Branch (160:11): [True: 0, False: 231]
  ------------------
  161|      0|        return false;
  162|      0|      }
  163|    231|      buffer_ = start_face_buffer_;
  164|    231|      if (traversal_size > static_cast<uint64_t>(buffer_.remaining_size())) {
  ------------------
  |  Branch (164:11): [True: 13, False: 218]
  ------------------
  165|     13|        return false;
  166|     13|      }
  167|    218|      buffer_.Advance(traversal_size);
  168|    218|      return true;
  169|    231|    }
  170|    496|#endif
  171|    496|    return start_face_decoder_.StartDecoding(&buffer_);
  172|    727|  }
_ZN5draco31MeshEdgebreakerTraversalDecoder20DecodeAttributeSeamsEv:
  174|    712|  bool DecodeAttributeSeams() {
  175|       |    // Prepare attribute decoding.
  176|    712|    if (num_attribute_data_ > 0) {
  ------------------
  |  Branch (176:9): [True: 388, False: 324]
  ------------------
  177|    388|      attribute_connectivity_decoders_ = std::unique_ptr<BinaryDecoder[]>(
  178|    388|          new BinaryDecoder[num_attribute_data_]);
  179|  2.44k|      for (int i = 0; i < num_attribute_data_; ++i) {
  ------------------
  |  Branch (179:23): [True: 2.06k, False: 383]
  ------------------
  180|  2.06k|        if (!attribute_connectivity_decoders_[i].StartDecoding(&buffer_)) {
  ------------------
  |  Branch (180:13): [True: 5, False: 2.06k]
  ------------------
  181|      5|          return false;
  182|      5|        }
  183|  2.06k|      }
  184|    388|    }
  185|    707|    return true;
  186|    712|  }

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

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

_ZN5draco21MeshSequentialDecoderC2Ev:
   27|    431|MeshSequentialDecoder::MeshSequentialDecoder() {}
_ZN5draco21MeshSequentialDecoder18DecodeConnectivityEv:
   29|    337|bool MeshSequentialDecoder::DecodeConnectivity() {
   30|    337|  uint32_t num_faces;
   31|    337|  uint32_t num_points;
   32|    337|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   33|    337|  if (bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|    337|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (33:7): [True: 118, False: 219]
  ------------------
   34|    118|    if (!buffer()->Decode(&num_faces)) {
  ------------------
  |  Branch (34:9): [True: 0, False: 118]
  ------------------
   35|      0|      return false;
   36|      0|    }
   37|    118|    if (!buffer()->Decode(&num_points)) {
  ------------------
  |  Branch (37:9): [True: 0, False: 118]
  ------------------
   38|      0|      return false;
   39|      0|    }
   40|       |
   41|    118|  } else
   42|    219|#endif
   43|    219|  {
   44|    219|    if (!DecodeVarint(&num_faces, buffer())) {
  ------------------
  |  Branch (44:9): [True: 0, False: 219]
  ------------------
   45|      0|      return false;
   46|      0|    }
   47|    219|    if (!DecodeVarint(&num_points, buffer())) {
  ------------------
  |  Branch (47:9): [True: 0, False: 219]
  ------------------
   48|      0|      return false;
   49|      0|    }
   50|    219|  }
   51|       |
   52|       |  // Check that num_faces and num_points are valid values.
   53|    337|  const uint64_t faces_64 = static_cast<uint64_t>(num_faces);
   54|       |  // Compressed sequential encoding can only handle (2^32 - 1) / 3 indices.
   55|    337|  if (faces_64 > 0xffffffff / 3) {
  ------------------
  |  Branch (55:7): [True: 1, False: 336]
  ------------------
   56|      1|    return false;
   57|      1|  }
   58|    336|  if (faces_64 > buffer()->remaining_size() / 3) {
  ------------------
  |  Branch (58:7): [True: 3, False: 333]
  ------------------
   59|       |    // The number of faces is unreasonably high, because face indices do not
   60|       |    // fit in the remaining size of the buffer.
   61|      3|    return false;
   62|      3|  }
   63|    333|  uint8_t connectivity_method;
   64|    333|  if (!buffer()->Decode(&connectivity_method)) {
  ------------------
  |  Branch (64:7): [True: 0, False: 333]
  ------------------
   65|      0|    return false;
   66|      0|  }
   67|    333|  if (connectivity_method == 0) {
  ------------------
  |  Branch (67:7): [True: 207, False: 126]
  ------------------
   68|    207|    if (!DecodeAndDecompressIndices(num_faces)) {
  ------------------
  |  Branch (68:9): [True: 193, False: 14]
  ------------------
   69|    193|      return false;
   70|    193|    }
   71|    207|  } else {
   72|    126|    if (num_points < 256) {
  ------------------
  |  Branch (72:9): [True: 88, False: 38]
  ------------------
   73|       |      // Decode indices as uint8_t.
   74|  90.9k|      for (uint32_t i = 0; i < num_faces; ++i) {
  ------------------
  |  Branch (74:28): [True: 90.8k, False: 87]
  ------------------
   75|  90.8k|        Mesh::Face face;
   76|   363k|        for (int j = 0; j < 3; ++j) {
  ------------------
  |  Branch (76:25): [True: 272k, False: 90.8k]
  ------------------
   77|   272k|          uint8_t val;
   78|   272k|          if (!buffer()->Decode(&val)) {
  ------------------
  |  Branch (78:15): [True: 1, False: 272k]
  ------------------
   79|      1|            return false;
   80|      1|          }
   81|   272k|          face[j] = val;
   82|   272k|        }
   83|  90.8k|        mesh()->AddFace(face);
   84|  90.8k|      }
   85|     88|    } else if (num_points < (1 << 16)) {
  ------------------
  |  Branch (85:16): [True: 24, False: 14]
  ------------------
   86|       |      // Decode indices as uint16_t.
   87|   108k|      for (uint32_t i = 0; i < num_faces; ++i) {
  ------------------
  |  Branch (87:28): [True: 108k, False: 16]
  ------------------
   88|   108k|        Mesh::Face face;
   89|   435k|        for (int j = 0; j < 3; ++j) {
  ------------------
  |  Branch (89:25): [True: 326k, False: 108k]
  ------------------
   90|   326k|          uint16_t val;
   91|   326k|          if (!buffer()->Decode(&val)) {
  ------------------
  |  Branch (91:15): [True: 8, False: 326k]
  ------------------
   92|      8|            return false;
   93|      8|          }
   94|   326k|          face[j] = val;
   95|   326k|        }
   96|   108k|        mesh()->AddFace(face);
   97|   108k|      }
   98|     24|    } else if (num_points < (1 << 21) &&
  ------------------
  |  Branch (98:16): [True: 3, False: 11]
  ------------------
   99|     14|               bitstream_version() >= DRACO_BITSTREAM_VERSION(2, 2)) {
  ------------------
  |  |  115|      3|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (99:16): [True: 2, False: 1]
  ------------------
  100|       |      // Decode indices as uint32_t.
  101|    225|      for (uint32_t i = 0; i < num_faces; ++i) {
  ------------------
  |  Branch (101:28): [True: 224, False: 1]
  ------------------
  102|    224|        Mesh::Face face;
  103|    895|        for (int j = 0; j < 3; ++j) {
  ------------------
  |  Branch (103:25): [True: 672, False: 223]
  ------------------
  104|    672|          uint32_t val;
  105|    672|          if (!DecodeVarint(&val, buffer())) {
  ------------------
  |  Branch (105:15): [True: 1, False: 671]
  ------------------
  106|      1|            return false;
  107|      1|          }
  108|    671|          face[j] = val;
  109|    671|        }
  110|    223|        mesh()->AddFace(face);
  111|    223|      }
  112|     12|    } else {
  113|       |      // Decode faces as uint32_t (default).
  114|  10.4k|      for (uint32_t i = 0; i < num_faces; ++i) {
  ------------------
  |  Branch (114:28): [True: 10.4k, False: 7]
  ------------------
  115|  10.4k|        Mesh::Face face;
  116|  41.8k|        for (int j = 0; j < 3; ++j) {
  ------------------
  |  Branch (116:25): [True: 31.3k, False: 10.4k]
  ------------------
  117|  31.3k|          uint32_t val;
  118|  31.3k|          if (!buffer()->Decode(&val)) {
  ------------------
  |  Branch (118:15): [True: 5, False: 31.3k]
  ------------------
  119|      5|            return false;
  120|      5|          }
  121|  31.3k|          face[j] = val;
  122|  31.3k|        }
  123|  10.4k|        mesh()->AddFace(face);
  124|  10.4k|      }
  125|     12|    }
  126|    126|  }
  127|    125|  point_cloud()->set_num_points(num_points);
  128|    125|  return true;
  129|    333|}
_ZN5draco21MeshSequentialDecoder23CreateAttributesDecoderEi:
  131|  13.4k|bool MeshSequentialDecoder::CreateAttributesDecoder(int32_t att_decoder_id) {
  132|       |  // Always create the basic attribute decoder.
  133|  13.4k|  return SetAttributesDecoder(
  134|  13.4k|      att_decoder_id,
  135|  13.4k|      std::unique_ptr<AttributesDecoder>(
  136|  13.4k|          new SequentialAttributeDecodersController(
  137|  13.4k|              std::unique_ptr<PointsSequencer>(
  138|  13.4k|                  new LinearSequencer(point_cloud()->num_points())))));
  139|  13.4k|}
_ZN5draco21MeshSequentialDecoder26DecodeAndDecompressIndicesEj:
  141|    207|bool MeshSequentialDecoder::DecodeAndDecompressIndices(uint32_t num_faces) {
  142|       |  // Get decoded indices differences that were encoded with an entropy code.
  143|    207|  std::vector<uint32_t> indices_buffer(num_faces * 3);
  144|    207|  if (!DecodeSymbols(num_faces * 3, 1, buffer(), indices_buffer.data())) {
  ------------------
  |  Branch (144:7): [True: 192, False: 15]
  ------------------
  145|    192|    return false;
  146|    192|  }
  147|       |  // Reconstruct the indices from the differences.
  148|       |  // See MeshSequentialEncoder::CompressAndEncodeIndices() for more details.
  149|     15|  int32_t last_index_value = 0;  // This will always be >= 0.
  150|     15|  int vertex_index = 0;
  151|  60.4k|  for (uint32_t i = 0; i < num_faces; ++i) {
  ------------------
  |  Branch (151:24): [True: 60.4k, False: 14]
  ------------------
  152|  60.4k|    Mesh::Face face;
  153|   241k|    for (int j = 0; j < 3; ++j) {
  ------------------
  |  Branch (153:21): [True: 181k, False: 60.4k]
  ------------------
  154|   181k|      const uint32_t encoded_val = indices_buffer[vertex_index++];
  155|   181k|      int32_t index_diff = (encoded_val >> 1);
  156|   181k|      if (encoded_val & 1) {
  ------------------
  |  Branch (156:11): [True: 981, False: 180k]
  ------------------
  157|    981|        if (index_diff > last_index_value) {
  ------------------
  |  Branch (157:13): [True: 1, False: 980]
  ------------------
  158|       |          // Subtracting index_diff would result in a negative index.
  159|      1|          return false;
  160|      1|        }
  161|    980|        index_diff = -index_diff;
  162|   180k|      } else {
  163|   180k|        if (index_diff >
  ------------------
  |  Branch (163:13): [True: 0, False: 180k]
  ------------------
  164|   180k|            (std::numeric_limits<int32_t>::max() - last_index_value)) {
  165|       |          // Adding index_diff to last_index_value would overflow.
  166|      0|          return false;
  167|      0|        }
  168|   180k|      }
  169|   181k|      const int32_t index_value = index_diff + last_index_value;
  170|   181k|      face[j] = index_value;
  171|   181k|      last_index_value = index_value;
  172|   181k|    }
  173|  60.4k|    mesh()->AddFace(face);
  174|  60.4k|  }
  175|     14|  return true;
  176|     15|}

_ZN5draco19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE16OnTraversalStartEv:
   54|    170|  void OnTraversalStart() {}
_ZN5draco19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE18TraverseFromCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   59|   216k|  bool TraverseFromCorner(CornerIndex corner_id) {
   60|   216k|    if (this->IsFaceVisited(corner_id)) {
  ------------------
  |  Branch (60:9): [True: 207k, False: 9.15k]
  ------------------
   61|   207k|      return true;  // Already traversed.
   62|   207k|    }
   63|       |
   64|  9.15k|    corner_traversal_stack_.clear();
   65|  9.15k|    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|  9.15k|    const VertexIndex next_vert =
   69|  9.15k|        this->corner_table()->Vertex(this->corner_table()->Next(corner_id));
   70|  9.15k|    const VertexIndex prev_vert =
   71|  9.15k|        this->corner_table()->Vertex(this->corner_table()->Previous(corner_id));
   72|  9.15k|    if (next_vert == kInvalidVertexIndex || prev_vert == kInvalidVertexIndex) {
  ------------------
  |  Branch (72:9): [True: 0, False: 9.15k]
  |  Branch (72:45): [True: 0, False: 9.15k]
  ------------------
   73|      0|      return false;
   74|      0|    }
   75|  9.15k|    if (!this->IsVertexVisited(next_vert)) {
  ------------------
  |  Branch (75:9): [True: 9.09k, False: 55]
  ------------------
   76|  9.09k|      this->MarkVertexVisited(next_vert);
   77|  9.09k|      this->traversal_observer().OnNewVertexVisited(
   78|  9.09k|          next_vert, this->corner_table()->Next(corner_id));
   79|  9.09k|    }
   80|  9.15k|    if (!this->IsVertexVisited(prev_vert)) {
  ------------------
  |  Branch (80:9): [True: 685, False: 8.46k]
  ------------------
   81|    685|      this->MarkVertexVisited(prev_vert);
   82|    685|      this->traversal_observer().OnNewVertexVisited(
   83|    685|          prev_vert, this->corner_table()->Previous(corner_id));
   84|    685|    }
   85|       |
   86|       |    // Start the actual traversal.
   87|  21.0k|    while (!corner_traversal_stack_.empty()) {
  ------------------
  |  Branch (87:12): [True: 11.8k, False: 9.15k]
  ------------------
   88|       |      // Currently processed corner.
   89|  11.8k|      corner_id = corner_traversal_stack_.back();
   90|  11.8k|      FaceIndex face_id(corner_id.value() / 3);
   91|       |      // Make sure the face hasn't been visited yet.
   92|  11.8k|      if (corner_id == kInvalidCornerIndex || this->IsFaceVisited(face_id)) {
  ------------------
  |  Branch (92:11): [True: 0, False: 11.8k]
  |  Branch (92:47): [True: 88, False: 11.7k]
  ------------------
   93|       |        // This face has been already traversed.
   94|     88|        corner_traversal_stack_.pop_back();
   95|     88|        continue;
   96|     88|      }
   97|   216k|      while (true) {
  ------------------
  |  Branch (97:14): [Folded - Ignored]
  ------------------
   98|   216k|        this->MarkFaceVisited(face_id);
   99|   216k|        this->traversal_observer().OnNewFaceVisited(face_id);
  100|   216k|        const VertexIndex vert_id = this->corner_table()->Vertex(corner_id);
  101|   216k|        if (vert_id == kInvalidVertexIndex) {
  ------------------
  |  Branch (101:13): [True: 0, False: 216k]
  ------------------
  102|      0|          return false;
  103|      0|        }
  104|   216k|        if (!this->IsVertexVisited(vert_id)) {
  ------------------
  |  Branch (104:13): [True: 105k, False: 111k]
  ------------------
  105|   105k|          const bool on_boundary = this->corner_table()->IsOnBoundary(vert_id);
  106|   105k|          this->MarkVertexVisited(vert_id);
  107|   105k|          this->traversal_observer().OnNewVertexVisited(vert_id, corner_id);
  108|   105k|          if (!on_boundary) {
  ------------------
  |  Branch (108:15): [True: 102k, False: 3.70k]
  ------------------
  109|   102k|            corner_id = this->corner_table()->GetRightCorner(corner_id);
  110|   102k|            face_id = FaceIndex(corner_id.value() / 3);
  111|   102k|            continue;
  112|   102k|          }
  113|   105k|        }
  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|   114k|        const CornerIndex right_corner_id =
  118|   114k|            this->corner_table()->GetRightCorner(corner_id);
  119|   114k|        const CornerIndex left_corner_id =
  120|   114k|            this->corner_table()->GetLeftCorner(corner_id);
  121|   114k|        const FaceIndex right_face_id(
  122|   114k|            (right_corner_id == kInvalidCornerIndex
  ------------------
  |  Branch (122:14): [True: 3.03k, False: 111k]
  ------------------
  123|   114k|                 ? kInvalidFaceIndex
  124|   114k|                 : FaceIndex(right_corner_id.value() / 3)));
  125|   114k|        const FaceIndex left_face_id(
  126|   114k|            (left_corner_id == kInvalidCornerIndex
  ------------------
  |  Branch (126:14): [True: 9.70k, False: 105k]
  ------------------
  127|   114k|                 ? kInvalidFaceIndex
  128|   114k|                 : FaceIndex(left_corner_id.value() / 3)));
  129|   114k|        if (this->IsFaceVisited(right_face_id)) {
  ------------------
  |  Branch (129:13): [True: 107k, False: 7.70k]
  ------------------
  130|       |          // Right face has been already visited.
  131|   107k|          if (this->IsFaceVisited(left_face_id)) {
  ------------------
  |  Branch (131:15): [True: 10.4k, False: 96.5k]
  ------------------
  132|       |            // Both neighboring faces are visited. End reached.
  133|  10.4k|            corner_traversal_stack_.pop_back();
  134|  10.4k|            break;  // Break from the while (true) loop.
  135|  96.5k|          } else {
  136|       |            // Go to the left face.
  137|  96.5k|            corner_id = left_corner_id;
  138|  96.5k|            face_id = left_face_id;
  139|  96.5k|          }
  140|   107k|        } else {
  141|       |          // Right face was not visited.
  142|  7.70k|          if (this->IsFaceVisited(left_face_id)) {
  ------------------
  |  Branch (142:15): [True: 6.34k, False: 1.35k]
  ------------------
  143|       |            // Left face visited, go to the right one.
  144|  6.34k|            corner_id = right_corner_id;
  145|  6.34k|            face_id = right_face_id;
  146|  6.34k|          } 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|  1.35k|            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|  1.35k|            corner_traversal_stack_.push_back(right_corner_id);
  157|       |            // Break from the while (true) loop.
  158|  1.35k|            break;
  159|  1.35k|          }
  160|  7.70k|        }
  161|   114k|      }
  162|  11.7k|    }
  163|  9.15k|    return true;
  164|  9.15k|  }
_ZN5draco19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE14OnTraversalEndEv:
   57|    170|  void OnTraversalEnd() {}
_ZN5draco19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEEC2Ev:
   51|    348|  DepthFirstTraverser() {}
_ZN5draco19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE16OnTraversalStartEv:
   54|    167|  void OnTraversalStart() {}
_ZN5draco19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE18TraverseFromCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   59|   172k|  bool TraverseFromCorner(CornerIndex corner_id) {
   60|   172k|    if (this->IsFaceVisited(corner_id)) {
  ------------------
  |  Branch (60:9): [True: 93.7k, False: 78.5k]
  ------------------
   61|  93.7k|      return true;  // Already traversed.
   62|  93.7k|    }
   63|       |
   64|  78.5k|    corner_traversal_stack_.clear();
   65|  78.5k|    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|  78.5k|    const VertexIndex next_vert =
   69|  78.5k|        this->corner_table()->Vertex(this->corner_table()->Next(corner_id));
   70|  78.5k|    const VertexIndex prev_vert =
   71|  78.5k|        this->corner_table()->Vertex(this->corner_table()->Previous(corner_id));
   72|  78.5k|    if (next_vert == kInvalidVertexIndex || prev_vert == kInvalidVertexIndex) {
  ------------------
  |  Branch (72:9): [True: 0, False: 78.5k]
  |  Branch (72:45): [True: 0, False: 78.5k]
  ------------------
   73|      0|      return false;
   74|      0|    }
   75|  78.5k|    if (!this->IsVertexVisited(next_vert)) {
  ------------------
  |  Branch (75:9): [True: 77.8k, False: 717]
  ------------------
   76|  77.8k|      this->MarkVertexVisited(next_vert);
   77|  77.8k|      this->traversal_observer().OnNewVertexVisited(
   78|  77.8k|          next_vert, this->corner_table()->Next(corner_id));
   79|  77.8k|    }
   80|  78.5k|    if (!this->IsVertexVisited(prev_vert)) {
  ------------------
  |  Branch (80:9): [True: 45.8k, False: 32.6k]
  ------------------
   81|  45.8k|      this->MarkVertexVisited(prev_vert);
   82|  45.8k|      this->traversal_observer().OnNewVertexVisited(
   83|  45.8k|          prev_vert, this->corner_table()->Previous(corner_id));
   84|  45.8k|    }
   85|       |
   86|       |    // Start the actual traversal.
   87|   162k|    while (!corner_traversal_stack_.empty()) {
  ------------------
  |  Branch (87:12): [True: 84.0k, False: 78.5k]
  ------------------
   88|       |      // Currently processed corner.
   89|  84.0k|      corner_id = corner_traversal_stack_.back();
   90|  84.0k|      FaceIndex face_id(corner_id.value() / 3);
   91|       |      // Make sure the face hasn't been visited yet.
   92|  84.0k|      if (corner_id == kInvalidCornerIndex || this->IsFaceVisited(face_id)) {
  ------------------
  |  Branch (92:11): [True: 0, False: 84.0k]
  |  Branch (92:47): [True: 520, False: 83.5k]
  ------------------
   93|       |        // This face has been already traversed.
   94|    520|        corner_traversal_stack_.pop_back();
   95|    520|        continue;
   96|    520|      }
   97|   172k|      while (true) {
  ------------------
  |  Branch (97:14): [Folded - Ignored]
  ------------------
   98|   172k|        this->MarkFaceVisited(face_id);
   99|   172k|        this->traversal_observer().OnNewFaceVisited(face_id);
  100|   172k|        const VertexIndex vert_id = this->corner_table()->Vertex(corner_id);
  101|   172k|        if (vert_id == kInvalidVertexIndex) {
  ------------------
  |  Branch (101:13): [True: 0, False: 172k]
  ------------------
  102|      0|          return false;
  103|      0|        }
  104|   172k|        if (!this->IsVertexVisited(vert_id)) {
  ------------------
  |  Branch (104:13): [True: 95.1k, False: 77.2k]
  ------------------
  105|  95.1k|          const bool on_boundary = this->corner_table()->IsOnBoundary(vert_id);
  106|  95.1k|          this->MarkVertexVisited(vert_id);
  107|  95.1k|          this->traversal_observer().OnNewVertexVisited(vert_id, corner_id);
  108|  95.1k|          if (!on_boundary) {
  ------------------
  |  Branch (108:15): [True: 42.7k, False: 52.3k]
  ------------------
  109|  42.7k|            corner_id = this->corner_table()->GetRightCorner(corner_id);
  110|  42.7k|            face_id = FaceIndex(corner_id.value() / 3);
  111|  42.7k|            continue;
  112|  42.7k|          }
  113|  95.1k|        }
  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|   129k|        const CornerIndex right_corner_id =
  118|   129k|            this->corner_table()->GetRightCorner(corner_id);
  119|   129k|        const CornerIndex left_corner_id =
  120|   129k|            this->corner_table()->GetLeftCorner(corner_id);
  121|   129k|        const FaceIndex right_face_id(
  122|   129k|            (right_corner_id == kInvalidCornerIndex
  ------------------
  |  Branch (122:14): [True: 49.4k, False: 80.1k]
  ------------------
  123|   129k|                 ? kInvalidFaceIndex
  124|   129k|                 : FaceIndex(right_corner_id.value() / 3)));
  125|   129k|        const FaceIndex left_face_id(
  126|   129k|            (left_corner_id == kInvalidCornerIndex
  ------------------
  |  Branch (126:14): [True: 81.4k, False: 48.2k]
  ------------------
  127|   129k|                 ? kInvalidFaceIndex
  128|   129k|                 : FaceIndex(left_corner_id.value() / 3)));
  129|   129k|        if (this->IsFaceVisited(right_face_id)) {
  ------------------
  |  Branch (129:13): [True: 107k, False: 22.3k]
  ------------------
  130|       |          // Right face has been already visited.
  131|   107k|          if (this->IsFaceVisited(left_face_id)) {
  ------------------
  |  Branch (131:15): [True: 80.8k, False: 26.4k]
  ------------------
  132|       |            // Both neighboring faces are visited. End reached.
  133|  80.8k|            corner_traversal_stack_.pop_back();
  134|  80.8k|            break;  // Break from the while (true) loop.
  135|  80.8k|          } else {
  136|       |            // Go to the left face.
  137|  26.4k|            corner_id = left_corner_id;
  138|  26.4k|            face_id = left_face_id;
  139|  26.4k|          }
  140|   107k|        } else {
  141|       |          // Right face was not visited.
  142|  22.3k|          if (this->IsFaceVisited(left_face_id)) {
  ------------------
  |  Branch (142:15): [True: 19.6k, False: 2.74k]
  ------------------
  143|       |            // Left face visited, go to the right one.
  144|  19.6k|            corner_id = right_corner_id;
  145|  19.6k|            face_id = right_face_id;
  146|  19.6k|          } 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|  2.74k|            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|  2.74k|            corner_traversal_stack_.push_back(right_corner_id);
  157|       |            // Break from the while (true) loop.
  158|  2.74k|            break;
  159|  2.74k|          }
  160|  22.3k|        }
  161|   129k|      }
  162|  83.5k|    }
  163|  78.5k|    return true;
  164|  78.5k|  }
_ZN5draco19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE14OnTraversalEndEv:
   57|    167|  void OnTraversalEnd() {}
_ZN5draco19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEEC2Ev:
   51|    342|  DepthFirstTraverser() {}

_ZN5draco28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE16OnTraversalStartEv:
   58|     30|  void OnTraversalStart() {
   59|     30|    prediction_degree_.resize(this->corner_table()->num_vertices(), 0);
   60|     30|  }
_ZN5draco28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE18TraverseFromCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   65|  43.5k|  bool TraverseFromCorner(CornerIndex corner_id) {
   66|  43.5k|    if (prediction_degree_.size() == 0) {
  ------------------
  |  Branch (66:9): [True: 0, False: 43.5k]
  ------------------
   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|  43.5k|    traversal_stacks_[0].push_back(corner_id);
   74|  43.5k|    best_priority_ = 0;
   75|       |    // For the first face, check the remaining corners as they may not be
   76|       |    // processed yet.
   77|  43.5k|    const VertexIndex next_vert =
   78|  43.5k|        this->corner_table()->Vertex(this->corner_table()->Next(corner_id));
   79|  43.5k|    const VertexIndex prev_vert =
   80|  43.5k|        this->corner_table()->Vertex(this->corner_table()->Previous(corner_id));
   81|  43.5k|    if (!this->IsVertexVisited(next_vert)) {
  ------------------
  |  Branch (81:9): [True: 456, False: 43.1k]
  ------------------
   82|    456|      this->MarkVertexVisited(next_vert);
   83|    456|      this->traversal_observer().OnNewVertexVisited(
   84|    456|          next_vert, this->corner_table()->Next(corner_id));
   85|    456|    }
   86|  43.5k|    if (!this->IsVertexVisited(prev_vert)) {
  ------------------
  |  Branch (86:9): [True: 110, False: 43.4k]
  ------------------
   87|    110|      this->MarkVertexVisited(prev_vert);
   88|    110|      this->traversal_observer().OnNewVertexVisited(
   89|    110|          prev_vert, this->corner_table()->Previous(corner_id));
   90|    110|    }
   91|  43.5k|    const VertexIndex tip_vertex = this->corner_table()->Vertex(corner_id);
   92|  43.5k|    if (!this->IsVertexVisited(tip_vertex)) {
  ------------------
  |  Branch (92:9): [True: 98, False: 43.4k]
  ------------------
   93|     98|      this->MarkVertexVisited(tip_vertex);
   94|     98|      this->traversal_observer().OnNewVertexVisited(tip_vertex, corner_id);
   95|     98|    }
   96|       |    // Start the actual traversal.
   97|   137k|    while ((corner_id = PopNextCornerToTraverse()) != kInvalidCornerIndex) {
  ------------------
  |  Branch (97:12): [True: 94.2k, False: 43.5k]
  ------------------
   98|  94.2k|      FaceIndex face_id(corner_id.value() / 3);
   99|       |      // Make sure the face hasn't been visited yet.
  100|  94.2k|      if (this->IsFaceVisited(face_id)) {
  ------------------
  |  Branch (100:11): [True: 64.2k, False: 30.0k]
  ------------------
  101|       |        // This face has been already traversed.
  102|  64.2k|        continue;
  103|  64.2k|      }
  104|       |
  105|  43.5k|      while (true) {
  ------------------
  |  Branch (105:14): [Folded - Ignored]
  ------------------
  106|  43.5k|        face_id = FaceIndex(corner_id.value() / 3);
  107|  43.5k|        this->MarkFaceVisited(face_id);
  108|  43.5k|        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|  43.5k|        const VertexIndex vert_id = this->corner_table()->Vertex(corner_id);
  113|  43.5k|        if (!this->IsVertexVisited(vert_id)) {
  ------------------
  |  Branch (113:13): [True: 21.9k, False: 21.6k]
  ------------------
  114|  21.9k|          this->MarkVertexVisited(vert_id);
  115|  21.9k|          this->traversal_observer().OnNewVertexVisited(vert_id, corner_id);
  116|  21.9k|        }
  117|       |
  118|       |        // Check whether we can traverse to the right and left neighboring
  119|       |        // faces.
  120|  43.5k|        const CornerIndex right_corner_id =
  121|  43.5k|            this->corner_table()->GetRightCorner(corner_id);
  122|  43.5k|        const CornerIndex left_corner_id =
  123|  43.5k|            this->corner_table()->GetLeftCorner(corner_id);
  124|  43.5k|        const FaceIndex right_face_id(
  125|  43.5k|            (right_corner_id == kInvalidCornerIndex
  ------------------
  |  Branch (125:14): [True: 678, False: 42.8k]
  ------------------
  126|  43.5k|                 ? kInvalidFaceIndex
  127|  43.5k|                 : FaceIndex(right_corner_id.value() / 3)));
  128|  43.5k|        const FaceIndex left_face_id(
  129|  43.5k|            (left_corner_id == kInvalidCornerIndex
  ------------------
  |  Branch (129:14): [True: 674, False: 42.9k]
  ------------------
  130|  43.5k|                 ? kInvalidFaceIndex
  131|  43.5k|                 : FaceIndex(left_corner_id.value() / 3)));
  132|  43.5k|        const bool is_right_face_visited = this->IsFaceVisited(right_face_id);
  133|  43.5k|        const bool is_left_face_visited = this->IsFaceVisited(left_face_id);
  134|       |
  135|  43.5k|        if (!is_left_face_visited) {
  ------------------
  |  Branch (135:13): [True: 27.8k, False: 15.7k]
  ------------------
  136|       |          // We can go to the left face.
  137|  27.8k|          const int priority = ComputePriority(left_corner_id);
  138|  27.8k|          if (is_right_face_visited && priority <= best_priority_) {
  ------------------
  |  Branch (138:15): [True: 6.60k, False: 21.2k]
  |  Branch (138:40): [True: 6.51k, False: 83]
  ------------------
  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|  6.51k|            corner_id = left_corner_id;
  144|  6.51k|            continue;
  145|  21.3k|          } else {
  146|  21.3k|            AddCornerToTraversalStack(left_corner_id, priority);
  147|  21.3k|          }
  148|  27.8k|        }
  149|  37.0k|        if (!is_right_face_visited) {
  ------------------
  |  Branch (149:13): [True: 36.4k, False: 645]
  ------------------
  150|       |          // Go to the right face.
  151|  36.4k|          const int priority = ComputePriority(right_corner_id);
  152|  36.4k|          if (priority <= best_priority_) {
  ------------------
  |  Branch (152:15): [True: 7.00k, False: 29.4k]
  ------------------
  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|  7.00k|            corner_id = right_corner_id;
  156|  7.00k|            continue;
  157|  29.4k|          } else {
  158|  29.4k|            AddCornerToTraversalStack(right_corner_id, priority);
  159|  29.4k|          }
  160|  36.4k|        }
  161|       |
  162|       |        // Couldn't proceed directly to the next corner
  163|  30.0k|        break;
  164|  37.0k|      }
  165|  30.0k|    }
  166|  43.5k|    return true;
  167|  43.5k|  }
_ZN5draco28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE23PopNextCornerToTraverseEv:
  173|   137k|  CornerIndex PopNextCornerToTraverse() {
  174|   283k|    for (int i = best_priority_; i < kMaxPriority; ++i) {
  ------------------
  |  Branch (174:34): [True: 240k, False: 43.5k]
  ------------------
  175|   240k|      if (!traversal_stacks_[i].empty()) {
  ------------------
  |  Branch (175:11): [True: 94.2k, False: 145k]
  ------------------
  176|  94.2k|        const CornerIndex ret = traversal_stacks_[i].back();
  177|  94.2k|        traversal_stacks_[i].pop_back();
  178|  94.2k|        best_priority_ = i;
  179|  94.2k|        return ret;
  180|  94.2k|      }
  181|   240k|    }
  182|  43.5k|    return kInvalidCornerIndex;
  183|   137k|  }
_ZN5draco28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE15ComputePriorityENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  194|  64.2k|  inline int ComputePriority(CornerIndex corner_id) {
  195|  64.2k|    const VertexIndex v_tip = this->corner_table()->Vertex(corner_id);
  196|       |    // Priority 0 when traversing to already visited vertices.
  197|  64.2k|    int priority = 0;
  198|  64.2k|    if (!this->IsVertexVisited(v_tip)) {
  ------------------
  |  Branch (198:9): [True: 42.9k, False: 21.2k]
  ------------------
  199|  42.9k|      const int degree = ++prediction_degree_[v_tip];
  200|       |      // Priority 1 when prediction degree > 1, otherwise 2.
  201|  42.9k|      priority = (degree > 1 ? 1 : 2);
  ------------------
  |  Branch (201:19): [True: 21.0k, False: 21.9k]
  ------------------
  202|  42.9k|    }
  203|       |    // Clamp the priority to the maximum number of buckets.
  204|  64.2k|    if (priority >= kMaxPriority) {
  ------------------
  |  Branch (204:9): [True: 0, False: 64.2k]
  ------------------
  205|      0|      priority = kMaxPriority - 1;
  206|      0|    }
  207|  64.2k|    return priority;
  208|  64.2k|  }
_ZN5draco28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE25AddCornerToTraversalStackENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEEi:
  185|  50.7k|  inline void AddCornerToTraversalStack(CornerIndex ci, int priority) {
  186|  50.7k|    traversal_stacks_[priority].push_back(ci);
  187|       |    // Make sure that the best available priority is up to date.
  188|  50.7k|    if (priority < best_priority_) {
  ------------------
  |  Branch (188:9): [True: 15.0k, False: 35.7k]
  ------------------
  189|  15.0k|      best_priority_ = priority;
  190|  15.0k|    }
  191|  50.7k|  }
_ZN5draco28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE14OnTraversalEndEv:
   63|     30|  void OnTraversalEnd() {}
_ZN5draco28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEEC2Ev:
   55|     64|  MaxPredictionDegreeTraverser() {}

_ZN5draco36MeshAttributeIndicesEncodingObserverINS_11CornerTableEE18OnNewVertexVisitedENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEENS3_IjNS_21CornerIndex_tag_type_EEE:
   50|   138k|  inline void OnNewVertexVisited(VertexIndex vertex, CornerIndex corner) {
   51|   138k|    const PointIndex point_id =
   52|   138k|        mesh_->face(FaceIndex(corner.value() / 3))[corner.value() % 3];
   53|       |    // Append the visited attribute to the encoding order.
   54|   138k|    sequencer_->AddPointId(point_id);
   55|       |
   56|       |    // Keep track of visited corners.
   57|   138k|    encoding_data_->encoded_attribute_value_index_to_corner_map.push_back(
   58|   138k|        corner);
   59|       |
   60|   138k|    encoding_data_
   61|   138k|        ->vertex_to_encoded_attribute_value_index_map[vertex.value()] =
   62|   138k|        encoding_data_->num_values;
   63|       |
   64|   138k|    encoding_data_->num_values++;
   65|   138k|  }
_ZN5draco36MeshAttributeIndicesEncodingObserverINS_11CornerTableEE16OnNewFaceVisitedENS_9IndexTypeIjNS_19FaceIndex_tag_type_EEE:
   48|   260k|  void OnNewFaceVisited(FaceIndex /* face */) {}
_ZN5draco36MeshAttributeIndicesEncodingObserverINS_11CornerTableEEC2EPKS1_PKNS_4MeshEPNS_15PointsSequencerEPNS_32MeshAttributeIndicesEncodingDataE:
   44|    206|        sequencer_(sequencer) {}
_ZN5draco36MeshAttributeIndicesEncodingObserverINS_11CornerTableEEC2Ev:
   36|    412|        sequencer_(nullptr) {}
_ZN5draco36MeshAttributeIndicesEncodingObserverINS_24MeshAttributeCornerTableEE18OnNewVertexVisitedENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEENS3_IjNS_21CornerIndex_tag_type_EEE:
   50|   218k|  inline void OnNewVertexVisited(VertexIndex vertex, CornerIndex corner) {
   51|   218k|    const PointIndex point_id =
   52|   218k|        mesh_->face(FaceIndex(corner.value() / 3))[corner.value() % 3];
   53|       |    // Append the visited attribute to the encoding order.
   54|   218k|    sequencer_->AddPointId(point_id);
   55|       |
   56|       |    // Keep track of visited corners.
   57|   218k|    encoding_data_->encoded_attribute_value_index_to_corner_map.push_back(
   58|   218k|        corner);
   59|       |
   60|   218k|    encoding_data_
   61|   218k|        ->vertex_to_encoded_attribute_value_index_map[vertex.value()] =
   62|   218k|        encoding_data_->num_values;
   63|       |
   64|   218k|    encoding_data_->num_values++;
   65|   218k|  }
_ZN5draco36MeshAttributeIndicesEncodingObserverINS_24MeshAttributeCornerTableEE16OnNewFaceVisitedENS_9IndexTypeIjNS_19FaceIndex_tag_type_EEE:
   48|   172k|  void OnNewFaceVisited(FaceIndex /* face */) {}
_ZN5draco36MeshAttributeIndicesEncodingObserverINS_24MeshAttributeCornerTableEEC2EPKS1_PKNS_4MeshEPNS_15PointsSequencerEPNS_32MeshAttributeIndicesEncodingDataE:
   44|    171|        sequencer_(sequencer) {}
_ZN5draco36MeshAttributeIndicesEncodingObserverINS_24MeshAttributeCornerTableEEC2Ev:
   36|    342|        sequencer_(nullptr) {}

_ZN5draco22MeshTraversalSequencerINS_28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEEC2EPKNS_4MeshEPKNS_32MeshAttributeIndicesEncodingDataE:
   34|     32|      : mesh_(mesh), encoding_data_(encoding_data), corner_order_(nullptr) {}
_ZN5draco22MeshTraversalSequencerINS_28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE34UpdatePointToAttributeIndexMappingEPNS_14PointAttributeE:
   48|    459|  bool UpdatePointToAttributeIndexMapping(PointAttribute *attribute) override {
   49|    459|    const auto *corner_table = traverser_.corner_table();
   50|    459|    attribute->SetExplicitMapping(mesh_->num_points());
   51|    459|    const size_t num_faces = mesh_->num_faces();
   52|    459|    const size_t num_points = mesh_->num_points();
   53|  80.8k|    for (FaceIndex f(0); f < static_cast<uint32_t>(num_faces); ++f) {
  ------------------
  |  Branch (53:26): [True: 80.4k, False: 459]
  ------------------
   54|  80.4k|      const auto &face = mesh_->face(f);
   55|   321k|      for (int p = 0; p < 3; ++p) {
  ------------------
  |  Branch (55:23): [True: 241k, False: 80.4k]
  ------------------
   56|   241k|        const PointIndex point_id = face[p];
   57|   241k|        const VertexIndex vert_id =
   58|   241k|            corner_table->Vertex(CornerIndex(3 * f.value() + p));
   59|   241k|        if (vert_id == kInvalidVertexIndex) {
  ------------------
  |  Branch (59:13): [True: 0, False: 241k]
  ------------------
   60|      0|          return false;
   61|      0|        }
   62|   241k|        const AttributeValueIndex att_entry_id(
   63|   241k|            encoding_data_
   64|   241k|                ->vertex_to_encoded_attribute_value_index_map[vert_id.value()]);
   65|   241k|        if (point_id >= num_points || att_entry_id.value() >= num_points) {
  ------------------
  |  Branch (65:13): [True: 0, False: 241k]
  |  Branch (65:13): [True: 0, False: 241k]
  |  Branch (65:39): [True: 0, False: 241k]
  ------------------
   66|       |          // There cannot be more attribute values than the number of points.
   67|      0|          return false;
   68|      0|        }
   69|   241k|        attribute->SetPointMapEntry(point_id, att_entry_id);
   70|   241k|      }
   71|  80.4k|    }
   72|    459|    return true;
   73|    459|  }
_ZN5draco22MeshTraversalSequencerINS_28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE24GenerateSequenceInternalEv:
   76|     30|  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|     30|    out_point_ids()->reserve(traverser_.corner_table()->num_vertices());
   80|       |
   81|     30|    traverser_.OnTraversalStart();
   82|     30|    if (corner_order_) {
  ------------------
  |  Branch (82:9): [True: 0, False: 30]
  ------------------
   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|     30|    } else {
   89|     30|      const int32_t num_faces = traverser_.corner_table()->num_faces();
   90|  43.6k|      for (int i = 0; i < num_faces; ++i) {
  ------------------
  |  Branch (90:23): [True: 43.5k, False: 30]
  ------------------
   91|  43.5k|        if (!ProcessCorner(CornerIndex(3 * i))) {
  ------------------
  |  Branch (91:13): [True: 0, False: 43.5k]
  ------------------
   92|      0|          return false;
   93|      0|        }
   94|  43.5k|      }
   95|     30|    }
   96|     30|    traverser_.OnTraversalEnd();
   97|     30|    return true;
   98|     30|  }
_ZN5draco22MeshTraversalSequencerINS_28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE13ProcessCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  101|  43.5k|  bool ProcessCorner(CornerIndex corner_id) {
  102|  43.5k|    return traverser_.TraverseFromCorner(corner_id);
  103|  43.5k|  }
_ZN5draco22MeshTraversalSequencerINS_28MaxPredictionDegreeTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE12SetTraverserERKS5_:
   35|     32|  void SetTraverser(const TraverserT &t) { traverser_ = t; }
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEEC2EPKNS_4MeshEPKNS_32MeshAttributeIndicesEncodingDataE:
   34|    174|      : mesh_(mesh), encoding_data_(encoding_data), corner_order_(nullptr) {}
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE34UpdatePointToAttributeIndexMappingEPNS_14PointAttributeE:
   48|    997|  bool UpdatePointToAttributeIndexMapping(PointAttribute *attribute) override {
   49|    997|    const auto *corner_table = traverser_.corner_table();
   50|    997|    attribute->SetExplicitMapping(mesh_->num_points());
   51|    997|    const size_t num_faces = mesh_->num_faces();
   52|    997|    const size_t num_points = mesh_->num_points();
   53|   612k|    for (FaceIndex f(0); f < static_cast<uint32_t>(num_faces); ++f) {
  ------------------
  |  Branch (53:26): [True: 611k, False: 997]
  ------------------
   54|   611k|      const auto &face = mesh_->face(f);
   55|  2.44M|      for (int p = 0; p < 3; ++p) {
  ------------------
  |  Branch (55:23): [True: 1.83M, False: 611k]
  ------------------
   56|  1.83M|        const PointIndex point_id = face[p];
   57|  1.83M|        const VertexIndex vert_id =
   58|  1.83M|            corner_table->Vertex(CornerIndex(3 * f.value() + p));
   59|  1.83M|        if (vert_id == kInvalidVertexIndex) {
  ------------------
  |  Branch (59:13): [True: 0, False: 1.83M]
  ------------------
   60|      0|          return false;
   61|      0|        }
   62|  1.83M|        const AttributeValueIndex att_entry_id(
   63|  1.83M|            encoding_data_
   64|  1.83M|                ->vertex_to_encoded_attribute_value_index_map[vert_id.value()]);
   65|  1.83M|        if (point_id >= num_points || att_entry_id.value() >= num_points) {
  ------------------
  |  Branch (65:13): [True: 0, False: 1.83M]
  |  Branch (65:13): [True: 0, False: 1.83M]
  |  Branch (65:39): [True: 0, False: 1.83M]
  ------------------
   66|       |          // There cannot be more attribute values than the number of points.
   67|      0|          return false;
   68|      0|        }
   69|  1.83M|        attribute->SetPointMapEntry(point_id, att_entry_id);
   70|  1.83M|      }
   71|   611k|    }
   72|    997|    return true;
   73|    997|  }
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE24GenerateSequenceInternalEv:
   76|    170|  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|    170|    out_point_ids()->reserve(traverser_.corner_table()->num_vertices());
   80|       |
   81|    170|    traverser_.OnTraversalStart();
   82|    170|    if (corner_order_) {
  ------------------
  |  Branch (82:9): [True: 0, False: 170]
  ------------------
   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|    170|    } else {
   89|    170|      const int32_t num_faces = traverser_.corner_table()->num_faces();
   90|   217k|      for (int i = 0; i < num_faces; ++i) {
  ------------------
  |  Branch (90:23): [True: 216k, False: 170]
  ------------------
   91|   216k|        if (!ProcessCorner(CornerIndex(3 * i))) {
  ------------------
  |  Branch (91:13): [True: 0, False: 216k]
  ------------------
   92|      0|          return false;
   93|      0|        }
   94|   216k|      }
   95|    170|    }
   96|    170|    traverser_.OnTraversalEnd();
   97|    170|    return true;
   98|    170|  }
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE13ProcessCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  101|   216k|  bool ProcessCorner(CornerIndex corner_id) {
  102|   216k|    return traverser_.TraverseFromCorner(corner_id);
  103|   216k|  }
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE12SetTraverserERKS5_:
   35|    174|  void SetTraverser(const TraverserT &t) { traverser_ = t; }
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEEC2EPKNS_4MeshEPKNS_32MeshAttributeIndicesEncodingDataE:
   34|    171|      : mesh_(mesh), encoding_data_(encoding_data), corner_order_(nullptr) {}
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE34UpdatePointToAttributeIndexMappingEPNS_14PointAttributeE:
   48|  1.24k|  bool UpdatePointToAttributeIndexMapping(PointAttribute *attribute) override {
   49|  1.24k|    const auto *corner_table = traverser_.corner_table();
   50|  1.24k|    attribute->SetExplicitMapping(mesh_->num_points());
   51|  1.24k|    const size_t num_faces = mesh_->num_faces();
   52|  1.24k|    const size_t num_points = mesh_->num_points();
   53|   285k|    for (FaceIndex f(0); f < static_cast<uint32_t>(num_faces); ++f) {
  ------------------
  |  Branch (53:26): [True: 284k, False: 1.24k]
  ------------------
   54|   284k|      const auto &face = mesh_->face(f);
   55|  1.13M|      for (int p = 0; p < 3; ++p) {
  ------------------
  |  Branch (55:23): [True: 853k, False: 284k]
  ------------------
   56|   853k|        const PointIndex point_id = face[p];
   57|   853k|        const VertexIndex vert_id =
   58|   853k|            corner_table->Vertex(CornerIndex(3 * f.value() + p));
   59|   853k|        if (vert_id == kInvalidVertexIndex) {
  ------------------
  |  Branch (59:13): [True: 0, False: 853k]
  ------------------
   60|      0|          return false;
   61|      0|        }
   62|   853k|        const AttributeValueIndex att_entry_id(
   63|   853k|            encoding_data_
   64|   853k|                ->vertex_to_encoded_attribute_value_index_map[vert_id.value()]);
   65|   853k|        if (point_id >= num_points || att_entry_id.value() >= num_points) {
  ------------------
  |  Branch (65:13): [True: 0, False: 853k]
  |  Branch (65:13): [True: 0, False: 853k]
  |  Branch (65:39): [True: 0, False: 853k]
  ------------------
   66|       |          // There cannot be more attribute values than the number of points.
   67|      0|          return false;
   68|      0|        }
   69|   853k|        attribute->SetPointMapEntry(point_id, att_entry_id);
   70|   853k|      }
   71|   284k|    }
   72|  1.24k|    return true;
   73|  1.24k|  }
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE24GenerateSequenceInternalEv:
   76|    167|  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|    167|    out_point_ids()->reserve(traverser_.corner_table()->num_vertices());
   80|       |
   81|    167|    traverser_.OnTraversalStart();
   82|    167|    if (corner_order_) {
  ------------------
  |  Branch (82:9): [True: 0, False: 167]
  ------------------
   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|    167|    } else {
   89|    167|      const int32_t num_faces = traverser_.corner_table()->num_faces();
   90|   172k|      for (int i = 0; i < num_faces; ++i) {
  ------------------
  |  Branch (90:23): [True: 172k, False: 167]
  ------------------
   91|   172k|        if (!ProcessCorner(CornerIndex(3 * i))) {
  ------------------
  |  Branch (91:13): [True: 0, False: 172k]
  ------------------
   92|      0|          return false;
   93|      0|        }
   94|   172k|      }
   95|    167|    }
   96|    167|    traverser_.OnTraversalEnd();
   97|    167|    return true;
   98|    167|  }
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE13ProcessCornerENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  101|   172k|  bool ProcessCorner(CornerIndex corner_id) {
  102|   172k|    return traverser_.TraverseFromCorner(corner_id);
  103|   172k|  }
_ZN5draco22MeshTraversalSequencerINS_19DepthFirstTraverserINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS2_EEEEE12SetTraverserERKS5_:
   35|    171|  void SetTraverser(const TraverserT &t) { traverser_ = t; }

_ZN5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEED2Ev:
   33|    342|  virtual ~TraverserBase() = default;
_ZNK5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE12corner_tableEv:
   70|  1.11M|  inline const CornerTable *corner_table() const { return corner_table_; }
_ZNK5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE15IsVertexVisitedENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEE:
   63|   473k|  inline bool IsVertexVisited(VertexIndex vert_id) const {
   64|   473k|    return is_vertex_visited_[vert_id.value()];
   65|   473k|  }
_ZN5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE17MarkVertexVisitedENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEE:
   66|   138k|  inline void MarkVertexVisited(VertexIndex vert_id) {
   67|   138k|    is_vertex_visited_[vert_id.value()] = true;
   68|   138k|  }
_ZN5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE18traversal_observerEv:
   74|   398k|  inline TraversalObserverT &traversal_observer() {
   75|   398k|    return traversal_observer_;
   76|   398k|  }
_ZNK5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE13IsFaceVisitedENS_9IndexTypeIjNS_19FaceIndex_tag_type_EEE:
   45|   422k|  inline bool IsFaceVisited(FaceIndex face_id) const {
   46|   422k|    if (face_id == kInvalidFaceIndex) {
  ------------------
  |  Branch (46:9): [True: 14.0k, False: 408k]
  ------------------
   47|  14.0k|      return true;  // Invalid faces are always considered as visited.
   48|  14.0k|    }
   49|   408k|    return is_face_visited_[face_id.value()];
   50|   422k|  }
_ZN5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE15MarkFaceVisitedENS_9IndexTypeIjNS_19FaceIndex_tag_type_EEE:
   60|   260k|  inline void MarkFaceVisited(FaceIndex face_id) {
   61|   260k|    is_face_visited_[face_id.value()] = true;
   62|   260k|  }
_ZN5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEEC2Ev:
   32|    412|  TraverserBase() : corner_table_(nullptr) {}
_ZN5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEED2Ev:
   33|    412|  virtual ~TraverserBase() = default;
_ZN5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE4InitEPKS1_S3_:
   36|    206|                    TraversalObserver traversal_observer) {
   37|    206|    corner_table_ = corner_table;
   38|    206|    is_face_visited_.assign(corner_table->num_faces(), false);
   39|    206|    is_vertex_visited_.assign(corner_table_->num_vertices(), false);
   40|    206|    traversal_observer_ = traversal_observer;
   41|    206|  }
_ZNK5draco13TraverserBaseINS_11CornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE13IsFaceVisitedENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   53|   216k|  inline bool IsFaceVisited(CornerIndex corner_id) const {
   54|   216k|    if (corner_id == kInvalidCornerIndex) {
  ------------------
  |  Branch (54:9): [True: 0, False: 216k]
  ------------------
   55|      0|      return true;  // Invalid faces are always considered as visited.
   56|      0|    }
   57|   216k|    return is_face_visited_[corner_id.value() / 3];
   58|   216k|  }
_ZNK5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE12corner_tableEv:
   70|  1.00M|  inline const CornerTable *corner_table() const { return corner_table_; }
_ZNK5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE13IsFaceVisitedENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
   53|   172k|  inline bool IsFaceVisited(CornerIndex corner_id) const {
   54|   172k|    if (corner_id == kInvalidCornerIndex) {
  ------------------
  |  Branch (54:9): [True: 0, False: 172k]
  ------------------
   55|      0|      return true;  // Invalid faces are always considered as visited.
   56|      0|    }
   57|   172k|    return is_face_visited_[corner_id.value() / 3];
   58|   172k|  }
_ZNK5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE15IsVertexVisitedENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEE:
   63|   329k|  inline bool IsVertexVisited(VertexIndex vert_id) const {
   64|   329k|    return is_vertex_visited_[vert_id.value()];
   65|   329k|  }
_ZN5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE17MarkVertexVisitedENS_9IndexTypeIjNS_21VertexIndex_tag_type_EEE:
   66|   218k|  inline void MarkVertexVisited(VertexIndex vert_id) {
   67|   218k|    is_vertex_visited_[vert_id.value()] = true;
   68|   218k|  }
_ZN5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE18traversal_observerEv:
   74|   391k|  inline TraversalObserverT &traversal_observer() {
   75|   391k|    return traversal_observer_;
   76|   391k|  }
_ZNK5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE13IsFaceVisitedENS_9IndexTypeIjNS_19FaceIndex_tag_type_EEE:
   45|   343k|  inline bool IsFaceVisited(FaceIndex face_id) const {
   46|   343k|    if (face_id == kInvalidFaceIndex) {
  ------------------
  |  Branch (46:9): [True: 130k, False: 212k]
  ------------------
   47|   130k|      return true;  // Invalid faces are always considered as visited.
   48|   130k|    }
   49|   212k|    return is_face_visited_[face_id.value()];
   50|   343k|  }
_ZN5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE15MarkFaceVisitedENS_9IndexTypeIjNS_19FaceIndex_tag_type_EEE:
   60|   172k|  inline void MarkFaceVisited(FaceIndex face_id) {
   61|   172k|    is_face_visited_[face_id.value()] = true;
   62|   172k|  }
_ZN5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEEC2Ev:
   32|    342|  TraverserBase() : corner_table_(nullptr) {}
_ZN5draco13TraverserBaseINS_24MeshAttributeCornerTableENS_36MeshAttributeIndicesEncodingObserverIS1_EEE4InitEPKS1_S3_:
   36|    171|                    TraversalObserver traversal_observer) {
   37|    171|    corner_table_ = corner_table;
   38|    171|    is_face_visited_.assign(corner_table->num_faces(), false);
   39|    171|    is_vertex_visited_.assign(corner_table_->num_vertices(), false);
   40|    171|    traversal_observer_ = traversal_observer;
   41|    171|  }

_ZN5draco17PointCloudDecoderC2Ev:
   26|  1.36k|      options_(nullptr) {}
_ZN5draco17PointCloudDecoder12DecodeHeaderEPNS_13DecoderBufferEPNS_11DracoHeaderE:
   29|  2.73k|                                       DracoHeader *out_header) {
   30|  2.73k|  constexpr char kIoErrorMsg[] = "Failed to parse Draco header.";
   31|  2.73k|  if (!buffer->Decode(out_header->draco_string, 5)) {
  ------------------
  |  Branch (31:7): [True: 0, False: 2.73k]
  ------------------
   32|      0|    return Status(Status::IO_ERROR, kIoErrorMsg);
   33|      0|  }
   34|  2.73k|  if (memcmp(out_header->draco_string, "DRACO", 5) != 0) {
  ------------------
  |  Branch (34:7): [True: 1, False: 2.73k]
  ------------------
   35|      1|    return Status(Status::DRACO_ERROR, "Not a Draco file.");
   36|      1|  }
   37|  2.73k|  if (!buffer->Decode(&(out_header->version_major))) {
  ------------------
  |  Branch (37:7): [True: 0, False: 2.73k]
  ------------------
   38|      0|    return Status(Status::IO_ERROR, kIoErrorMsg);
   39|      0|  }
   40|  2.73k|  if (!buffer->Decode(&(out_header->version_minor))) {
  ------------------
  |  Branch (40:7): [True: 0, False: 2.73k]
  ------------------
   41|      0|    return Status(Status::IO_ERROR, kIoErrorMsg);
   42|      0|  }
   43|  2.73k|  if (!buffer->Decode(&(out_header->encoder_type))) {
  ------------------
  |  Branch (43:7): [True: 0, False: 2.73k]
  ------------------
   44|      0|    return Status(Status::IO_ERROR, kIoErrorMsg);
   45|      0|  }
   46|  2.73k|  if (!buffer->Decode(&(out_header->encoder_method))) {
  ------------------
  |  Branch (46:7): [True: 0, False: 2.73k]
  ------------------
   47|      0|    return Status(Status::IO_ERROR, kIoErrorMsg);
   48|      0|  }
   49|  2.73k|  if (!buffer->Decode(&(out_header->flags))) {
  ------------------
  |  Branch (49:7): [True: 0, False: 2.73k]
  ------------------
   50|      0|    return Status(Status::IO_ERROR, kIoErrorMsg);
   51|      0|  }
   52|  2.73k|  return OkStatus();
   53|  2.73k|}
_ZN5draco17PointCloudDecoder14DecodeMetadataEv:
   55|    290|Status PointCloudDecoder::DecodeMetadata() {
   56|    290|  std::unique_ptr<GeometryMetadata> metadata =
   57|    290|      std::unique_ptr<GeometryMetadata>(new GeometryMetadata());
   58|    290|  MetadataDecoder metadata_decoder;
   59|    290|  if (!metadata_decoder.DecodeGeometryMetadata(buffer_, metadata.get())) {
  ------------------
  |  Branch (59:7): [True: 182, False: 108]
  ------------------
   60|    182|    return Status(Status::DRACO_ERROR, "Failed to decode metadata.");
   61|    182|  }
   62|    108|  point_cloud_->AddMetadata(std::move(metadata));
   63|    108|  return OkStatus();
   64|    290|}
_ZN5draco17PointCloudDecoder6DecodeERKNS_12DracoOptionsINS_17GeometryAttribute4TypeEEEPNS_13DecoderBufferEPNS_10PointCloudE:
   68|  1.36k|                                 PointCloud *out_point_cloud) {
   69|  1.36k|  options_ = &options;
   70|  1.36k|  buffer_ = in_buffer;
   71|  1.36k|  point_cloud_ = out_point_cloud;
   72|  1.36k|  DracoHeader header;
   73|  1.36k|  DRACO_RETURN_IF_ERROR(DecodeHeader(buffer_, &header))
  ------------------
  |  |   74|  1.36k|  {                                                   \
  |  |   75|  1.36k|    const draco::Status _local_status = (expression); \
  |  |   76|  1.36k|    if (!_local_status.ok()) {                        \
  |  |  ------------------
  |  |  |  Branch (76:9): [True: 0, False: 1.36k]
  |  |  ------------------
  |  |   77|      0|      return _local_status;                           \
  |  |   78|      0|    }                                                 \
  |  |   79|  1.36k|  }
  ------------------
   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|  1.36k|  if (header.encoder_type != GetGeometryType()) {
  ------------------
  |  Branch (76:7): [True: 0, False: 1.36k]
  ------------------
   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|  1.36k|  version_major_ = header.version_major;
   83|  1.36k|  version_minor_ = header.version_minor;
   84|       |
   85|  1.36k|  const uint8_t max_supported_major_version =
   86|  1.36k|      header.encoder_type == POINT_CLOUD ? kDracoPointCloudBitstreamVersionMajor
  ------------------
  |  Branch (86:7): [True: 0, False: 1.36k]
  ------------------
   87|  1.36k|                                         : kDracoMeshBitstreamVersionMajor;
   88|  1.36k|  const uint8_t max_supported_minor_version =
   89|  1.36k|      header.encoder_type == POINT_CLOUD ? kDracoPointCloudBitstreamVersionMinor
  ------------------
  |  Branch (89:7): [True: 0, False: 1.36k]
  ------------------
   90|  1.36k|                                         : kDracoMeshBitstreamVersionMinor;
   91|       |
   92|       |  // Check for version compatibility.
   93|  1.36k|#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
   94|  1.36k|  if (version_major_ < 1 || version_major_ > max_supported_major_version) {
  ------------------
  |  Branch (94:7): [True: 0, False: 1.36k]
  |  Branch (94:29): [True: 0, False: 1.36k]
  ------------------
   95|      0|    return Status(Status::UNKNOWN_VERSION, "Unknown major version.");
   96|      0|  }
   97|  1.36k|  if (version_major_ == max_supported_major_version &&
  ------------------
  |  Branch (97:7): [True: 1.05k, False: 307]
  ------------------
   98|  1.36k|      version_minor_ > max_supported_minor_version) {
  ------------------
  |  Branch (98:7): [True: 0, False: 1.05k]
  ------------------
   99|      0|    return Status(Status::UNKNOWN_VERSION, "Unknown minor version.");
  100|      0|  }
  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|  1.36k|  buffer_->set_bitstream_version(
  110|  1.36k|      DRACO_BITSTREAM_VERSION(version_major_, version_minor_));
  ------------------
  |  |  115|  1.36k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  111|       |
  112|  1.36k|  if (bitstream_version() >= DRACO_BITSTREAM_VERSION(1, 3) &&
  ------------------
  |  |  115|  2.73k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
  |  Branch (112:7): [True: 1.25k, False: 107]
  ------------------
  113|  1.36k|      (header.flags & METADATA_FLAG_MASK)) {
  ------------------
  |  |  151|  1.25k|#define METADATA_FLAG_MASK 0x8000
  ------------------
  |  Branch (113:7): [True: 290, False: 969]
  ------------------
  114|    290|    DRACO_RETURN_IF_ERROR(DecodeMetadata())
  ------------------
  |  |   74|    290|  {                                                   \
  |  |   75|    290|    const draco::Status _local_status = (expression); \
  |  |   76|    290|    if (!_local_status.ok()) {                        \
  |  |  ------------------
  |  |  |  Branch (76:9): [True: 182, False: 108]
  |  |  ------------------
  |  |   77|    182|      return _local_status;                           \
  |  |   78|    182|    }                                                 \
  |  |   79|    290|  }
  ------------------
  115|    290|  }
  116|  1.18k|  if (!InitializeDecoder()) {
  ------------------
  |  Branch (116:7): [True: 0, False: 1.18k]
  ------------------
  117|      0|    return Status(Status::DRACO_ERROR, "Failed to initialize the decoder.");
  118|      0|  }
  119|  1.18k|  if (!DecodeGeometryData()) {
  ------------------
  |  Branch (119:7): [True: 640, False: 544]
  ------------------
  120|    640|    return Status(Status::DRACO_ERROR, "Failed to decode geometry data.");
  121|    640|  }
  122|    544|  if (!DecodePointAttributes()) {
  ------------------
  |  Branch (122:7): [True: 474, False: 70]
  ------------------
  123|    474|    return Status(Status::DRACO_ERROR, "Failed to decode point attributes.");
  124|    474|  }
  125|     70|  return OkStatus();
  126|    544|}
_ZN5draco17PointCloudDecoder21DecodePointAttributesEv:
  128|    544|bool PointCloudDecoder::DecodePointAttributes() {
  129|    544|  uint8_t num_attributes_decoders;
  130|    544|  if (!buffer_->Decode(&num_attributes_decoders)) {
  ------------------
  |  Branch (130:7): [True: 3, False: 541]
  ------------------
  131|      3|    return false;
  132|      3|  }
  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|  14.3k|  for (int i = 0; i < num_attributes_decoders; ++i) {
  ------------------
  |  Branch (136:19): [True: 13.8k, False: 501]
  ------------------
  137|  13.8k|    if (!CreateAttributesDecoder(i)) {
  ------------------
  |  Branch (137:9): [True: 40, False: 13.8k]
  ------------------
  138|     40|      return false;
  139|     40|    }
  140|  13.8k|  }
  141|       |
  142|       |  // Initialize all attributes decoders. No data is decoded here.
  143|  13.8k|  for (auto &att_dec : attributes_decoders_) {
  ------------------
  |  Branch (143:22): [True: 13.8k, False: 501]
  ------------------
  144|  13.8k|    if (!att_dec->Init(this, point_cloud_)) {
  ------------------
  |  Branch (144:9): [True: 0, False: 13.8k]
  ------------------
  145|      0|      return false;
  146|      0|    }
  147|  13.8k|  }
  148|       |
  149|       |  // Decode any data needed by the attribute decoders.
  150|  5.01k|  for (int i = 0; i < num_attributes_decoders; ++i) {
  ------------------
  |  Branch (150:19): [True: 4.58k, False: 433]
  ------------------
  151|  4.58k|    if (!attributes_decoders_[i]->DecodeAttributesDecoderData(buffer_)) {
  ------------------
  |  Branch (151:9): [True: 68, False: 4.51k]
  ------------------
  152|     68|      return false;
  153|     68|    }
  154|  4.58k|  }
  155|       |
  156|       |  // Create map between attribute and decoder ids.
  157|  2.65k|  for (int i = 0; i < num_attributes_decoders; ++i) {
  ------------------
  |  Branch (157:19): [True: 2.22k, False: 433]
  ------------------
  158|  2.22k|    const int32_t num_attributes = attributes_decoders_[i]->GetNumAttributes();
  159|  24.7k|    for (int j = 0; j < num_attributes; ++j) {
  ------------------
  |  Branch (159:21): [True: 22.5k, False: 2.22k]
  ------------------
  160|  22.5k|      int att_id = attributes_decoders_[i]->GetAttributeId(j);
  161|  22.5k|      if (att_id >= attribute_to_decoder_map_.size()) {
  ------------------
  |  Branch (161:11): [True: 22.5k, False: 0]
  ------------------
  162|  22.5k|        attribute_to_decoder_map_.resize(att_id + 1);
  163|  22.5k|      }
  164|  22.5k|      attribute_to_decoder_map_[att_id] = i;
  165|  22.5k|    }
  166|  2.22k|  }
  167|       |
  168|       |  // Decode the actual attributes using the created attribute decoders.
  169|    433|  if (!DecodeAllAttributes()) {
  ------------------
  |  Branch (169:7): [True: 363, False: 70]
  ------------------
  170|    363|    return false;
  171|    363|  }
  172|       |
  173|     70|  if (!OnAttributesDecoded()) {
  ------------------
  |  Branch (173:7): [True: 0, False: 70]
  ------------------
  174|      0|    return false;
  175|      0|  }
  176|     70|  return true;
  177|     70|}
_ZN5draco17PointCloudDecoder19DecodeAllAttributesEv:
  179|    433|bool PointCloudDecoder::DecodeAllAttributes() {
  180|    718|  for (auto &att_dec : attributes_decoders_) {
  ------------------
  |  Branch (180:22): [True: 718, False: 70]
  ------------------
  181|    718|    if (!att_dec->DecodeAttributes(buffer_)) {
  ------------------
  |  Branch (181:9): [True: 363, False: 355]
  ------------------
  182|    363|      return false;
  183|    363|    }
  184|    718|  }
  185|     70|  return true;
  186|    433|}
_ZN5draco17PointCloudDecoder20GetPortableAttributeEi:
  189|    237|    int32_t parent_att_id) {
  190|    237|  if (parent_att_id < 0 || parent_att_id >= point_cloud_->num_attributes()) {
  ------------------
  |  Branch (190:7): [True: 0, False: 237]
  |  Branch (190:28): [True: 0, False: 237]
  ------------------
  191|      0|    return nullptr;
  192|      0|  }
  193|    237|  const int32_t parent_att_decoder_id =
  194|    237|      attribute_to_decoder_map_[parent_att_id];
  195|    237|  return attributes_decoders_[parent_att_decoder_id]->GetPortableAttribute(
  196|    237|      parent_att_id);
  197|    237|}

_ZN5draco17PointCloudDecoder20SetAttributesDecoderEiNSt3__110unique_ptrINS_26AttributesDecoderInterfaceENS1_14default_deleteIS3_EEEE:
   44|  13.8k|      int att_decoder_id, std::unique_ptr<AttributesDecoderInterface> decoder) {
   45|  13.8k|    if (att_decoder_id < 0) {
  ------------------
  |  Branch (45:9): [True: 0, False: 13.8k]
  ------------------
   46|      0|      return false;
   47|      0|    }
   48|  13.8k|    if (att_decoder_id >= static_cast<int>(attributes_decoders_.size())) {
  ------------------
  |  Branch (48:9): [True: 13.8k, False: 0]
  ------------------
   49|  13.8k|      attributes_decoders_.resize(att_decoder_id + 1);
   50|  13.8k|    }
   51|  13.8k|    attributes_decoders_[att_decoder_id] = std::move(decoder);
   52|  13.8k|    return true;
   53|  13.8k|  }
_ZNK5draco17PointCloudDecoder17bitstream_versionEv:
   63|  88.1k|  uint16_t bitstream_version() const {
   64|  88.1k|    return DRACO_BITSTREAM_VERSION(version_major_, version_minor_);
  ------------------
  |  |  115|  88.1k|  ((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
  ------------------
   65|  88.1k|  }
_ZN5draco17PointCloudDecoder18attributes_decoderEi:
   67|    622|  const AttributesDecoderInterface *attributes_decoder(int dec_id) {
   68|    622|    return attributes_decoders_[dec_id].get();
   69|    622|  }
_ZNK5draco17PointCloudDecoder23num_attributes_decodersEv:
   70|    622|  int32_t num_attributes_decoders() const {
   71|    622|    return static_cast<int32_t>(attributes_decoders_.size());
   72|    622|  }
_ZN5draco17PointCloudDecoder11point_cloudEv:
   76|  44.5k|  PointCloud *point_cloud() { return point_cloud_; }
_ZNK5draco17PointCloudDecoder11point_cloudEv:
   77|  1.40k|  const PointCloud *point_cloud() const { return point_cloud_; }
_ZN5draco17PointCloudDecoder6bufferEv:
   79|   644k|  DecoderBuffer *buffer() { return buffer_; }
_ZNK5draco17PointCloudDecoder7optionsEv:
   80|  1.59k|  const DecoderOptions *options() const { return options_; }
_ZN5draco17PointCloudDecoder17InitializeDecoderEv:
   85|    337|  virtual bool InitializeDecoder() { return true; }
_ZN5draco17PointCloudDecoder18DecodeGeometryDataEv:
   89|    544|  virtual bool DecodeGeometryData() { return true; }
_ZN5draco17PointCloudDecoder19OnAttributesDecodedEv:
   93|     15|  virtual bool OnAttributesDecoded() { return true; }
_ZN5draco17PointCloudDecoderD2Ev:
   31|  1.36k|  virtual ~PointCloudDecoder() = default;

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

_ZN5draco18MostSignificantBitEj:
   58|     19|inline int MostSignificantBit(uint32_t n) {
   59|     19|#if defined(__GNUC__)
   60|     19|  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|       |  // TODO(fgalligan): Optimize this code.
   68|       |  int msb = -1;
   69|       |  while (n != 0) {
   70|       |    msb++;
   71|       |    n >>= 1;
   72|       |  }
   73|       |  return msb;
   74|       |#endif
   75|     19|}
_ZN5draco24ConvertSymbolToSignedIntIjEENSt3__111make_signedIT_E4typeES3_:
  109|  19.9M|    IntTypeT val) {
  110|  19.9M|  static_assert(std::is_integral<IntTypeT>::value, "IntTypeT is not integral.");
  111|  19.9M|  typedef typename std::make_signed<IntTypeT>::type SignedType;
  112|  19.9M|  const bool is_positive = !static_cast<bool>(val & 1);
  113|  19.9M|  val >>= 1;
  114|  19.9M|  if (is_positive) {
  ------------------
  |  Branch (114:7): [True: 14.9M, False: 5.02M]
  ------------------
  115|  14.9M|    return static_cast<SignedType>(val);
  116|  14.9M|  }
  117|  5.02M|  SignedType ret = static_cast<SignedType>(val);
  118|  5.02M|  ret = -ret - 1;
  119|  5.02M|  return ret;
  120|  19.9M|}

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

_ZN5draco20DataBufferDescriptorC2Ev:
   28|  71.0k|  DataBufferDescriptor() : buffer_id(0), buffer_update_count(0) {}
_ZN5draco10DataBuffer5WriteElPKvm:
   53|   147k|  void Write(int64_t byte_pos, const void *in_data, size_t data_size) {
   54|   147k|    memcpy(const_cast<uint8_t *>(data()) + byte_pos, in_data, data_size);
   55|   147k|  }
_ZNK5draco10DataBuffer12update_countEv:
   67|  4.10k|  int64_t update_count() const { return descriptor_.buffer_update_count; }
_ZNK5draco10DataBuffer9data_sizeEv:
   68|   346k|  size_t data_size() const { return data_.size(); }
_ZN5draco10DataBuffer4dataEv:
   70|   608k|  uint8_t *data() { return data_.data(); }
_ZNK5draco10DataBuffer9buffer_idEv:
   71|  4.10k|  int64_t buffer_id() const { return descriptor_.buffer_id; }

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

_ZN5draco13DecoderBuffer28DecodeLeastSignificantBits32EjPj:
   57|  6.51M|  bool DecodeLeastSignificantBits32(uint32_t nbits, uint32_t *out_value) {
   58|  6.51M|    if (!bit_decoder_active()) {
  ------------------
  |  Branch (58:9): [True: 0, False: 6.51M]
  ------------------
   59|      0|      return false;
   60|      0|    }
   61|  6.51M|    return bit_decoder_.GetBits(nbits, out_value);
   62|  6.51M|  }
_ZN5draco13DecoderBuffer6DecodeEPvm:
   76|  13.1M|  bool Decode(void *out_data, size_t size_to_decode) {
   77|  13.1M|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (77:9): [True: 74, False: 13.1M]
  ------------------
   78|     74|      return false;  // Buffer overflow.
   79|     74|    }
   80|  13.1M|    memcpy(out_data, (data_ + pos_), size_to_decode);
   81|  13.1M|    pos_ += size_to_decode;
   82|  13.1M|    return true;
   83|  13.1M|  }
_ZN5draco13DecoderBuffer7AdvanceEl:
  105|  4.07k|  void Advance(int64_t bytes) { pos_ += bytes; }
_ZN5draco13DecoderBuffer21set_bitstream_versionEt:
  111|  1.36k|  void set_bitstream_version(uint16_t version) { bitstream_version_ = version; }
_ZNK5draco13DecoderBuffer9data_headEv:
  114|  5.73k|  const char *data_head() const { return data_ + pos_; }
_ZNK5draco13DecoderBuffer14remaining_sizeEv:
  115|   186k|  int64_t remaining_size() const { return data_size_ - pos_; }
_ZNK5draco13DecoderBuffer12decoded_sizeEv:
  116|    743|  int64_t decoded_size() const { return pos_; }
_ZNK5draco13DecoderBuffer18bit_decoder_activeEv:
  117|  6.52M|  bool bit_decoder_active() const { return bit_mode_; }
_ZNK5draco13DecoderBuffer17bitstream_versionEv:
  120|  14.3k|  uint16_t bitstream_version() const { return bitstream_version_; }
_ZN5draco13DecoderBuffer10BitDecoder5resetEPKvm:
  130|  1.01k|    inline void reset(const void *b, size_t s) {
  131|  1.01k|      bit_offset_ = 0;
  132|  1.01k|      bit_buffer_ = static_cast<const uint8_t *>(b);
  133|  1.01k|      bit_buffer_end_ = bit_buffer_ + s;
  134|  1.01k|    }
_ZNK5draco13DecoderBuffer10BitDecoder11BitsDecodedEv:
  137|    712|    inline uint64_t BitsDecoded() const {
  138|    712|      return static_cast<uint64_t>(bit_offset_);
  139|    712|    }
_ZN5draco13DecoderBuffer10BitDecoder7GetBitsEjPj:
  160|  6.51M|    inline bool GetBits(uint32_t nbits, uint32_t *x) {
  161|  6.51M|      if (nbits > 32) {
  ------------------
  |  Branch (161:11): [True: 0, False: 6.51M]
  ------------------
  162|      0|        return false;
  163|      0|      }
  164|  6.51M|      uint32_t value = 0;
  165|  15.2M|      for (uint32_t bit = 0; bit < nbits; ++bit) {
  ------------------
  |  Branch (165:30): [True: 8.76M, False: 6.51M]
  ------------------
  166|  8.76M|        value |= GetBit() << bit;
  167|  8.76M|      }
  168|  6.51M|      *x = value;
  169|  6.51M|      return true;
  170|  6.51M|    }
_ZN5draco13DecoderBuffer10BitDecoder6GetBitEv:
  175|  8.76M|    inline int GetBit() {
  176|  8.76M|      const size_t off = bit_offset_;
  177|  8.76M|      const size_t byte_offset = off >> 3;
  178|  8.76M|      const int bit_shift = static_cast<int>(off & 0x7);
  179|  8.76M|      if (bit_buffer_ + byte_offset < bit_buffer_end_) {
  ------------------
  |  Branch (179:11): [True: 8.70M, False: 65.4k]
  ------------------
  180|  8.70M|        const int bit = (bit_buffer_[byte_offset] >> bit_shift) & 1;
  181|  8.70M|        bit_offset_ = off + 1;
  182|  8.70M|        return bit;
  183|  8.70M|      }
  184|  65.4k|      return 0;
  185|  8.76M|    }
_ZN5draco13DecoderBuffer6DecodeIhEEbPT_:
   68|  16.0M|  bool Decode(T *out_val) {
   69|  16.0M|    if (!Peek(out_val)) {
  ------------------
  |  Branch (69:9): [True: 307, False: 16.0M]
  ------------------
   70|    307|      return false;
   71|    307|    }
   72|  16.0M|    pos_ += sizeof(T);
   73|  16.0M|    return true;
   74|  16.0M|  }
_ZN5draco13DecoderBuffer4PeekIhEEbPT_:
   87|  16.0M|  bool Peek(T *out_val) {
   88|  16.0M|    const size_t size_to_decode = sizeof(T);
   89|  16.0M|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (89:9): [True: 307, False: 16.0M]
  ------------------
   90|    307|      return false;  // Buffer overflow.
   91|    307|    }
   92|  16.0M|    memcpy(out_val, (data_ + pos_), size_to_decode);
   93|  16.0M|    return true;
   94|  16.0M|  }
_ZN5draco13DecoderBuffer6DecodeIiEEbPT_:
   68|  1.39k|  bool Decode(T *out_val) {
   69|  1.39k|    if (!Peek(out_val)) {
  ------------------
  |  Branch (69:9): [True: 1, False: 1.39k]
  ------------------
   70|      1|      return false;
   71|      1|    }
   72|  1.39k|    pos_ += sizeof(T);
   73|  1.39k|    return true;
   74|  1.39k|  }
_ZN5draco13DecoderBuffer4PeekIiEEbPT_:
   87|  1.39k|  bool Peek(T *out_val) {
   88|  1.39k|    const size_t size_to_decode = sizeof(T);
   89|  1.39k|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (89:9): [True: 1, False: 1.39k]
  ------------------
   90|      1|      return false;  // Buffer overflow.
   91|      1|    }
   92|  1.39k|    memcpy(out_val, (data_ + pos_), size_to_decode);
   93|  1.39k|    return true;
   94|  1.39k|  }
_ZN5draco13DecoderBuffer6DecodeIjEEbPT_:
   68|   414k|  bool Decode(T *out_val) {
   69|   414k|    if (!Peek(out_val)) {
  ------------------
  |  Branch (69:9): [True: 30, False: 414k]
  ------------------
   70|     30|      return false;
   71|     30|    }
   72|   414k|    pos_ += sizeof(T);
   73|   414k|    return true;
   74|   414k|  }
_ZN5draco13DecoderBuffer4PeekIjEEbPT_:
   87|   414k|  bool Peek(T *out_val) {
   88|   414k|    const size_t size_to_decode = sizeof(T);
   89|   414k|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (89:9): [True: 30, False: 414k]
  ------------------
   90|     30|      return false;  // Buffer overflow.
   91|     30|    }
   92|   414k|    memcpy(out_val, (data_ + pos_), size_to_decode);
   93|   414k|    return true;
   94|   414k|  }
_ZN5draco13DecoderBuffer6DecodeIaEEbPT_:
   68|  4.40k|  bool Decode(T *out_val) {
   69|  4.40k|    if (!Peek(out_val)) {
  ------------------
  |  Branch (69:9): [True: 21, False: 4.38k]
  ------------------
   70|     21|      return false;
   71|     21|    }
   72|  4.38k|    pos_ += sizeof(T);
   73|  4.38k|    return true;
   74|  4.40k|  }
_ZN5draco13DecoderBuffer4PeekIaEEbPT_:
   87|  4.40k|  bool Peek(T *out_val) {
   88|  4.40k|    const size_t size_to_decode = sizeof(T);
   89|  4.40k|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (89:9): [True: 21, False: 4.38k]
  ------------------
   90|     21|      return false;  // Buffer overflow.
   91|     21|    }
   92|  4.38k|    memcpy(out_val, (data_ + pos_), size_to_decode);
   93|  4.38k|    return true;
   94|  4.40k|  }
_ZN5draco13DecoderBuffer6DecodeINS_13HoleEventDataEEEbPT_:
   68|   596k|  bool Decode(T *out_val) {
   69|   596k|    if (!Peek(out_val)) {
  ------------------
  |  Branch (69:9): [True: 31, False: 596k]
  ------------------
   70|     31|      return false;
   71|     31|    }
   72|   596k|    pos_ += sizeof(T);
   73|   596k|    return true;
   74|   596k|  }
_ZN5draco13DecoderBuffer4PeekINS_13HoleEventDataEEEbPT_:
   87|   596k|  bool Peek(T *out_val) {
   88|   596k|    const size_t size_to_decode = sizeof(T);
   89|   596k|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (89:9): [True: 31, False: 596k]
  ------------------
   90|     31|      return false;  // Buffer overflow.
   91|     31|    }
   92|   596k|    memcpy(out_val, (data_ + pos_), size_to_decode);
   93|   596k|    return true;
   94|   596k|  }
_ZN5draco13DecoderBuffer6DecodeItEEbPT_:
   68|   329k|  bool Decode(T *out_val) {
   69|   329k|    if (!Peek(out_val)) {
  ------------------
  |  Branch (69:9): [True: 8, False: 329k]
  ------------------
   70|      8|      return false;
   71|      8|    }
   72|   329k|    pos_ += sizeof(T);
   73|   329k|    return true;
   74|   329k|  }
_ZN5draco13DecoderBuffer4PeekItEEbPT_:
   87|   329k|  bool Peek(T *out_val) {
   88|   329k|    const size_t size_to_decode = sizeof(T);
   89|   329k|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (89:9): [True: 8, False: 329k]
  ------------------
   90|      8|      return false;  // Buffer overflow.
   91|      8|    }
   92|   329k|    memcpy(out_val, (data_ + pos_), size_to_decode);
   93|   329k|    return true;
   94|   329k|  }
_ZN5draco13DecoderBuffer6DecodeImEEbPT_:
   68|    576|  bool Decode(T *out_val) {
   69|    576|    if (!Peek(out_val)) {
  ------------------
  |  Branch (69:9): [True: 0, False: 576]
  ------------------
   70|      0|      return false;
   71|      0|    }
   72|    576|    pos_ += sizeof(T);
   73|    576|    return true;
   74|    576|  }
_ZN5draco13DecoderBuffer4PeekImEEbPT_:
   87|    576|  bool Peek(T *out_val) {
   88|    576|    const size_t size_to_decode = sizeof(T);
   89|    576|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (89:9): [True: 0, False: 576]
  ------------------
   90|      0|      return false;  // Buffer overflow.
   91|      0|    }
   92|    576|    memcpy(out_val, (data_ + pos_), size_to_decode);
   93|    576|    return true;
   94|    576|  }
_ZN5draco13DecoderBuffer6DecodeIfEEbPT_:
   68|     45|  bool Decode(T *out_val) {
   69|     45|    if (!Peek(out_val)) {
  ------------------
  |  Branch (69:9): [True: 0, False: 45]
  ------------------
   70|      0|      return false;
   71|      0|    }
   72|     45|    pos_ += sizeof(T);
   73|     45|    return true;
   74|     45|  }
_ZN5draco13DecoderBuffer4PeekIfEEbPT_:
   87|     45|  bool Peek(T *out_val) {
   88|     45|    const size_t size_to_decode = sizeof(T);
   89|     45|    if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) {
  ------------------
  |  Branch (89:9): [True: 0, False: 45]
  ------------------
   90|      0|      return false;  // Buffer overflow.
   91|      0|    }
   92|     45|    memcpy(out_val, (data_ + pos_), size_to_decode);
   93|     45|    return true;
   94|     45|  }

_ZNK5draco9IndexTypeIjNS_29AttributeValueIndex_tag_type_EE5valueEv:
   72|  5.47M|  constexpr ValueTypeT value() const { return value_; }
_ZNK5draco9IndexTypeIjNS_20PointIndex_tag_type_EE5valueEv:
   72|  3.98M|  constexpr ValueTypeT value() const { return value_; }
_ZNK5draco9IndexTypeIjNS_19FaceIndex_tag_type_EEgeERKj:
   97|   712k|  constexpr bool operator>=(const ValueTypeT &val) const {
   98|   712k|    return value_ >= val;
   99|   712k|  }
_ZNK5draco9IndexTypeIjNS_19FaceIndex_tag_type_EE5valueEv:
   72|  68.7M|  constexpr ValueTypeT value() const { return value_; }
_ZNK5draco9IndexTypeIjNS_21CornerIndex_tag_type_EE5valueEv:
   72|  1.31G|  constexpr ValueTypeT value() const { return value_; }
_ZNK5draco9IndexTypeIjNS_19FaceIndex_tag_type_EEltERKj:
   89|  1.69M|  constexpr bool operator<(const ValueTypeT &val) const { return value_ < val; }
_ZN5draco9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEaSERKS2_:
  150|  4.32M|  inline ThisIndexType &operator=(const ThisIndexType &i) {
  151|  4.32M|    value_ = i.value_;
  152|  4.32M|    return *this;
  153|  4.32M|  }
_ZN5draco9IndexTypeIjNS_20PointIndex_tag_type_EEaSERKS2_:
  150|   211M|  inline ThisIndexType &operator=(const ThisIndexType &i) {
  151|   211M|    value_ = i.value_;
  152|   211M|    return *this;
  153|   211M|  }
_ZN5draco9IndexTypeIjNS_19FaceIndex_tag_type_EEppEv:
  101|  1.68M|  inline ThisIndexType &operator++() {
  102|  1.68M|    ++value_;
  103|  1.68M|    return *this;
  104|  1.68M|  }
_ZNK5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEeqERKS2_:
   74|   974M|  constexpr bool operator==(const IndexType &i) const {
   75|   974M|    return value_ == i.value_;
   76|   974M|  }
_ZNK5draco9IndexTypeIjNS_21VertexIndex_tag_type_EE5valueEv:
   72|   363M|  constexpr ValueTypeT value() const { return value_; }
_ZNK5draco9IndexTypeIjNS_21VertexIndex_tag_type_EEltERKS2_:
   86|  9.08k|  constexpr bool operator<(const IndexType &i) const {
   87|  9.08k|    return value_ < i.value_;
   88|  9.08k|  }
_ZNK5draco9IndexTypeIjNS_21VertexIndex_tag_type_EEeqERKS2_:
   74|  63.4M|  constexpr bool operator==(const IndexType &i) const {
   75|  63.4M|    return value_ == i.value_;
   76|  63.4M|  }
_ZNK5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEmiERKj:
  130|  28.5M|  constexpr ThisIndexType operator-(const ValueTypeT &val) const {
  131|  28.5M|    return ThisIndexType(value_ - val);
  132|  28.5M|  }
_ZNK5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEplERKj:
  124|   337M|  constexpr ThisIndexType operator+(const ValueTypeT &val) const {
  125|   337M|    return ThisIndexType(value_ + val);
  126|   337M|  }
_ZNK5draco9IndexTypeIjNS_19FaceIndex_tag_type_EEeqERKS2_:
   74|   766k|  constexpr bool operator==(const IndexType &i) const {
   75|   766k|    return value_ == i.value_;
   76|   766k|  }
_ZNK5draco9IndexTypeIjNS_21VertexIndex_tag_type_EEneERKS2_:
   80|  94.9M|  constexpr bool operator!=(const IndexType &i) const {
   81|  94.9M|    return value_ != i.value_;
   82|  94.9M|  }
_ZNK5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEneERKS2_:
   80|   128M|  constexpr bool operator!=(const IndexType &i) const {
   81|   128M|    return value_ != i.value_;
   82|   128M|  }
_ZN5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEppEv:
  101|   295M|  inline ThisIndexType &operator++() {
  102|   295M|    ++value_;
  103|   295M|    return *this;
  104|   295M|  }
_ZN5draco9IndexTypeIjNS_21VertexIndex_tag_type_EEaSERKS2_:
  150|   214M|  inline ThisIndexType &operator=(const ThisIndexType &i) {
  151|   214M|    value_ = i.value_;
  152|   214M|    return *this;
  153|   214M|  }
_ZN5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEaSERKS2_:
  150|   458M|  inline ThisIndexType &operator=(const ThisIndexType &i) {
  151|   458M|    value_ = i.value_;
  152|   458M|    return *this;
  153|   458M|  }
_ZNK5draco9IndexTypeIjNS_20PointIndex_tag_type_EEgeERKj:
   97|  2.92M|  constexpr bool operator>=(const ValueTypeT &val) const {
   98|  2.92M|    return value_ >= val;
   99|  2.92M|  }
_ZNK5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEltERKj:
   89|   496k|  constexpr bool operator<(const ValueTypeT &val) const { return value_ < val; }
_ZN5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEC2Ej:
   70|   431M|  constexpr explicit IndexType(ValueTypeT value) : value_(value) {}
_ZN5draco9IndexTypeIjNS_19FaceIndex_tag_type_EEC2Ej:
   70|  63.4M|  constexpr explicit IndexType(ValueTypeT value) : value_(value) {}
_ZN5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEC2Ev:
   69|  89.1M|  constexpr IndexType() : value_(ValueTypeT()) {}
_ZNK5draco9IndexTypeIjNS_21VertexIndex_tag_type_EEplERKj:
  124|  1.93M|  constexpr ThisIndexType operator+(const ValueTypeT &val) const {
  125|  1.93M|    return ThisIndexType(value_ + val);
  126|  1.93M|  }
_ZN5draco9IndexTypeIjNS_21VertexIndex_tag_type_EEC2Ej:
   70|  37.1M|  constexpr explicit IndexType(ValueTypeT value) : value_(value) {}
_ZNK5draco9IndexTypeIjNS_19FaceIndex_tag_type_EEltERKS2_:
   86|   934k|  constexpr bool operator<(const IndexType &i) const {
   87|   934k|    return value_ < i.value_;
   88|   934k|  }
_ZN5draco9IndexTypeIjNS_20PointIndex_tag_type_EEC2Ev:
   69|   212M|  constexpr IndexType() : value_(ValueTypeT()) {}
_ZN5draco9IndexTypeIjNS_29AttributeValueIndex_tag_type_EEC2Ej:
   70|  4.31M|  constexpr explicit IndexType(ValueTypeT value) : value_(value) {}
_ZN5draco9IndexTypeIjNS_19FaceIndex_tag_type_EEaSERKS2_:
  150|   337k|  inline ThisIndexType &operator=(const ThisIndexType &i) {
  151|   337k|    value_ = i.value_;
  152|   337k|    return *this;
  153|   337k|  }
_ZN5draco9IndexTypeIjNS_21CornerIndex_tag_type_EEpLERKj:
  138|   496k|  inline ThisIndexType operator+=(const ValueTypeT &val) {
  139|   496k|    value_ += val;
  140|   496k|    return *this;
  141|   496k|  }
_ZN5draco9IndexTypeIjNS_20PointIndex_tag_type_EEaSERKj:
  154|  2.94M|  inline ThisIndexType &operator=(const ValueTypeT &val) {
  155|  2.94M|    value_ = val;
  156|  2.94M|    return *this;
  157|  2.94M|  }
_ZN5draco9IndexTypeIjNS_20PointIndex_tag_type_EEC2Ej:
   70|   209M|  constexpr explicit IndexType(ValueTypeT value) : value_(value) {}
_ZNK5draco9IndexTypeIjNS_21VertexIndex_tag_type_EEltERKj:
   89|   519k|  constexpr bool operator<(const ValueTypeT &val) const { return value_ < val; }
_ZN5draco9IndexTypeIjNS_21VertexIndex_tag_type_EEppEv:
  101|   517k|  inline ThisIndexType &operator++() {
  102|   517k|    ++value_;
  103|   517k|    return *this;
  104|   517k|  }
_ZNK5draco9IndexTypeIjNS_20PointIndex_tag_type_EEltERKj:
   89|   470k|  constexpr bool operator<(const ValueTypeT &val) const { return value_ < val; }
_ZN5draco9IndexTypeIjNS_20PointIndex_tag_type_EEppEv:
  101|   469k|  inline ThisIndexType &operator++() {
  102|   469k|    ++value_;
  103|   469k|    return *this;
  104|   469k|  }

_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_IjNS_29AttributeValueIndex_tag_type_EEEEixERKS3_:
   73|   584k|  inline const_reference operator[](const IndexTypeT &index) const {
   74|   584k|    return vector_[index.value()];
   75|   584k|  }
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_IjNS_29AttributeValueIndex_tag_type_EEEE4sizeEv:
   59|   470k|  size_t size() const { return vector_.size(); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_IjNS_29AttributeValueIndex_tag_type_EEEE5clearEv:
   48|  3.36k|  void clear() { vector_.clear(); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_IjNS_29AttributeValueIndex_tag_type_EEEE6resizeEmRKS5_:
   51|  3.24k|  void resize(size_t size, const ValueTypeT &val) { vector_.resize(size, val); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_IjNS_29AttributeValueIndex_tag_type_EEEEixERKS3_:
   70|  3.39M|  inline reference operator[](const IndexTypeT &index) {
   71|  3.39M|    return vector_[index.value()];
   72|  3.39M|  }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_19FaceIndex_tag_type_EEENSt3__15arrayINS1_IjNS_20PointIndex_tag_type_EEELm3EEEE9push_backERKS8_:
   62|   270k|  void push_back(const ValueTypeT &val) { vector_.push_back(val); }
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_19FaceIndex_tag_type_EEENSt3__15arrayINS1_IjNS_20PointIndex_tag_type_EEELm3EEEE4sizeEv:
   59|  1.42M|  size_t size() const { return vector_.size(); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_19FaceIndex_tag_type_EEENSt3__15arrayINS1_IjNS_20PointIndex_tag_type_EEELm3EEEE6resizeEmRKS8_:
   51|    420|  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|   712k|  inline reference operator[](const IndexTypeT &index) {
   71|   712k|    return vector_[index.value()];
   72|   712k|  }
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_19FaceIndex_tag_type_EEENSt3__15arrayINS1_IjNS_20PointIndex_tag_type_EEELm3EEEEixERKS3_:
   73|  1.33M|  inline const_reference operator[](const IndexTypeT &index) const {
   74|  1.33M|    return vector_[index.value()];
   75|  1.33M|  }
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEENS1_IjNS_21CornerIndex_tag_type_EEEE4sizeEv:
   59|  63.7M|  size_t size() const { return vector_.size(); }
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEENS1_IjNS_21VertexIndex_tag_type_EEEE4sizeEv:
   59|   507k|  size_t size() const { return vector_.size(); }
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEES3_EixERKS3_:
   73|   126M|  inline const_reference operator[](const IndexTypeT &index) const {
   74|   126M|    return vector_[index.value()];
   75|   126M|  }
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEENS1_IjNS_21VertexIndex_tag_type_EEEEixERKS3_:
   73|   356M|  inline const_reference operator[](const IndexTypeT &index) const {
   74|   356M|    return vector_[index.value()];
   75|   356M|  }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEENS1_IjNS_21VertexIndex_tag_type_EEEEixERKS3_:
   70|   211M|  inline reference operator[](const IndexTypeT &index) {
   71|   211M|    return vector_[index.value()];
   72|   211M|  }
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEENS1_IjNS_21CornerIndex_tag_type_EEEEixERKS3_:
   73|  31.4M|  inline const_reference operator[](const IndexTypeT &index) const {
   74|  31.4M|    return vector_[index.value()];
   75|  31.4M|  }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEES3_EixERKS3_:
   70|   181M|  inline reference operator[](const IndexTypeT &index) {
   71|   181M|    return vector_[index.value()];
   72|   181M|  }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEENS1_IjNS_21CornerIndex_tag_type_EEEE9push_backERKS5_:
   62|  32.4M|  void push_back(const ValueTypeT &val) { vector_.push_back(val); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEENS1_IjNS_21CornerIndex_tag_type_EEEEixERKS3_:
   70|  93.5M|  inline reference operator[](const IndexTypeT &index) {
   71|  93.5M|    return vector_[index.value()];
   72|  93.5M|  }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEiE6resizeEmRKi:
   51|    322|  void resize(size_t size, const ValueTypeT &val) { vector_.resize(size, val); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEiEixERKS3_:
   70|  3.82M|  inline reference operator[](const IndexTypeT &index) {
   71|  3.82M|    return vector_[index.value()];
   72|  3.82M|  }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEiEC2Ev:
   39|  8.57k|  IndexTypeVector() {}
_ZNK5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEiE4sizeEv:
   59|  43.5k|  size_t size() const { return vector_.size(); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEaEC2Ev:
   39|  8.16k|  IndexTypeVector() {}
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEENS1_IjNS_21VertexIndex_tag_type_EEEEC2Ev:
   39|    833|  IndexTypeVector() {}
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEES3_EC2Ev:
   39|    833|  IndexTypeVector() {}
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEENS1_IjNS_21CornerIndex_tag_type_EEEEC2Ev:
   39|    833|  IndexTypeVector() {}
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEES3_EC2Ev:
   39|    833|  IndexTypeVector() {}
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEiE5clearEv:
   48|  2.49k|  void clear() { vector_.clear(); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEiE4swapERS4_:
   55|  2.49k|  void swap(IndexTypeVector<IndexTypeT, ValueTypeT> &arg) {
   56|  2.49k|    vector_.swap(arg.vector_);
   57|  2.49k|  }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEaE5clearEv:
   48|  2.49k|  void clear() { vector_.clear(); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEEaE4swapERS4_:
   55|  2.49k|  void swap(IndexTypeVector<IndexTypeT, ValueTypeT> &arg) {
   56|  2.49k|    vector_.swap(arg.vector_);
   57|  2.49k|  }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEENS1_IjNS_21VertexIndex_tag_type_EEEE6assignEmRKS5_:
   52|    833|  void assign(size_t size, const ValueTypeT &val) { vector_.assign(size, val); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21CornerIndex_tag_type_EEES3_E6assignEmRKS3_:
   52|    833|  void assign(size_t size, const ValueTypeT &val) { vector_.assign(size, val); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_21VertexIndex_tag_type_EEENS1_IjNS_21CornerIndex_tag_type_EEEE7reserveEm:
   49|    833|  void reserve(size_t size) { vector_.reserve(size); }
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_19FaceIndex_tag_type_EEENSt3__15arrayINS1_IjNS_20PointIndex_tag_type_EEELm3EEEEC2Ev:
   39|  1.36k|  IndexTypeVector() {}
_ZN5draco15IndexTypeVectorINS_9IndexTypeIjNS_20PointIndex_tag_type_EEENS1_IjNS_29AttributeValueIndex_tag_type_EEEEC2Ev:
   39|  66.8k|  IndexTypeVector() {}

_ZN5draco14DataTypeLengthENS_8DataTypeE:
   19|  72.7k|int32_t DataTypeLength(DataType dt) {
   20|  72.7k|  switch (dt) {
   21|  65.3k|    case DT_INT8:
  ------------------
  |  Branch (21:5): [True: 65.3k, False: 7.49k]
  ------------------
   22|  65.8k|    case DT_UINT8:
  ------------------
  |  Branch (22:5): [True: 529, False: 72.2k]
  ------------------
   23|  65.8k|      return 1;
   24|    329|    case DT_INT16:
  ------------------
  |  Branch (24:5): [True: 329, False: 72.4k]
  ------------------
   25|    351|    case DT_UINT16:
  ------------------
  |  Branch (25:5): [True: 22, False: 72.7k]
  ------------------
   26|    351|      return 2;
   27|  5.69k|    case DT_INT32:
  ------------------
  |  Branch (27:5): [True: 5.69k, False: 67.1k]
  ------------------
   28|  5.75k|    case DT_UINT32:
  ------------------
  |  Branch (28:5): [True: 63, False: 72.7k]
  ------------------
   29|  5.75k|      return 4;
   30|     66|    case DT_INT64:
  ------------------
  |  Branch (30:5): [True: 66, False: 72.7k]
  ------------------
   31|    247|    case DT_UINT64:
  ------------------
  |  Branch (31:5): [True: 181, False: 72.6k]
  ------------------
   32|    247|      return 8;
   33|    462|    case DT_FLOAT32:
  ------------------
  |  Branch (33:5): [True: 462, False: 72.3k]
  ------------------
   34|    462|      return 4;
   35|      6|    case DT_FLOAT64:
  ------------------
  |  Branch (35:5): [True: 6, False: 72.7k]
  ------------------
   36|      6|      return 8;
   37|    146|    case DT_BOOL:
  ------------------
  |  Branch (37:5): [True: 146, False: 72.6k]
  ------------------
   38|    146|      return 1;
   39|      0|    default:
  ------------------
  |  Branch (39:5): [True: 0, False: 72.7k]
  ------------------
   40|      0|      return -1;
   41|  72.7k|  }
   42|  72.7k|}

_ZN5draco7IntSqrtEm:
   31|    472|inline uint64_t IntSqrt(uint64_t number) {
   32|    472|  if (number == 0) {
  ------------------
  |  Branch (32:7): [True: 58, False: 414]
  ------------------
   33|     58|    return 0;
   34|     58|  }
   35|       |  // First estimate good initial value of the square root as log2(number).
   36|    414|  uint64_t act_number = number;
   37|    414|  uint64_t square_root = 1;
   38|  8.27k|  while (act_number >= 2) {
  ------------------
  |  Branch (38:10): [True: 7.86k, False: 414]
  ------------------
   39|       |    // Double the square root until |square_root * square_root > number|.
   40|  7.86k|    square_root *= 2;
   41|  7.86k|    act_number /= 4;
   42|  7.86k|  }
   43|       |  // Perform Newton's (or Babylonian) method to find the true floor(sqrt()).
   44|  1.15k|  do {
   45|       |    // New |square_root| estimate is computed as the average between
   46|       |    // |square_root| and |number / square_root|.
   47|  1.15k|    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|  1.15k|  } while (square_root * square_root > number);
  ------------------
  |  Branch (53:12): [True: 745, False: 414]
  ------------------
   54|    414|  return square_root;
   55|    472|}
_ZN5draco13AddAsUnsignedIiLPv0EEET_S2_S2_:
   63|   310k|inline DataTypeT AddAsUnsigned(DataTypeT a, DataTypeT b) {
   64|   310k|  typedef typename std::make_unsigned<DataTypeT>::type DataTypeUT;
   65|   310k|  return static_cast<DataTypeT>(static_cast<DataTypeUT>(a) +
   66|   310k|                                static_cast<DataTypeUT>(b));
   67|   310k|}

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

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

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

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

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

_ZN5draco8StatusOrINSt3__110unique_ptrINS_11MeshDecoderENS1_14default_deleteIS3_EEEEEC2EOS6_:
   39|  1.36k|  StatusOr(T &&value) : status_(OkStatus()), value_(std::move(value)) {}
_ZN5draco8StatusOrINSt3__110unique_ptrINS_4MeshENS1_14default_deleteIS3_EEEEEC2ERKNS_6StatusE:
   37|  1.29k|  StatusOr(const Status &status) : status_(status) {}
_ZN5draco8StatusOrINSt3__110unique_ptrINS_4MeshENS1_14default_deleteIS3_EEEEEC2EOS6_:
   39|     70|  StatusOr(T &&value) : status_(OkStatus()), value_(std::move(value)) {}
_ZNK5draco8StatusOrINSt3__110unique_ptrINS_11MeshDecoderENS1_14default_deleteIS3_EEEEE2okEv:
   53|  1.36k|  bool ok() const { return status_.ok(); }
_ZNO5draco8StatusOrINSt3__110unique_ptrINS_11MeshDecoderENS1_14default_deleteIS3_EEEEE5valueEv:
   46|  1.36k|  T &&value() && { return std::move(value_); }

_ZN5draco12DecodeVarintIjEEbPT_PNS_13DecoderBufferE:
   63|   430k|bool DecodeVarint(IntTypeT *out_val, DecoderBuffer *buffer) {
   64|   430k|  if (std::is_unsigned<IntTypeT>::value) {
  ------------------
  |  Branch (64:7): [Folded - Ignored]
  ------------------
   65|   430k|    if (!DecodeVarintUnsigned<IntTypeT>(1, out_val, buffer)) {
  ------------------
  |  Branch (65:9): [True: 147, False: 430k]
  ------------------
   66|    147|      return false;
   67|    147|    }
   68|   430k|  } 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|   430k|  return true;
   77|   430k|}
mesh_edgebreaker_decoder_impl.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedIjEEbiPT_PNS_13DecoderBufferE:
   30|   196k|bool DecodeVarintUnsigned(int depth, IntTypeT *out_val, DecoderBuffer *buffer) {
   31|   196k|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|   196k|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 35, False: 196k]
  ------------------
   33|     35|    return false;
   34|     35|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|   196k|  uint8_t in;
   39|   196k|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 76, False: 196k]
  ------------------
   40|     76|    return false;
   41|     76|  }
   42|   196k|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 4.71k, False: 191k]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|  4.71k|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 175, False: 4.53k]
  ------------------
   45|    175|      return false;
   46|    175|    }
   47|       |    // Append decoded info from this byte.
   48|  4.53k|    *out_val <<= 7;
   49|  4.53k|    *out_val |= in & ((1 << 7) - 1);
   50|   191k|  } else {
   51|       |    // Last byte reached
   52|   191k|    *out_val = in;
   53|   191k|  }
   54|   195k|  return true;
   55|   196k|}
mesh_sequential_decoder.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedIjEEbiPT_PNS_13DecoderBufferE:
   30|  1.32k|bool DecodeVarintUnsigned(int depth, IntTypeT *out_val, DecoderBuffer *buffer) {
   31|  1.32k|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|  1.32k|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 0, False: 1.32k]
  ------------------
   33|      0|    return false;
   34|      0|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|  1.32k|  uint8_t in;
   39|  1.32k|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 1, False: 1.32k]
  ------------------
   40|      1|    return false;
   41|      1|  }
   42|  1.32k|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 218, False: 1.10k]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|    218|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 0, False: 218]
  ------------------
   45|      0|      return false;
   46|      0|    }
   47|       |    // Append decoded info from this byte.
   48|    218|    *out_val <<= 7;
   49|    218|    *out_val |= in & ((1 << 7) - 1);
   50|  1.10k|  } else {
   51|       |    // Last byte reached
   52|  1.10k|    *out_val = in;
   53|  1.10k|  }
   54|  1.32k|  return true;
   55|  1.32k|}
_ZN5draco12DecodeVarintImEEbPT_PNS_13DecoderBufferE:
   63|    488|bool DecodeVarint(IntTypeT *out_val, DecoderBuffer *buffer) {
   64|    488|  if (std::is_unsigned<IntTypeT>::value) {
  ------------------
  |  Branch (64:7): [Folded - Ignored]
  ------------------
   65|    488|    if (!DecodeVarintUnsigned<IntTypeT>(1, out_val, buffer)) {
  ------------------
  |  Branch (65:9): [True: 0, False: 488]
  ------------------
   66|      0|      return false;
   67|      0|    }
   68|    488|  } 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|    488|  return true;
   77|    488|}
decoder_buffer.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedImEEbiPT_PNS_13DecoderBufferE:
   30|    297|bool DecodeVarintUnsigned(int depth, IntTypeT *out_val, DecoderBuffer *buffer) {
   31|    297|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|    297|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 0, False: 297]
  ------------------
   33|      0|    return false;
   34|      0|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|    297|  uint8_t in;
   39|    297|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 0, False: 297]
  ------------------
   40|      0|    return false;
   41|      0|  }
   42|    297|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 10, False: 287]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|     10|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 0, False: 10]
  ------------------
   45|      0|      return false;
   46|      0|    }
   47|       |    // Append decoded info from this byte.
   48|     10|    *out_val <<= 7;
   49|     10|    *out_val |= in & ((1 << 7) - 1);
   50|    287|  } else {
   51|       |    // Last byte reached
   52|    287|    *out_val = in;
   53|    287|  }
   54|    297|  return true;
   55|    297|}
metadata_decoder.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedIjEEbiPT_PNS_13DecoderBufferE:
   30|   230k|bool DecodeVarintUnsigned(int depth, IntTypeT *out_val, DecoderBuffer *buffer) {
   31|   230k|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|   230k|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 6, False: 230k]
  ------------------
   33|      6|    return false;
   34|      6|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|   230k|  uint8_t in;
   39|   230k|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 18, False: 230k]
  ------------------
   40|     18|    return false;
   41|     18|  }
   42|   230k|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 995, False: 229k]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|    995|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 30, False: 965]
  ------------------
   45|     30|      return false;
   46|     30|    }
   47|       |    // Append decoded info from this byte.
   48|    965|    *out_val <<= 7;
   49|    965|    *out_val |= in & ((1 << 7) - 1);
   50|   229k|  } else {
   51|       |    // Last byte reached
   52|   229k|    *out_val = in;
   53|   229k|  }
   54|   230k|  return true;
   55|   230k|}
sequential_integer_attribute_decoder.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedIjEEbiPT_PNS_13DecoderBufferE:
   30|    493|bool DecodeVarintUnsigned(int depth, IntTypeT *out_val, DecoderBuffer *buffer) {
   31|    493|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|    493|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 1, False: 492]
  ------------------
   33|      1|    return false;
   34|      1|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|    492|  uint8_t in;
   39|    492|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 0, False: 492]
  ------------------
   40|      0|    return false;
   41|      0|  }
   42|    492|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 128, False: 364]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|    128|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 5, False: 123]
  ------------------
   45|      5|      return false;
   46|      5|    }
   47|       |    // Append decoded info from this byte.
   48|    123|    *out_val <<= 7;
   49|    123|    *out_val |= in & ((1 << 7) - 1);
   50|    364|  } else {
   51|       |    // Last byte reached
   52|    364|    *out_val = in;
   53|    364|  }
   54|    487|  return true;
   55|    492|}
rans_bit_decoder.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedIjEEbiPT_PNS_13DecoderBufferE:
   30|  2.82k|bool DecodeVarintUnsigned(int depth, IntTypeT *out_val, DecoderBuffer *buffer) {
   31|  2.82k|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|  2.82k|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 2, False: 2.82k]
  ------------------
   33|      2|    return false;
   34|      2|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|  2.82k|  uint8_t in;
   39|  2.82k|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 0, False: 2.82k]
  ------------------
   40|      0|    return false;
   41|      0|  }
   42|  2.82k|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 76, False: 2.74k]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|     76|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 10, False: 66]
  ------------------
   45|     10|      return false;
   46|     10|    }
   47|       |    // Append decoded info from this byte.
   48|     66|    *out_val <<= 7;
   49|     66|    *out_val |= in & ((1 << 7) - 1);
   50|  2.74k|  } else {
   51|       |    // Last byte reached
   52|  2.74k|    *out_val = in;
   53|  2.74k|  }
   54|  2.81k|  return true;
   55|  2.82k|}
symbol_decoding.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedIjEEbiPT_PNS_13DecoderBufferE:
   30|    858|bool DecodeVarintUnsigned(int depth, IntTypeT *out_val, DecoderBuffer *buffer) {
   31|    858|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|    858|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 0, False: 858]
  ------------------
   33|      0|    return false;
   34|      0|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|    858|  uint8_t in;
   39|    858|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 0, False: 858]
  ------------------
   40|      0|    return false;
   41|      0|  }
   42|    858|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 274, False: 584]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|    274|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 0, False: 274]
  ------------------
   45|      0|      return false;
   46|      0|    }
   47|       |    // Append decoded info from this byte.
   48|    274|    *out_val <<= 7;
   49|    274|    *out_val |= in & ((1 << 7) - 1);
   50|    584|  } else {
   51|       |    // Last byte reached
   52|    584|    *out_val = in;
   53|    584|  }
   54|    858|  return true;
   55|    858|}
symbol_decoding.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedImEEbiPT_PNS_13DecoderBufferE:
   30|    449|bool DecodeVarintUnsigned(int depth, IntTypeT *out_val, DecoderBuffer *buffer) {
   31|    449|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|    449|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 0, False: 449]
  ------------------
   33|      0|    return false;
   34|      0|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|    449|  uint8_t in;
   39|    449|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 0, False: 449]
  ------------------
   40|      0|    return false;
   41|      0|  }
   42|    449|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 248, False: 201]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|    248|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 0, False: 248]
  ------------------
   45|      0|      return false;
   46|      0|    }
   47|       |    // Append decoded info from this byte.
   48|    248|    *out_val <<= 7;
   49|    248|    *out_val |= in & ((1 << 7) - 1);
   50|    248|  } else {
   51|       |    // Last byte reached
   52|    201|    *out_val = in;
   53|    201|  }
   54|    449|  return true;
   55|    449|}
attributes_decoder.cc:_ZN5draco12_GLOBAL__N_120DecodeVarintUnsignedIjEEbiPT_PNS_13DecoderBufferE:
   30|  4.64k|bool DecodeVarintUnsigned(int depth, IntTypeT *out_val, DecoderBuffer *buffer) {
   31|  4.64k|  constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3);
   32|  4.64k|  if (depth > max_depth) {
  ------------------
  |  Branch (32:7): [True: 3, False: 4.63k]
  ------------------
   33|      3|    return false;
   34|      3|  }
   35|       |  // Coding of unsigned values.
   36|       |  // 0-6 bit - data
   37|       |  // 7 bit - next byte?
   38|  4.63k|  uint8_t in;
   39|  4.63k|  if (!buffer->Decode(&in)) {
  ------------------
  |  Branch (39:7): [True: 5, False: 4.63k]
  ------------------
   40|      5|    return false;
   41|      5|  }
   42|  4.63k|  if (in & (1 << 7)) {
  ------------------
  |  Branch (42:7): [True: 73, False: 4.56k]
  ------------------
   43|       |    // Next byte is available, decode it first.
   44|     73|    if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) {
  ------------------
  |  Branch (44:9): [True: 17, False: 56]
  ------------------
   45|     17|      return false;
   46|     17|    }
   47|       |    // Append decoded info from this byte.
   48|     56|    *out_val <<= 7;
   49|     56|    *out_val |= in & ((1 << 7) - 1);
   50|  4.56k|  } else {
   51|       |    // Last byte reached
   52|  4.56k|    *out_val = in;
   53|  4.56k|  }
   54|  4.61k|  return true;
   55|  4.63k|}

_ZNK5draco7VectorDIfLi3EEixEi:
  113|   392k|  const Scalar &operator[](int i) const { return v_[i]; }
_ZN5draco7VectorDIfLi3EEixEi:
  112|   508k|  Scalar &operator[](int i) { return v_[i]; }
_ZNK5draco7VectorDIfLi3EEmiERKS1_:
  137|  42.3k|  Self operator-(const Self &o) const {
  138|  42.3k|    Self ret;
  139|   169k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (139:21): [True: 127k, False: 42.3k]
  ------------------
  140|   127k|      ret[i] = (*this)[i] - o[i];
  141|   127k|    }
  142|  42.3k|    return ret;
  143|  42.3k|  }
_ZN5draco7VectorDIfLi3EEC2Ev:
   40|   105k|  VectorD() {
   41|   422k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (41:21): [True: 316k, False: 105k]
  ------------------
   42|   316k|      (*this)[i] = Scalar(0);
   43|   316k|    }
   44|   105k|  }
_ZNK5draco7VectorDIlLi3EEixEi:
  113|   568k|  const Scalar &operator[](int i) const { return v_[i]; }
_ZNK5draco7VectorDIlLi3EEmiERKS1_:
  137|  46.1k|  Self operator-(const Self &o) const {
  138|  46.1k|    Self ret;
  139|   184k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (139:21): [True: 138k, False: 46.1k]
  ------------------
  140|   138k|      ret[i] = (*this)[i] - o[i];
  141|   138k|    }
  142|  46.1k|    return ret;
  143|  46.1k|  }
_ZN5draco12CrossProductIlEENS_7VectorDIT_Li3EEERKS3_S5_:
  318|  22.2k|                                 const VectorD<ScalarT, 3> &v) {
  319|       |  // Preventing accidental use with uint32_t and the like.
  320|  22.2k|  static_assert(std::is_signed<ScalarT>::value,
  321|  22.2k|                "ScalarT must be a signed type. ");
  322|  22.2k|  VectorD<ScalarT, 3> r;
  323|  22.2k|  r[0] = (u[1] * v[2]) - (u[2] * v[1]);
  324|  22.2k|  r[1] = (u[2] * v[0]) - (u[0] * v[2]);
  325|  22.2k|  r[2] = (u[0] * v[1]) - (u[1] * v[0]);
  326|  22.2k|  return r;
  327|  22.2k|}
_ZN5draco7VectorDIlLi3EE4dataEv:
  282|  22.2k|  Scalar *data() { return &(v_[0]); }
_ZNK5draco7VectorDIlLi3EE4dataEv:
  283|  22.2k|  const Scalar *data() const { return &(v_[0]); }
_ZNK5draco7VectorDIlLi3EE6AbsSumEv:
  237|  5.72k|  Scalar AbsSum() const {
  238|  5.72k|    Scalar result(0);
  239|  21.5k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (239:21): [True: 16.7k, False: 4.84k]
  ------------------
  240|  16.7k|      Scalar next_value = std::abs(v_[i]);
  241|  16.7k|      if (result > std::numeric_limits<Scalar>::max() - next_value) {
  ------------------
  |  Branch (241:11): [True: 880, False: 15.8k]
  ------------------
  242|       |        // Return the max if adding would have caused an overflow.
  243|    880|        return std::numeric_limits<Scalar>::max();
  244|    880|      }
  245|  15.8k|      result += next_value;
  246|  15.8k|    }
  247|  4.84k|    return result;
  248|  5.72k|  }
_ZNK5draco7VectorDIlLi3EEdvERKl:
  182|  3.15k|  Self operator/(const Scalar &o) const {
  183|  3.15k|    Self ret;
  184|  12.6k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (184:21): [True: 9.45k, False: 3.15k]
  ------------------
  185|  9.45k|      ret[i] = (*this)[i] / o;
  186|  9.45k|    }
  187|  3.15k|    return ret;
  188|  3.15k|  }
_ZN5draco7VectorDIlLi3EEixEi:
  112|   678k|  Scalar &operator[](int i) { return v_[i]; }
_ZN5draco7VectorDIiLi3EEixEi:
  112|  22.3k|  Scalar &operator[](int i) { return v_[i]; }
_ZN5draco7VectorDIiLi3EE4dataEv:
  282|  17.1k|  Scalar *data() { return &(v_[0]); }
_ZNK5draco7VectorDIiLi3EEngEv:
  120|  3.67k|  Self operator-() const {
  121|  3.67k|    Self ret;
  122|  14.6k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (122:21): [True: 11.0k, False: 3.67k]
  ------------------
  123|  11.0k|      ret[i] = -(*this)[i];
  124|  11.0k|    }
  125|  3.67k|    return ret;
  126|  3.67k|  }
_ZNK5draco7VectorDIiLi3EEixEi:
  113|  11.0k|  const Scalar &operator[](int i) const { return v_[i]; }
_ZNK5draco7VectorDIjLi2EEmiERKS1_:
  137|    320|  Self operator-(const Self &o) const {
  138|    320|    Self ret;
  139|    960|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (139:21): [True: 640, False: 320]
  ------------------
  140|    640|      ret[i] = (*this)[i] - o[i];
  141|    640|    }
  142|    320|    return ret;
  143|    320|  }
_ZN5draco7VectorDIjLi2EEixEi:
  112|  3.84k|  Scalar &operator[](int i) { return v_[i]; }
_ZNK5draco7VectorDIjLi2EEixEi:
  113|  5.76k|  const Scalar &operator[](int i) const { return v_[i]; }
_ZN5draco7VectorDIiLi2EEixEi:
  112|   488k|  Scalar &operator[](int i) { return v_[i]; }
_ZNK5draco7VectorDIjLi2EEplERKS1_:
  129|    640|  Self operator+(const Self &o) const {
  130|    640|    Self ret;
  131|  1.92k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (131:21): [True: 1.28k, False: 640]
  ------------------
  132|  1.28k|      ret[i] = (*this)[i] + o[i];
  133|  1.28k|    }
  134|    640|    return ret;
  135|    640|  }
_ZNK5draco7VectorDIiLi2EEixEi:
  113|   322k|  const Scalar &operator[](int i) const { return v_[i]; }
_ZNK5draco7VectorDIiLi2EEmiERKS1_:
  137|  14.5k|  Self operator-(const Self &o) const {
  138|  14.5k|    Self ret;
  139|  43.5k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (139:21): [True: 29.0k, False: 14.5k]
  ------------------
  140|  29.0k|      ret[i] = (*this)[i] - o[i];
  141|  29.0k|    }
  142|  14.5k|    return ret;
  143|  14.5k|  }
_ZNK5draco7VectorDIiLi2EEplERKS1_:
  129|  14.5k|  Self operator+(const Self &o) const {
  130|  14.5k|    Self ret;
  131|  43.5k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (131:21): [True: 29.0k, False: 14.5k]
  ------------------
  132|  29.0k|      ret[i] = (*this)[i] + o[i];
  133|  29.0k|    }
  134|  14.5k|    return ret;
  135|  14.5k|  }
_ZNK5draco7VectorDIfLi2EEeqERKS1_:
  206|  66.1k|  bool operator==(const Self &o) const {
  207|   158k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (207:21): [True: 113k, False: 45.3k]
  ------------------
  208|   113k|      if ((*this)[i] != o[i]) {
  ------------------
  |  Branch (208:11): [True: 20.7k, False: 92.4k]
  ------------------
  209|  20.7k|        return false;
  210|  20.7k|      }
  211|   113k|    }
  212|  45.3k|    return true;
  213|  66.1k|  }
_ZNK5draco7VectorDIfLi2EEixEi:
  113|   796k|  const Scalar &operator[](int i) const { return v_[i]; }
_ZNK5draco7VectorDIfLi3EE11SquaredNormEv:
  234|  21.6k|  Scalar SquaredNorm() const { return this->Dot(*this); }
_ZNK5draco7VectorDIfLi3EE3DotERKS1_:
  250|  22.6k|  Scalar Dot(const Self &o) const {
  251|  22.6k|    Scalar ret(0);
  252|  90.4k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (252:21): [True: 67.8k, False: 22.6k]
  ------------------
  253|  67.8k|      ret += (*this)[i] * o[i];
  254|  67.8k|    }
  255|  22.6k|    return ret;
  256|  22.6k|  }
_ZNK5draco7VectorDIfLi3EEmlERKf:
  174|    938|  Self operator*(const Scalar &o) const {
  175|    938|    Self ret;
  176|  3.75k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (176:21): [True: 2.81k, False: 938]
  ------------------
  177|  2.81k|      ret[i] = (*this)[i] * o;
  178|  2.81k|    }
  179|    938|    return ret;
  180|    938|  }
_ZNK5draco7VectorDIfLi2EEmiERKS1_:
  137|  20.7k|  Self operator-(const Self &o) const {
  138|  20.7k|    Self ret;
  139|  62.1k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (139:21): [True: 41.4k, False: 20.7k]
  ------------------
  140|  41.4k|      ret[i] = (*this)[i] - o[i];
  141|  41.4k|    }
  142|  20.7k|    return ret;
  143|  20.7k|  }
_ZN5draco7VectorDIfLi2EEC2Ev:
   40|  41.4k|  VectorD() {
   41|   124k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (41:21): [True: 82.9k, False: 41.4k]
  ------------------
   42|  82.9k|      (*this)[i] = Scalar(0);
   43|  82.9k|    }
   44|  41.4k|  }
_ZN5draco7VectorDIfLi2EEC2ERKfS3_:
   52|   152k|  VectorD(const Scalar &c0, const Scalar &c1) : v_({{c0, c1}}) {
   53|   152k|    DRACO_DCHECK_EQ(dimension, 2);
   54|   152k|    v_[0] = c0;
   55|   152k|    v_[1] = c1;
   56|   152k|  }
_ZN5draco7VectorDIfLi2EEixEi:
  112|   165k|  Scalar &operator[](int i) { return v_[i]; }
_ZNK5draco7VectorDIlLi2EEeqERKS1_:
  206|  6.54k|  bool operator==(const Self &o) const {
  207|  18.3k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (207:21): [True: 12.5k, False: 5.84k]
  ------------------
  208|  12.5k|      if ((*this)[i] != o[i]) {
  ------------------
  |  Branch (208:11): [True: 697, False: 11.8k]
  ------------------
  209|    697|        return false;
  210|    697|      }
  211|  12.5k|    }
  212|  5.84k|    return true;
  213|  6.54k|  }
_ZNK5draco7VectorDIlLi2EEixEi:
  113|  49.0k|  const Scalar &operator[](int i) const { return v_[i]; }
_ZN5draco7VectorDIlLi3EEC2Ev:
   40|   130k|  VectorD() {
   41|   521k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (41:21): [True: 391k, False: 130k]
  ------------------
   42|   391k|      (*this)[i] = Scalar(0);
   43|   391k|    }
   44|   130k|  }
_ZNK5draco7VectorDIlLi3EE11SquaredNormEv:
  234|  1.16k|  Scalar SquaredNorm() const { return this->Dot(*this); }
_ZNK5draco7VectorDIlLi3EE3DotERKS1_:
  250|  1.64k|  Scalar Dot(const Self &o) const {
  251|  1.64k|    Scalar ret(0);
  252|  6.57k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (252:21): [True: 4.92k, False: 1.64k]
  ------------------
  253|  4.92k|      ret += (*this)[i] * o[i];
  254|  4.92k|    }
  255|  1.64k|    return ret;
  256|  1.64k|  }
_ZNK5draco7VectorDIlLi2EEmiERKS1_:
  137|    474|  Self operator-(const Self &o) const {
  138|    474|    Self ret;
  139|  1.42k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (139:21): [True: 948, False: 474]
  ------------------
  140|    948|      ret[i] = (*this)[i] - o[i];
  141|    948|    }
  142|    474|    return ret;
  143|    474|  }
_ZNK5draco7VectorDIlLi2EEmlERKl:
  174|  1.41k|  Self operator*(const Scalar &o) const {
  175|  1.41k|    Self ret;
  176|  4.25k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (176:21): [True: 2.83k, False: 1.41k]
  ------------------
  177|  2.83k|      ret[i] = (*this)[i] * o;
  178|  2.83k|    }
  179|  1.41k|    return ret;
  180|  1.41k|  }
_ZNK5draco7VectorDIlLi2EEplERKS1_:
  129|    473|  Self operator+(const Self &o) const {
  130|    473|    Self ret;
  131|  1.41k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (131:21): [True: 946, False: 473]
  ------------------
  132|    946|      ret[i] = (*this)[i] + o[i];
  133|    946|    }
  134|    473|    return ret;
  135|    473|  }
_ZN5dracomlIlLi2EEENS_7VectorDIT_XT0_EEERKS2_RKS3_:
  292|    473|    const ScalarT &o, const VectorD<ScalarT, dimension_t> &v) {
  293|    473|  return v * o;
  294|    473|}
_ZNK5draco7VectorDIlLi3EEplERKS1_:
  129|    472|  Self operator+(const Self &o) const {
  130|    472|    Self ret;
  131|  1.88k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (131:21): [True: 1.41k, False: 472]
  ------------------
  132|  1.41k|      ret[i] = (*this)[i] + o[i];
  133|  1.41k|    }
  134|    472|    return ret;
  135|    472|  }
_ZN5dracomlIlLi3EEENS_7VectorDIT_XT0_EEERKS2_RKS3_:
  292|    472|    const ScalarT &o, const VectorD<ScalarT, dimension_t> &v) {
  293|    472|  return v * o;
  294|    472|}
_ZNK5draco7VectorDIlLi3EEmlERKl:
  174|    472|  Self operator*(const Scalar &o) const {
  175|    472|    Self ret;
  176|  1.88k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (176:21): [True: 1.41k, False: 472]
  ------------------
  177|  1.41k|      ret[i] = (*this)[i] * o;
  178|  1.41k|    }
  179|    472|    return ret;
  180|    472|  }
_ZN5draco7VectorDIlLi2EEC2ERKlS3_:
   52|  13.5k|  VectorD(const Scalar &c0, const Scalar &c1) : v_({{c0, c1}}) {
   53|  13.5k|    DRACO_DCHECK_EQ(dimension, 2);
   54|  13.5k|    v_[0] = c0;
   55|  13.5k|    v_[1] = c1;
   56|  13.5k|  }
_ZN5draco7VectorDIlLi2EEC2Ev:
   40|  3.30k|  VectorD() {
   41|  9.92k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (41:21): [True: 6.61k, False: 3.30k]
  ------------------
   42|  6.61k|      (*this)[i] = Scalar(0);
   43|  6.61k|    }
   44|  3.30k|  }
_ZN5draco7VectorDImLi2EEC2IlLi2EEERKNS0_IT_XT0_EEE:
  102|    944|  explicit VectorD(const VectorD<OtherScalarT, other_dimension_t> &src_vector) {
  103|  2.83k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (103:21): [True: 1.88k, False: 944]
  ------------------
  104|  1.88k|      if (i < other_dimension_t) {
  ------------------
  |  Branch (104:11): [True: 1.88k, False: 0]
  ------------------
  105|  1.88k|        v_[i] = Scalar(src_vector[i]);
  106|  1.88k|      } else {
  107|      0|        v_[i] = Scalar(0);
  108|      0|      }
  109|  1.88k|    }
  110|    944|  }
_ZNK5draco7VectorDImLi2EEplERKS1_:
  129|    177|  Self operator+(const Self &o) const {
  130|    177|    Self ret;
  131|    531|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (131:21): [True: 354, False: 177]
  ------------------
  132|    354|      ret[i] = (*this)[i] + o[i];
  133|    354|    }
  134|    177|    return ret;
  135|    177|  }
_ZN5draco7VectorDImLi2EEC2Ev:
   40|    472|  VectorD() {
   41|  1.41k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (41:21): [True: 944, False: 472]
  ------------------
   42|    944|      (*this)[i] = Scalar(0);
   43|    944|    }
   44|    472|  }
_ZNK5draco7VectorDImLi2EEixEi:
  113|  2.83k|  const Scalar &operator[](int i) const { return v_[i]; }
_ZN5draco7VectorDImLi2EEixEi:
  112|  1.88k|  Scalar &operator[](int i) { return v_[i]; }
_ZN5draco7VectorDIlLi2EEC2ImLi2EEERKNS0_IT_XT0_EEE:
  102|    472|  explicit VectorD(const VectorD<OtherScalarT, other_dimension_t> &src_vector) {
  103|  1.41k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (103:21): [True: 944, False: 472]
  ------------------
  104|    944|      if (i < other_dimension_t) {
  ------------------
  |  Branch (104:11): [True: 944, False: 0]
  ------------------
  105|    944|        v_[i] = Scalar(src_vector[i]);
  106|    944|      } else {
  107|      0|        v_[i] = Scalar(0);
  108|      0|      }
  109|    944|    }
  110|    472|  }
_ZNK5draco7VectorDIlLi2EEdvERKl:
  182|    472|  Self operator/(const Scalar &o) const {
  183|    472|    Self ret;
  184|  1.41k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (184:21): [True: 944, False: 472]
  ------------------
  185|    944|      ret[i] = (*this)[i] / o;
  186|    944|    }
  187|    472|    return ret;
  188|    472|  }
_ZNK5draco7VectorDImLi2EEmiERKS1_:
  137|    295|  Self operator-(const Self &o) const {
  138|    295|    Self ret;
  139|    885|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (139:21): [True: 590, False: 295]
  ------------------
  140|    590|      ret[i] = (*this)[i] - o[i];
  141|    590|    }
  142|    295|    return ret;
  143|    295|  }
_ZN5draco7VectorDIlLi2EEixEi:
  112|  13.2k|  Scalar &operator[](int i) { return v_[i]; }
_ZN5draco7VectorDIiLi3EEC2Ev:
   40|  3.79k|  VectorD() {
   41|  15.1k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (41:21): [True: 11.3k, False: 3.79k]
  ------------------
   42|  11.3k|      (*this)[i] = Scalar(0);
   43|  11.3k|    }
   44|  3.79k|  }
_ZN5draco7VectorDIiLi2EEC2ERKiS3_:
   52|  85.9k|  VectorD(const Scalar &c0, const Scalar &c1) : v_({{c0, c1}}) {
   53|  85.9k|    DRACO_DCHECK_EQ(dimension, 2);
   54|  85.9k|    v_[0] = c0;
   55|  85.9k|    v_[1] = c1;
   56|  85.9k|  }
_ZN5draco7VectorDIjLi2EEC2IiLi2EEERKNS0_IT_XT0_EEE:
  102|  1.92k|  explicit VectorD(const VectorD<OtherScalarT, other_dimension_t> &src_vector) {
  103|  5.76k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (103:21): [True: 3.84k, False: 1.92k]
  ------------------
  104|  3.84k|      if (i < other_dimension_t) {
  ------------------
  |  Branch (104:11): [True: 3.84k, False: 0]
  ------------------
  105|  3.84k|        v_[i] = Scalar(src_vector[i]);
  106|  3.84k|      } else {
  107|      0|        v_[i] = Scalar(0);
  108|      0|      }
  109|  3.84k|    }
  110|  1.92k|  }
_ZN5draco7VectorDIjLi2EEC2Ev:
   40|    960|  VectorD() {
   41|  2.88k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (41:21): [True: 1.92k, False: 960]
  ------------------
   42|  1.92k|      (*this)[i] = Scalar(0);
   43|  1.92k|    }
   44|    960|  }
_ZN5draco7VectorDIiLi2EEC2IjLi2EEERKNS0_IT_XT0_EEE:
  102|    960|  explicit VectorD(const VectorD<OtherScalarT, other_dimension_t> &src_vector) {
  103|  2.88k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (103:21): [True: 1.92k, False: 960]
  ------------------
  104|  1.92k|      if (i < other_dimension_t) {
  ------------------
  |  Branch (104:11): [True: 1.92k, False: 0]
  ------------------
  105|  1.92k|        v_[i] = Scalar(src_vector[i]);
  106|  1.92k|      } else {
  107|      0|        v_[i] = Scalar(0);
  108|      0|      }
  109|  1.92k|    }
  110|    960|  }
_ZN5draco7VectorDIiLi2EEC2ERKS1_:
   88|  70.8k|  VectorD(const Self &o) {
   89|   212k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (89:21): [True: 141k, False: 70.8k]
  ------------------
   90|   141k|      (*this)[i] = o[i];
   91|   141k|    }
   92|  70.8k|  }
_ZN5draco7VectorDIiLi2EEC2Ev:
   40|  29.0k|  VectorD() {
   41|  87.1k|    for (int i = 0; i < dimension; ++i) {
  ------------------
  |  Branch (41:21): [True: 58.0k, False: 29.0k]
  ------------------
   42|  58.0k|      (*this)[i] = Scalar(0);
   43|  58.0k|    }
   44|  29.0k|  }

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

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

_ZN5draco21VertexCornersIteratorINS_11CornerTableEEC2EPKS1_NS_9IndexTypeIjNS_21VertexIndex_tag_type_EEE:
  231|  7.67k|        left_traversal_(true) {}
_ZNK5draco21VertexCornersIteratorINS_11CornerTableEE3EndEv:
  244|  68.5k|  bool End() const { return corner_ == kInvalidCornerIndex; }
_ZN5draco21VertexCornersIteratorINS_11CornerTableEEppEv:
  267|  44.6k|  VertexCornersIterator &operator++() {
  268|  44.6k|    Next();
  269|  44.6k|    return *this;
  270|  44.6k|  }
_ZN5draco21VertexCornersIteratorINS_11CornerTableEE4NextEv:
  247|  57.3k|  void Next() {
  248|  57.3k|    if (left_traversal_) {
  ------------------
  |  Branch (248:9): [True: 36.5k, False: 20.7k]
  ------------------
  249|  36.5k|      corner_ = corner_table_->SwingLeft(corner_);
  250|  36.5k|      if (corner_ == kInvalidCornerIndex) {
  ------------------
  |  Branch (250:11): [True: 4.70k, False: 31.8k]
  ------------------
  251|       |        // Open boundary reached.
  252|  4.70k|        corner_ = corner_table_->SwingRight(start_corner_);
  253|  4.70k|        left_traversal_ = false;
  254|  31.8k|      } else if (corner_ == start_corner_) {
  ------------------
  |  Branch (254:18): [True: 6.43k, False: 25.4k]
  ------------------
  255|       |        // End reached.
  256|  6.43k|        corner_ = kInvalidCornerIndex;
  257|  6.43k|      }
  258|  36.5k|    } else {
  259|       |      // Go to the right until we reach a boundary there (no explicit check
  260|       |      // is needed in this case).
  261|  20.7k|      corner_ = corner_table_->SwingRight(corner_);
  262|  20.7k|    }
  263|  57.3k|  }
_ZNK5draco21VertexCornersIteratorINS_11CornerTableEE6CornerEv:
  241|  63.0k|  CornerIndex Corner() const { return corner_; }
_ZNK5draco21VertexCornersIteratorINS_24MeshAttributeCornerTableEE3EndEv:
  244|  11.7k|  bool End() const { return corner_ == kInvalidCornerIndex; }
_ZNK5draco21VertexCornersIteratorINS_24MeshAttributeCornerTableEE6CornerEv:
  241|  9.16k|  CornerIndex Corner() const { return corner_; }
_ZN5draco21VertexCornersIteratorINS_24MeshAttributeCornerTableEE4NextEv:
  247|  9.53k|  void Next() {
  248|  9.53k|    if (left_traversal_) {
  ------------------
  |  Branch (248:9): [True: 8.22k, False: 1.31k]
  ------------------
  249|  8.22k|      corner_ = corner_table_->SwingLeft(corner_);
  250|  8.22k|      if (corner_ == kInvalidCornerIndex) {
  ------------------
  |  Branch (250:11): [True: 1.01k, False: 7.21k]
  ------------------
  251|       |        // Open boundary reached.
  252|  1.01k|        corner_ = corner_table_->SwingRight(start_corner_);
  253|  1.01k|        left_traversal_ = false;
  254|  7.21k|      } else if (corner_ == start_corner_) {
  ------------------
  |  Branch (254:18): [True: 1.24k, False: 5.96k]
  ------------------
  255|       |        // End reached.
  256|  1.24k|        corner_ = kInvalidCornerIndex;
  257|  1.24k|      }
  258|  8.22k|    } else {
  259|       |      // Go to the right until we reach a boundary there (no explicit check
  260|       |      // is needed in this case).
  261|  1.31k|      corner_ = corner_table_->SwingRight(corner_);
  262|  1.31k|    }
  263|  9.53k|  }
_ZN5draco21VertexCornersIteratorINS_24MeshAttributeCornerTableEEC2EPKS1_NS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  238|  2.25k|        left_traversal_(true) {}
_ZN5draco21VertexCornersIteratorINS_11CornerTableEEC2EPKS1_NS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  238|  3.46k|        left_traversal_(true) {}

_ZN5draco4MeshC2Ev:
   29|  1.36k|Mesh::Mesh() {}

_ZN5draco4Mesh7AddFaceERKNSt3__15arrayINS_9IndexTypeIjNS_20PointIndex_tag_type_EEELm3EEE:
   62|   270k|  void AddFace(const Face &face) { faces_.push_back(face); }
_ZN5draco4Mesh7SetFaceENS_9IndexTypeIjNS_19FaceIndex_tag_type_EEERKNSt3__15arrayINS1_IjNS_20PointIndex_tag_type_EEELm3EEE:
   64|   712k|  void SetFace(FaceIndex face_id, const Face &face) {
   65|   712k|    if (face_id >= static_cast<uint32_t>(faces_.size())) {
  ------------------
  |  Branch (65:9): [True: 0, False: 712k]
  ------------------
   66|      0|      faces_.resize(face_id.value() + 1, Face());
   67|      0|    }
   68|   712k|    faces_[face_id] = face;
   69|   712k|  }
_ZN5draco4Mesh11SetNumFacesEm:
   73|    420|  void SetNumFaces(size_t num_faces) { faces_.resize(num_faces, Face()); }
_ZNK5draco4Mesh9num_facesEv:
   75|   715k|  FaceIndex::ValueType num_faces() const {
   76|   715k|    return static_cast<uint32_t>(faces_.size());
   77|   715k|  }
_ZNK5draco4Mesh4faceENS_9IndexTypeIjNS_19FaceIndex_tag_type_EEE:
   78|  1.33M|  const Face &face(FaceIndex face_id) const {
   79|  1.33M|    DRACO_DCHECK_LE(0, face_id.value());
   80|  1.33M|    DRACO_DCHECK_LT(face_id.value(), static_cast<int>(faces_.size()));
   81|  1.33M|    return faces_[face_id];
   82|  1.33M|  }
_ZN5draco4Mesh12SetAttributeEiNSt3__110unique_ptrINS_14PointAttributeENS1_14default_deleteIS3_EEEE:
   84|  64.9k|  void SetAttribute(int att_id, std::unique_ptr<PointAttribute> pa) override {
   85|  64.9k|    PointCloud::SetAttribute(att_id, std::move(pa));
   86|  64.9k|    if (static_cast<int>(attribute_data_.size()) <= att_id) {
  ------------------
  |  Branch (86:9): [True: 64.9k, False: 0]
  ------------------
   87|  64.9k|      attribute_data_.resize(att_id + 1);
   88|  64.9k|    }
   89|  64.9k|  }
_ZN5draco4Mesh13AttributeDataC2Ev:
  155|  64.9k|    AttributeData() : element_type(MESH_CORNER_ATTRIBUTE) {}

_ZN5draco24MeshAttributeCornerTableC2Ev:
   23|  4.84k|    : no_interior_seams_(true), corner_table_(nullptr), valence_cache_(*this) {}
_ZN5draco24MeshAttributeCornerTable9InitEmptyEPKNS_11CornerTableE:
   25|  1.65k|bool MeshAttributeCornerTable::InitEmpty(const CornerTable *table) {
   26|  1.65k|  if (table == nullptr) {
  ------------------
  |  Branch (26:7): [True: 0, False: 1.65k]
  ------------------
   27|      0|    return false;
   28|      0|  }
   29|  1.65k|  valence_cache_.ClearValenceCache();
   30|  1.65k|  valence_cache_.ClearValenceCacheInaccurate();
   31|  1.65k|  is_edge_on_seam_.assign(table->num_corners(), false);
   32|  1.65k|  is_vertex_on_seam_.assign(table->num_vertices(), false);
   33|  1.65k|  corner_to_vertex_map_.assign(table->num_corners(), kInvalidVertexIndex);
   34|  1.65k|  vertex_to_attribute_entry_id_map_.reserve(table->num_vertices());
   35|  1.65k|  vertex_to_left_most_corner_map_.reserve(table->num_vertices());
   36|  1.65k|  corner_table_ = table;
   37|  1.65k|  no_interior_seams_ = true;
   38|  1.65k|  return true;
   39|  1.65k|}
_ZN5draco24MeshAttributeCornerTable11AddSeamEdgeENS_9IndexTypeIjNS_21CornerIndex_tag_type_EEE:
  108|   765k|void MeshAttributeCornerTable::AddSeamEdge(CornerIndex c) {
  109|   765k|  DRACO_DCHECK(GetValenceCache().IsCacheEmpty());
  110|   765k|  is_edge_on_seam_[c.value()] = true;
  111|       |  // Mark seam vertices.
  112|   765k|  is_vertex_on_seam_[corner_table_->Vertex(corner_table_->Next(c)).value()] =
  113|   765k|      true;
  114|   765k|  is_vertex_on_seam_[corner_table_->Vertex(corner_table_->Previous(c))
  115|   765k|                         .value()] = true;
  116|       |
  117|   765k|  const CornerIndex opp_corner = corner_table_->Opposite(c);
  118|   765k|  if (opp_corner != kInvalidCornerIndex) {
  ------------------
  |  Branch (118:7): [True: 611k, False: 154k]
  ------------------
  119|   611k|    no_interior_seams_ = false;
  120|   611k|    is_edge_on_seam_[opp_corner.value()] = true;
  121|   611k|    is_vertex_on_seam_[corner_table_->Vertex(corner_table_->Next(opp_corner))
  122|   611k|                           .value()] = true;
  123|   611k|    is_vertex_on_seam_
  124|   611k|        [corner_table_->Vertex(corner_table_->Previous(opp_corner)).value()] =
  125|   611k|            true;
  126|   611k|  }
  127|   765k|}
_ZN5draco24MeshAttributeCornerTable17RecomputeVerticesEPKNS_4MeshEPKNS_14PointAttributeE:
  130|  1.65k|                                                 const PointAttribute *att) {
  131|  1.65k|  DRACO_DCHECK(GetValenceCache().IsCacheEmpty());
  132|  1.65k|  if (mesh != nullptr && att != nullptr) {
  ------------------
  |  Branch (132:7): [True: 0, False: 1.65k]
  |  Branch (132:26): [True: 0, False: 0]
  ------------------
  133|      0|    return RecomputeVerticesInternal<true>(mesh, att);
  134|  1.65k|  } else {
  135|  1.65k|    return RecomputeVerticesInternal<false>(nullptr, nullptr);
  136|  1.65k|  }
  137|  1.65k|}
_ZN5draco24MeshAttributeCornerTable25RecomputeVerticesInternalILb0EEEbPKNS_4MeshEPKNS_14PointAttributeE:
  141|  1.65k|    const Mesh *mesh, const PointAttribute *att) {
  142|  1.65k|  DRACO_DCHECK(GetValenceCache().IsCacheEmpty());
  143|  1.65k|  vertex_to_attribute_entry_id_map_.clear();
  144|  1.65k|  vertex_to_left_most_corner_map_.clear();
  145|  1.65k|  int num_new_vertices = 0;
  146|   519k|  for (VertexIndex v(0); v < corner_table_->num_vertices(); ++v) {
  ------------------
  |  Branch (146:26): [True: 517k, False: 1.65k]
  ------------------
  147|   517k|    const CornerIndex c = corner_table_->LeftMostCorner(v);
  148|   517k|    if (c == kInvalidCornerIndex) {
  ------------------
  |  Branch (148:9): [True: 25.9k, False: 491k]
  ------------------
  149|  25.9k|      continue;  // Isolated vertex?
  150|  25.9k|    }
  151|   491k|    AttributeValueIndex first_vert_id(num_new_vertices++);
  152|   491k|    if (init_vertex_to_attribute_entry_map) {
  ------------------
  |  Branch (152:9): [Folded - Ignored]
  ------------------
  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|   491k|    } else {
  156|       |      // Identity mapping
  157|   491k|      vertex_to_attribute_entry_id_map_.push_back(first_vert_id);
  158|   491k|    }
  159|   491k|    CornerIndex first_c = c;
  160|   491k|    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|   491k|    if (is_vertex_on_seam_[v.value()]) {
  ------------------
  |  Branch (163:9): [True: 324k, False: 167k]
  ------------------
  164|       |      // Try to swing left on the modified corner table. We need to get the
  165|       |      // first corner that defines an attribute seam.
  166|   324k|      act_c = SwingLeft(first_c);
  167|   344k|      while (act_c != kInvalidCornerIndex) {
  ------------------
  |  Branch (167:14): [True: 20.3k, False: 324k]
  ------------------
  168|  20.3k|        first_c = act_c;
  169|  20.3k|        act_c = SwingLeft(act_c);
  170|  20.3k|        if (act_c == c) {
  ------------------
  |  Branch (170:13): [True: 0, False: 20.3k]
  ------------------
  171|       |          // We reached the initial corner which shouldn't happen when we swing
  172|       |          // left from |c|.
  173|      0|          return false;
  174|      0|        }
  175|  20.3k|      }
  176|   324k|    }
  177|   491k|    corner_to_vertex_map_[first_c.value()] = VertexIndex(first_vert_id.value());
  178|   491k|    vertex_to_left_most_corner_map_.push_back(first_c);
  179|   491k|    act_c = corner_table_->SwingRight(first_c);
  180|  2.42M|    while (act_c != kInvalidCornerIndex && act_c != first_c) {
  ------------------
  |  Branch (180:12): [True: 2.27M, False: 155k]
  |  Branch (180:44): [True: 1.93M, False: 336k]
  ------------------
  181|  1.93M|      if (IsCornerOppositeToSeamEdge(corner_table_->Next(act_c))) {
  ------------------
  |  Branch (181:11): [True: 890k, False: 1.04M]
  ------------------
  182|   890k|        first_vert_id = AttributeValueIndex(num_new_vertices++);
  183|   890k|        if (init_vertex_to_attribute_entry_map) {
  ------------------
  |  Branch (183:13): [Folded - Ignored]
  ------------------
  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|   890k|        } else {
  188|       |          // Identity mapping.
  189|   890k|          vertex_to_attribute_entry_id_map_.push_back(first_vert_id);
  190|   890k|        }
  191|   890k|        vertex_to_left_most_corner_map_.push_back(act_c);
  192|   890k|      }
  193|  1.93M|      corner_to_vertex_map_[act_c.value()] = VertexIndex(first_vert_id.value());
  194|  1.93M|      act_c = corner_table_->SwingRight(act_c);
  195|  1.93M|    }
  196|   491k|  }
  197|  1.65k|  return true;
  198|  1.65k|}

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

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

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

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

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

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

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

_ZN5draco10PointCloudC2Ev:
   27|  1.36k|PointCloud::PointCloud() : num_points_(0) {}
_ZNK5draco10PointCloud18NumNamedAttributesENS_17GeometryAttribute4TypeE:
   56|    237|int32_t PointCloud::NumNamedAttributes(GeometryAttribute::Type type) const {
   57|    237|  if (type == GeometryAttribute::INVALID ||
  ------------------
  |  Branch (57:7): [True: 0, False: 237]
  ------------------
   58|    237|      type >= GeometryAttribute::NAMED_ATTRIBUTES_COUNT) {
  ------------------
  |  Branch (58:7): [True: 0, False: 237]
  ------------------
   59|      0|    return 0;
   60|      0|  }
   61|    237|  return static_cast<int32_t>(named_attribute_index_[type].size());
   62|    237|}
_ZNK5draco10PointCloud19GetNamedAttributeIdENS_17GeometryAttribute4TypeE:
   64|    237|int32_t PointCloud::GetNamedAttributeId(GeometryAttribute::Type type) const {
   65|    237|  return GetNamedAttributeId(type, 0);
   66|    237|}
_ZNK5draco10PointCloud19GetNamedAttributeIdENS_17GeometryAttribute4TypeEi:
   69|    237|                                        int i) const {
   70|    237|  if (NumNamedAttributes(type) <= i) {
  ------------------
  |  Branch (70:7): [True: 0, False: 237]
  ------------------
   71|      0|    return -1;
   72|      0|  }
   73|    237|  return named_attribute_index_[type][i];
   74|    237|}
_ZN5draco10PointCloud12AddAttributeENSt3__110unique_ptrINS_14PointAttributeENS1_14default_deleteIS3_EEEE:
  134|  64.9k|int PointCloud::AddAttribute(std::unique_ptr<PointAttribute> pa) {
  135|  64.9k|  SetAttribute(static_cast<int>(attributes_.size()), std::move(pa));
  136|  64.9k|  return static_cast<int>(attributes_.size() - 1);
  137|  64.9k|}
_ZN5draco10PointCloud12SetAttributeEiNSt3__110unique_ptrINS_14PointAttributeENS1_14default_deleteIS3_EEEE:
  172|  64.9k|void PointCloud::SetAttribute(int att_id, std::unique_ptr<PointAttribute> pa) {
  173|  64.9k|  DRACO_DCHECK(att_id >= 0);
  174|  64.9k|  if (static_cast<int>(attributes_.size()) <= att_id) {
  ------------------
  |  Branch (174:7): [True: 64.9k, False: 0]
  ------------------
  175|  64.9k|    attributes_.resize(att_id + 1);
  176|  64.9k|  }
  177|  64.9k|  if (pa->attribute_type() < GeometryAttribute::NAMED_ATTRIBUTES_COUNT) {
  ------------------
  |  Branch (177:7): [True: 64.9k, False: 0]
  ------------------
  178|  64.9k|    named_attribute_index_[pa->attribute_type()].push_back(att_id);
  179|  64.9k|  }
  180|  64.9k|  pa->set_unique_id(att_id);
  181|  64.9k|  attributes_[att_id] = std::move(pa);
  182|  64.9k|}

_ZNK5draco10PointCloud14num_attributesEv:
   75|    237|  int32_t num_attributes() const {
   76|    237|    return static_cast<int32_t>(attributes_.size());
   77|    237|  }
_ZNK5draco10PointCloud9attributeEi:
   78|  1.40k|  const PointAttribute *attribute(int32_t att_id) const {
   79|  1.40k|    DRACO_DCHECK_LE(0, att_id);
   80|  1.40k|    DRACO_DCHECK_LT(att_id, static_cast<int32_t>(attributes_.size()));
   81|  1.40k|    return attributes_[att_id].get();
   82|  1.40k|  }
_ZN5draco10PointCloud9attributeEi:
   86|  95.2k|  PointAttribute *attribute(int32_t att_id) {
   87|  95.2k|    DRACO_DCHECK_LE(0, att_id);
   88|  95.2k|    DRACO_DCHECK_LT(att_id, static_cast<int32_t>(attributes_.size()));
   89|  95.2k|    return attributes_[att_id].get();
   90|  95.2k|  }
_ZN5draco10PointCloud11AddMetadataENSt3__110unique_ptrINS_16GeometryMetadataENS1_14default_deleteIS3_EEEE:
  141|    108|  void AddMetadata(std::unique_ptr<GeometryMetadata> metadata) {
  142|    108|    metadata_ = std::move(metadata);
  143|    108|  }
_ZNK5draco10PointCloud10num_pointsEv:
  195|  18.8k|  PointIndex::ValueType num_points() const { return num_points_; }
_ZN5draco10PointCloud14set_num_pointsEj:
  200|    544|  void set_num_points(PointIndex::ValueType num) { num_points_ = num; }
_ZN5draco10PointCloudD2Ev:
   36|  1.36k|  virtual ~PointCloud() = default;

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

