// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package decimal128

import (
	
	
	
	
	

	
)

const (
	MaxPrecision = 38
	MaxScale     = 38
)

var (
	MaxDecimal128 = New(542101086242752217, 687399551400673280-1)
)

func ( int32) Num {
	return scaleMultipliers[].Sub(FromU64(1))
}

// Num represents a signed 128-bit integer in two's complement.
// Calculations wrap around and overflow is ignored.
//
// For a discussion of the algorithms, look at Knuth's volume 2,
// Semi-numerical Algorithms section 4.3.1.
//
// Adapted from the Apache ORC C++ implementation
type Num struct {
	lo uint64 // low bits
	hi int64  // high bits
}

// New returns a new signed 128-bit integer value.
func ( int64,  uint64) Num {
	return Num{lo: , hi: }
}

// FromU64 returns a new signed 128-bit integer value from the provided uint64 one.
func ( uint64) Num {
	return New(0, )
}

// FromI64 returns a new signed 128-bit integer value from the provided int64 one.
func ( int64) Num {
	switch {
	case  > 0:
		return New(0, uint64())
	case  < 0:
		return New(-1, uint64())
	default:
		return Num{}
	}
}

// FromBigInt will convert a big.Int to a Num, if the value in v has a
// BitLen > 128, this will panic.
func ( *big.Int) ( Num) {
	 := .BitLen()
	if  > 127 {
		panic("arrow/decimal128: cannot represent value larger than 128bits")
	} else if  == 0 {
		// if bitlen is 0, then the value is 0 so return the default zeroed
		// out n
		return
	}

	// if the value is negative, then get the high and low bytes from
	// v, and then negate it. this is because Num uses a two's compliment
	// representation of values and big.Int stores the value as a bool for
	// the sign and the absolute value of the integer. This means that the
	// raw bytes are *always* the absolute value.
	 := .Bits()
	.lo = uint64([0])
	if len() > 1 {
		.hi = int64([1])
	}
	if .Sign() < 0 {
		return .Negate()
	}
	return
}

// Negate returns a copy of this Decimal128 value but with the sign negated
func ( Num) () Num {
	.lo = ^.lo + 1
	.hi = ^.hi
	if .lo == 0 {
		.hi += 1
	}
	return 
}

func ( Num) ( Num) Num {
	.hi += .hi
	var  uint64
	.lo,  = bits.Add64(.lo, .lo, 0)
	.hi += int64()
	return 
}

func ( Num) ( Num) Num {
	.hi -= .hi
	var  uint64
	.lo,  = bits.Sub64(.lo, .lo, 0)
	.hi -= int64()
	return 
}

func ( Num) ( Num) Num {
	,  := bits.Mul64(.lo, .lo)
	 += (uint64(.hi) * .lo) + (.lo * uint64(.hi))
	return Num{hi: int64(), lo: }
}

func ( Num) ( Num) (,  Num) {
	 := .BigInt()
	,  := .QuoRem(, .BigInt(), &big.Int{})
	return FromBigInt(), FromBigInt()
}

func ( Num) ( Num) Num {
	 := .BigInt()
	return FromBigInt(.Exp(, .BigInt(), nil))
}

func scalePositiveFloat64( float64, ,  int32) (float64, error) {
	var  float64
	if  >= -38 &&  <= 38 {
		 = float64PowersOfTen[+38]
	} else {
		 = math.Pow10(int())
	}

	 *= 
	 = math.RoundToEven()
	 := float64PowersOfTen[+38]
	if  <= - ||  >=  {
		return 0, fmt.Errorf("cannot convert %f to decimal128(precision=%d, scale=%d): overflow", , , )
	}
	return , nil
}

func fromPositiveFloat64( float64, ,  int32) (Num, error) {
	,  := scalePositiveFloat64(, , )
	if  != nil {
		return Num{}, 
	}

	 := math.Floor(math.Ldexp(, -64))
	 :=  - math.Ldexp(, 64)
	return Num{hi: int64(), lo: uint64()}, nil
}

// this has to exist despite sharing some code with fromPositiveFloat64
// because if we don't do the casts back to float32 in between each
// step, we end up with a significantly different answer!
// Aren't floating point values so much fun?
//
// example value to use:
//
//	v := float32(1.8446746e+15)
//
// You'll end up with a different values if you do:
//
//	FromFloat64(float64(v), 20, 4)
//
// vs
//
//	FromFloat32(v, 20, 4)
//
// because float64(v) == 1844674629206016 rather than 1844674600000000
func fromPositiveFloat32( float32, ,  int32) (Num, error) {
	,  := scalePositiveFloat64(float64(), , )
	if  != nil {
		return Num{}, 
	}

	 := float32(math.Floor(math.Ldexp(float64(float32()), -64)))
	 := float32() - float32(math.Ldexp(float64(), 64))
	return Num{hi: int64(), lo: uint64()}, nil
}

// FromFloat32 returns a new decimal128.Num constructed from the given float32
// value using the provided precision and scale. Will return an error if the
// value cannot be accurately represented with the desired precision and scale.
func ( float32, ,  int32) (Num, error) {
	if  < 0 {
		,  := fromPositiveFloat32(-, , )
		if  != nil {
			return , 
		}
		return .Negate(), nil
	}
	return fromPositiveFloat32(, , )
}

// FromFloat64 returns a new decimal128.Num constructed from the given float64
// value using the provided precision and scale. Will return an error if the
// value cannot be accurately represented with the desired precision and scale.
func ( float64, ,  int32) (Num, error) {
	if  < 0 {
		,  := fromPositiveFloat64(-, , )
		if  != nil {
			return , 
		}
		return .Negate(), nil
	}
	return fromPositiveFloat64(, , )
}

var pt5 = big.NewFloat(0.5)

func ( string, ,  int32) ( Num,  error) {
	// time for some math!
	// Our input precision means "number of digits of precision" but the
	// math/big library refers to precision in floating point terms
	// where it refers to the "number of bits of precision in the mantissa".
	// So we need to figure out how many bits we should use for precision,
	// based on the input precision. Too much precision and we aren't rounding
	// when we should. Too little precision and we round when we shouldn't.
	//
	// In general, the number of decimal digits you get from a given number
	// of bits will be:
	//
	//	digits = log[base 10](2^nbits)
	//
	// it thus follows that:
	//
	//	digits = nbits * log[base 10](2)
	//  nbits = digits / log[base 10](2)
	//
	// So we need to account for our scale since we're going to be multiplying
	// by 10^scale in order to get the integral value we're actually going to use
	// So to get our number of bits we do:
	//
	// 	(prec + scale + 1) / log[base10](2)
	//
	// Finally, we still have a sign bit, so we -1 to account for the sign bit.
	// Aren't floating point numbers fun?
	var  = uint(math.Round(float64(++1)/math.Log10(2))) + 1

	var  *big.Float
	, _,  = big.ParseFloat(, 10, 128, big.ToNearestEven)
	if  != nil {
		return
	}

	if  < 0 {
		var  big.Int
		,  := .Int(&)
		if .BitLen() > 127 {
			return Num{}, errors.New("bitlen too large for decimal128")
		}
		 = FromBigInt()
		, _ = .Div(scaleMultipliers[-])
	} else {
		// Since we're going to truncate this to get an integer, we need to round
		// the value instead because of edge cases so that we match how other implementations
		// (e.g. C++) handles Decimal values. So if we're negative we'll subtract 0.5 and if
		// we're positive we'll add 0.5.
		 := (&big.Float{}).SetInt(scaleMultipliers[].BigInt())
		.SetPrec().Mul(, )
		if .Signbit() {
			.Sub(, pt5)
		} else {
			.Add(, pt5)
		}

		var  big.Int
		,  := .Int(&)
		if .BitLen() > 127 {
			return Num{}, errors.New("bitlen too large for decimal128")
		}
		 = FromBigInt()
	}

	if !.FitsInPrecision() {
		 = fmt.Errorf("val %v doesn't fit in precision %d", , )
	}
	return
}

// ToFloat32 returns a float32 value representative of this decimal128.Num,
// but with the given scale.
func ( Num) ( int32) float32 {
	return float32(.ToFloat64())
}

func ( Num) ( int32) float64 {
	const  float64 = 1.8446744073709552e+19
	 := float64(.hi) * 
	 += float64(.lo)
	if  >= -38 &&  <= 38 {
		return  * float64PowersOfTen[-+38]
	}

	return  * math.Pow10(-int())
}

// ToFloat64 returns a float64 value representative of this decimal128.Num,
// but with the given scale.
func ( Num) ( int32) float64 {
	if .hi < 0 {
		return -.Negate().tofloat64Positive()
	}
	return .tofloat64Positive()
}

func ( Num) ( int32) *big.Float {
	 := (&big.Float{}).SetInt(.BigInt())
	if  < 0 {
		.SetPrec(128).Mul(, (&big.Float{}).SetInt(scaleMultipliers[-].BigInt()))
	} else {
		.SetPrec(128).Quo(, (&big.Float{}).SetInt(scaleMultipliers[].BigInt()))
	}
	return 
}

// LowBits returns the low bits of the two's complement representation of the number.
func ( Num) () uint64 { return .lo }

// HighBits returns the high bits of the two's complement representation of the number.
func ( Num) () int64 { return .hi }

// Sign returns:
//
// -1 if x <  0
//
//	0 if x == 0
//
// +1 if x >  0
func ( Num) () int {
	if  == (Num{}) {
		return 0
	}
	return int(1 | (.hi >> 63))
}

func toBigIntPositive( Num) *big.Int {
	return (&big.Int{}).SetBits([]big.Word{big.Word(.lo), big.Word(.hi)})
}

// while the code would be simpler to just do lsh/rsh and add
// it turns out from benchmarking that calling SetBits passing
// in the words and negating ends up being >2x faster
func ( Num) () *big.Int {
	if .Sign() < 0 {
		 := toBigIntPositive(.Negate())
		return .Neg()
	}
	return toBigIntPositive()
}

// Greater returns true if the value represented by n is > other
func ( Num) ( Num) bool {
	return .Less()
}

// GreaterEqual returns true if the value represented by n is >= other
func ( Num) ( Num) bool {
	return !.Less()
}

// Less returns true if the value represented by n is < other
func ( Num) ( Num) bool {
	return .hi < .hi || (.hi == .hi && .lo < .lo)
}

// LessEqual returns true if the value represented by n is <= other
func ( Num) ( Num) bool {
	return !.Greater()
}

// Max returns the largest Decimal128 that was passed in the arguments
func ( Num,  ...Num) Num {
	 := 
	for ,  := range  {
		if .Greater() {
			 = 
		}
	}
	return 
}

// Min returns the smallest Decimal128 that was passed in the arguments
func ( Num,  ...Num) Num {
	 := 
	for ,  := range  {
		if .Less() {
			 = 
		}
	}
	return 
}

// Cmp compares the numbers represented by n and other and returns:
//
//	+1 if n > other
//	 0 if n == other
//	-1 if n < other
func ( Num) ( Num) int {
	switch {
	case .Greater():
		return 1
	case .Less():
		return -1
	}
	return 0
}

// IncreaseScaleBy returns a new decimal128.Num with the value scaled up by
// the desired amount. Must be 0 <= increase <= 38. Any data loss from scaling
// is ignored. If you wish to prevent data loss, use Rescale which will
// return an error if data loss is detected.
func ( Num) ( int32) Num {
	debug.Assert( >= 0, "invalid increase scale for decimal128")
	debug.Assert( <= 38, "invalid increase scale for decimal128")

	 := scaleMultipliers[].BigInt()
	return FromBigInt(.Mul(.BigInt(), ))
}

// ReduceScaleBy returns a new decimal128.Num with the value scaled down by
// the desired amount and, if 'round' is true, the value will be rounded
// accordingly. Assumes 0 <= reduce <= 38. Any data loss from scaling
// is ignored. If you wish to prevent data loss, use Rescale which will
// return an error if data loss is detected.
func ( Num) ( int32,  bool) Num {
	debug.Assert( >= 0, "invalid reduce scale for decimal128")
	debug.Assert( <= 38, "invalid reduce scale for decimal128")

	if  == 0 {
		return 
	}

	 := scaleMultipliers[].BigInt()
	,  := .QuoRem(.BigInt(), , (&big.Int{}))
	if  {
		 := scaleMultipliersHalf[]
		if .Abs().Cmp(.BigInt()) != -1 {
			.Add(, big.NewInt(int64(.Sign())))
		}
	}
	return FromBigInt()
}

func ( Num) ( int32,  Num) ( Num,  bool) {
	var (
		, ,  *big.Int
	)
	 = .BigInt()
	if  < 0 {
		debug.Assert(.lo != 0 || .hi != 0, "multiplier needs to not be zero")
		,  = (&big.Int{}).QuoRem(, .BigInt(), (&big.Int{}))
		return FromBigInt(), .Cmp(big.NewInt(0)) != 0
	}

	 = (&big.Int{}).Mul(, .BigInt())
	 = FromBigInt()
	 := .Cmp()
	if .Sign() < 0 {
		 =  == 1
	} else {
		 =  == -1
	}
	return
}

// Rescale returns a new decimal128.Num with the value updated assuming
// the current value is scaled to originalScale with the new value scaled
// to newScale. If rescaling this way would cause data loss, an error is
// returned instead.
func ( Num) (,  int32) ( Num,  error) {
	if  ==  {
		return , nil
	}

	 :=  - 
	 := int32(math.Abs(float64()))

	 := scaleMultipliers[]
	var  bool
	,  = .rescaleWouldCauseDataLoss(, )
	if  {
		 = errors.New("rescale data loss")
	}
	return
}

// Abs returns a new decimal128.Num that contains the absolute value of n
func ( Num) () Num {
	switch .Sign() {
	case -1:
		return .Negate()
	}
	return 
}

// FitsInPrecision returns true or false if the value currently held by
// n would fit within precision (0 < prec <= 38) without losing any data.
func ( Num) ( int32) bool {
	debug.Assert( > 0, "precision must be > 0")
	debug.Assert( <= 38, "precision must be <= 38")
	return .Abs().Less(scaleMultipliers[])
}

func ( Num) ( int32) string {
	 := (&big.Float{}).SetInt(.BigInt())
	if  < 0 {
		.SetPrec(128).Mul(, (&big.Float{}).SetInt(scaleMultipliers[-].BigInt()))
	} else {
		.SetPrec(128).Quo(, (&big.Float{}).SetInt(scaleMultipliers[].BigInt()))
	}
	return .Text('f', int())
}

func ( int) Num { return scaleMultipliers[] }

func ( int) Num { return scaleMultipliersHalf[] }

var (
	scaleMultipliers = [...]Num{
		FromU64(1),
		FromU64(10),
		FromU64(100),
		FromU64(1000),
		FromU64(10000),
		FromU64(100000),
		FromU64(1000000),
		FromU64(10000000),
		FromU64(100000000),
		FromU64(1000000000),
		FromU64(10000000000),
		FromU64(100000000000),
		FromU64(1000000000000),
		FromU64(10000000000000),
		FromU64(100000000000000),
		FromU64(1000000000000000),
		FromU64(10000000000000000),
		FromU64(100000000000000000),
		FromU64(1000000000000000000),
		New(0, 10000000000000000000),
		New(5, 7766279631452241920),
		New(54, 3875820019684212736),
		New(542, 1864712049423024128),
		New(5421, 200376420520689664),
		New(54210, 2003764205206896640),
		New(542101, 1590897978359414784),
		New(5421010, 15908979783594147840),
		New(54210108, 11515845246265065472),
		New(542101086, 4477988020393345024),
		New(5421010862, 7886392056514347008),
		New(54210108624, 5076944270305263616),
		New(542101086242, 13875954555633532928),
		New(5421010862427, 9632337040368467968),
		New(54210108624275, 4089650035136921600),
		New(542101086242752, 4003012203950112768),
		New(5421010862427522, 3136633892082024448),
		New(54210108624275221, 12919594847110692864),
		New(542101086242752217, 68739955140067328),
		New(5421010862427522170, 687399551400673280),
	}

	scaleMultipliersHalf = [...]Num{
		FromU64(0),
		FromU64(5),
		FromU64(50),
		FromU64(500),
		FromU64(5000),
		FromU64(50000),
		FromU64(500000),
		FromU64(5000000),
		FromU64(50000000),
		FromU64(500000000),
		FromU64(5000000000),
		FromU64(50000000000),
		FromU64(500000000000),
		FromU64(5000000000000),
		FromU64(50000000000000),
		FromU64(500000000000000),
		FromU64(5000000000000000),
		FromU64(50000000000000000),
		FromU64(500000000000000000),
		FromU64(5000000000000000000),
		New(2, 13106511852580896768),
		New(27, 1937910009842106368),
		New(271, 932356024711512064),
		New(2710, 9323560247115120640),
		New(27105, 1001882102603448320),
		New(271050, 10018821026034483200),
		New(2710505, 7954489891797073920),
		New(27105054, 5757922623132532736),
		New(271050543, 2238994010196672512),
		New(2710505431, 3943196028257173504),
		New(27105054312, 2538472135152631808),
		New(271050543121, 6937977277816766464),
		New(2710505431213, 14039540557039009792),
		New(27105054312137, 11268197054423236608),
		New(271050543121376, 2001506101975056384),
		New(2710505431213761, 1568316946041012224),
		New(27105054312137610, 15683169460410122240),
		New(271050543121376108, 9257742014424809472),
		New(2710505431213761085, 343699775700336640),
	}

	float64PowersOfTen = [...]float64{
		1e-38, 1e-37, 1e-36, 1e-35, 1e-34, 1e-33, 1e-32, 1e-31, 1e-30, 1e-29,
		1e-28, 1e-27, 1e-26, 1e-25, 1e-24, 1e-23, 1e-22, 1e-21, 1e-20, 1e-19,
		1e-18, 1e-17, 1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9,
		1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e0, 1e1,
		1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
		1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21,
		1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31,
		1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38,
	}
)