// @generated by scripts/extraction/learned/export_rust.py -- do not edit.
//
// Copyright (c) 2026 Innovation Trigger B.V.
//
// PDFluent is available under two licences, at your option: the GNU AGPLv3, or
// the PDFluent Commercial Licence. See the LICENSE file in this repository --
// that file travels with the copy you received, which a URL does not.
//! The `line_classes` model: 320 trees, 9600 splits, depth at most 8, in 3 part(s).
//!
//! Every one of those trees runs on every prediction: the 4 classes share one flat list and tree i scores class i % 4.
//!
//! Model sha256 (of model.json): 392b1796532ca12733f33111d0dbba034f849a21f9038e1604c8a6e4b7858148
mod part_00;
mod part_01;
mod part_02;
/// The sha256 of the LightGBM dump this code was generated from.
pub const MODEL_SHA256: &str = "392b1796532ca12733f33111d0dbba034f849a21f9038e1604c8a6e4b7858148";
/// The input, in order: `x[i]` is `FEATURES[i]`, NaN when missing.
pub const FEATURES: [&str; 105] = ["marker_bullet", "marker_ordered", "marker_figure", "first_token_chars", "first_gap_em", "indent_em", "indent_vs_prev_em", "prev_short_em", "prev_ends_terminal", "prev_runs_on", "width_frac", "size_ratio", "bold", "line_index", "lines_in_block", "gap_above_em", "block_is_list", "block_size_ratio", "first_is_lone_symbol", "same_head_on_page", "block_is_table_cell", "max_gap_em", "prev_block_ends_colon", "of_block_size_ratio", "of_block_bold", "of_block_italic", "of_block_all_caps", "of_block_n_chars", "of_block_n_words", "of_block_n_lines", "of_block_x_frac", "of_block_width_frac", "of_block_y_frac", "of_block_gap_above_em", "of_block_gap_below_em", "of_block_ends_terminal", "of_block_ends_colon", "of_block_section_number", "of_block_has_marker", "of_block_has_caption", "of_block_first_on_page", "of_block_last_on_page", "of_block_prev_ends_terminal", "of_block_prev_size_ratio", "of_block_next_x_frac", "of_block_next_size_ratio", "of_block_repeats_in_document", "of_block_font_is_the_body_face", "of_block_title_case", "of_block_number_kind", "of_block_number_depth", "of_block_width_vs_column", "of_block_ends_comma", "up2_marker_bullet", "up2_marker_ordered", "up2_first_token_chars", "up2_indent_em", "up2_prev_ends_terminal", "up2_width_frac", "up2_size_ratio", "up2_bold", "up2_gap_above_em", "up2_block_is_list", "up2_block_is_table_cell", "up2_max_gap_em", "up2_same_block", "up1_marker_bullet", "up1_marker_ordered", "up1_first_token_chars", "up1_indent_em", "up1_prev_ends_terminal", "up1_width_frac", "up1_size_ratio", "up1_bold", "up1_gap_above_em", "up1_block_is_list", "up1_block_is_table_cell", "up1_max_gap_em", "up1_same_block", "down1_marker_bullet", "down1_marker_ordered", "down1_first_token_chars", "down1_indent_em", "down1_prev_ends_terminal", "down1_width_frac", "down1_size_ratio", "down1_bold", "down1_gap_above_em", "down1_block_is_list", "down1_block_is_table_cell", "down1_max_gap_em", "down1_same_block", "down2_marker_bullet", "down2_marker_ordered", "down2_first_token_chars", "down2_indent_em", "down2_prev_ends_terminal", "down2_width_frac", "down2_size_ratio", "down2_bold", "down2_gap_above_em", "down2_block_is_list", "down2_block_is_table_cell", "down2_max_gap_em", "down2_same_block"];
/// How many classes [`predict_margins`] returns.
pub const CLASSES: usize = 4;
/// LightGBM's numerical decision, missing values included.
#[inline(always)]
fn go_left(value: f64, threshold: f64, default_left: bool, missing: u8) -> bool {
// 0: None, 1: Zero, 2: NaN -- LightGBM's MissingType.
let value = if missing != 2 && value.is_nan() { 0.0 } else { value };
if (missing == 1 && value.abs() <= 1e-35) || (missing == 2 && value.is_nan()) {
return default_left;
}
value <= threshold
}
/// The raw margins, one per class, before any softmax.
pub fn predict_margins(x: &[f64; 105]) -> [f64; 4] {
let acc = [0.0f64; 4];
let acc = part_00::add(x, acc);
let acc = part_01::add(x, acc);
part_02::add(x, acc)
}