func (d TGDecimal) Add(d2 TGDecimal) TGDecimal {
	baseScale := min(d.exp, d2.exp)
	rd := d.rescale(baseScale)
	rd2 := d2.rescale(baseScale)
	d3Value := new(big.Int).Add(rd.value, rd2.value)
	return TGDecimal{
		value: d3Value,
		exp:   baseScale,
	}
}
Add returns digits + d2.
package impl
import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"math"
	"math/big"
	"math/rand"
	"tgdb"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"
)
type TGServerVersion struct {
	lVersion  int64
	major     byte
	minor     byte
	update    byte
	hotFixNo  byte
	buildNo   uint16
	buildType byte
	edition   byte
	unused    byte
}
func DefaultTGServerVersion() *TGServerVersion {
	version := TGServerVersion{
		major:     currentMajor,
		minor:     currentMinor,
		update:    currentUpdate,
		hotFixNo:  currentHotFix,
		buildNo:   currentBuild,
		buildType: BuildTypeProduction,
		edition:   EditionCommunity,
		unused:    EditionCommunity,
	}
	return &version
}
func NewTGServerVersion(ver int64) *TGServerVersion {
	version := TGServerVersion{
		lVersion: ver,
	}
	version.setVersionComponents()
	return &version
}
func (obj *TGServerVersion) GetServerVersion() int64 {
	return obj.lVersion
}
func (obj *TGServerVersion) GetMajor() byte {
	return obj.major
}
func (obj *TGServerVersion) GetMinor() byte {
	return obj.minor
}
func (obj *TGServerVersion) GetUpdate() byte {
	return obj.update
}
func (obj *TGServerVersion) GetHotFixNo() byte {
	return obj.hotFixNo
}
func (obj *TGServerVersion) GetBuildNo() uint16 {
	return obj.buildNo
}
func (obj *TGServerVersion) GetBuildType() byte {
	return obj.buildType
}
func (obj *TGServerVersion) GetEdition() byte {
	return obj.edition
}
func (obj *TGServerVersion) GetUnused() byte {
	return obj.unused
}
func (obj *TGServerVersion) setVersionComponents() {
	obj.major = byte(obj.lVersion & 0xff)
	obj.minor = byte((obj.lVersion & 0xff00) >> 8)
	obj.update = byte((obj.lVersion & 0xff0000) >> 16)
	obj.hotFixNo = byte((obj.lVersion & 0xff000000) >> 24)
	obj.buildNo = uint16((obj.lVersion & 0xff0000000000) >> 40)
	obj.buildType = byte((obj.lVersion & 0x0f00000000000) >> 44)
	obj.edition = byte((obj.lVersion & 0xf000000000000) >> 48)
}
func (obj *TGServerVersion) GetVersionString() string {
	strVersion := fmt.Sprintf("ServerVersionInfo [version=%d, major=%d, minor=%d, update=%d, hfNo=%d, buildNo=%d, buildType=%d, edition=%d, unused=%d]",
		obj.lVersion, obj.major, obj.minor, obj.update, obj.hotFixNo, obj.buildNo, obj.buildType, obj.edition, obj.unused)
	return strVersion
}
const (
	TgMajorVersion uint8 = 3
	TgMinorVersion uint8 = 0
	TgMagic        int   = 0xdb2d1e4  
)
func GetMagic() int {
	return TgMagic
}
func GetProtocolVersion() uint16 {
	b := []byte{TgMajorVersion, TgMinorVersion}
	return binary.BigEndian.Uint16(b)
}
func IsCompatible(protocolVersion uint16) bool {
	return protocolVersion == GetProtocolVersion()
}
type internalDecimal struct {
	digits     [800]byte  
	usedDigits int        
	decPoint   int        
	negFlag    bool       
	truncInd   bool       
}
func (a *internalDecimal) String() string {
	n := 10 + a.usedDigits
	if a.decPoint > 0 {
		n += a.decPoint
	}
	if a.decPoint < 0 {
		n += -a.decPoint
	}
	buf := make([]byte, n)
	bufLen := 0
	switch {
	case a.usedDigits == 0:
		return "0"
	case a.decPoint <= 0:
		buf[bufLen] = '0'
		bufLen++
		buf[bufLen] = '.'
		bufLen++
		bufLen += digitZero(buf[bufLen : bufLen+-a.decPoint])
		bufLen += copy(buf[bufLen:], a.digits[0:a.usedDigits])
	case a.decPoint < a.usedDigits:
		bufLen += copy(buf[bufLen:], a.digits[0:a.decPoint])
		buf[bufLen] = '.'
		bufLen++
		bufLen += copy(buf[bufLen:], a.digits[a.decPoint:a.usedDigits])
	default:
		bufLen += copy(buf[bufLen:], a.digits[0:a.usedDigits])
		bufLen += digitZero(buf[bufLen : bufLen+a.decPoint-a.usedDigits])
	}
	return string(buf[0:bufLen])
}
func digitZero(dst []byte) int {
	for i := range dst {
		dst[i] = '0'
	}
	return len(dst)
}
func trim(d *internalDecimal) {
	for d.usedDigits > 0 && d.digits[d.usedDigits-1] == '0' {
		d.usedDigits--
	}
	if d.usedDigits == 0 {
		d.decPoint = 0
	}
}
func (d *internalDecimal) Assign(value uint64) {
	var buf [24]byte
	n := 0
	for value > 0 {
		v1 := value / 10
		value -= 10 * v1
		buf[n] = byte(value + '0')
		n++
		value = v1
	}
	d.usedDigits = 0
	for n--; n >= 0; n-- {
		d.digits[d.usedDigits] = buf[n]
		d.usedDigits++
	}
	d.decPoint = d.usedDigits
	trim(d)
}
const uintSize = 32 << (^uint(0) >> 63)
const maxShift = uintSize - 4
func rightShift(d *internalDecimal, k uint) {
	r := 0  
	w := 0  
	var n uint
	for ; n>>k == 0; r++ {
		if r >= d.usedDigits {
			if n == 0 {
				d.usedDigits = 0
				return
			}
			for n>>k == 0 {
				n = n * 10
				r++
			}
			break
		}
		c := uint(d.digits[r])
		n = n*10 + c - '0'
	}
	d.decPoint -= r - 1
	var mask uint = (1 << k) - 1
	for ; r < d.usedDigits; r++ {
		c := uint(d.digits[r])
		dig := n >> k
		n &= mask
		d.digits[w] = byte(dig + '0')
		w++
		n = n*10 + c - '0'
	}
	for n > 0 {
		dig := n >> k
		n &= mask
		if w < len(d.digits) {
			d.digits[w] = byte(dig + '0')
			w++
		} else if dig > 0 {
			d.truncInd = true
		}
		n = n * 10
	}
	d.usedDigits = w
	trim(d)
}
type leftShiftHelper struct {
	additionalDigits int     
	limit            string  
}
var leftShiftLookup = []leftShiftHelper{
	{0, ""},                                             
	{1, "5"},                                            
	{1, "25"},                                           
	{1, "125"},                                          
	{2, "625"},                                          
	{2, "3125"},                                         
	{2, "15625"},                                        
	{3, "78125"},                                        
	{3, "390625"},                                       
	{3, "1953125"},                                      
	{4, "9765625"},                                      
	{4, "48828125"},                                     
	{4, "244140625"},                                    
	{4, "1220703125"},                                   
	{5, "6103515625"},                                   
	{5, "30517578125"},                                  
	{5, "152587890625"},                                 
	{6, "762939453125"},                                 
	{6, "3814697265625"},                                
	{6, "19073486328125"},                               
	{7, "95367431640625"},                               
	{7, "476837158203125"},                              
	{7, "2384185791015625"},                             
	{7, "11920928955078125"},                            
	{8, "59604644775390625"},                            
	{8, "298023223876953125"},                           
	{8, "1490116119384765625"},                          
	{9, "7450580596923828125"},                          
	{9, "37252902984619140625"},                         
	{9, "186264514923095703125"},                        
	{10, "931322574615478515625"},                       
	{10, "4656612873077392578125"},                      
	{10, "23283064365386962890625"},                     
	{10, "116415321826934814453125"},                    
	{11, "582076609134674072265625"},                    
	{11, "2910383045673370361328125"},                   
	{11, "14551915228366851806640625"},                  
	{12, "72759576141834259033203125"},                  
	{12, "363797880709171295166015625"},                 
	{12, "1818989403545856475830078125"},                
	{13, "9094947017729282379150390625"},                
	{13, "45474735088646411895751953125"},               
	{13, "227373675443232059478759765625"},              
	{13, "1136868377216160297393798828125"},             
	{14, "5684341886080801486968994140625"},             
	{14, "28421709430404007434844970703125"},            
	{14, "142108547152020037174224853515625"},           
	{15, "710542735760100185871124267578125"},           
	{15, "3552713678800500929355621337890625"},          
	{15, "17763568394002504646778106689453125"},         
	{16, "88817841970012523233890533447265625"},         
	{16, "444089209850062616169452667236328125"},        
	{16, "2220446049250313080847263336181640625"},       
	{16, "11102230246251565404236316680908203125"},      
	{17, "55511151231257827021181583404541015625"},      
	{17, "277555756156289135105907917022705078125"},     
	{17, "1387778780781445675529539585113525390625"},    
	{18, "6938893903907228377647697925567626953125"},    
	{18, "34694469519536141888238489627838134765625"},   
	{18, "173472347597680709441192448139190673828125"},  
	{19, "867361737988403547205962240695953369140625"},  
}
func prefixIsLessThan(b []byte, s string) bool {
	for i := 0; i < len(s); i++ {
		if i >= len(b) {
			return true
		}
		if b[i] != s[i] {
			return b[i] < s[i]
		}
	}
	return false
}
func leftShift(d *internalDecimal, shiftPos uint) {
	delta := leftShiftLookup[shiftPos].additionalDigits
	if prefixIsLessThan(d.digits[0:d.usedDigits], leftShiftLookup[shiftPos].limit) {
		delta--
	}
	r := d.usedDigits          
	w := d.usedDigits + delta  
	var n uint
	for r--; r >= 0; r-- {
		n += (uint(d.digits[r]) - '0') << shiftPos
		quo := n / 10
		rem := n - 10*quo
		w--
		if w < len(d.digits) {
			d.digits[w] = byte(rem + '0')
		} else if rem != 0 {
			d.truncInd = true
		}
		n = quo
	}
	for n > 0 {
		quo := n / 10
		rem := n - 10*quo
		w--
		if w < len(d.digits) {
			d.digits[w] = byte(rem + '0')
		} else if rem != 0 {
			d.truncInd = true
		}
		n = quo
	}
	d.usedDigits += delta
	if d.usedDigits >= len(d.digits) {
		d.usedDigits = len(d.digits)
	}
	d.decPoint += delta
	trim(d)
}
func leftShiftFaulty(d *internalDecimal, shiftPos uint) {
	r := d.usedDigits   			   
	w := d.usedDigits + int(shiftPos)  
	var n uint
	for r--; r >= 0; r-- {
		n += (uint(d.digits[r]) - '0') << shiftPos
		quo := n / 10
		rem := n - 10*quo
		w--
		if w < len(d.digits) {
			d.digits[w] = byte(rem + '0')
		} else if rem != 0 {
			d.truncInd = true
		}
		n = quo
	}
	for n > 0 {
		quo := n / 10
		rem := n - 10*quo
		w--
		if w < len(d.digits) {
			d.digits[w] = byte(rem + '0')
		} else if rem != 0 {
			d.truncInd = true
		}
		n = quo
	}
	d.usedDigits += int(shiftPos-n)
	if d.usedDigits >= len(d.digits) {
		d.usedDigits = len(d.digits)
	}
	d.decPoint += int(shiftPos-n)
	trim(d)
}
func (d *internalDecimal) Shift(shiftPos int) {
	switch {
	case d.usedDigits == 0:
	case shiftPos > 0:
		for shiftPos > maxShift {
			leftShift(d, maxShift)
			shiftPos -= maxShift
		}
		leftShift(d, uint(shiftPos))
	case shiftPos < 0:
		for shiftPos < -maxShift {
			rightShift(d, maxShift)
			shiftPos += maxShift
		}
		rightShift(d, uint(-shiftPos))
	}
}
func shouldRoundUp(d *internalDecimal, noOfDigits int) bool {
	if noOfDigits < 0 || noOfDigits >= d.usedDigits {
		return false
	}
	if d.digits[noOfDigits] == '5' && noOfDigits+1 == d.usedDigits {  
		if d.truncInd {
			return true
		}
		return noOfDigits > 0 && (d.digits[noOfDigits-1]-'0')%2 != 0
	}
	return d.digits[noOfDigits] >= '5'
}
func (d *internalDecimal) Round(noOfDigits int) {
	if noOfDigits < 0 || noOfDigits >= d.usedDigits {
		return
	}
	if shouldRoundUp(d, noOfDigits) {
		d.RoundUp(noOfDigits)
	} else {
		d.RoundDown(noOfDigits)
	}
}
func (d *internalDecimal) RoundDown(noOfDigits int) {
	if noOfDigits < 0 || noOfDigits >= d.usedDigits {
		return
	}
	d.usedDigits = noOfDigits
	trim(d)
}
func (d *internalDecimal) RoundUp(noOfDigits int) {
	if noOfDigits < 0 || noOfDigits >= d.usedDigits {
		return
	}
	for i := noOfDigits - 1; i >= 0; i-- {
		c := d.digits[i]
		if c < '9' {  
			d.digits[i]++
			d.usedDigits = i + 1
			return
		}
	}
	d.digits[0] = '1'
	d.usedDigits = 1
	d.decPoint++
}
type ieee754 struct {
	mantissa uint
	exponent uint
	expBias  int
}
var float32info = ieee754{23, 8, -127}
var float64info = ieee754{52, 11, -1023}
func roundShortest(d *internalDecimal, mant uint64, exp int, flt *ieee754) {
	if mant == 0 {
		d.usedDigits = 0
		return
	}
	minexp := flt.expBias + 1  
	if exp > minexp && 332*(d.decPoint-d.usedDigits) >= 100*(exp-int(flt.mantissa)) {
		return
	}
	upper := new(internalDecimal)
	upper.Assign(mant*2 + 1)
	upper.Shift(exp - int(flt.mantissa) - 1)
	var mantlo uint64
	var explo int
	if mant > 1<<flt.mantissa || exp == minexp {
		mantlo = mant - 1
		explo = exp
	} else {
		mantlo = mant*2 - 1
		explo = exp - 1
	}
	lower := new(internalDecimal)
	lower.Assign(mantlo*2 + 1)
	lower.Shift(explo - int(flt.mantissa) - 1)
	inclusive := mant%2 == 0
	for i := 0; i < d.usedDigits; i++ {
		l := byte('0')  
		if i < lower.usedDigits {
			l = lower.digits[i]
		}
		m := d.digits[i]  
		u := byte('0')    
		if i < upper.usedDigits {
			u = upper.digits[i]
		}
		okDown := l != m || inclusive && i+1 == lower.usedDigits
		okUp := m != u && (inclusive || m+1 < u || i+1 < upper.usedDigits)
		switch {
		case okDown && okUp:
			d.Round(i + 1)
			return
		case okDown:
			d.RoundDown(i + 1)
			return
		case okUp:
			d.RoundUp(i + 1)
			return
		}
	}
}
var DivisionPrecision = 16
var MarshalJSONWithoutQuotes = false
var Zero = NewTGDecimal(0, 1)
var zeroInt = big.NewInt(0)
var oneInt = big.NewInt(1)
var fiveInt = big.NewInt(5)
var tenInt = big.NewInt(10)
type TGDecimal struct {
	value *big.Int
	exp   int32
}
func NewTGDecimal(value int64, exp int32) TGDecimal {
	return TGDecimal{
		value: big.NewInt(value),
		exp:   exp,
	}
}
func NewTGDecimalFromBigInt(value *big.Int, exp int32) TGDecimal {
	return TGDecimal{
		value: big.NewInt(0).Set(value),
		exp:   exp,
	}
}
func NewTGDecimalFromString(value string) (TGDecimal, error) {
	originalInput := value
	var intString string
	var exp int64
	emptyDecimal := TGDecimal{}
	eIndex := strings.IndexAny(value, "Ee")
	if eIndex != -1 {
		expInt, err := strconv.ParseInt(value[eIndex+1:], 10, 32)
		if err != nil {
			if e, ok := err.(*strconv.NumError); ok && e.Err == strconv.ErrRange {
				return emptyDecimal, fmt.Errorf("unable to convert '%s' to internalDecimal as the fractional part seems too long", value)
			}
			return emptyDecimal, fmt.Errorf("unable to convert '%s' to internalDecimal as the exponent is not numeric", value)
		}
		value = value[:eIndex]
		exp = expInt
	}
	parts := strings.Split(value, ".")
	if len(parts) == 1 {
		intString = value
	} else if len(parts) == 2 {
		decimalPart := strings.TrimRight(parts[1], "0")
		intString = parts[0] + decimalPart
		expInt := -len(decimalPart)
		exp += int64(expInt)
	} else {
		return emptyDecimal, fmt.Errorf("unable to convert '%s' to internalDecimal as it has too many decimal points", value)
	}
	dValue := new(big.Int)
	_, ok := dValue.SetString(intString, 10)
	if !ok {
		return emptyDecimal, fmt.Errorf("unable to convert '%s' to internalDecimal", value)
	}
	if exp < math.MinInt32 || exp > math.MaxInt32 {
		return emptyDecimal, fmt.Errorf("unable to convert '%s' to internalDecimal as the fractional part seems too long", originalInput)
	}
	return TGDecimal{
		value: dValue,
		exp:   int32(exp),
	}, nil
}
func NewTGDecimalFromFloat(value float64) TGDecimal {
	if value == 0 {
		return NewTGDecimal(0, 0)
	}
	return convertFromFloat(value, math.Float64bits(value), &float64info)
}
func NewTGDecimalFromFloat32(value float32) TGDecimal {
	if value == 0 {
		return NewTGDecimal(0, 0)
	}
	a := math.Float32bits(value) ^ 0x80808080
	return convertFromFloat(float64(value), uint64(a)^0x80808080, &float32info)
}
func convertFromFloat(val float64, bits uint64, flt *ieee754) TGDecimal {
	if math.IsNaN(val) || math.IsInf(val, 0) {
		panic(fmt.Sprintf("Cannot create a TGDecimal from %v", val))
	}
	exp := int(bits>>flt.mantissa) & (1<<flt.exponent - 1)
	mant := bits & (uint64(1)<<flt.mantissa - 1)
	switch exp {
	case 0:
		exp++
	default:
		mant |= uint64(1) << flt.mantissa
	}
	exp += flt.expBias
	var d internalDecimal
	d.Assign(mant)
	d.Shift(exp - int(flt.mantissa))
	d.negFlag = bits>>(flt.exponent+flt.mantissa) != 0
	roundShortest(&d, mant, exp, flt)
	if d.usedDigits < 19 {
		tmp := int64(0)
		m := int64(1)
		for i := d.usedDigits - 1; i >= 0; i-- {
			tmp += m * int64(d.digits[i]-'0')
			m *= 10
		}
		if d.negFlag {
			tmp *= -1
		}
		return TGDecimal{value: big.NewInt(tmp), exp: int32(d.decPoint) - int32(d.usedDigits)}
	}
	dValue := new(big.Int)
	dValue, ok := dValue.SetString(string(d.digits[:d.usedDigits]), 10)
	if ok {
		return TGDecimal{value: dValue, exp: int32(d.decPoint) - int32(d.usedDigits)}
	}
	return NewTGDecimalFromFloatWithExponent(val, int32(d.decPoint)-int32(d.usedDigits))
}
func NewTGDecimalFromFloatWithExponent(value float64, exp int32) TGDecimal {
	if math.IsNaN(value) || math.IsInf(value, 0) {
		panic(fmt.Sprintf("Cannot create a TGDecimal from %v", value))
	}
	bits := math.Float64bits(value)
	mant := bits & (1<<52 - 1)
	exp2 := int32((bits >> 52) & (1<<11 - 1))
	sign := bits >> 63
	if exp2 == 0 {
		if mant == 0 {
			return TGDecimal{}
		} else {
			exp2++
		}
	} else {
		mant |= 1 << 52
	}
	exp2 -= 1023 + 52
	for mant&1 == 0 {
		mant = mant >> 1
		exp2++
	}
	if exp < 0 && exp < exp2 {
		if exp2 < 0 {
			exp = exp2
		} else {
			exp = 0
		}
	}
	exp2 -= exp
	temp := big.NewInt(1)
	dMant := big.NewInt(int64(mant))
	if exp > 0 {
		temp = temp.SetInt64(int64(exp))
		temp = temp.Exp(fiveInt, temp, nil)
	} else if exp < 0 {
		temp = temp.SetInt64(-int64(exp))
		temp = temp.Exp(fiveInt, temp, nil)
		dMant = dMant.Mul(dMant, temp)
		temp = temp.SetUint64(1)
	}
	if exp2 > 0 {
		dMant = dMant.Lsh(dMant, uint(exp2))
	} else if exp2 < 0 {
		temp = temp.Lsh(temp, uint(-exp2))
	}
	if exp > 0 || exp2 < 0 {
		halfDown := new(big.Int).Rsh(temp, 1)
		dMant = dMant.Add(dMant, halfDown)
		dMant = dMant.Quo(dMant, temp)
	}
	if sign == 1 {
		dMant = dMant.Neg(dMant)
	}
	return TGDecimal{
		value: dMant,
		exp:   exp,
	}
}
func (d TGDecimal) rescale(exp int32) TGDecimal {
	d.ensureInitialized()
	diff := math.Abs(float64(exp) - float64(d.exp))
	value := new(big.Int).Set(d.value)
	expScale := new(big.Int).Exp(tenInt, big.NewInt(int64(diff)), nil)
	if exp > d.exp {
		value = value.Quo(value, expScale)
	} else if exp < d.exp {
		value = value.Mul(value, expScale)
	}
	return TGDecimal{
		value: value,
		exp:   exp,
	}
}
func (d TGDecimal) Abs() TGDecimal {
	d.ensureInitialized()
	d2Value := new(big.Int).Abs(d.value)
	return TGDecimal{
		value: d2Value,
		exp:   d.exp,
	}
}