package jx

import (
	
	

	
)

var (
	pow10       = [...]uint64{1, 10, 100, 1000, 10000, 100000, 1000000}
	floatDigits = [256]int8{}
)

const (
	dotInNumber int8 = -iota - 1
	expInNumber
	plusInNumber
	minusInNumber
	endOfNumber
	invalidCharForNumber

	maxFloat64 = 1<<63 - 1
)

func () {
	for  := 0;  < len(floatDigits); ++ {
		floatDigits[] = invalidCharForNumber
	}
	floatDigits[','] = endOfNumber
	floatDigits[']'] = endOfNumber
	floatDigits['}'] = endOfNumber
	for ,  := range spaceSet {
		if  == 1 {
			floatDigits[] = endOfNumber
		}
	}
	for  := int8('0');  <= int8('9'); ++ {
		floatDigits[] =  - int8('0')
	}
	floatDigits['.'] = dotInNumber
	floatDigits['e'] = expInNumber
	floatDigits['E'] = expInNumber
	floatDigits['+'] = plusInNumber
	floatDigits['-'] = minusInNumber
}

// Float32 reads float32 value.
func ( *Decoder) () (float32, error) {
	,  := .more()
	if  != nil {
		return 0, 
	}
	if  != '-' {
		.unread()
	}
	,  := .positiveFloat32()
	if  != nil {
		return 0, 
	}
	if  == '-' {
		 *= -1
	}
	return , nil
}

func ( *Decoder) () (float32, error) {
	 := .head
	// First char.
	if  == .tail {
		return .float32Slow()
	}
	 := .buf[]
	++
	 := floatDigits[]
	switch  {
	case invalidCharForNumber, endOfNumber:
		return 0, badToken(, .offset())
	case dotInNumber, plusInNumber, expInNumber:
		 := badToken(, .offset())
		return 0, errors.Wrapf(, "leading %q", )
	case minusInNumber: // minus handled by caller
		 := badToken(, .offset())
		return 0, errors.Wrap(, "double minus")
	case 0:
		if  == .tail {
			return .float32Slow()
		}
		 = .buf[]
		if floatDigits[] >= 0 {
			 := badToken(, .offset()+1)
			return 0, errors.Wrap(, "leading zero")
		}
	}
	 := uint64()
	// Chars before dot.
:
	for ;  < .tail; ++ {
		 = .buf[]
		 := floatDigits[]
		switch  {
		case invalidCharForNumber:
			return 0, badToken(, .offset()+)
		case endOfNumber:
			.head = 
			return float32(), nil
		case dotInNumber, expInNumber:
			break 
		}
		if  > uint64SafeToMultiple10 {
			return .float32Slow()
		}
		 = ( << 3) + ( << 1) + uint64() // value = value * 10 + ind;
	}
	// Chars after dot.
	if  == '.' {
		++
		 := 0
		if  == .tail {
			return .float32Slow()
		}
		for ;  < .tail; ++ {
			 = .buf[]
			 := floatDigits[]
			switch  {
			case endOfNumber:
				if  > 0 &&  < len(pow10) {
					.head = 
					return float32(float64() / float64(pow10[])), nil
				}
				// too many decimal places
				return .float32Slow()
			case dotInNumber, expInNumber, plusInNumber, minusInNumber:
				return .float32Slow()
			case invalidCharForNumber:
				return 0, badToken(, .offset()+)
			}
			++
			if  > uint64SafeToMultiple10 {
				return .float32Slow()
			}
			 = ( << 3) + ( << 1) + uint64()
		}
	}
	return .float32Slow()
}

// Float64 read float64
func ( *Decoder) () (float64, error) {
	,  := .more()
	if  != nil {
		return 0, 
	}
	if  != '-' {
		.unread()
	}
	,  := .positiveFloat64()
	if  != nil {
		return 0, 
	}
	if  == '-' {
		 *= -1
	}
	return , nil
}

func ( *Decoder) () (float64, error) {
	 := .head
	// First char.
	if  == .tail {
		return .float64Slow()
	}
	 := .buf[]
	++
	 := floatDigits[]
	switch  {
	case invalidCharForNumber, endOfNumber:
		return 0, badToken(, .offset())
	case dotInNumber, plusInNumber, expInNumber:
		 := badToken(, .offset())
		return 0, errors.Wrapf(, "leading %q", )
	case minusInNumber: // minus handled by caller
		 := badToken(, .offset())
		return 0, errors.Wrap(, "double minus")
	case 0:
		if  == .tail {
			return .float64Slow()
		}
		 = .buf[]
		if floatDigits[] >= 0 {
			 := badToken(, .offset()+1)
			return 0, errors.Wrap(, "leading zero")
		}
	}
	 := uint64()
	// Chars before dot.
:
	for ;  < .tail; ++ {
		 = .buf[]
		 := floatDigits[]
		switch  {
		case invalidCharForNumber:
			return 0, badToken(, .offset()+)
		case endOfNumber:
			.head = 
			return float64(), nil
		case dotInNumber, expInNumber:
			break 
		}
		if  > uint64SafeToMultiple10 {
			return .float64Slow()
		}
		 = ( << 3) + ( << 1) + uint64() // value = value * 10 + ind;
	}
	// chars after dot
	if  == '.' {
		++
		 := 0
		if  == .tail {
			return .float64Slow()
		}
		for ;  < .tail; ++ {
			 = .buf[]
			 := floatDigits[]
			switch  {
			case endOfNumber:
				if  > 0 &&  < len(pow10) {
					.head = 
					return float64() / float64(pow10[]), nil
				}
				// too many decimal places
				return .float64Slow()
			case dotInNumber, expInNumber, plusInNumber, minusInNumber:
				return .float64Slow()
			case invalidCharForNumber:
				return 0, badToken(, .offset()+)
			}
			++
			// Not checking for uint64SafeToMultiple10 here because
			// if condition is positive value multiplied by 10 is
			// guaranteed to be bigger than maxFloat64.
			 = ( << 3) + ( << 1) + uint64()
			if  > maxFloat64 {
				return .float64Slow()
			}
		}
	}
	return .float64Slow()
}

func ( *Decoder) () (float32, error) {
	,  := .floatSlow(32)
	if  != nil {
		return 0, 
	}
	return float32(), 
}

func ( *Decoder) () (float64, error) { return .floatSlow(64) }

func ( *Decoder) ( int) (float64, error) {
	var (
		    [32]byte
		 = .offset()
	)

	,  := .numberAppend([:0])
	if  != nil {
		return 0, errors.Wrap(, "number")
	}

	if  := validateFloat(, );  != nil {
		return 0, 
	}

	,  := strconv.ParseFloat(string(), )
	if  != nil {
		return 0, 
	}

	return , nil
}

func ( []byte,  int) error {
	// strconv.ParseFloat is not validating `1.` or `1.e1`
	if len() == 0 {
		// FIXME(tdakkota): use io.ErrUnexpectedEOF?
		return errors.New("empty")
	}

	switch  := [0]; floatDigits[] {
	case dotInNumber, plusInNumber, expInNumber:
		 := badToken(, )
		return errors.Wrapf(, "leading %q", )
	case minusInNumber: // minus handled by caller
		 := badToken(, )
		return errors.Wrap(, "double minus")
	case 0:
		if len() >= 2 {
			switch [1] {
			case 'e', 'E', '.':
			default:
				 := badToken([1], +1)
				return errors.Wrap(, "leading zero")
			}
		}
	}

	 := bytes.IndexByte(, '.')
	if  != -1 {
		if  == len()-1 {
			// FIXME(tdakkota): use io.ErrUnexpectedEOF?
			return errors.New("dot as last char")
		}
		switch  := [+1];  {
		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
		default:
			 := badToken(, ++1)
			return errors.Wrap(, "no digit after dot")
		}
	}
	return nil
}