///|
pub(all) struct WeightedClassificationDataset {
  rows : Array[Array[Double]]
  labels : Array[Int]
  weights : Array[Double]
  feature_total : Int
  class_total : Int
  weight_total : Double
} derive(Eq, Debug)

///|
pub(all) struct WeightedRegressionDataset {
  rows : Array[Array[Double]]
  targets : Array[Double]
  weights : Array[Double]
  feature_total : Int
  weight_total : Double
} derive(Eq, Debug)

///|
pub(all) enum WeightedClassificationNode {
  WeightedClassificationLeaf(Int, Array[Double], Int, Double, Double)
  WeightedClassificationBranch(
    Int,
    Double,
    WeightedClassificationNode,
    WeightedClassificationNode,
    Int,
    Double,
    Double,
    Double
  )
} derive(Eq, Debug)

///|
pub(all) struct WeightedClassificationTree {
  root : WeightedClassificationNode
  feature_total : Int
  class_total : Int
  config : ClassificationConfig
} derive(Eq, Debug)

///|
pub(all) enum WeightedRegressionNode {
  WeightedRegressionLeaf(Double, Int, Double, Double)
  WeightedRegressionBranch(
    Int,
    Double,
    WeightedRegressionNode,
    WeightedRegressionNode,
    Int,
    Double,
    Double,
    Double
  )
} derive(Eq, Debug)

///|
pub(all) struct WeightedRegressionTree {
  root : WeightedRegressionNode
  feature_total : Int
  config : RegressionConfig
} derive(Eq, Debug)

///|
priv struct WeightedClassificationSplit {
  feature_index : Int
  threshold : Double
  gain : Double
}

///|
priv struct WeightedRegressionSplit {
  feature_index : Int
  threshold : Double
  gain : Double
}