package humanize

import (
	
	
	
	
)

var siPrefixTable = map[float64]string{
	-30: "q", // quecto
	-27: "r", // ronto
	-24: "y", // yocto
	-21: "z", // zepto
	-18: "a", // atto
	-15: "f", // femto
	-12: "p", // pico
	-9:  "n", // nano
	-6:  "ยต", // micro
	-3:  "m", // milli
	0:   "",
	3:   "k", // kilo
	6:   "M", // mega
	9:   "G", // giga
	12:  "T", // tera
	15:  "P", // peta
	18:  "E", // exa
	21:  "Z", // zetta
	24:  "Y", // yotta
	27:  "R", // ronna
	30:  "Q", // quetta
}

var revSIPrefixTable = revfmap(siPrefixTable)

// revfmap reverses the map and precomputes the power multiplier
func revfmap( map[float64]string) map[string]float64 {
	 := map[string]float64{}
	for ,  := range  {
		[] = math.Pow(10, )
	}
	return 
}

var riParseRegex *regexp.Regexp

func init() {
	 := `^([\-0-9.]+)\s?([`
	for ,  := range siPrefixTable {
		 += 
	}
	 += `]?)(.*)`

	riParseRegex = regexp.MustCompile()
}

// ComputeSI finds the most appropriate SI prefix for the given number
// and returns the prefix along with the value adjusted to be within
// that prefix.
//
// See also: SI, ParseSI.
//
// e.g. ComputeSI(2.2345e-12) -> (2.2345, "p")
func ( float64) (float64, string) {
	if  == 0 {
		return 0, ""
	}
	 := math.Abs()
	 := math.Floor(logn(, 10))
	 = math.Floor(/3) * 3

	 :=  / math.Pow(10, )

	// Handle special case where value is exactly 1000.0
	// Should return 1 M instead of 1000 k
	if  == 1000.0 {
		 += 3
		 =  / math.Pow(10, )
	}

	 = math.Copysign(, )

	 := siPrefixTable[]
	return , 
}

// SI returns a string with default formatting.
//
// SI uses Ftoa to format float value, removing trailing zeros.
//
// See also: ComputeSI, ParseSI.
//
// e.g. SI(1000000, "B") -> 1 MB
// e.g. SI(2.2345e-12, "F") -> 2.2345 pF
func ( float64,  string) string {
	,  := ComputeSI()
	return Ftoa() + " " +  + 
}

// SIWithDigits works like SI but limits the resulting string to the
// given number of decimal places.
//
// e.g. SIWithDigits(1000000, 0, "B") -> 1 MB
// e.g. SIWithDigits(2.2345e-12, 2, "F") -> 2.23 pF
func ( float64,  int,  string) string {
	,  := ComputeSI()
	return FtoaWithDigits(, ) + " " +  + 
}

var errInvalid = errors.New("invalid input")

// ParseSI parses an SI string back into the number and unit.
//
// See also: SI, ComputeSI.
//
// e.g. ParseSI("2.2345 pF") -> (2.2345e-12, "F", nil)
func ( string) (float64, string, error) {
	 := riParseRegex.FindStringSubmatch()
	if len() != 4 {
		return 0, "", errInvalid
	}
	 := revSIPrefixTable[[2]]
	 := [3]

	,  := strconv.ParseFloat([1], 64)
	return  * , , 
}