double (double[] features) { assert features.length >= floatFeatureCount; // Binarise features int[] binaryFeatures = new int[binaryFeatureCount]; for (int i = 0; i < binaryFeatureCount; i++) { double[] borders = floatFeatureBorders.get(i); for (double border : borders) { int index = floatFeaturesIndex[i]; binaryFeatures[i] += (features[index] > border) ? 1 : 0; } } // Extract and sum values from trees double result = 0.; int treeSplitsIndex = 0; int currentTreeLeafValuesIndex = 0; for (int treeId = 0; treeId < treeCount; treeId++) { int current_tree_depth = treeDepth[treeId]; int index = 0; for (int depth = 0; depth < current_tree_depth; depth++) { int border_val = treeSplitBorder[treeSplitsIndex + depth]; int feature_index = treeSplitFeatureIndex[treeSplitsIndex + depth]; int xor_mask = treeSplitXorMask[treeSplitsIndex + depth]; int res = ((binaryFeatures[feature_index] ^ xor_mask) >= border_val) ? 1 : 0; index |= res << depth; } result += leafValues[currentTreeLeafValuesIndex + index]; treeSplitsIndex += current_tree_depth; currentTreeLeafValuesIndex += (1 << current_tree_depth); } result = scale * result + bias; return predictProbability ? sigmoid(result) : result; }