| 70 | } |
| 71 | |
| 72 | int Tree::SplitCategorical(int leaf, int feature, int real_feature, const uint32_t* threshold_bin, int num_threshold_bin, |
| 73 | const uint32_t* threshold, int num_threshold, double left_value, double right_value, |
| 74 | data_size_t left_cnt, data_size_t right_cnt, double left_weight, double right_weight, float gain, MissingType missing_type) { |
| 75 | Split(leaf, feature, real_feature, left_value, right_value, left_cnt, right_cnt, left_weight, right_weight, gain); |
| 76 | int new_node_idx = num_leaves_ - 1; |
| 77 | decision_type_[new_node_idx] = 0; |
| 78 | SetDecisionType(&decision_type_[new_node_idx], true, kCategoricalMask); |
| 79 | if (missing_type == MissingType::None) { |
| 80 | SetMissingType(&decision_type_[new_node_idx], 0); |
| 81 | } else if (missing_type == MissingType::Zero) { |
| 82 | SetMissingType(&decision_type_[new_node_idx], 1); |
| 83 | } else if (missing_type == MissingType::NaN) { |
| 84 | SetMissingType(&decision_type_[new_node_idx], 2); |
| 85 | } |
| 86 | threshold_in_bin_[new_node_idx] = num_cat_; |
| 87 | threshold_[new_node_idx] = num_cat_; |
| 88 | ++num_cat_; |
| 89 | cat_boundaries_.push_back(cat_boundaries_.back() + num_threshold); |
| 90 | for (int i = 0; i < num_threshold; ++i) { |
| 91 | cat_threshold_.push_back(threshold[i]); |
| 92 | } |
| 93 | cat_boundaries_inner_.push_back(cat_boundaries_inner_.back() + num_threshold_bin); |
| 94 | for (int i = 0; i < num_threshold_bin; ++i) { |
| 95 | cat_threshold_inner_.push_back(threshold_bin[i]); |
| 96 | } |
| 97 | ++num_leaves_; |
| 98 | return num_leaves_ - 1; |
| 99 | } |
| 100 | |
| 101 | #define PredictionFun(niter, fidx_in_iter, start_pos, decision_fun, iter_idx, data_idx) \ |
| 102 | std::vector<std::unique_ptr<BinIterator>> iter((niter)); \ |
no test coverage detected