func (gini *Gini) ComputeContinu(src *[]float64, target, classes *[]string) {
	gini.IsContinu = true
	A2 := make([]float64, len(*src))
	copy(A2, *src)
	T2 := make([]string, len(*target))
	copy(T2, *target)
	gini.SortedIndex = floats64.IndirectSort(A2, true)
	if debug.Value >= 1 {
		fmt.Println("[gini] attr sorted :", A2)
	}
	libstrings.SortByIndex(&T2, gini.SortedIndex)
	gini.createContinuPartition(&A2)
	gini.Index = make([]float64, len(gini.ContinuPart))
	gini.Gain = make([]float64, len(gini.ContinuPart))
	gini.MinIndexValue = 1.0
	gini.Value = gini.compute(&T2, classes)
	gini.computeContinuGain(&A2, &T2, classes)
}
ComputeContinu Given an attribute "src" and the target attribute "target"
which contain n classes, compute the information gain of "src".

The result of Gini partitions value, Gini Index, and Gini Gain is saved in
ContinuPart, Index, and Gain.
package gini
import (
	"fmt"
	"github.com/shuLhan/share/lib/debug"
	"github.com/shuLhan/share/lib/floats64"
	libstrings "github.com/shuLhan/share/lib/strings"
)
type Gini struct {
	Skip bool
	IsContinu bool
	Value float64
	MaxPartGain int
	MaxGainValue float64
	MinIndexPart int
	MinIndexValue float64
	SortedIndex []int
	ContinuPart []float64
	DiscretePart libstrings.Table
	Index []float64
	Gain []float64
}
func (gini *Gini) ComputeDiscrete(src, discval, target, classes *[]string) {
	gini.IsContinu = false
	gini.createDiscretePartition((*discval))
	if debug.Value >= 2 {
		fmt.Println("[gini] part :", gini.DiscretePart)
	}
	gini.Index = make([]float64, len(gini.DiscretePart))
	gini.Gain = make([]float64, len(gini.DiscretePart))
	gini.MinIndexValue = 1.0
	gini.Value = gini.compute(target, classes)
	gini.computeDiscreteGain(src, target, classes)
}
func (gini *Gini) computeDiscreteGain(src, target, classes *[]string) {
	nsample := float64(len(*src))
	if debug.Value >= 3 {
		fmt.Println("[gini] sample:", target)
		fmt.Printf("[gini] Gini(a=%s) = %f\n", (*src), gini.Value)
	}
	for i, subPart := range gini.DiscretePart {
		if len(subPart) == 0 {
			continue
		}
		sumGI := 0.0
		for _, part := range subPart {
			ndisc := 0.0
			var subT []string
			for _, el := range part {
				for t, a := range *src {
					if a != el {
						continue
					}
					ndisc++
					subT = append(subT, (*target)[t])
				}
			}
			giniIndex := gini.compute(&subT, classes)
			p := ndisc / nsample
			probIndex := p * giniIndex
			sumGI += probIndex
			if debug.Value >= 3 {
				fmt.Printf("[gini] subsample: %v\n", subT)
				fmt.Printf("[gini] Gini(a=%s) = %f/%f * %f = %f\n",
					part, ndisc, nsample,
					giniIndex, probIndex)
			}
		}
		gini.Index[i] = sumGI
		gini.Gain[i] = gini.Value - sumGI
		if debug.Value >= 3 {
			fmt.Printf("[gini] sample: %v\n", subPart)
			fmt.Printf("[gini] Gain(a=%s) = %f - %f = %f\n",
				subPart, gini.Value, sumGI,
				gini.Gain[i])
		}
		if gini.MinIndexValue > gini.Index[i] && gini.Index[i] != 0 {
			gini.MinIndexValue = gini.Index[i]
			gini.MinIndexPart = i
		}
		if gini.MaxGainValue < gini.Gain[i] {
			gini.MaxGainValue = gini.Gain[i]
			gini.MaxPartGain = i
		}
	}
}
func (gini *Gini) createDiscretePartition(discval []string) {
	if len(discval) == 0 {
		return
	}
	gini.DiscretePart = libstrings.Partition(discval, 2)
}