package pgtype

import (
	
	
	
	
	
	
	

	
)
PostgreSQL internal numeric storage uses 16-bit "digits" with base of 10,000
const nbase = 10000

const (
	pgNumericNaN     = 0x00000000c0000000
	pgNumericNaNSign = 0xc000
)

var big0 *big.Int = big.NewInt(0)
var big1 *big.Int = big.NewInt(1)
var big10 *big.Int = big.NewInt(10)
var big100 *big.Int = big.NewInt(100)
var big1000 *big.Int = big.NewInt(1000)

var bigMaxInt8 *big.Int = big.NewInt(math.MaxInt8)
var bigMinInt8 *big.Int = big.NewInt(math.MinInt8)
var bigMaxInt16 *big.Int = big.NewInt(math.MaxInt16)
var bigMinInt16 *big.Int = big.NewInt(math.MinInt16)
var bigMaxInt32 *big.Int = big.NewInt(math.MaxInt32)
var bigMinInt32 *big.Int = big.NewInt(math.MinInt32)
var bigMaxInt64 *big.Int = big.NewInt(math.MaxInt64)
var bigMinInt64 *big.Int = big.NewInt(math.MinInt64)
var bigMaxInt *big.Int = big.NewInt(int64(maxInt))
var bigMinInt *big.Int = big.NewInt(int64(minInt))

var bigMaxUint8 *big.Int = big.NewInt(math.MaxUint8)
var bigMaxUint16 *big.Int = big.NewInt(math.MaxUint16)
var bigMaxUint32 *big.Int = big.NewInt(math.MaxUint32)
var bigMaxUint64 *big.Int = (&big.Int{}).SetUint64(uint64(math.MaxUint64))
var bigMaxUint *big.Int = (&big.Int{}).SetUint64(uint64(maxUint))

var bigNBase *big.Int = big.NewInt(nbase)
var bigNBaseX2 *big.Int = big.NewInt(nbase * nbase)
var bigNBaseX3 *big.Int = big.NewInt(nbase * nbase * nbase)
var bigNBaseX4 *big.Int = big.NewInt(nbase * nbase * nbase * nbase)

type Numeric struct {
	Int    *big.Int
	Exp    int32
	Status Status
	NaN    bool
}

func ( *Numeric) ( interface{}) error {
	if  == nil {
		* = Numeric{Status: Null}
		return nil
	}

	if ,  := .(interface{ () interface{} });  {
		 := .()
		if  !=  {
			return .()
		}
	}

	switch value := .(type) {
	case float32:
		if math.IsNaN(float64()) {
			* = Numeric{Status: Present, NaN: true}
			return nil
		}
		, ,  := parseNumericString(strconv.FormatFloat(float64(), 'f', -1, 64))
		if  != nil {
			return 
		}
		* = Numeric{Int: , Exp: , Status: Present}
	case float64:
		if math.IsNaN() {
			* = Numeric{Status: Present, NaN: true}
			return nil
		}
		, ,  := parseNumericString(strconv.FormatFloat(, 'f', -1, 64))
		if  != nil {
			return 
		}
		* = Numeric{Int: , Exp: , Status: Present}
	case int8:
		* = Numeric{Int: big.NewInt(int64()), Status: Present}
	case uint8:
		* = Numeric{Int: big.NewInt(int64()), Status: Present}
	case int16:
		* = Numeric{Int: big.NewInt(int64()), Status: Present}
	case uint16:
		* = Numeric{Int: big.NewInt(int64()), Status: Present}
	case int32:
		* = Numeric{Int: big.NewInt(int64()), Status: Present}
	case uint32:
		* = Numeric{Int: big.NewInt(int64()), Status: Present}
	case int64:
		* = Numeric{Int: big.NewInt(), Status: Present}
	case uint64:
		* = Numeric{Int: (&big.Int{}).SetUint64(), Status: Present}
	case int:
		* = Numeric{Int: big.NewInt(int64()), Status: Present}
	case uint:
		* = Numeric{Int: (&big.Int{}).SetUint64(uint64()), Status: Present}
	case string:
		, ,  := parseNumericString()
		if  != nil {
			return 
		}
		* = Numeric{Int: , Exp: , Status: Present}
	case *float64:
		if  == nil {
			* = Numeric{Status: Null}
		} else {
			return .(*)
		}
	case *float32:
		if  == nil {
			* = Numeric{Status: Null}
		} else {
			return .(*)
		}
	case *int8:
		if  == nil {
			* = Numeric{Status: Null}
		} else {
			return .(*)
		}
	case *uint8:
		if  == nil {
			* = Numeric{Status: Null}
		} else {
			return .(*)
		}
	case *int16:
		if  == nil {
			* = Numeric{Status: Null}
		} else {
			return .(*)
		}
	case *uint16:
		if  == nil {
			* = Numeric{Status: Null}
		} else {
			return .(*)
		}
	case *int32:
		if  == nil {
			* = Numeric{Status: Null}
		} else {
			return .(*)
		}
	case *uint32:
		if  == nil {
			* = Numeric{Status: Null}
		} else {
			return .(*)
		}
	case *int64:
		if  == nil {
			* = Numeric{Status: Null}
		} else {
			return .(*)
		}
	case *uint64:
		if  == nil {
			* = Numeric{Status: Null}
		} else {
			return .(*)
		}
	case *int:
		if  == nil {
			* = Numeric{Status: Null}
		} else {
			return .(*)
		}
	case *uint:
		if  == nil {
			* = Numeric{Status: Null}
		} else {
			return .(*)
		}
	case *string:
		if  == nil {
			* = Numeric{Status: Null}
		} else {
			return .(*)
		}
	default:
		if ,  := underlyingNumberType();  {
			return .()
		}
		return fmt.Errorf("cannot convert %v to Numeric", )
	}

	return nil
}

func ( Numeric) () interface{} {
	switch .Status {
	case Present:
		return 
	case Null:
		return nil
	default:
		return .Status
	}
}

func ( *Numeric) ( interface{}) error {
	switch .Status {
	case Present:
		switch v := .(type) {
		case *float32:
			,  := .toFloat64()
			if  != nil {
				return 
			}
			return float64AssignTo(, .Status, )
		case *float64:
			,  := .toFloat64()
			if  != nil {
				return 
			}
			return float64AssignTo(, .Status, )
		case *int:
			,  := .toBigInt()
			if  != nil {
				return 
			}
			if .Cmp(bigMaxInt) > 0 {
				return fmt.Errorf("%v is greater than maximum value for %T", , *)
			}
			if .Cmp(bigMinInt) < 0 {
				return fmt.Errorf("%v is less than minimum value for %T", , *)
			}
			* = int(.Int64())
		case *int8:
			,  := .toBigInt()
			if  != nil {
				return 
			}
			if .Cmp(bigMaxInt8) > 0 {
				return fmt.Errorf("%v is greater than maximum value for %T", , *)
			}
			if .Cmp(bigMinInt8) < 0 {
				return fmt.Errorf("%v is less than minimum value for %T", , *)
			}
			* = int8(.Int64())
		case *int16:
			,  := .toBigInt()
			if  != nil {
				return 
			}
			if .Cmp(bigMaxInt16) > 0 {
				return fmt.Errorf("%v is greater than maximum value for %T", , *)
			}
			if .Cmp(bigMinInt16) < 0 {
				return fmt.Errorf("%v is less than minimum value for %T", , *)
			}
			* = int16(.Int64())
		case *int32:
			,  := .toBigInt()
			if  != nil {
				return 
			}
			if .Cmp(bigMaxInt32) > 0 {
				return fmt.Errorf("%v is greater than maximum value for %T", , *)
			}
			if .Cmp(bigMinInt32) < 0 {
				return fmt.Errorf("%v is less than minimum value for %T", , *)
			}
			* = int32(.Int64())
		case *int64:
			,  := .toBigInt()
			if  != nil {
				return 
			}
			if .Cmp(bigMaxInt64) > 0 {
				return fmt.Errorf("%v is greater than maximum value for %T", , *)
			}
			if .Cmp(bigMinInt64) < 0 {
				return fmt.Errorf("%v is less than minimum value for %T", , *)
			}
			* = .Int64()
		case *uint:
			,  := .toBigInt()
			if  != nil {
				return 
			}
			if .Cmp(big0) < 0 {
				return fmt.Errorf("%d is less than zero for %T", , *)
			} else if .Cmp(bigMaxUint) > 0 {
				return fmt.Errorf("%d is greater than maximum value for %T", , *)
			}
			* = uint(.Uint64())
		case *uint8:
			,  := .toBigInt()
			if  != nil {
				return 
			}
			if .Cmp(big0) < 0 {
				return fmt.Errorf("%d is less than zero for %T", , *)
			} else if .Cmp(bigMaxUint8) > 0 {
				return fmt.Errorf("%d is greater than maximum value for %T", , *)
			}
			* = uint8(.Uint64())
		case *uint16:
			,  := .toBigInt()
			if  != nil {
				return 
			}
			if .Cmp(big0) < 0 {
				return fmt.Errorf("%d is less than zero for %T", , *)
			} else if .Cmp(bigMaxUint16) > 0 {
				return fmt.Errorf("%d is greater than maximum value for %T", , *)
			}
			* = uint16(.Uint64())
		case *uint32:
			,  := .toBigInt()
			if  != nil {
				return 
			}
			if .Cmp(big0) < 0 {
				return fmt.Errorf("%d is less than zero for %T", , *)
			} else if .Cmp(bigMaxUint32) > 0 {
				return fmt.Errorf("%d is greater than maximum value for %T", , *)
			}
			* = uint32(.Uint64())
		case *uint64:
			,  := .toBigInt()
			if  != nil {
				return 
			}
			if .Cmp(big0) < 0 {
				return fmt.Errorf("%d is less than zero for %T", , *)
			} else if .Cmp(bigMaxUint64) > 0 {
				return fmt.Errorf("%d is greater than maximum value for %T", , *)
			}
			* = .Uint64()
		default:
			if ,  := GetAssignToDstType();  {
				return .()
			}
			return fmt.Errorf("unable to assign to %T", )
		}
	case Null:
		return NullAssignTo()
	}

	return nil
}

func ( *Numeric) () (*big.Int, error) {
	if .Exp == 0 {
		return .Int, nil
	}

	 := &big.Int{}
	.Set(.Int)
	if .Exp > 0 {
		 := &big.Int{}
		.Exp(big10, big.NewInt(int64(.Exp)), nil)
		.Mul(, )
		return , nil
	}

	 := &big.Int{}
	.Exp(big10, big.NewInt(int64(-.Exp)), nil)
	 := &big.Int{}
	.DivMod(, , )
	if .Cmp(big0) != 0 {
		return nil, fmt.Errorf("cannot convert %v to integer", )
	}
	return , nil
}

func ( *Numeric) () (float64, error) {
	if .NaN {
		return math.NaN(), nil
	}

	 := make([]byte, 0, 32)

	 = append(, .Int.String()...)
	 = append(, 'e')
	 = append(, strconv.FormatInt(int64(.Exp), 10)...)

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

func ( *Numeric) ( *ConnInfo,  []byte) error {
	if  == nil {
		* = Numeric{Status: Null}
		return nil
	}

	if string() == "NaN" {
		* = Numeric{Status: Present, NaN: true}
		return nil
	}

	, ,  := parseNumericString(string())
	if  != nil {
		return 
	}

	* = Numeric{Int: , Exp: , Status: Present}
	return nil
}

func ( string) ( *big.Int,  int32,  error) {
	 := strings.SplitN(, ".", 2)
	 := strings.Join(, "")

	if len() > 1 {
		 = int32(-len([1]))
	} else {
		for len() > 1 && [len()-1] == '0' && [len()-2] != '-' {
			 = [:len()-1]
			++
		}
	}

	 := &big.Int{}
	if ,  := .SetString(, 10); ! {
		return nil, 0, fmt.Errorf("%s is not a number", )
	}

	return , , nil
}

func ( *Numeric) ( *ConnInfo,  []byte) error {
	if  == nil {
		* = Numeric{Status: Null}
		return nil
	}

	if len() < 8 {
		return fmt.Errorf("numeric incomplete %v", )
	}

	 := 0
	 := int16(binary.BigEndian.Uint16([:]))
	 += 2
	 := int16(binary.BigEndian.Uint16([:]))
	 += 2
	 := uint16(binary.BigEndian.Uint16([:]))
	 += 2
	 := int16(binary.BigEndian.Uint16([:]))
	 += 2

	if  == pgNumericNaNSign {
		* = Numeric{Status: Present, NaN: true}
		return nil
	}

	if  == 0 {
		* = Numeric{Int: big.NewInt(0), Status: Present}
		return nil
	}

	if len([:]) < int()*2 {
		return fmt.Errorf("numeric incomplete %v", )
	}

	 := &big.Int{}

	for  := 0;  < int(+3)/4; ++ {
		, ,  := nbaseDigitsToInt64([:])
		 += 

		if  > 0 {
			var  *big.Int
			switch  {
			case 1:
				 = bigNBase
			case 2:
				 = bigNBaseX2
			case 3:
				 = bigNBaseX3
			case 4:
				 = bigNBaseX4
			default:
				return fmt.Errorf("invalid digitsRead: %d (this can't happen)", )
			}
			.Mul(, )
		}

		.Add(, big.NewInt())
	}

	 := (int32() - int32() + 1) * 4

	if  > 0 {
		 :=  -  - 1
		 :=  * 4

		if  >  {
			 := int( - )
			for  := 0;  < ; ++ {
				.Mul(, big10)
				--
			}
		} else if  <  {
			 := int( - )
			for  := 0;  < ; ++ {
				.Div(, big10)
				++
			}
		}
	}

	 := &big.Int{}
	 := &big.Int{}
	if  >= 0 {
		for {
			.DivMod(, big10, )
			if .Cmp(big0) != 0 {
				break
			}
			.Set()
			++
		}
	}

	if  != 0 {
		.Neg()
	}

	* = Numeric{Int: , Exp: , Status: Present}

	return nil

}

func ( []byte) ( int64, ,  int) {
	 := len() / 2
	if  > 4 {
		 = 4
	}

	 := 0

	for  := 0;  < ; ++ {
		if  > 0 {
			 *= nbase
		}
		 += int64(binary.BigEndian.Uint16([:]))
		 += 2
	}

	return , , 
}

func ( Numeric) ( *ConnInfo,  []byte) ([]byte, error) {
	switch .Status {
	case Null:
		return nil, nil
	case Undefined:
		return nil, errUndefined
	}

	if .NaN {
		 = append(, "NaN"...)
		return , nil
	}

	 = append(, .Int.String()...)
	 = append(, 'e')
	 = append(, strconv.FormatInt(int64(.Exp), 10)...)
	return , nil
}

func ( Numeric) ( *ConnInfo,  []byte) ([]byte, error) {
	switch .Status {
	case Null:
		return nil, nil
	case Undefined:
		return nil, errUndefined
	}

	if .NaN {
		 = pgio.AppendUint64(, pgNumericNaN)
		return , nil
	}

	var  int16
	if .Int.Cmp(big0) < 0 {
		 = 16384
	}

	 := &big.Int{}
	 := &big.Int{}
	 := &big.Int{}
	 := &big.Int{}
	.Abs(.Int)
Normalize absInt and exp to where exp is always a multiple of 4. This makes converting to 16-bit base 10,000 digits easier.
	var  int32
	switch .Exp % 4 {
	case 1, -3:
		 = .Exp - 1
		.Mul(, big10)
	case 2, -2:
		 = .Exp - 2
		.Mul(, big100)
	case 3, -1:
		 = .Exp - 3
		.Mul(, big1000)
	default:
		 = .Exp
	}

	if  < 0 {
		 := &big.Int{}
		.Exp(big10, big.NewInt(int64(-)), nil)
		.DivMod(, , )
		.Add(, )
	} else {
		 = 
	}

	var ,  []int16

	for .Cmp(big0) != 0 {
		.DivMod(, bigNBase, )
		 = append(, int16(.Int64()))
	}

	if .Cmp(big0) != 0 {
		for .Cmp(big1) != 0 {
			.DivMod(, bigNBase, )
			 = append(, int16(.Int64()))
		}
	}

	 = pgio.AppendInt16(, int16(len()+len()))

	var  int16
	if len() > 0 {
		 = int16(len() - 1)
		if  > 0 {
			 += int16( / 4)
		}
	} else {
		 = int16(/4) - 1 + int16(len())
	}
	 = pgio.AppendInt16(, )

	 = pgio.AppendInt16(, )

	var  int16
	if .Exp < 0 {
		 = int16(-.Exp)
	}
	 = pgio.AppendInt16(, )

	for  := len() - 1;  >= 0; -- {
		 = pgio.AppendInt16(, [])
	}

	for  := len() - 1;  >= 0; -- {
		 = pgio.AppendInt16(, [])
	}

	return , nil
}
Scan implements the database/sql Scanner interface.
func ( *Numeric) ( interface{}) error {
	if  == nil {
		* = Numeric{Status: Null}
		return nil
	}

	switch src := .(type) {
	case string:
		return .DecodeText(nil, []byte())
	case []byte:
		 := make([]byte, len())
		copy(, )
		return .DecodeText(nil, )
	}

	return fmt.Errorf("cannot scan %T", )
}
Value implements the database/sql/driver Valuer interface.
func ( Numeric) () (driver.Value, error) {
	switch .Status {
	case Present:
		,  := .EncodeText(nil, nil)
		if  != nil {
			return nil, 
		}

		return string(), nil
	case Null:
		return nil, nil
	default:
		return nil, errUndefined
	}